replacing a recursive call with a goto; saves lots of stack space.
This commit is contained in:
parent
e119a66bcd
commit
43cb51f640
|
@ -660,8 +660,8 @@ static void list(value_t *pv, uint32_t nargs, value_t *plastcdr)
|
||||||
|
|
||||||
#define eval(e) (selfevaluating(e) ? (e) : eval_sexpr((e),penv,0))
|
#define eval(e) (selfevaluating(e) ? (e) : eval_sexpr((e),penv,0))
|
||||||
#define topeval(e, env) (selfevaluating(e) ? (e) : eval_sexpr((e),env,1))
|
#define topeval(e, env) (selfevaluating(e) ? (e) : eval_sexpr((e),env,1))
|
||||||
#define tail_eval(xpr) do { SP = saveSP; \
|
#define tail_eval(xpr) do { \
|
||||||
if (selfevaluating(xpr)) { return (xpr); } \
|
if (selfevaluating(xpr)) { SP=saveSP; return (xpr); } \
|
||||||
else { e=(xpr); goto eval_top; } } while (0)
|
else { e=(xpr); goto eval_top; } } while (0)
|
||||||
|
|
||||||
/* eval a list of expressions, giving a list of the results */
|
/* eval a list of expressions, giving a list of the results */
|
||||||
|
@ -767,24 +767,30 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
|
||||||
value_t f, v, *pv, *lenv;
|
value_t f, v, *pv, *lenv;
|
||||||
cons_t *c;
|
cons_t *c;
|
||||||
symbol_t *sym;
|
symbol_t *sym;
|
||||||
uint32_t saveSP, envsz, nargs;
|
uint32_t saveSP, bp, envsz, nargs;
|
||||||
int i, noeval=0;
|
int i, noeval=0;
|
||||||
fixnum_t s, lo, hi;
|
fixnum_t s, lo, hi;
|
||||||
cvalue_t *cv;
|
cvalue_t *cv;
|
||||||
int64_t accum;
|
int64_t accum;
|
||||||
|
|
||||||
|
/*
|
||||||
|
ios_printf(ios_stdout, "eval "); print(ios_stdout, e, 0);
|
||||||
|
ios_printf(ios_stdout, " in "); print(ios_stdout, penv[0], 0);
|
||||||
|
ios_printf(ios_stdout, "\n");
|
||||||
|
*/
|
||||||
|
saveSP = SP;
|
||||||
eval_top:
|
eval_top:
|
||||||
if (issymbol(e)) {
|
if (issymbol(e)) {
|
||||||
sym = (symbol_t*)ptr(e);
|
sym = (symbol_t*)ptr(e);
|
||||||
if (sym->syntax == TAG_CONST) return sym->binding;
|
if (sym->syntax == TAG_CONST) { SP=saveSP; return sym->binding; }
|
||||||
while (1) {
|
while (1) {
|
||||||
v = *penv++;
|
v = *penv++;
|
||||||
while (iscons(v)) {
|
while (iscons(v)) {
|
||||||
if (car_(v)==e) return *penv;
|
if (car_(v)==e) { SP=saveSP; return *penv; }
|
||||||
v = cdr_(v); penv++;
|
v = cdr_(v); penv++;
|
||||||
}
|
}
|
||||||
if (v != NIL) {
|
if (v != NIL) {
|
||||||
if (v == e) return *penv; // dotted list
|
if (v == e) { SP=saveSP; return *penv; } // dotted list
|
||||||
penv++;
|
penv++;
|
||||||
}
|
}
|
||||||
if (*penv == NIL) break;
|
if (*penv == NIL) break;
|
||||||
|
@ -792,11 +798,15 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
|
||||||
}
|
}
|
||||||
if (__unlikely((v = sym->binding) == UNBOUND))
|
if (__unlikely((v = sym->binding) == UNBOUND))
|
||||||
raise(list2(UnboundError, e));
|
raise(list2(UnboundError, e));
|
||||||
|
SP = saveSP;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
if (__unlikely(SP >= (N_STACK-MAX_ARGS-4)))
|
if (__unlikely(SP >= (N_STACK-MAX_ARGS-4))) {
|
||||||
return new_stackseg(e, penv, tail);
|
v = new_stackseg(e, penv, tail);
|
||||||
saveSP = SP;
|
SP = saveSP;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
bp = SP;
|
||||||
v = car_(e);
|
v = car_(e);
|
||||||
PUSH(cdr_(e));
|
PUSH(cdr_(e));
|
||||||
if (selfevaluating(v)) f=v;
|
if (selfevaluating(v)) f=v;
|
||||||
|
@ -809,40 +819,40 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
|
||||||
else {
|
else {
|
||||||
noeval = 2;
|
noeval = 2;
|
||||||
PUSH(f);
|
PUSH(f);
|
||||||
v = Stack[saveSP];
|
v = Stack[bp];
|
||||||
goto move_args;
|
goto move_args;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else f = eval(v);
|
else f = eval(v);
|
||||||
PUSH(f);
|
PUSH(f);
|
||||||
v = Stack[saveSP];
|
v = Stack[bp];
|
||||||
// evaluate argument list, placing arguments on stack
|
// evaluate argument list, placing arguments on stack
|
||||||
while (iscons(v)) {
|
while (iscons(v)) {
|
||||||
if (SP-saveSP-2 == MAX_ARGS) {
|
if (SP-bp-2 == MAX_ARGS) {
|
||||||
v = evlis(&Stack[saveSP], penv);
|
v = evlis(&Stack[bp], penv);
|
||||||
PUSH(v);
|
PUSH(v);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
v = car_(v);
|
v = car_(v);
|
||||||
v = eval(v);
|
v = eval(v);
|
||||||
PUSH(v);
|
PUSH(v);
|
||||||
v = Stack[saveSP] = cdr_(Stack[saveSP]);
|
v = Stack[bp] = cdr_(Stack[bp]);
|
||||||
}
|
}
|
||||||
do_apply:
|
do_apply:
|
||||||
nargs = SP - saveSP - 2;
|
nargs = SP - bp - 2;
|
||||||
if (isbuiltinish(f)) {
|
if (isbuiltinish(f)) {
|
||||||
// handle builtin function
|
// handle builtin function
|
||||||
apply_special:
|
apply_special:
|
||||||
switch (uintval(f)) {
|
switch (uintval(f)) {
|
||||||
// special forms
|
// special forms
|
||||||
case F_QUOTE:
|
case F_QUOTE:
|
||||||
if (__unlikely(!iscons(Stack[saveSP])))
|
if (__unlikely(!iscons(Stack[bp])))
|
||||||
lerror(ArgError, "quote: expected argument");
|
lerror(ArgError, "quote: expected argument");
|
||||||
v = car_(Stack[saveSP]);
|
v = car_(Stack[bp]);
|
||||||
break;
|
break;
|
||||||
case F_SETQ:
|
case F_SETQ:
|
||||||
e = car(Stack[saveSP]);
|
e = car(Stack[bp]);
|
||||||
v = car(cdr_(Stack[saveSP]));
|
v = car(cdr_(Stack[bp]));
|
||||||
v = eval(v);
|
v = eval(v);
|
||||||
while (1) {
|
while (1) {
|
||||||
f = *penv++;
|
f = *penv++;
|
||||||
|
@ -890,7 +900,7 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
|
||||||
PUSH(penv[1]); // env has already been captured; share
|
PUSH(penv[1]); // env has already been captured; share
|
||||||
}
|
}
|
||||||
c = (cons_t*)ptr(v=cons_reserve(3));
|
c = (cons_t*)ptr(v=cons_reserve(3));
|
||||||
e = Stack[saveSP];
|
e = Stack[bp];
|
||||||
if (!iscons(e)) goto notpair;
|
if (!iscons(e)) goto notpair;
|
||||||
c->car = LAMBDA;
|
c->car = LAMBDA;
|
||||||
c->cdr = tagptr(c+1, TAG_CONS); c++;
|
c->cdr = tagptr(c+1, TAG_CONS); c++;
|
||||||
|
@ -901,15 +911,15 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
|
||||||
c->cdr = Stack[SP-1]; //env
|
c->cdr = Stack[SP-1]; //env
|
||||||
break;
|
break;
|
||||||
case F_IF:
|
case F_IF:
|
||||||
if (!iscons(Stack[saveSP])) goto notpair;
|
if (!iscons(Stack[bp])) goto notpair;
|
||||||
v = car_(Stack[saveSP]);
|
v = car_(Stack[bp]);
|
||||||
if (eval(v) != FL_F) {
|
if (eval(v) != FL_F) {
|
||||||
v = cdr_(Stack[saveSP]);
|
v = cdr_(Stack[bp]);
|
||||||
if (!iscons(v)) goto notpair;
|
if (!iscons(v)) goto notpair;
|
||||||
v = car_(v);
|
v = car_(v);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
v = cdr_(Stack[saveSP]);
|
v = cdr_(Stack[bp]);
|
||||||
if (!iscons(v)) goto notpair;
|
if (!iscons(v)) goto notpair;
|
||||||
if (!iscons(v=cdr_(v))) v = FL_F; // allow 2-arg form
|
if (!iscons(v=cdr_(v))) v = FL_F; // allow 2-arg form
|
||||||
else v = car_(v);
|
else v = car_(v);
|
||||||
|
@ -917,7 +927,7 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
|
||||||
tail_eval(v);
|
tail_eval(v);
|
||||||
break;
|
break;
|
||||||
case F_COND:
|
case F_COND:
|
||||||
pv = &Stack[saveSP]; v = FL_F;
|
pv = &Stack[bp]; v = FL_F;
|
||||||
while (iscons(*pv)) {
|
while (iscons(*pv)) {
|
||||||
c = tocons(car_(*pv), "cond");
|
c = tocons(car_(*pv), "cond");
|
||||||
v = c->car;
|
v = c->car;
|
||||||
|
@ -941,7 +951,7 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case F_AND:
|
case F_AND:
|
||||||
pv = &Stack[saveSP]; v = FL_T;
|
pv = &Stack[bp]; v = FL_T;
|
||||||
if (iscons(*pv)) {
|
if (iscons(*pv)) {
|
||||||
while (iscons(cdr_(*pv))) {
|
while (iscons(cdr_(*pv))) {
|
||||||
if ((v=eval(car_(*pv))) == FL_F) {
|
if ((v=eval(car_(*pv))) == FL_F) {
|
||||||
|
@ -953,7 +963,7 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case F_OR:
|
case F_OR:
|
||||||
pv = &Stack[saveSP]; v = FL_F;
|
pv = &Stack[bp]; v = FL_F;
|
||||||
if (iscons(*pv)) {
|
if (iscons(*pv)) {
|
||||||
while (iscons(cdr_(*pv))) {
|
while (iscons(cdr_(*pv))) {
|
||||||
if ((v=eval(car_(*pv))) != FL_F) {
|
if ((v=eval(car_(*pv))) != FL_F) {
|
||||||
|
@ -965,11 +975,11 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case F_WHILE:
|
case F_WHILE:
|
||||||
PUSH(cdr(Stack[saveSP]));
|
PUSH(cdr(Stack[bp]));
|
||||||
lenv = &Stack[SP-1];
|
lenv = &Stack[SP-1];
|
||||||
PUSH(*lenv);
|
PUSH(*lenv);
|
||||||
Stack[saveSP] = car_(Stack[saveSP]);
|
Stack[bp] = car_(Stack[bp]);
|
||||||
value_t *cond = &Stack[saveSP];
|
value_t *cond = &Stack[bp];
|
||||||
PUSH(FL_F);
|
PUSH(FL_F);
|
||||||
pv = &Stack[SP-1];
|
pv = &Stack[SP-1];
|
||||||
while (eval(*cond) != FL_F) {
|
while (eval(*cond) != FL_F) {
|
||||||
|
@ -983,7 +993,7 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
|
||||||
break;
|
break;
|
||||||
case F_BEGIN:
|
case F_BEGIN:
|
||||||
// return last arg
|
// return last arg
|
||||||
pv = &Stack[saveSP];
|
pv = &Stack[bp];
|
||||||
if (iscons(*pv)) {
|
if (iscons(*pv)) {
|
||||||
while (iscons(cdr_(*pv))) {
|
while (iscons(cdr_(*pv))) {
|
||||||
v = car_(*pv);
|
v = car_(*pv);
|
||||||
|
@ -996,7 +1006,7 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
|
||||||
break;
|
break;
|
||||||
case F_PROG1:
|
case F_PROG1:
|
||||||
// return first arg
|
// return first arg
|
||||||
pv = &Stack[saveSP];
|
pv = &Stack[bp];
|
||||||
if (__unlikely(!iscons(*pv)))
|
if (__unlikely(!iscons(*pv)))
|
||||||
lerror(ArgError, "prog1: too few arguments");
|
lerror(ArgError, "prog1: too few arguments");
|
||||||
PUSH(eval(car_(*pv)));
|
PUSH(eval(car_(*pv)));
|
||||||
|
@ -1008,7 +1018,7 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
|
||||||
v = POP();
|
v = POP();
|
||||||
break;
|
break;
|
||||||
case F_TRYCATCH:
|
case F_TRYCATCH:
|
||||||
v = do_trycatch(car(Stack[saveSP]), penv);
|
v = do_trycatch(car(Stack[bp]), penv);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// ordinary functions
|
// ordinary functions
|
||||||
|
@ -1033,8 +1043,8 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
|
||||||
break;
|
break;
|
||||||
case F_LIST:
|
case F_LIST:
|
||||||
if (nargs) {
|
if (nargs) {
|
||||||
Stack[saveSP] = v;
|
Stack[bp] = v;
|
||||||
list(&v, nargs, &Stack[saveSP]);
|
list(&v, nargs, &Stack[bp]);
|
||||||
}
|
}
|
||||||
// else v is already set to the final cdr, which is the result
|
// else v is already set to the final cdr, which is the result
|
||||||
break;
|
break;
|
||||||
|
@ -1065,7 +1075,7 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
|
||||||
}
|
}
|
||||||
else i = 0;
|
else i = 0;
|
||||||
v = alloc_vector(nargs+i, 0);
|
v = alloc_vector(nargs+i, 0);
|
||||||
memcpy(&vector_elt(v,0), &Stack[saveSP+2], nargs*sizeof(value_t));
|
memcpy(&vector_elt(v,0), &Stack[bp+2], nargs*sizeof(value_t));
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
e = Stack[SP-1];
|
e = Stack[SP-1];
|
||||||
while (iscons(e)) {
|
while (iscons(e)) {
|
||||||
|
@ -1185,7 +1195,7 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
|
||||||
break;
|
break;
|
||||||
case F_ADD:
|
case F_ADD:
|
||||||
s = 0;
|
s = 0;
|
||||||
i = saveSP+2;
|
i = bp+2;
|
||||||
if (nargs > MAX_ARGS) goto add_ovf;
|
if (nargs > MAX_ARGS) goto add_ovf;
|
||||||
for (; i < (int)SP; i++) {
|
for (; i < (int)SP; i++) {
|
||||||
if (__likely(isfixnum(Stack[i]))) {
|
if (__likely(isfixnum(Stack[i]))) {
|
||||||
|
@ -1206,7 +1216,7 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
|
||||||
break;
|
break;
|
||||||
case F_SUB:
|
case F_SUB:
|
||||||
if (__unlikely(nargs < 1)) lerror(ArgError, "-: too few arguments");
|
if (__unlikely(nargs < 1)) lerror(ArgError, "-: too few arguments");
|
||||||
i = saveSP+2;
|
i = bp+2;
|
||||||
if (nargs == 1) {
|
if (nargs == 1) {
|
||||||
if (__likely(isfixnum(Stack[i])))
|
if (__likely(isfixnum(Stack[i])))
|
||||||
v = fixnum(-numval(Stack[i]));
|
v = fixnum(-numval(Stack[i]));
|
||||||
|
@ -1239,7 +1249,7 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
|
||||||
break;
|
break;
|
||||||
case F_MUL:
|
case F_MUL:
|
||||||
accum = 1;
|
accum = 1;
|
||||||
i = saveSP+2;
|
i = bp+2;
|
||||||
if (nargs > MAX_ARGS) goto mul_ovf;
|
if (nargs > MAX_ARGS) goto mul_ovf;
|
||||||
for (; i < (int)SP; i++) {
|
for (; i < (int)SP; i++) {
|
||||||
if (__likely(isfixnum(Stack[i]))) {
|
if (__likely(isfixnum(Stack[i]))) {
|
||||||
|
@ -1259,7 +1269,7 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
|
||||||
break;
|
break;
|
||||||
case F_DIV:
|
case F_DIV:
|
||||||
if (__unlikely(nargs < 1)) lerror(ArgError, "/: too few arguments");
|
if (__unlikely(nargs < 1)) lerror(ArgError, "/: too few arguments");
|
||||||
i = saveSP+2;
|
i = bp+2;
|
||||||
if (nargs == 1) {
|
if (nargs == 1) {
|
||||||
v = fl_div2(fixnum(1), Stack[i]);
|
v = fl_div2(fixnum(1), Stack[i]);
|
||||||
}
|
}
|
||||||
|
@ -1361,20 +1371,20 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case F_SPECIAL_APPLY:
|
case F_SPECIAL_APPLY:
|
||||||
f = Stack[saveSP-4];
|
f = Stack[bp-4];
|
||||||
v = Stack[saveSP-3];
|
v = Stack[bp-3];
|
||||||
PUSH(f);
|
PUSH(f);
|
||||||
PUSH(v);
|
PUSH(v);
|
||||||
nargs = 2;
|
nargs = 2;
|
||||||
// falls through!!
|
// falls through!!
|
||||||
case F_APPLY:
|
case F_APPLY:
|
||||||
argcount("apply", nargs, 2);
|
argcount("apply", nargs, 2);
|
||||||
v = Stack[saveSP] = Stack[SP-1]; // second arg is new arglist
|
v = Stack[bp] = Stack[SP-1]; // second arg is new arglist
|
||||||
f = Stack[saveSP+1] = Stack[SP-2]; // first arg is new function
|
f = Stack[bp+1] = Stack[SP-2]; // first arg is new function
|
||||||
POPN(2); // pop apply's args
|
POPN(2); // pop apply's args
|
||||||
move_args:
|
move_args:
|
||||||
while (iscons(v)) {
|
while (iscons(v)) {
|
||||||
if (SP-saveSP-2 == MAX_ARGS) {
|
if (SP-bp-2 == MAX_ARGS) {
|
||||||
PUSH(v);
|
PUSH(v);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1388,15 +1398,15 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
|
||||||
goto apply_type_error;
|
goto apply_type_error;
|
||||||
default:
|
default:
|
||||||
// function pointer tagged as a builtin
|
// function pointer tagged as a builtin
|
||||||
v = ((builtin_t)ptr(f))(&Stack[saveSP+2], nargs);
|
v = ((builtin_t)ptr(f))(&Stack[bp+2], nargs);
|
||||||
}
|
}
|
||||||
SP = saveSP;
|
SP = saveSP;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
if (__likely(iscons(f))) {
|
if (__likely(iscons(f))) {
|
||||||
// apply lambda expression
|
// apply lambda expression
|
||||||
f = Stack[saveSP+1];
|
f = Stack[bp+1];
|
||||||
f = Stack[saveSP+1] = cdr_(f);
|
f = Stack[bp+1] = cdr_(f);
|
||||||
if (!iscons(f)) goto notpair;
|
if (!iscons(f)) goto notpair;
|
||||||
v = car_(f); // arglist
|
v = car_(f); // arglist
|
||||||
i = nargs;
|
i = nargs;
|
||||||
|
@ -1424,20 +1434,19 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
|
||||||
PUSH(NIL);
|
PUSH(NIL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f = cdr_(Stack[saveSP+1]);
|
f = cdr_(Stack[bp+1]);
|
||||||
if (!iscons(f)) goto notpair;
|
if (!iscons(f)) goto notpair;
|
||||||
e = car_(f);
|
e = car_(f);
|
||||||
if (selfevaluating(e)) { SP=saveSP; return(e); }
|
if (selfevaluating(e)) { SP=saveSP; return(e); }
|
||||||
PUSH(cdr_(f)); // add closed environment
|
PUSH(cdr_(f)); // add closed environment
|
||||||
Stack[saveSP+1] = car_(Stack[saveSP+1]); // put lambda list
|
Stack[bp+1] = car_(Stack[bp+1]); // put lambda list
|
||||||
envsz = SP - saveSP - 1;
|
envsz = SP - bp - 1;
|
||||||
|
|
||||||
if (noeval == 2) {
|
if (noeval == 2) {
|
||||||
// macro: evaluate body in lambda environment
|
// macro: evaluate body in lambda environment
|
||||||
Stack[saveSP] = fixnum(envsz);
|
Stack[bp] = fixnum(envsz);
|
||||||
e = eval_sexpr(e, &Stack[saveSP+1], 1);
|
e = eval_sexpr(e, &Stack[bp+1], 1);
|
||||||
SP = saveSP;
|
if (selfevaluating(e)) { SP=saveSP; return(e); }
|
||||||
if (selfevaluating(e)) return(e);
|
|
||||||
noeval = 0;
|
noeval = 0;
|
||||||
// macro: evaluate expansion in calling environment
|
// macro: evaluate expansion in calling environment
|
||||||
goto eval_top;
|
goto eval_top;
|
||||||
|
@ -1447,15 +1456,15 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
|
||||||
// ok to overwrite environment
|
// ok to overwrite environment
|
||||||
penv[-1] = fixnum(envsz);
|
penv[-1] = fixnum(envsz);
|
||||||
for(i=0; i < (int)envsz; i++)
|
for(i=0; i < (int)envsz; i++)
|
||||||
penv[i] = Stack[saveSP+1+i];
|
penv[i] = Stack[bp+1+i];
|
||||||
SP = (penv-Stack)+envsz;
|
SP = (penv-Stack)+envsz;
|
||||||
goto eval_top;
|
goto eval_top;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Stack[saveSP] = fixnum(envsz);
|
Stack[bp] = fixnum(envsz);
|
||||||
v = eval_sexpr(e, &Stack[saveSP+1], 1);
|
penv = &Stack[bp+1];
|
||||||
SP = saveSP;
|
tail = 1;
|
||||||
return v;
|
goto eval_top;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// not reached
|
// not reached
|
||||||
|
|
Loading…
Reference in New Issue