From 6c2108e6bd19ffa47b33f61501f25db47ddb4cfb Mon Sep 17 00:00:00 2001 From: Xavier Del Campo Romero Date: Sat, 15 Nov 2025 18:53:12 +0100 Subject: Add select operator --- src/op/select.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 src/op/select.c (limited to 'src/op/select.c') diff --git a/src/op/select.c b/src/op/select.c new file mode 100644 index 0000000..7705af9 --- /dev/null +++ b/src/op/select.c @@ -0,0 +1,119 @@ +/* + * nanowasm, a tiny WebAssembly/Wasm interpreter + * Copyright (C) 2023-2025 Xavier Del Campo Romero + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include +#include +#include +#include +#include + +static enum nw_state push(struct nw_interp *const i) +{ + struct nw_i_sm_select *const s = &i->sm.select; + const enum nw_state n = nwp_stack_push(i, &s->io); + + if (n) + return n; + + nwp_interp_resume(i); + return NW_AGAIN; +} + +static enum nw_state pop_left(struct nw_interp *const i) +{ + struct nw_i_sm_select *const s = &i->sm.select; + const enum nw_state n = nwp_stack_pop(i, &s->io); + struct nw_sm_io io = {0}; + + if (n) + return n; + + io.buf = s->condition ? &s->left : &s->right; + io.n = s->sz; + s->io = io; + i->next = push; + return NW_AGAIN; +} + +static enum nw_state pop_right(struct nw_interp *const i) +{ + struct nw_i_sm_select *const s = &i->sm.select; + const enum nw_state n = nwp_stack_pop(i, &s->io); + + if (n) + return n; + else + { + struct nw_sm_io io = {0}; + + io.buf = &s->left; + io.n = s->sz; + s->io = io; + } + + i->next = pop_left; + return NW_AGAIN; +} + +static enum nw_state pop_condition(struct nw_interp *const i) +{ + struct nw_i_sm_select *const s = &i->sm.select; + const enum nw_state n = nwp_stack_pop(i, &s->io); + + if (n) + return n; + else + { + struct nw_sm_io io = {0}; + + io.buf = &s->right; + io.n = s->sz; + s->io = io; + } + + i->next = pop_right; + return NW_AGAIN; +} + +static enum nw_state check(struct nw_interp *const i) +{ + struct nw_i_sm_select *const s = &i->sm.select; + + if (nwp_type_sz(i->push_type, &s->sz)) + { + static const char *const exc = "invalid type"; + + i->exception = exc; +#ifdef NW_LOG + nwp_log("%s: %#x\n", exc, (unsigned)i->push_type); +#endif + return NW_FATAL; + } + else + { + struct nw_sm_io io = {0}; + + io.buf = &s->condition; + io.n = sizeof s->condition; + s->io = io; + } + + i->next = pop_condition; + return NW_AGAIN; +} + +void nwp_op_select(struct nw_interp *const i) +{ + const struct nw_i_sm_select s = {0}; + + i->sm.select = s; + i->next = check; +} -- cgit v1.2.3