From d9364885fe639a0b861f184e7f9d65f793de0167 Mon Sep 17 00:00:00 2001 From: mtardy Date: Mon, 24 Aug 2020 19:43:55 +0200 Subject: [PATCH] Add Throw mechanism and hierarchy in verbose mode --- parse.leg | 137 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 98 insertions(+), 39 deletions(-) diff --git a/parse.leg b/parse.leg index 2a05345..4d14505 100644 --- a/parse.leg +++ b/parse.leg @@ -18,7 +18,7 @@ _DO(PreDecVariable) _DO(PreDecMember) _DO(PreDecIndex) \ _DO(PostDecVariable) _DO(PostDecMember) _DO(PostDecIndex) \ _DO(GetVariable) _DO(GetMember) _DO(SetMember) _DO(GetIndex) _DO(SetIndex) \ - _DO(Return) _DO(Break) _DO(Continue) \ + _DO(Return) _DO(Break) _DO(Continue) _DO(Throw) \ _DO(Quasiquote) _DO(Unquote) typedef enum { @@ -38,6 +38,7 @@ enum jb_t { j_return = 1, j_break, j_continue, + j_throw, }; typedef struct jb_record @@ -49,14 +50,6 @@ typedef struct jb_record jb_record *jbs= NULL; -void jbsCheck(char *msg) -{ - if (NULL == jbs) { - fprintf(stderr, "\n%s\n", msg); - exit(1); - } -} - jb_record *jbRecPush() { jb_record *newJbRec = memcheck(malloc(sizeof(jb_record))); newJbRec->result = null; @@ -607,10 +600,11 @@ exp = VAR l:ident ASSIGN e:exp { $$ = newDeclarati | DO s:stmt WHILE LPAREN c:exp RPAREN { $$ = newDo(s, c) } | FOR LPAREN i:stmt c:stmt u:exp RPAREN s:stmt { $$ = newFor(i, c, u, s) } | s:switch { $$ = s } - | RETURN e:exp { $$ = newReturn(e) } + | RETURN e:exp { $$ = newReturn(e) } | RETURN { $$ = newReturn(null) } | BREAK { $$ = newBreak() } | CONTINUE { $$ = newContinue() } + | THROW e:exp { $$ = newUnary(Throw_proto, e) } | l:IDENT o:assignOp e:exp { $$ = newAssign(Assign_proto, l, o, e) } | l:postfix DOT i:IDENT o:assignOp e:exp { $$ = newSetMap(SetMember_proto, l, i, o, e) } | l:postfix LBRAC i:exp RBRAC o:assignOp e:exp { $$ = newSetMap(SetIndex_proto, l, i, o, e) } @@ -772,7 +766,7 @@ eol = ( "\n""\r"* comment = "//" ( ![\n\r] . )* | "/*" ( !"*/" . )* "*/" -keyword = FUN | SYNTAX | VAR | SWITCH | CASE | DEFAULT | DO | FOR | WHILE | IF | ELSE | NULL | RETURN | BREAK | CONTINUE +keyword = FUN | SYNTAX | VAR | SWITCH | CASE | DEFAULT | DO | FOR | WHILE | IF | ELSE | NULL | RETURN | BREAK | CONTINUE | THROW IDENT = !keyword < [a-zA-Z_][a-zA-Z0-9_]* > - { $$ = intern(yytext) } @@ -797,6 +791,7 @@ NULL = 'null' ![a-zA-Z0-9_] - RETURN = 'return' ![a-zA-Z0-9_] - BREAK = 'break' ![a-zA-Z0-9_] - CONTINUE = 'continue' ![a-zA-Z0-9_] - +THROW = 'throw' ![a-zA-Z0-9_] - IMPORT = 'import' ![a-zA-Z0-9_] - HASH = '#' - LOGOR = '||' - @@ -1029,7 +1024,7 @@ oop evalArgs(oop scope, oop args); oop eval(oop scope, oop ast) { - if (opt_v) { + if (opt_v > 3) { printf("EVAL: "); println(ast); } @@ -1094,12 +1089,13 @@ oop eval(oop scope, oop ast) jbRecPush(); int jbt = sigsetjmp(jbs->jb, 0); switch (jbt) { - case j_return: { + case j_return: + case j_throw: { oop result = jbs->result; jbRecPop(); - jbsCheck("return outside a function"); + assert(jbs); jbs->result = result; - siglongjmp(jbs->jb, j_return); + siglongjmp(jbs->jb, jbt); assert(0); } case j_break: { @@ -1123,12 +1119,13 @@ oop eval(oop scope, oop ast) jbRecPush(); int jbt = sigsetjmp(jbs->jb, 0); switch (jbt) { - case j_return: { + case j_return: + case j_throw: { oop result = jbs->result; jbRecPop(); - jbsCheck("return outside a function"); + assert(jbs); jbs->result = result; - siglongjmp(jbs->jb, j_return); + siglongjmp(jbs->jb, jbt); assert(0); } case j_break: { @@ -1158,12 +1155,13 @@ oop eval(oop scope, oop ast) jbRecPush(); int jbt = sigsetjmp(jbs->jb, 0); switch (jbt) { - case j_return: { + case j_return: + case j_throw: { oop result = jbs->result; jbRecPop(); - jbsCheck("return outside a function"); + assert(jbs); jbs->result = result; - siglongjmp(jbs->jb, j_return); + siglongjmp(jbs->jb, jbt); assert(0); } case j_break: { @@ -1179,6 +1177,7 @@ oop eval(oop scope, oop ast) result= eval(localScope, body); restart_for:; } + jbRecPop(); return result; } case t_Switch: { @@ -1195,12 +1194,13 @@ oop eval(oop scope, oop ast) jbRecPush(); int jbt = sigsetjmp(jbs->jb, 0); switch (jbt) { - case j_return: { + case j_return: + case j_throw: { oop result = jbs->result; jbRecPop(); - jbsCheck("return outside a function"); + assert(jbs); jbs->result = result; - siglongjmp(jbs->jb, j_return); + siglongjmp(jbs->jb, jbt); assert(0); } case j_break: { @@ -1209,7 +1209,7 @@ oop eval(oop scope, oop ast) } case j_continue: { jbRecPop(); - jbsCheck("continue outside a loop"); + assert(jbs); siglongjmp(jbs->jb, j_continue); assert(0); } @@ -1219,6 +1219,7 @@ oop eval(oop scope, oop ast) assert(map_hasIntegerKey(statements, i)); result= eval(scope, get(statements, Map, elements)[i].value); } + jbRecPop(); return result; } case t_Assign: { @@ -1238,7 +1239,7 @@ oop eval(oop scope, oop ast) oop body = map_get(ast, body_symbol); oop fixed = map_get(ast, fixed_symbol); oop func = makeFunction(NULL, name, param, body, scope, fixed); - if (opt_v) { + if (opt_v > 4) { printf("funcscope: "); println(scope); printf("globalScope: "); @@ -1264,7 +1265,7 @@ oop eval(oop scope, oop ast) oop localScope = map_zip(param, args); map_set(localScope, __arguments___symbol, args); map_set(localScope, __proto___symbol, get(func, Function, parentScope)); - if (opt_v) { + if (opt_v > 4) { printf("parentScope: "); println(get(func, Function, parentScope)); printf("localScope: "); @@ -1287,6 +1288,12 @@ oop eval(oop scope, oop ast) fprintf(stderr, "\ncontinue outside of a loop\n"); exit(1); } + case j_throw: { + oop res= jbs->result; + jbRecPop(); + jbs->result= res; + siglongjmp(jbs->jb, j_throw); + } } oop result = eval(localScope, get(func, Function, body)); @@ -1315,7 +1322,7 @@ oop eval(oop scope, oop ast) map_set(localScope, this_symbol, this); map_set(localScope, __arguments___symbol, args); map_set(localScope, __proto___symbol, get(func, Function, parentScope)); - if (opt_v) { + if (opt_v > 4) { printf("parentScope: "); println(get(func, Function, parentScope)); printf("localScope: "); @@ -1338,6 +1345,12 @@ oop eval(oop scope, oop ast) fprintf(stderr, "\ncontinue outside of a loop\n"); exit(1); } + case j_throw: { + oop res= jbs->result; + jbRecPop(); + jbs->result= res; + siglongjmp(jbs->jb, j_throw); + } } oop result = eval(localScope, get(func, Function, body)); @@ -1346,18 +1359,23 @@ oop eval(oop scope, oop ast) } case t_Return: { - jbsCheck("return outside a function"); + assert(jbs); jbs->result = eval(scope, map_get(ast, value_symbol)); siglongjmp(jbs->jb, j_return); } case t_Break: { - jbsCheck("break outside a loop"); + assert(jbs); siglongjmp(jbs->jb, j_break); } case t_Continue: { - jbsCheck("continue outside a loop"); + assert(jbs); siglongjmp(jbs->jb, j_continue); } + case t_Throw: { + assert(jbs); + jbs->result = eval(scope, map_get(ast, rhs_symbol)); + siglongjmp(jbs->jb, j_throw); + } case t_Block: { oop statements = map_get(ast, statements_symbol); int i = 0; @@ -1664,6 +1682,12 @@ oop prim_invoke(oop params) fprintf(stderr, "\ncontinue outside of a loop\n"); exit(1); } + case j_throw: { + oop res= jbs->result; + jbRecPop(); + jbs->result= res; + siglongjmp(jbs->jb, j_throw); + } } oop result= eval(localScope, get(func, Function, body)); jbRecPop(); @@ -1700,6 +1724,12 @@ oop apply(oop func, oop args) fprintf(stderr, "\ncontinue outside of a loop\n"); exit(1); } + case j_throw: { + oop res= jbs->result; + jbRecPop(); + jbs->result= res; + siglongjmp(jbs->jb, j_throw); + } } oop result= eval(localScope, get(func, Function, body)); jbRecPop(); @@ -1743,15 +1773,44 @@ oop AST= NULL; void readEvalPrint(char *fileName) { inputStackPush(fileName); + jbRecPush(); + jb_record *jtop= jbs; + int jbt= sigsetjmp(jbs->jb, 0); + + if (0 == jbt) { + while (inputStack && yyparse()) { + if (opt_v > 1) printf("%s:%i: ", inputStack->name, inputStack->lineNumber); + if (!yylval) { + fclose(inputStack->file); + inputStackPop(); + continue; + } // EOF + if (opt_v > 1) println(yylval); + oop res = eval(globals, yylval); + if (opt_v > 0) println(res); + assert(jbs == jtop); + } + jbRecPop(); + return; + } - while (inputStack && yyparse()) { - if (!yylval) { - fclose(inputStack->file); - inputStackPop(); - continue; - } // EOF - if (opt_v) println(yylval); - println(eval(globals, yylval)); + assert(jbs == jtop); + oop res = jbs->result; + jbRecPop(); + switch (jbt) { + case j_return: + fprintf(stderr, "\nreturn outside of a function\n"); + exit(1); + case j_break: + fprintf(stderr, "\nbreak outside of a loop or switch\n"); + exit(1); + case j_continue: + fprintf(stderr, "\ncontinue outside of a loop\n"); + exit(1); + case j_throw: + printf("\nunhandled exception: "); + println(res); + exit(1); } }