|
@ -6,19 +6,19 @@ |
|
|
* run: echo "3+4" | ./parse |
|
|
* run: echo "3+4" | ./parse |
|
|
*/ |
|
|
*/ |
|
|
|
|
|
|
|
|
#define DO_PROTOS() \ |
|
|
|
|
|
_DO(If) _DO(While) _DO(Do) _DO(For) _DO(Switch) _DO(Call) _DO(Invoke) _DO(Func) _DO(Block) \ |
|
|
|
|
|
_DO(Declaration) _DO(Assign) \ |
|
|
|
|
|
_DO(Map) _DO(Symbol) _DO(Integer) _DO(String) \ |
|
|
|
|
|
_DO(Logor) _DO(Logand) _DO(Bitor) _DO(Bitxor) _DO(Bitand) \ |
|
|
|
|
|
_DO(Equal) _DO(Noteq) _DO(Less) _DO(Lesseq) _DO(Greater) _DO(Greatereq) _DO(Shleft) _DO(Shright) \ |
|
|
|
|
|
_DO(Add) _DO(Sub) _DO(Mul) _DO(Div) _DO(Mod) _DO(Not) _DO(Neg) _DO(Com) \ |
|
|
|
|
|
_DO(PreIncVariable) _DO(PreIncMember) _DO(PreIncIndex) \ |
|
|
|
|
|
_DO(PostIncVariable) _DO(PostIncMember) _DO(PostIncIndex) \ |
|
|
|
|
|
_DO(PreDecVariable) _DO(PreDecMember) _DO(PreDecIndex) \ |
|
|
|
|
|
_DO(PostDecVariable) _DO(PostDecMember) _DO(PostDecIndex) \ |
|
|
|
|
|
_DO(GetVariable) _DO(GetMember) _DO(SetMember) _DO(GetIndex) _DO(SetIndex) _DO(Slice) \ |
|
|
|
|
|
_DO(Return) _DO(Break) _DO(Continue) _DO(Throw) _DO(Try) \ |
|
|
|
|
|
|
|
|
#define DO_PROTOS() \ |
|
|
|
|
|
_DO(If) _DO(While) _DO(Do) _DO(For) _DO(ForIn) _DO(Switch) _DO(Call) \ |
|
|
|
|
|
_DO(Invoke) _DO(Func) _DO(Block) _DO(Declaration) _DO(Assign) \ |
|
|
|
|
|
_DO(Map) _DO(Symbol) _DO(Integer) _DO(String) \ |
|
|
|
|
|
_DO(Logor) _DO(Logand) _DO(Bitor) _DO(Bitxor) _DO(Bitand) \ |
|
|
|
|
|
_DO(Equal) _DO(Noteq) _DO(Less) _DO(Lesseq) _DO(Greater) _DO(Greatereq) _DO(Shleft) _DO(Shright) \ |
|
|
|
|
|
_DO(Add) _DO(Sub) _DO(Mul) _DO(Div) _DO(Mod) _DO(Not) _DO(Neg) _DO(Com) \ |
|
|
|
|
|
_DO(PreIncVariable) _DO(PreIncMember) _DO(PreIncIndex) \ |
|
|
|
|
|
_DO(PostIncVariable) _DO(PostIncMember) _DO(PostIncIndex) \ |
|
|
|
|
|
_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(Throw) _DO(Try) \ |
|
|
_DO(Quasiquote) _DO(Unquote) |
|
|
_DO(Quasiquote) _DO(Unquote) |
|
|
|
|
|
|
|
|
typedef enum { |
|
|
typedef enum { |
|
@ -51,7 +51,7 @@ typedef struct jb_record |
|
|
jb_record *jbs= NULL; |
|
|
jb_record *jbs= NULL; |
|
|
|
|
|
|
|
|
jb_record *jbRecPush() { |
|
|
jb_record *jbRecPush() { |
|
|
jb_record *newJbRec = memcheck(malloc(sizeof(jb_record))); |
|
|
|
|
|
|
|
|
jb_record *newJbRec = malloc(sizeof(jb_record)); |
|
|
newJbRec->result = null; |
|
|
newJbRec->result = null; |
|
|
newJbRec->next = jbs; |
|
|
newJbRec->next = jbs; |
|
|
jbs = newJbRec; |
|
|
jbs = newJbRec; |
|
@ -75,8 +75,7 @@ oop globals= 0; |
|
|
_DO(lhs) _DO(rhs) _DO(scope) _DO(args) _DO(expression) _DO(labels) _DO(statements) _DO(initialise) \ |
|
|
_DO(lhs) _DO(rhs) _DO(scope) _DO(args) _DO(expression) _DO(labels) _DO(statements) _DO(initialise) \ |
|
|
_DO(update) _DO(this) _DO(fixed) _DO(operator) _DO(map) _DO(func) \ |
|
|
_DO(update) _DO(this) _DO(fixed) _DO(operator) _DO(map) _DO(func) \ |
|
|
_DO(try) _DO(catch) _DO(finally) _DO(exception) \ |
|
|
_DO(try) _DO(catch) _DO(finally) _DO(exception) \ |
|
|
_DO(__line__) _DO(__file__) \ |
|
|
|
|
|
_DO(start) _DO(stop) |
|
|
|
|
|
|
|
|
_DO(__line__) _DO(__file__) |
|
|
|
|
|
|
|
|
#define _DO(NAME) oop NAME##_symbol; |
|
|
#define _DO(NAME) oop NAME##_symbol; |
|
|
DO_SYMBOLS() |
|
|
DO_SYMBOLS() |
|
@ -89,6 +88,8 @@ DO_PROTOS() |
|
|
int opt_v= 0; |
|
|
int opt_v= 0; |
|
|
oop mrAST= &_null; |
|
|
oop mrAST= &_null; |
|
|
|
|
|
|
|
|
|
|
|
void printBacktrace(oop top); |
|
|
|
|
|
|
|
|
typedef struct input_t |
|
|
typedef struct input_t |
|
|
{ |
|
|
{ |
|
|
oop name; |
|
|
oop name; |
|
@ -110,7 +111,7 @@ void inputStackPush(char *name) { |
|
|
} else { |
|
|
} else { |
|
|
name= "<stdin>"; |
|
|
name= "<stdin>"; |
|
|
} |
|
|
} |
|
|
input_t *input = memcheck(malloc(sizeof(input_t))); |
|
|
|
|
|
|
|
|
input_t *input = malloc(sizeof(input_t)); |
|
|
input->name= makeString(name); |
|
|
input->name= makeString(name); |
|
|
input->lineNumber= 1; |
|
|
input->lineNumber= 1; |
|
|
input->file= file; |
|
|
input->file= file; |
|
@ -176,9 +177,6 @@ oop getVariable(oop object, oop key) |
|
|
while (!map_hasKey(object, key)) { |
|
|
while (!map_hasKey(object, key)) { |
|
|
object = map_get(object, __proto___symbol); |
|
|
object = map_get(object, __proto___symbol); |
|
|
if (null == object) { |
|
|
if (null == object) { |
|
|
printf("\nUndefined: "); |
|
|
|
|
|
println(key); |
|
|
|
|
|
exit(1); |
|
|
|
|
|
return null; |
|
|
return null; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@ -203,6 +201,7 @@ oop getMember(oop object, oop key) |
|
|
if (!map_hasKey(object, key)) { |
|
|
if (!map_hasKey(object, key)) { |
|
|
printf("\nUndefined: ."); |
|
|
printf("\nUndefined: ."); |
|
|
println(key); |
|
|
println(key); |
|
|
|
|
|
printBacktrace(mrAST); |
|
|
exit(1); |
|
|
exit(1); |
|
|
return null; |
|
|
return null; |
|
|
} |
|
|
} |
|
@ -259,6 +258,15 @@ oop newFor(oop init, oop cond, oop step, oop body) |
|
|
return obj; |
|
|
return obj; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
oop newForIn(oop name, oop expression, oop body) |
|
|
|
|
|
{ |
|
|
|
|
|
oop obj= newObject(ForIn_proto); |
|
|
|
|
|
map_set(obj, name_symbol, name); |
|
|
|
|
|
map_set(obj, expression_symbol, expression); |
|
|
|
|
|
map_set(obj, body_symbol, body); |
|
|
|
|
|
return obj; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
oop newSwitch(oop expression, oop labels, oop statements) |
|
|
oop newSwitch(oop expression, oop labels, oop statements) |
|
|
{ |
|
|
{ |
|
|
oop obj= newObject(Switch_proto); |
|
|
oop obj= newObject(Switch_proto); |
|
@ -486,7 +494,7 @@ oop newFunc(oop name, oop param, oop body, oop fixed) |
|
|
return func; |
|
|
return func; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
oop apply(oop scope, oop func, oop args); |
|
|
|
|
|
|
|
|
oop apply(oop scope, oop this, oop func, oop args, oop ast); |
|
|
|
|
|
|
|
|
oop getSyntaxId(int n, oop key) |
|
|
oop getSyntaxId(int n, oop key) |
|
|
{ |
|
|
{ |
|
@ -548,15 +556,6 @@ oop newContinue(void) |
|
|
return obj; |
|
|
return obj; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
oop newSlice(oop value, oop start, oop stop) |
|
|
|
|
|
{ |
|
|
|
|
|
oop obj= newObject(Slice_proto); |
|
|
|
|
|
map_set(obj, value_symbol, value); |
|
|
|
|
|
map_set(obj, start_symbol, start); |
|
|
|
|
|
map_set(obj, stop_symbol, stop); |
|
|
|
|
|
return obj; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
oop newTry(oop try, oop exception, oop catch, oop finally) |
|
|
oop newTry(oop try, oop exception, oop catch, oop finally) |
|
|
{ |
|
|
{ |
|
|
oop obj = newObject(Try_proto); |
|
|
oop obj = newObject(Try_proto); |
|
@ -569,10 +568,10 @@ oop newTry(oop try, oop exception, oop catch, oop finally) |
|
|
|
|
|
|
|
|
oop fold(oop ast); |
|
|
oop fold(oop ast); |
|
|
|
|
|
|
|
|
#define YY_INPUT(buf, result, max_size) \ |
|
|
|
|
|
{ \ |
|
|
|
|
|
int yyc= getc(inputStack->file); \ |
|
|
|
|
|
result= (EOF == yyc) ? 0 : (*(buf)= yyc, 1); \ |
|
|
|
|
|
|
|
|
#define YY_INPUT(buf, result, max_size) \ |
|
|
|
|
|
{ \ |
|
|
|
|
|
int yyc= feof(inputStack->file) ? EOF : getc(inputStack->file); \ |
|
|
|
|
|
result= (EOF == yyc) ? 0 : (*(buf)= yyc, 1); \ |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
#define YYSTYPE oop |
|
|
#define YYSTYPE oop |
|
@ -596,6 +595,7 @@ int yyparsefrom(int (*yystart)(struct _yycontext *yy)); |
|
|
%} |
|
|
%} |
|
|
|
|
|
|
|
|
start = - ( IMPORT s:STRING { yylval = null; inputStackPush(get(s, String, value)) } |
|
|
start = - ( IMPORT s:STRING { yylval = null; inputStackPush(get(s, String, value)) } |
|
|
|
|
|
| e:exp ';' { yylval = e } |
|
|
| e:stmt { yylval = e } |
|
|
| e:stmt { yylval = e } |
|
|
| !. { yylval = 0 } |
|
|
| !. { yylval = 0 } |
|
|
| error |
|
|
| error |
|
@ -608,7 +608,7 @@ stmt = e:exp SEMICOLON* { $$ = e } |
|
|
| s:block { $$ = s } |
|
|
| s:block { $$ = s } |
|
|
|
|
|
|
|
|
block = LCB m:makeMap |
|
|
block = LCB m:makeMap |
|
|
( s:stmt { map_append(m, s) } |
|
|
|
|
|
|
|
|
( s:stmt { map_append(m, s) } |
|
|
) * |
|
|
) * |
|
|
RCB { $$ = newBlock(m) } |
|
|
RCB { $$ = newBlock(m) } |
|
|
|
|
|
|
|
@ -624,6 +624,7 @@ exp = VAR l:ident ASSIGN e:exp { $$ = newDeclarati |
|
|
| IF LPAREN c:exp RPAREN t:stmt { $$ = newIf(c, t, null) } |
|
|
| IF LPAREN c:exp RPAREN t:stmt { $$ = newIf(c, t, null) } |
|
|
| WHILE LPAREN c:exp RPAREN s:stmt { $$ = newWhile(c, s) } |
|
|
| WHILE LPAREN c:exp RPAREN s:stmt { $$ = newWhile(c, s) } |
|
|
| DO s:stmt WHILE LPAREN c:exp RPAREN { $$ = newDo(s, c) } |
|
|
| DO s:stmt WHILE LPAREN c:exp RPAREN { $$ = newDo(s, c) } |
|
|
|
|
|
| FOR LPAREN i:ident IN e:exp RPAREN s:stmt { $$ = newForIn(i, e, s) } |
|
|
| FOR LPAREN i:stmt c:stmt u:exp RPAREN s:stmt { $$ = newFor(i, c, u, s) } |
|
|
| FOR LPAREN i:stmt c:stmt u:exp RPAREN s:stmt { $$ = newFor(i, c, u, s) } |
|
|
| s:switch { $$ = s } |
|
|
| s:switch { $$ = s } |
|
|
| RETURN e:exp { $$ = newReturn(e) } |
|
|
| RETURN e:exp { $$ = newReturn(e) } |
|
@ -635,7 +636,7 @@ exp = VAR l:ident ASSIGN e:exp { $$ = newDeclarati |
|
|
| l:IDENT o:assignOp e:exp { $$ = newAssign(Assign_proto, l, o, 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 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) } |
|
|
| l:postfix LBRAC i:exp RBRAC o:assignOp e:exp { $$ = newSetMap(SetIndex_proto, l, i, o, e) } |
|
|
| l:syntax2 a:argumentList s:block { $$ = (map_append(a, s), apply(globals, l, a)) } |
|
|
|
|
|
|
|
|
| l:syntax2 a:argumentList s:block { $$ = (map_append(a, s), apply(globals, globals, l, a, a)) } |
|
|
| c:cond { $$ = c } |
|
|
| c:cond { $$ = c } |
|
|
|
|
|
|
|
|
ident = l:IDENT { $$ = l } |
|
|
ident = l:IDENT { $$ = l } |
|
@ -674,24 +675,24 @@ cond = c:logor QUERY t:exp COLON f:cond { $$ = newIf(c, t, |
|
|
| logor |
|
|
| logor |
|
|
|
|
|
|
|
|
logor = l:logand |
|
|
logor = l:logand |
|
|
( LOGOR r:logand { l = newBinary(Logor_proto, l, r) } |
|
|
|
|
|
)* { $$ = l } |
|
|
|
|
|
|
|
|
( LOGOR r:logand { l = newBinary(Logor_proto, l, r) } |
|
|
|
|
|
)* { $$ = l } |
|
|
|
|
|
|
|
|
logand = l:bitor |
|
|
logand = l:bitor |
|
|
( LOGAND r:bitor { l = newBinary(Logand_proto, l, r) } |
|
|
|
|
|
)* { $$ = l } |
|
|
|
|
|
|
|
|
( LOGAND r:bitor { l = newBinary(Logand_proto, l, r) } |
|
|
|
|
|
)* { $$ = l } |
|
|
|
|
|
|
|
|
bitor = l:bitxor |
|
|
bitor = l:bitxor |
|
|
( BITOR r:bitxor { l = newBinary(Bitor_proto, l, r) } |
|
|
|
|
|
)* { $$ = l } |
|
|
|
|
|
|
|
|
( BITOR r:bitxor { l = newBinary(Bitor_proto, l, r) } |
|
|
|
|
|
)* { $$ = l } |
|
|
|
|
|
|
|
|
bitxor = l:bitand |
|
|
bitxor = l:bitand |
|
|
( BITXOR r:bitand { l = newBinary(Bitxor_proto, l, r) } |
|
|
|
|
|
)* { $$ = l } |
|
|
|
|
|
|
|
|
( BITXOR r:bitand { l = newBinary(Bitxor_proto, l, r) } |
|
|
|
|
|
)* { $$ = l } |
|
|
|
|
|
|
|
|
bitand = l:eq |
|
|
bitand = l:eq |
|
|
( BITAND r:eq { l = newBinary(Bitand_proto, l, r) } |
|
|
|
|
|
)* { $$ = l } |
|
|
|
|
|
|
|
|
( BITAND r:eq { l = newBinary(Bitand_proto, l, r) } |
|
|
|
|
|
)* { $$ = l } |
|
|
|
|
|
|
|
|
eq = l:ineq |
|
|
eq = l:ineq |
|
|
( EQUAL r:ineq { l = newBinary(Equal_proto, l, r) } |
|
|
( EQUAL r:ineq { l = newBinary(Equal_proto, l, r) } |
|
@ -711,8 +712,8 @@ shift = l:sum |
|
|
)* { $$ = l } |
|
|
)* { $$ = l } |
|
|
|
|
|
|
|
|
sum = l:prod |
|
|
sum = l:prod |
|
|
( PLUS r:prod { l = newBinary(Add_proto, l, r) } |
|
|
|
|
|
| MINUS r:prod { l = newBinary(Sub_proto, l, r) } |
|
|
|
|
|
|
|
|
( PLUS r:prod { l = newBinary(Add_proto, l, r) } |
|
|
|
|
|
| MINUS r:prod { l = newBinary(Sub_proto, l, r) } |
|
|
)* { $$ = l } |
|
|
)* { $$ = l } |
|
|
|
|
|
|
|
|
prod = l:prefix |
|
|
prod = l:prefix |
|
@ -733,12 +734,8 @@ prefix = PLUS n:prefix { $$= n } |
|
|
|
|
|
|
|
|
postfix = i:value ( DOT s:IDENT a:argumentList { i = newInvoke(i, s, a) } |
|
|
postfix = i:value ( DOT s:IDENT a:argumentList { i = newInvoke(i, s, a) } |
|
|
| DOT s:IDENT !assignOp { i = newGetMap(GetMember_proto, i, s) } |
|
|
| DOT s:IDENT !assignOp { i = newGetMap(GetMember_proto, i, s) } |
|
|
| LBRAC e1:exp COLON e2:exp RBRAC !assignOp { i = newSlice(i, e1, e2) } |
|
|
|
|
|
| LBRAC e1:exp COLON RBRAC !assignOp { i = newSlice(i, e1, null) } |
|
|
|
|
|
| LBRAC COLON e2:exp RBRAC !assignOp { i = newSlice(i, null, e2) } |
|
|
|
|
|
| LBRAC COLON RBRAC !assignOp { i = newSlice(i, null, null) } |
|
|
|
|
|
| LBRAC p:exp RBRAC !assignOp { i = newGetMap(GetIndex_proto, i, p) } |
|
|
| LBRAC p:exp RBRAC !assignOp { i = newGetMap(GetIndex_proto, i, p) } |
|
|
| a:argumentList { i = (null != getSyntax(1, i)) ? apply(globals, getSyntax(1, i), a) : newCall(i, a) } |
|
|
|
|
|
|
|
|
| a:argumentList { i = (null != getSyntax(1, i)) ? apply(globals, globals, getSyntax(1, i), a, i) : newCall(i, a) } |
|
|
| PLUSPLUS { i = newPostIncrement(i) } |
|
|
| PLUSPLUS { i = newPostIncrement(i) } |
|
|
| MINUSMINUS { i = newPostDecrement(i) } |
|
|
| MINUSMINUS { i = newPostDecrement(i) } |
|
|
) * { $$ = i } |
|
|
) * { $$ = i } |
|
@ -764,6 +761,7 @@ value = n:NUMBER { $$ = newInteger(n) } |
|
|
| NULL { $$ = null } |
|
|
| NULL { $$ = null } |
|
|
| i:IDENT { $$ = newGetVariable(i) } |
|
|
| i:IDENT { $$ = newGetVariable(i) } |
|
|
| LPAREN i:stmt RPAREN { $$ = i } |
|
|
| LPAREN i:stmt RPAREN { $$ = i } |
|
|
|
|
|
| b:block { $$ = b } |
|
|
|
|
|
|
|
|
string = s:STRING - { $$ = s } |
|
|
string = s:STRING - { $$ = s } |
|
|
|
|
|
|
|
@ -800,10 +798,10 @@ eol = ( "\n""\r"* |
|
|
| "\r""\n"* |
|
|
| "\r""\n"* |
|
|
) { inputStack->lineNumber++ } |
|
|
) { inputStack->lineNumber++ } |
|
|
|
|
|
|
|
|
comment = "//" ( ![\n\r] . )* |
|
|
|
|
|
| "/*" ( !"*/" . )* "*/" |
|
|
|
|
|
|
|
|
comment = "//" ( ![\n\r] . )* |
|
|
|
|
|
| "/*" ( !"*/" (eol | .) )* "*/" |
|
|
|
|
|
|
|
|
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 | IN | WHILE | IF | ELSE | NULL | RETURN | BREAK | CONTINUE |
|
|
| THROW | TRY | CATCH | FINALLY |
|
|
| THROW | TRY | CATCH | FINALLY |
|
|
|
|
|
|
|
|
IDENT = !keyword < [a-zA-Z_][a-zA-Z0-9_]* > - { $$ = intern(yytext) } |
|
|
IDENT = !keyword < [a-zA-Z_][a-zA-Z0-9_]* > - { $$ = intern(yytext) } |
|
@ -822,6 +820,7 @@ CASE = 'case' ![a-zA-Z0-9_] - |
|
|
DEFAULT = 'default' ![a-zA-Z0-9_] - |
|
|
DEFAULT = 'default' ![a-zA-Z0-9_] - |
|
|
DO = 'do' ![a-zA-Z0-9_] - |
|
|
DO = 'do' ![a-zA-Z0-9_] - |
|
|
FOR = 'for' ![a-zA-Z0-9_] - |
|
|
FOR = 'for' ![a-zA-Z0-9_] - |
|
|
|
|
|
IN = 'in' ![a-zA-Z0-9_] - |
|
|
WHILE = 'while' ![a-zA-Z0-9_] - |
|
|
WHILE = 'while' ![a-zA-Z0-9_] - |
|
|
IF = 'if' ![a-zA-Z0-9_] - |
|
|
IF = 'if' ![a-zA-Z0-9_] - |
|
|
ELSE = 'else' ![a-zA-Z0-9_] - |
|
|
ELSE = 'else' ![a-zA-Z0-9_] - |
|
@ -946,7 +945,7 @@ void trace(oop ast, oop func) |
|
|
|
|
|
|
|
|
void untrace(oop ast) |
|
|
void untrace(oop ast) |
|
|
{ |
|
|
{ |
|
|
struct Call top= CallArray_pop(&backtrace); assert(top.ast == ast); |
|
|
|
|
|
|
|
|
struct Call top= CallArray_pop(&backtrace); assert(top.ast == ast); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void printLocation(oop ast) |
|
|
void printLocation(oop ast) |
|
@ -1067,30 +1066,37 @@ oop fold(oop ast) |
|
|
if (isFalse(fold(rhs))) return makeInteger(0); |
|
|
if (isFalse(fold(rhs))) return makeInteger(0); |
|
|
return makeInteger(1); |
|
|
return makeInteger(1); |
|
|
} |
|
|
} |
|
|
# define BINARY(NAME, OPERATOR) \ |
|
|
|
|
|
|
|
|
# define RELATION(NAME, OPERATOR) \ |
|
|
|
|
|
case t_##NAME: { \ |
|
|
|
|
|
oop lhs= fold(map_get(ast, lhs_symbol)); \ |
|
|
|
|
|
oop rhs= fold(map_get(ast, rhs_symbol)); \ |
|
|
|
|
|
return makeInteger(oopcmp(lhs, rhs) OPERATOR 0); \ |
|
|
|
|
|
} |
|
|
|
|
|
# define BINARY(NAME, OPERATOR) \ |
|
|
case t_##NAME: { \ |
|
|
case t_##NAME: { \ |
|
|
oop lhs= fold(map_get(ast, lhs_symbol)); \ |
|
|
oop lhs= fold(map_get(ast, lhs_symbol)); \ |
|
|
oop rhs= fold(map_get(ast, rhs_symbol)); \ |
|
|
oop rhs= fold(map_get(ast, rhs_symbol)); \ |
|
|
return makeInteger(getInteger(lhs) OPERATOR getInteger(rhs)); \ |
|
|
return makeInteger(getInteger(lhs) OPERATOR getInteger(rhs)); \ |
|
|
} |
|
|
} |
|
|
BINARY(Bitor, | ); |
|
|
|
|
|
BINARY(Bitxor, ^ ); |
|
|
|
|
|
BINARY(Bitand, & ); |
|
|
|
|
|
BINARY(Equal, ==); |
|
|
|
|
|
BINARY(Noteq, !=); |
|
|
|
|
|
BINARY(Less, < ); |
|
|
|
|
|
BINARY(Lesseq, <=); |
|
|
|
|
|
BINARY(Greatereq, >=); |
|
|
|
|
|
BINARY(Greater, > ); |
|
|
|
|
|
BINARY(Shleft, <<); |
|
|
|
|
|
BINARY(Shright, >>); |
|
|
|
|
|
BINARY(Add, + ); |
|
|
|
|
|
BINARY(Sub, - ); |
|
|
|
|
|
BINARY(Mul, * ); |
|
|
|
|
|
BINARY(Div, / ); |
|
|
|
|
|
BINARY(Mod, % ); |
|
|
|
|
|
# undef BINARY |
|
|
|
|
|
# define UNARY(NAME, OPERATOR) \ |
|
|
|
|
|
|
|
|
BINARY(Bitor, | ); |
|
|
|
|
|
BINARY(Bitxor, ^ ); |
|
|
|
|
|
BINARY(Bitand, & ); |
|
|
|
|
|
RELATION(Equal, ==); |
|
|
|
|
|
RELATION(Noteq, !=); |
|
|
|
|
|
RELATION(Less, < ); |
|
|
|
|
|
RELATION(Lesseq, <=); |
|
|
|
|
|
RELATION(Greatereq, >=); |
|
|
|
|
|
RELATION(Greater, > ); |
|
|
|
|
|
BINARY(Shleft, <<); |
|
|
|
|
|
BINARY(Shright, >>); |
|
|
|
|
|
BINARY(Add, + ); |
|
|
|
|
|
BINARY(Sub, - ); |
|
|
|
|
|
BINARY(Mul, * ); |
|
|
|
|
|
BINARY(Div, / ); |
|
|
|
|
|
BINARY(Mod, % ); |
|
|
|
|
|
# undef BINARY |
|
|
|
|
|
# undef RELATION |
|
|
|
|
|
# define UNARY(NAME, OPERATOR) \ |
|
|
case t_##NAME: { \ |
|
|
case t_##NAME: { \ |
|
|
oop rhs = fold(map_get(ast, rhs_symbol)); \ |
|
|
oop rhs = fold(map_get(ast, rhs_symbol)); \ |
|
|
return makeInteger(OPERATOR getInteger(rhs)); \ |
|
|
return makeInteger(OPERATOR getInteger(rhs)); \ |
|
@ -1098,7 +1104,7 @@ oop fold(oop ast) |
|
|
UNARY(Not, !); |
|
|
UNARY(Not, !); |
|
|
UNARY(Neg, -); |
|
|
UNARY(Neg, -); |
|
|
UNARY(Com, ~); |
|
|
UNARY(Com, ~); |
|
|
# undef UNARY |
|
|
|
|
|
|
|
|
# undef UNARY |
|
|
default: |
|
|
default: |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
@ -1113,28 +1119,71 @@ oop fold(oop ast) |
|
|
oop applyOperator(oop ast, oop op, oop lhs, oop rhs) |
|
|
oop applyOperator(oop ast, oop op, oop lhs, oop rhs) |
|
|
{ |
|
|
{ |
|
|
if (null != op) { assert(is(Symbol, op)); |
|
|
if (null != op) { assert(is(Symbol, op)); |
|
|
switch (get(op, Symbol, prototype)) { |
|
|
|
|
|
case t_Add: return addOperation(ast, lhs, rhs); |
|
|
|
|
|
case t_Sub: return makeInteger(getInteger(lhs) - getInteger(rhs)); |
|
|
|
|
|
case t_Mul: return mulOperation(ast, lhs, rhs); |
|
|
|
|
|
case t_Div: return makeInteger(getInteger(lhs) / getInteger(rhs)); |
|
|
|
|
|
case t_Mod: return makeInteger(getInteger(lhs) % getInteger(rhs)); |
|
|
|
|
|
case t_Bitor: return makeInteger(getInteger(lhs) | getInteger(rhs)); |
|
|
|
|
|
case t_Bitxor: return makeInteger(getInteger(lhs) ^ getInteger(rhs)); |
|
|
|
|
|
case t_Bitand: return makeInteger(getInteger(lhs) & getInteger(rhs)); |
|
|
|
|
|
case t_Shleft: return makeInteger(getInteger(lhs) << getInteger(rhs)); |
|
|
|
|
|
case t_Shright: return makeInteger(getInteger(lhs) >> getInteger(rhs)); |
|
|
|
|
|
default: { |
|
|
|
|
|
fprintf(stderr, "\nIllegal operator %i\n", get(op, Symbol, prototype)); |
|
|
|
|
|
exit(1); |
|
|
|
|
|
|
|
|
switch (get(op, Symbol, prototype)) { |
|
|
|
|
|
case t_Add: return addOperation(ast, lhs, rhs); |
|
|
|
|
|
case t_Sub: return makeInteger(getInteger(lhs) - getInteger(rhs)); |
|
|
|
|
|
case t_Mul: return mulOperation(ast, lhs, rhs); |
|
|
|
|
|
case t_Div: return makeInteger(getInteger(lhs) / getInteger(rhs)); |
|
|
|
|
|
case t_Mod: return makeInteger(getInteger(lhs) % getInteger(rhs)); |
|
|
|
|
|
case t_Bitor: return makeInteger(getInteger(lhs) | getInteger(rhs)); |
|
|
|
|
|
case t_Bitxor: return makeInteger(getInteger(lhs) ^ getInteger(rhs)); |
|
|
|
|
|
case t_Bitand: return makeInteger(getInteger(lhs) & getInteger(rhs)); |
|
|
|
|
|
case t_Shleft: return makeInteger(getInteger(lhs) << getInteger(rhs)); |
|
|
|
|
|
case t_Shright: return makeInteger(getInteger(lhs) >> getInteger(rhs)); |
|
|
|
|
|
default: { |
|
|
|
|
|
fprintf(stderr, "\nIllegal operator %i\n", get(op, Symbol, prototype)); |
|
|
|
|
|
exit(1); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
return rhs; |
|
|
return rhs; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
oop evalArgs(oop scope, oop args); |
|
|
oop evalArgs(oop scope, oop args); |
|
|
|
|
|
|
|
|
|
|
|
oop apply(oop scope, oop this, oop func, oop args, oop ast) |
|
|
|
|
|
{ |
|
|
|
|
|
assert(is(Function, func)); |
|
|
|
|
|
|
|
|
|
|
|
if (NULL != get(func, Function, primitive)) { |
|
|
|
|
|
return get(func, Function, primitive)(scope, args); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
oop param = get(func, Function, param); |
|
|
|
|
|
oop localScope = map_zip(param, args); |
|
|
|
|
|
map_set(localScope, this_symbol, this); |
|
|
|
|
|
map_set(localScope, __arguments___symbol, args); |
|
|
|
|
|
map_set(localScope, __proto___symbol, get(func, Function, parentScope)); |
|
|
|
|
|
jbRecPush(); |
|
|
|
|
|
trace(ast, func); |
|
|
|
|
|
int jbt = sigsetjmp(jbs->jb, 0); |
|
|
|
|
|
switch (jbt) { |
|
|
|
|
|
case j_return: { |
|
|
|
|
|
untrace(ast); |
|
|
|
|
|
oop result = jbs->result; |
|
|
|
|
|
jbRecPop(); |
|
|
|
|
|
return result; |
|
|
|
|
|
} |
|
|
|
|
|
case j_break: { |
|
|
|
|
|
runtimeError("break outside of a loop or switch"); |
|
|
|
|
|
} |
|
|
|
|
|
case j_continue: { |
|
|
|
|
|
runtimeError("continue outside of a loop"); |
|
|
|
|
|
} |
|
|
|
|
|
case j_throw: { |
|
|
|
|
|
untrace(ast); |
|
|
|
|
|
oop res= jbs->result; |
|
|
|
|
|
jbRecPop(); |
|
|
|
|
|
jbs->result= res; |
|
|
|
|
|
siglongjmp(jbs->jb, j_throw); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
oop result= eval(localScope, get(func, Function, body)); |
|
|
|
|
|
untrace(ast); |
|
|
|
|
|
jbRecPop(); |
|
|
|
|
|
return result; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
oop eval(oop scope, oop ast) |
|
|
oop eval(oop scope, oop ast) |
|
|
{ |
|
|
{ |
|
|
if (opt_v > 3) { |
|
|
if (opt_v > 3) { |
|
@ -1280,7 +1329,7 @@ oop eval(oop scope, oop ast) |
|
|
} |
|
|
} |
|
|
case j_break: { |
|
|
case j_break: { |
|
|
jbRecPop(); |
|
|
jbRecPop(); |
|
|
return null; |
|
|
|
|
|
|
|
|
return result; |
|
|
} |
|
|
} |
|
|
case j_continue: { |
|
|
case j_continue: { |
|
|
goto restart_for; |
|
|
goto restart_for; |
|
@ -1294,6 +1343,40 @@ oop eval(oop scope, oop ast) |
|
|
jbRecPop(); |
|
|
jbRecPop(); |
|
|
return result; |
|
|
return result; |
|
|
} |
|
|
} |
|
|
|
|
|
case t_ForIn: { |
|
|
|
|
|
oop expr = eval(scope, map_get(ast, expression_symbol)); if (!is(Map, expr)) return null; |
|
|
|
|
|
oop name = map_get(ast, name_symbol ) ; |
|
|
|
|
|
oop body = map_get(ast, body_symbol ) ; |
|
|
|
|
|
oop result = null; |
|
|
|
|
|
oop localScope = newObject(scope); |
|
|
|
|
|
jbRecPush(); |
|
|
|
|
|
int jbt = sigsetjmp(jbs->jb, 0); |
|
|
|
|
|
switch (jbt) { |
|
|
|
|
|
case j_return: |
|
|
|
|
|
case j_throw: { |
|
|
|
|
|
oop result = jbs->result; |
|
|
|
|
|
jbRecPop(); |
|
|
|
|
|
assert(jbs); |
|
|
|
|
|
jbs->result = result; |
|
|
|
|
|
siglongjmp(jbs->jb, jbt); |
|
|
|
|
|
assert(0); |
|
|
|
|
|
} |
|
|
|
|
|
case j_break: { |
|
|
|
|
|
jbRecPop(); |
|
|
|
|
|
return result; |
|
|
|
|
|
} |
|
|
|
|
|
case j_continue: { |
|
|
|
|
|
goto restart_forin; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
for (size_t i= 0; i < map_size(expr); ++i) { |
|
|
|
|
|
map_set(localScope, name, get(expr, Map, elements)[i].key); |
|
|
|
|
|
result= eval(localScope, body); |
|
|
|
|
|
restart_forin:; |
|
|
|
|
|
} |
|
|
|
|
|
jbRecPop(); |
|
|
|
|
|
return result; |
|
|
|
|
|
} |
|
|
case t_Switch: { |
|
|
case t_Switch: { |
|
|
oop expression = map_get(ast, expression_symbol ); |
|
|
oop expression = map_get(ast, expression_symbol ); |
|
|
oop labels = map_get(ast, labels_symbol ); |
|
|
oop labels = map_get(ast, labels_symbol ); |
|
@ -1369,107 +1452,26 @@ oop eval(oop scope, oop ast) |
|
|
printBacktrace(ast); |
|
|
printBacktrace(ast); |
|
|
exit(1); |
|
|
exit(1); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
oop args = map_get(ast, args_symbol); |
|
|
oop args = map_get(ast, args_symbol); |
|
|
if (isFalse(get(func, Function, fixed))) { |
|
|
if (isFalse(get(func, Function, fixed))) { |
|
|
args = evalArgs(scope, args); |
|
|
args = evalArgs(scope, args); |
|
|
} |
|
|
} |
|
|
if (get(func, Function, primitive) == NULL) { |
|
|
|
|
|
oop param = get(func, Function, param); |
|
|
|
|
|
oop localScope = map_zip(param, args); |
|
|
|
|
|
map_set(localScope, __arguments___symbol, args); |
|
|
|
|
|
map_set(localScope, __proto___symbol, get(func, Function, parentScope)); |
|
|
|
|
|
if (opt_v > 4) { |
|
|
|
|
|
printf("parentScope: "); |
|
|
|
|
|
println(get(func, Function, parentScope)); |
|
|
|
|
|
printf("localScope: "); |
|
|
|
|
|
println(localScope); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
jbRecPush(); |
|
|
|
|
|
trace(ast, func); |
|
|
|
|
|
int jbt = sigsetjmp(jbs->jb, 0); |
|
|
|
|
|
switch (jbt) { |
|
|
|
|
|
case j_return: { |
|
|
|
|
|
untrace(ast); |
|
|
|
|
|
oop result = jbs->result; |
|
|
|
|
|
jbRecPop(); |
|
|
|
|
|
return result; |
|
|
|
|
|
} |
|
|
|
|
|
case j_break: { |
|
|
|
|
|
runtimeError("break outside of a loop"); |
|
|
|
|
|
} |
|
|
|
|
|
case j_continue: { |
|
|
|
|
|
runtimeError("continue outside of a loop"); |
|
|
|
|
|
} |
|
|
|
|
|
case j_throw: { |
|
|
|
|
|
untrace(ast); |
|
|
|
|
|
oop res= jbs->result; |
|
|
|
|
|
jbRecPop(); |
|
|
|
|
|
jbs->result= res; |
|
|
|
|
|
siglongjmp(jbs->jb, j_throw); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
oop result = eval(localScope, get(func, Function, body)); |
|
|
|
|
|
untrace(ast); |
|
|
|
|
|
jbRecPop(); |
|
|
|
|
|
return result; |
|
|
|
|
|
} |
|
|
|
|
|
return get(func, Function, primitive)(scope, args); |
|
|
|
|
|
|
|
|
return apply(scope, globals, func, args, ast); |
|
|
} |
|
|
} |
|
|
case t_Invoke: { |
|
|
case t_Invoke: { |
|
|
// this is what differs from t_call |
|
|
|
|
|
oop this = eval(scope, map_get(ast, this_symbol)); |
|
|
oop this = eval(scope, map_get(ast, this_symbol)); |
|
|
oop func = getVariable(this, map_get(ast, name_symbol)); |
|
|
|
|
|
|
|
|
oop func = map_get(ast, name_symbol); assert(is(Symbol, func)); |
|
|
|
|
|
func = getVariable(this, func); |
|
|
if (!is(Function, func)) { |
|
|
if (!is(Function, func)) { |
|
|
printf("\ncannot invoke %s\n", printString(func)); |
|
|
printf("\ncannot invoke %s\n", printString(func)); |
|
|
printBacktrace(ast); |
|
|
printBacktrace(ast); |
|
|
exit(1); |
|
|
exit(1); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
oop args = evalArgs(scope, map_get(ast, args_symbol)); |
|
|
|
|
|
if (NULL != get(func, Function, primitive)) { |
|
|
|
|
|
return get(func, Function, primitive)(scope, args); |
|
|
|
|
|
} |
|
|
|
|
|
oop param = get(func, Function, param); |
|
|
|
|
|
oop localScope = map_zip(param, args); |
|
|
|
|
|
// and set this in the local scope |
|
|
|
|
|
map_set(localScope, this_symbol, this); |
|
|
|
|
|
map_set(localScope, __arguments___symbol, args); |
|
|
|
|
|
map_set(localScope, __proto___symbol, get(func, Function, parentScope)); |
|
|
|
|
|
if (opt_v > 4) { |
|
|
|
|
|
printf("parentScope: "); |
|
|
|
|
|
println(get(func, Function, parentScope)); |
|
|
|
|
|
printf("localScope: "); |
|
|
|
|
|
println(localScope); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
jbRecPush(); |
|
|
|
|
|
int jbt = sigsetjmp(jbs->jb, 0); |
|
|
|
|
|
switch (jbt) { |
|
|
|
|
|
case j_return: { |
|
|
|
|
|
oop result = jbs->result; |
|
|
|
|
|
jbRecPop(); |
|
|
|
|
|
return result; |
|
|
|
|
|
} |
|
|
|
|
|
case j_break: { |
|
|
|
|
|
runtimeError("break outside of a loop"); |
|
|
|
|
|
} |
|
|
|
|
|
case j_continue: { |
|
|
|
|
|
runtimeError("continue outside of a loop"); |
|
|
|
|
|
} |
|
|
|
|
|
case j_throw: { |
|
|
|
|
|
oop res= jbs->result; |
|
|
|
|
|
jbRecPop(); |
|
|
|
|
|
jbs->result= res; |
|
|
|
|
|
siglongjmp(jbs->jb, j_throw); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
oop args = map_get(ast, args_symbol); |
|
|
|
|
|
if (isFalse(get(func, Function, fixed))) { |
|
|
|
|
|
args = evalArgs(scope, args); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
oop result = eval(localScope, get(func, Function, body)); |
|
|
|
|
|
jbRecPop(); |
|
|
|
|
|
return result; |
|
|
|
|
|
|
|
|
return apply(scope, this, func, args, ast); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
case t_Return: { |
|
|
case t_Return: { |
|
@ -1570,23 +1572,11 @@ oop eval(oop scope, oop ast) |
|
|
oop key = eval(scope, map_get(ast, key_symbol)); |
|
|
oop key = eval(scope, map_get(ast, key_symbol)); |
|
|
switch (getType(map)) { |
|
|
switch (getType(map)) { |
|
|
case String: |
|
|
case String: |
|
|
if (!isInteger(key)) { |
|
|
|
|
|
runtimeError("non-integer index"); |
|
|
|
|
|
} |
|
|
|
|
|
ssize_t i= getInteger(key); |
|
|
|
|
|
size_t len= string_size(map); |
|
|
|
|
|
if (i < 0) i+= len; |
|
|
|
|
|
if (i < 0 || i >= len) { |
|
|
|
|
|
runtimeError("GetIndex out of bounds on String"); |
|
|
|
|
|
|
|
|
if (getInteger(key) >= get(map, String, size)) { |
|
|
|
|
|
runtimeError("GetIndex out of range on String"); |
|
|
} |
|
|
} |
|
|
return makeInteger(get(map, String, value)[i]); |
|
|
|
|
|
|
|
|
return makeInteger(unescape(get(map, String, value))[getInteger(key)]); |
|
|
case Map: |
|
|
case Map: |
|
|
if (isInteger(key) && getInteger(key) < 0) { |
|
|
|
|
|
size_t size= map_size(map); |
|
|
|
|
|
if (size > 0 && map_hasIntegerKey(map, size - 1)) { |
|
|
|
|
|
key= makeInteger(getInteger(key) + size); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return map_get(map, key); |
|
|
return map_get(map, key); |
|
|
default: |
|
|
default: |
|
|
runtimeError("GetIndex on non Map or String"); |
|
|
runtimeError("GetIndex on non Map or String"); |
|
@ -1600,7 +1590,7 @@ oop eval(oop scope, oop ast) |
|
|
switch (getType(map)) { |
|
|
switch (getType(map)) { |
|
|
case String: |
|
|
case String: |
|
|
if (getInteger(key) >= get(map, String, size)) { |
|
|
if (getInteger(key) >= get(map, String, size)) { |
|
|
runtimeError("SetIndex out of bounds on String"); |
|
|
|
|
|
|
|
|
runtimeError("SetIndex out of range on String"); |
|
|
} |
|
|
} |
|
|
get(map, String, value)[getInteger(key)] = getInteger(value); |
|
|
get(map, String, value)[getInteger(key)] = getInteger(value); |
|
|
return value; |
|
|
return value; |
|
@ -1612,35 +1602,6 @@ oop eval(oop scope, oop ast) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
case t_Slice: { |
|
|
|
|
|
oop pre= eval(scope, map_get(ast, value_symbol)); |
|
|
|
|
|
oop start= eval(scope, map_get(ast, start_symbol)); |
|
|
|
|
|
oop stop= eval(scope, map_get(ast, stop_symbol)); |
|
|
|
|
|
ssize_t first= start == null ? 0 : getInteger(start); |
|
|
|
|
|
|
|
|
|
|
|
if (start == null) { |
|
|
|
|
|
start= makeInteger(0); |
|
|
|
|
|
} |
|
|
|
|
|
switch (getType(pre)) { |
|
|
|
|
|
case String: { |
|
|
|
|
|
ssize_t last= stop == null ? string_size(pre) : getInteger(stop); |
|
|
|
|
|
oop res= string_slice(pre, first, last); |
|
|
|
|
|
if (NULL == res) { |
|
|
|
|
|
runtimeError("index out of bounds"); |
|
|
|
|
|
} |
|
|
|
|
|
return res; |
|
|
|
|
|
} |
|
|
|
|
|
case Map: { |
|
|
|
|
|
ssize_t last= stop == null ? map_size(pre) : getInteger(stop); |
|
|
|
|
|
oop res= map_slice(pre, first, last); |
|
|
|
|
|
if (NULL == res) { |
|
|
|
|
|
runtimeError("index out of bounds"); |
|
|
|
|
|
} |
|
|
|
|
|
return res; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
runtimeError("slicing a non-String or non-Map"); |
|
|
|
|
|
} |
|
|
|
|
|
case t_Symbol: |
|
|
case t_Symbol: |
|
|
case t_Integer: |
|
|
case t_Integer: |
|
|
case t_String: { |
|
|
case t_String: { |
|
@ -1660,31 +1621,29 @@ oop eval(oop scope, oop ast) |
|
|
if (isFalse(eval(scope, rhs))) return makeInteger(0); |
|
|
if (isFalse(eval(scope, rhs))) return makeInteger(0); |
|
|
return makeInteger(1); |
|
|
return makeInteger(1); |
|
|
} |
|
|
} |
|
|
|
|
|
# define RELATION(NAME, OPERATOR) \ |
|
|
|
|
|
case t_##NAME: { \ |
|
|
|
|
|
oop lhs = eval(scope, map_get(ast, lhs_symbol)); \ |
|
|
|
|
|
oop rhs = eval(scope, map_get(ast, rhs_symbol)); \ |
|
|
|
|
|
return makeInteger(oopcmp(lhs, rhs) OPERATOR 0); \ |
|
|
|
|
|
} |
|
|
# define BINARY(NAME, OPERATOR) \ |
|
|
# define BINARY(NAME, OPERATOR) \ |
|
|
case t_##NAME: { \ |
|
|
case t_##NAME: { \ |
|
|
oop lhs = eval(scope, map_get(ast, lhs_symbol)); \ |
|
|
oop lhs = eval(scope, map_get(ast, lhs_symbol)); \ |
|
|
oop rhs = eval(scope, map_get(ast, rhs_symbol)); \ |
|
|
oop rhs = eval(scope, map_get(ast, rhs_symbol)); \ |
|
|
return makeInteger(getInteger(lhs) OPERATOR getInteger(rhs)); \ |
|
|
return makeInteger(getInteger(lhs) OPERATOR getInteger(rhs)); \ |
|
|
} |
|
|
} |
|
|
BINARY(Bitor, | ); |
|
|
|
|
|
BINARY(Bitxor, ^ ); |
|
|
|
|
|
BINARY(Bitand, & ); |
|
|
|
|
|
case t_Equal: { |
|
|
|
|
|
oop lhs = eval(scope, map_get(ast, lhs_symbol)); |
|
|
|
|
|
oop rhs = eval(scope, map_get(ast, rhs_symbol)); |
|
|
|
|
|
return makeInteger(0 == oopcmp(lhs, rhs)); |
|
|
|
|
|
} |
|
|
|
|
|
case t_Noteq: { |
|
|
|
|
|
oop lhs = eval(scope, map_get(ast, lhs_symbol)); |
|
|
|
|
|
oop rhs = eval(scope, map_get(ast, rhs_symbol)); |
|
|
|
|
|
return makeInteger(0 != oopcmp(lhs, rhs)); |
|
|
|
|
|
} |
|
|
|
|
|
BINARY(Less, < ); |
|
|
|
|
|
BINARY(Lesseq, <=); |
|
|
|
|
|
BINARY(Greatereq, >=); |
|
|
|
|
|
BINARY(Greater, > ); |
|
|
|
|
|
BINARY(Shleft, <<); |
|
|
|
|
|
BINARY(Shright, >>); |
|
|
|
|
|
|
|
|
BINARY(Bitor, | ); |
|
|
|
|
|
BINARY(Bitxor, ^ ); |
|
|
|
|
|
BINARY(Bitand, & ); |
|
|
|
|
|
RELATION(Equal, ==); |
|
|
|
|
|
RELATION(Noteq, !=); |
|
|
|
|
|
RELATION(Less, < ); |
|
|
|
|
|
RELATION(Lesseq, <=); |
|
|
|
|
|
RELATION(Greatereq, >=); |
|
|
|
|
|
RELATION(Greater, > ); |
|
|
|
|
|
BINARY(Shleft, <<); |
|
|
|
|
|
BINARY(Shright, >>); |
|
|
// BINARY(Add, + ); |
|
|
// BINARY(Add, + ); |
|
|
case t_Add: { |
|
|
case t_Add: { |
|
|
oop lhs = eval(scope, map_get(ast, lhs_symbol)); |
|
|
oop lhs = eval(scope, map_get(ast, lhs_symbol)); |
|
@ -1701,6 +1660,7 @@ oop eval(oop scope, oop ast) |
|
|
BINARY(Div, / ); |
|
|
BINARY(Div, / ); |
|
|
BINARY(Mod, % ); |
|
|
BINARY(Mod, % ); |
|
|
# undef BINARY |
|
|
# undef BINARY |
|
|
|
|
|
# undef RELATION |
|
|
case t_Not: { |
|
|
case t_Not: { |
|
|
oop rhs = eval(scope, map_get(ast, rhs_symbol)); |
|
|
oop rhs = eval(scope, map_get(ast, rhs_symbol)); |
|
|
return makeInteger(isFalse(rhs)); |
|
|
return makeInteger(isFalse(rhs)); |
|
@ -1848,94 +1808,18 @@ oop prim_length(oop scope, oop params) |
|
|
return null; |
|
|
return null; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
oop prim_apply(oop scope, oop params) { |
|
|
|
|
|
oop func= null; if (map_hasIntegerKey(params, 0)) func= get(params, Map, elements)[0].value; |
|
|
|
|
|
oop args= null; if (map_hasIntegerKey(params, 1)) args= get(params, Map, elements)[1].value; |
|
|
|
|
|
return apply(scope, globals, func, args, mrAST); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
oop prim_invoke(oop scope, oop params) |
|
|
oop prim_invoke(oop scope, oop params) |
|
|
{ |
|
|
{ |
|
|
oop this= null; if (map_hasIntegerKey(params, 0)) this= get(params, Map, elements)[0].value; |
|
|
oop this= null; if (map_hasIntegerKey(params, 0)) this= get(params, Map, elements)[0].value; |
|
|
oop func= null; if (map_hasIntegerKey(params, 1)) func= get(params, Map, elements)[1].value; |
|
|
oop func= null; if (map_hasIntegerKey(params, 1)) func= get(params, Map, elements)[1].value; |
|
|
oop args= null; if (map_hasIntegerKey(params, 2)) args= get(params, Map, elements)[2].value; |
|
|
oop args= null; if (map_hasIntegerKey(params, 2)) args= get(params, Map, elements)[2].value; |
|
|
if (!is(Function, func)) { |
|
|
|
|
|
printf("\ncannot invoke %s\n", printString(func)); |
|
|
|
|
|
printBacktrace(mrAST); |
|
|
|
|
|
exit(1); |
|
|
|
|
|
} |
|
|
|
|
|
if (NULL != get(func, Function, primitive)) { |
|
|
|
|
|
return get(func, Function, primitive)(scope, args); |
|
|
|
|
|
} |
|
|
|
|
|
oop param = get(func, Function, param); |
|
|
|
|
|
oop localScope = map_zip(param, args); |
|
|
|
|
|
map_set(localScope, this_symbol, this); |
|
|
|
|
|
map_set(localScope, __arguments___symbol, args); |
|
|
|
|
|
map_set(localScope, __proto___symbol, get(func, Function, parentScope)); |
|
|
|
|
|
jbRecPush(); |
|
|
|
|
|
int jbt = sigsetjmp(jbs->jb, 0); |
|
|
|
|
|
switch (jbt) { |
|
|
|
|
|
case j_return: { |
|
|
|
|
|
oop result = jbs->result; |
|
|
|
|
|
jbRecPop(); |
|
|
|
|
|
return result; |
|
|
|
|
|
} |
|
|
|
|
|
case j_break: { |
|
|
|
|
|
runtimeError("break outside of a loop or switch"); |
|
|
|
|
|
} |
|
|
|
|
|
case j_continue: { |
|
|
|
|
|
runtimeError("continue oustide of a loop"); |
|
|
|
|
|
} |
|
|
|
|
|
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(); |
|
|
|
|
|
return result; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
oop apply(oop scope, oop func, oop args) |
|
|
|
|
|
{ |
|
|
|
|
|
if (!is(Function, func)) { |
|
|
|
|
|
printf("\ncannot apply %s\n", printString(func)); |
|
|
|
|
|
printBacktrace(mrAST); |
|
|
|
|
|
exit(1); |
|
|
|
|
|
} |
|
|
|
|
|
if (NULL != get(func, Function, primitive)) { |
|
|
|
|
|
return get(func, Function, primitive)(scope, args); |
|
|
|
|
|
} |
|
|
|
|
|
oop param = get(func, Function, param); |
|
|
|
|
|
oop localScope = map_zip(param, args); |
|
|
|
|
|
map_set(localScope, __arguments___symbol, args); |
|
|
|
|
|
map_set(localScope, __proto___symbol, get(func, Function, parentScope)); |
|
|
|
|
|
jbRecPush(); |
|
|
|
|
|
int jbt = sigsetjmp(jbs->jb, 0); |
|
|
|
|
|
switch (jbt) { |
|
|
|
|
|
case j_return: { |
|
|
|
|
|
oop result = jbs->result; |
|
|
|
|
|
jbRecPop(); |
|
|
|
|
|
return result; |
|
|
|
|
|
} |
|
|
|
|
|
case j_break: { |
|
|
|
|
|
runtimeError("break outside of a loop or switch"); |
|
|
|
|
|
} |
|
|
|
|
|
case j_continue: { |
|
|
|
|
|
runtimeError("continue outside of a loop"); |
|
|
|
|
|
} |
|
|
|
|
|
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(); |
|
|
|
|
|
return result; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
oop prim_apply(oop scope, oop params) { |
|
|
|
|
|
oop func= null; if (map_hasIntegerKey(params, 0)) func= get(params, Map, elements)[0].value; |
|
|
|
|
|
oop args= null; if (map_hasIntegerKey(params, 1)) args= get(params, Map, elements)[1].value; |
|
|
|
|
|
return apply(scope, func, args); |
|
|
|
|
|
|
|
|
return apply(scope, this, func, args, mrAST); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
oop prim_clone(oop scope, oop params) |
|
|
oop prim_clone(oop scope, oop params) |
|
@ -2033,11 +1917,11 @@ oop prim_scope(oop scope, oop params) |
|
|
|
|
|
|
|
|
#include <sys/resource.h> |
|
|
#include <sys/resource.h> |
|
|
|
|
|
|
|
|
oop prim_millis(oop scope, oop params) |
|
|
|
|
|
|
|
|
oop prim_microseconds(oop scope, oop params) |
|
|
{ |
|
|
{ |
|
|
struct rusage ru; |
|
|
struct rusage ru; |
|
|
getrusage(RUSAGE_SELF, &ru); |
|
|
getrusage(RUSAGE_SELF, &ru); |
|
|
return makeInteger(ru.ru_utime.tv_sec * 1000 + ru.ru_utime.tv_usec / 1000); |
|
|
|
|
|
|
|
|
return makeInteger(ru.ru_utime.tv_sec * 1000*1000 + ru.ru_utime.tv_usec); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
int main(int argc, char **argv) |
|
|
int main(int argc, char **argv) |
|
@ -2049,16 +1933,16 @@ int main(int argc, char **argv) |
|
|
symbol_table= makeMap(); |
|
|
symbol_table= makeMap(); |
|
|
globals= makeMap(); |
|
|
globals= makeMap(); |
|
|
|
|
|
|
|
|
map_set(globals, intern("exit") , makeFunction(prim_exit, intern("exit"), null, null, globals, null)); |
|
|
|
|
|
map_set(globals, intern("keys") , makeFunction(prim_keys, intern("keys"), null, null, globals, null)); |
|
|
|
|
|
map_set(globals, intern("values") , makeFunction(prim_values, intern("values"), null, null, globals, null)); |
|
|
|
|
|
map_set(globals, intern("length") , makeFunction(prim_length, intern("length"), null, null, globals, null)); |
|
|
|
|
|
map_set(globals, intern("print") , makeFunction(prim_print, intern("print"), null, null, globals, null)); |
|
|
|
|
|
map_set(globals, intern("invoke") , makeFunction(prim_invoke, intern("invoke"), null, null, globals, null)); |
|
|
|
|
|
map_set(globals, intern("apply") , makeFunction(prim_apply, intern("apply"), null, null, globals, null)); |
|
|
|
|
|
map_set(globals, intern("clone") , makeFunction(prim_clone, intern("clone"), null, null, globals, null)); |
|
|
|
|
|
map_set(globals, intern("import") , makeFunction(prim_import, intern("import"), null, null, globals, null)); |
|
|
|
|
|
map_set(globals, intern("millis") , makeFunction(prim_millis, intern("millis"), null, null, globals, null)); |
|
|
|
|
|
|
|
|
map_set(globals, intern("exit" ), makeFunction(prim_exit, intern("exit" ), null, null, globals, null)); |
|
|
|
|
|
map_set(globals, intern("keys" ), makeFunction(prim_keys, intern("keys" ), null, null, globals, null)); |
|
|
|
|
|
map_set(globals, intern("values" ), makeFunction(prim_values, intern("values" ), null, null, globals, null)); |
|
|
|
|
|
map_set(globals, intern("length" ), makeFunction(prim_length, intern("length" ), null, null, globals, null)); |
|
|
|
|
|
map_set(globals, intern("print" ), makeFunction(prim_print, intern("print" ), null, null, globals, null)); |
|
|
|
|
|
map_set(globals, intern("invoke" ), makeFunction(prim_invoke, intern("invoke" ), null, null, globals, null)); |
|
|
|
|
|
map_set(globals, intern("apply" ), makeFunction(prim_apply, intern("apply" ), null, null, globals, null)); |
|
|
|
|
|
map_set(globals, intern("clone" ), makeFunction(prim_clone, intern("clone" ), null, null, globals, null)); |
|
|
|
|
|
map_set(globals, intern("import" ), makeFunction(prim_import, intern("import" ), null, null, globals, null)); |
|
|
|
|
|
map_set(globals, intern("microseconds"), makeFunction(prim_microseconds, intern("microseconds"), null, null, globals, null)); |
|
|
|
|
|
|
|
|
map_set(globals, intern("scope"), makeFunction(prim_scope, intern("scope"), null, null, globals, null)); |
|
|
map_set(globals, intern("scope"), makeFunction(prim_scope, intern("scope"), null, null, globals, null)); |
|
|
|
|
|
|
|
|