|
|
@ -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); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|