From c220bef8469ed3bb72f73bfe22d6372255a43056 Mon Sep 17 00:00:00 2001 From: Ian Piumarta Date: Fri, 24 Jan 2025 16:04:15 +0900 Subject: [PATCH] block eval pops scopes properly during nonlocal return --- main.leg | 27 ++++++++++++++++++++++----- test.txt | 3 ++- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/main.leg b/main.leg index 45dfdac..6d1b335 100644 --- a/main.leg +++ b/main.leg @@ -1,6 +1,6 @@ # main.leg -- C parser + interpreter # -# Last edited: 2025-01-24 14:48:22 by piumarta on zora-1043.local +# Last edited: 2025-01-24 16:03:00 by piumarta on zora %{ ; @@ -1263,8 +1263,10 @@ void printiln(oop obj, int indent) break; } case Scope: { - printf("SCOPE\n"); - printiln(get(obj, Scope,names), indent+1); + printf("SCOPE "); + oop names = get(obj, Scope,names); + Array_do(names, name) printf(" %s", toString(name)); + printf("\n"); break; } case TypeName: { @@ -1704,13 +1706,16 @@ oop apply(oop function, oop arguments, oop env) case Function: { oop parameters = get(function, Function,parameters); oop body = get(function, Function,body); + int variadic = get(function, Function,variadic); int parc = get(parameters, Array,size); int argc = get(arguments, Array,size); - assert(get(function, Function,variadic) || (parc == argc)); + if (argc < parc) + fatal("too few arguments calling %s", toString(function)); + if (argc > parc && !variadic) + fatal("too many arguments calling %s", toString(function)); oop *parv = get(parameters, Array,elements); oop *argv = get(arguments, Array,elements); Scope_begin(); - if (get(function, Function,variadic)) --parc; int argn = 0; while (argn < parc) { oop var = parv[argn]; @@ -1839,10 +1844,17 @@ oop eval(oop exp, oop env) oop *elts = get(stmts, Array,elements); Object *result = nil; Scope_begin(); + switch (nlrPush()) { // longjmp occurred + case NLR_INIT: break; + case NLR_RETURN: Scope_end(); return nlrPop(); + case NLR_CONTINUE: Scope_end(); nlrReturn(NLR_CONTINUE, nlrPop()); + case NLR_BREAK: Scope_end(); nlrReturn(NLR_BREAK, nlrPop()); + } for (int i = 0; i < size; ++i) { result = eval(elts[i], env); } Scope_end(); + nlrPop(); return result; } case Address: { @@ -3061,9 +3073,12 @@ void replFile(char *name, FILE *file) case NLR_BREAK: fatal("break outside loop"); } if (opt_v > 1) printf("---------------- typecheck\n"); + assert(1 == Array_size(scopes)); typeCheck(yysval, nil); + assert(1 == Array_size(scopes)); if (opt_v > 1) printf("---------------- declare\n"); result = preval(yysval); + assert(1 == Array_size(scopes)); nlrPop(); } if (opt_v > 0) { @@ -3172,5 +3187,7 @@ int main(int argc, char **argv) fatal("main did not return an integer"); } + assert(1 == Array_size(scopes)); + return _integerValue(result); } diff --git a/test.txt b/test.txt index f65db58..00efabf 100755 --- a/test.txt +++ b/test.txt @@ -4,7 +4,7 @@ int x = 21; -int baz(int x, ...) { return 42; } +int baz(int xx, ...) { return 42; } int foo(void) { return x + x; } @@ -13,6 +13,7 @@ char *bar(void) { return "bye bye"; } int main(int argc, char **argv) { printf("hello, world %d %s\n", foo(), bar()); + printf("baz is %d %d %d\n", baz(1), baz(1, 2), baz(1, "two", 3)); int x = 42; int *p = &x; printf("x is %d p is %p\n", *p, p);