###### 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
}
## interp exec cases
}
- return rv;
+ ret.lval = lrv;
+ ret.val = rv;
+ return ret;
}
## Language elements
###### 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)
if (v->merged)
v = v->merged;
- return dup_value(v->val);
+ lrv = &v->val;
+ break;
}
###### ast functions
###### 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:
{
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);
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.