From: NeilBrown Date: Tue, 30 Apr 2019 06:24:09 +0000 (+1000) Subject: oceani: add some support for lvalues. X-Git-Tag: JamisonCreek-3~31 X-Git-Url: https://ocean-lang.org/code/?p=ocean;a=commitdiff_plain;h=f4b24ac2cd27f5ee0e370063509f154f1e5646bf oceani: add some support for lvalues. New linterp_exec() returns an lvalue, (pointer to value) and individual cases can provide either an lvalue or an rvalue. This means the RHS of assignment might not be a simple variable, so we leave the "v = v->merged" part to the "interp exec" for Xvar. Also, linterp_exec() might return NULL, so be careful. This might happen, e.g., when an array index is out of bounds. Signed-off-by: NeilBrown --- diff --git a/csrc/oceani.mdc b/csrc/oceani.mdc index 97fa311..9e1ce02 100644 --- a/csrc/oceani.mdc +++ b/csrc/oceani.mdc @@ -1459,18 +1459,45 @@ Each `exec` can return a value, which may be `Tnone` but must be non-NULL; ###### core functions + struct lrval { + struct value val, *lval; + }; + + static struct lrval _interp_exec(struct exec *e); + static struct value interp_exec(struct exec *e) { - struct value rv; + struct lrval ret = _interp_exec(e); + + if (ret.lval) + return dup_value(*ret.lval); + else + return ret.val; + } + + static struct value *linterp_exec(struct exec *e) + { + struct lrval ret = _interp_exec(e); + + return ret.lval; + } + + static struct lrval _interp_exec(struct exec *e) + { + struct lrval ret; + struct value rv, *lrv = NULL; rv.type = Tnone; - if (!e) - return rv; + if (!e) { + ret.lval = lrv; + ret.val = rv; + return ret; + } switch(e->type) { case Xbinode: { struct binode *b = cast(binode, e); - struct value left, right; + struct value left, right, *lleft; left.type = right.type = Tnone; switch (b->op) { ## interp binode cases @@ -1480,7 +1507,9 @@ Each `exec` can return a value, which may be `Tnone` but must be non-NULL; } ## interp exec cases } - return rv; + ret.lval = lrv; + ret.val = rv; + return ret; } ## Language elements @@ -1579,7 +1608,8 @@ an executable. ###### interp exec cases case Xval: - return dup_value(cast(val, e)->val); + rv = dup_value(cast(val, e)->val); + break; ###### ast functions static void free_val(struct val *v) @@ -1801,7 +1831,8 @@ link to find the primary instance. if (v->merged) v = v->merged; - return dup_value(v->val); + lrv = &v->val; + break; } ###### ast functions @@ -2597,16 +2628,15 @@ it is declared, and error will be raised as the name is created as ###### interp binode cases case Assign: - { - struct variable *v = cast(var, b->left)->var; - if (v->merged) - v = v->merged; + lleft = linterp_exec(b->left); right = interp_exec(b->right); - free_value(v->val); - v->val = right; + if (lleft) { + free_value(*lleft); + *lleft = right; + } else + free_value(right); right.type = NULL; break; - } case Declare: { @@ -3113,10 +3143,10 @@ defined. interp_exec(c->dopart); if (c->thenpart) { - v = interp_exec(c->thenpart); - if (v.type != Tnone || !c->dopart) - return v; - free_value(v); + rv = interp_exec(c->thenpart); + if (rv.type != Tnone || !c->dopart) + goto Xcond_done; + free_value(rv); } } while (c->dopart); @@ -3125,15 +3155,18 @@ defined. if (value_cmp(v, cnd) == 0) { free_value(v); free_value(cnd); - return interp_exec(cp->action); + rv = interp_exec(cp->action); + goto Xcond_done; } free_value(v); } free_value(cnd); if (c->elsepart) - return interp_exec(c->elsepart); - v.type = Tnone; - return v; + rv = interp_exec(c->elsepart); + else + rv.type = Tnone; + Xcond_done: + break; } ### Finally the whole program.