|
@ -50,21 +50,14 @@ typedef struct jb_record |
|
|
|
|
|
|
|
|
jb_record *jbs= NULL; |
|
|
jb_record *jbs= NULL; |
|
|
|
|
|
|
|
|
jb_record *jbRecPush() { |
|
|
|
|
|
jb_record *newJbRec = malloc(sizeof(jb_record)); |
|
|
|
|
|
newJbRec->result = null; |
|
|
|
|
|
newJbRec->next = jbs; |
|
|
|
|
|
jbs = newJbRec; |
|
|
|
|
|
return newJbRec; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
jb_record *jbRecPop() { |
|
|
|
|
|
assert(jbs); |
|
|
|
|
|
jb_record *head = jbs; |
|
|
|
|
|
jbs = head->next; |
|
|
|
|
|
return head; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
#define jbRecPush() \ |
|
|
|
|
|
struct jb_record jbrec; \ |
|
|
|
|
|
jbrec.next= jbs; \ |
|
|
|
|
|
jbs= &jbrec |
|
|
|
|
|
|
|
|
|
|
|
#define jbRecPop() \ |
|
|
|
|
|
assert(jbs == &jbrec); \ |
|
|
|
|
|
jbs= jbrec.next |
|
|
|
|
|
|
|
|
// this is the global scope |
|
|
// this is the global scope |
|
|
oop globals= 0; |
|
|
oop globals= 0; |
|
@ -85,6 +78,7 @@ DO_SYMBOLS() |
|
|
DO_PROTOS() |
|
|
DO_PROTOS() |
|
|
#undef _DO |
|
|
#undef _DO |
|
|
|
|
|
|
|
|
|
|
|
int opt_g= 0; |
|
|
int opt_v= 0; |
|
|
int opt_v= 0; |
|
|
oop mrAST= &_null; |
|
|
oop mrAST= &_null; |
|
|
|
|
|
|
|
@ -761,7 +755,6 @@ 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 } |
|
|
|
|
|
|
|
@ -887,11 +880,11 @@ SQUOTE = "'" |
|
|
; |
|
|
; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
oop map_zip(oop keys, oop values) |
|
|
|
|
|
|
|
|
oop map_zip(oop map, oop keys, oop values) |
|
|
{ |
|
|
{ |
|
|
|
|
|
assert(is(Map, map)); |
|
|
assert(is(Map, keys)); |
|
|
assert(is(Map, keys)); |
|
|
assert(is(Map, values)); |
|
|
assert(is(Map, values)); |
|
|
oop map= makeMap(); |
|
|
|
|
|
size_t sk= map_size(keys), sv= map_size(values); |
|
|
size_t sk= map_size(keys), sv= map_size(values); |
|
|
if (sk < sv) sk= sv; |
|
|
if (sk < sv) sk= sv; |
|
|
for (size_t i= 0; i < sk; ++i) { |
|
|
for (size_t i= 0; i < sk; ++i) { |
|
@ -1139,6 +1132,38 @@ oop applyOperator(oop ast, oop op, oop lhs, oop rhs) |
|
|
return rhs; |
|
|
return rhs; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
oop freeScopes= 0; // pool of free scopes |
|
|
|
|
|
|
|
|
|
|
|
oop fixScope(oop scope) // prevent this scope and its parents from being recycled |
|
|
|
|
|
{ assert(is(Map, scope)); |
|
|
|
|
|
oop tmp= scope; |
|
|
|
|
|
while (is(Map, tmp) && (0 == (tmp->Map.flags & MAP_ENCLOSED))) { |
|
|
|
|
|
tmp->Map.flags |= MAP_ENCLOSED; |
|
|
|
|
|
tmp= map_get(tmp, __proto___symbol); |
|
|
|
|
|
} |
|
|
|
|
|
return scope; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
oop newScope(oop parent) |
|
|
|
|
|
{ |
|
|
|
|
|
if (0 == freeScopes) freeScopes= makeMap(); |
|
|
|
|
|
oop scope= freeScopes; assert(is(Map, scope)); |
|
|
|
|
|
freeScopes= freeScopes->Map.pool; |
|
|
|
|
|
scope->Map.size= 0; |
|
|
|
|
|
map_set(scope, __proto___symbol, parent); |
|
|
|
|
|
return scope; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void delScope(oop scope) |
|
|
|
|
|
{ assert(is(Map, scope)); |
|
|
|
|
|
if (scope->Map.flags & MAP_ENCLOSED) { |
|
|
|
|
|
printf("IGNORE %p\n", scope); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
scope->Map.pool= freeScopes; |
|
|
|
|
|
freeScopes= scope; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
oop evalArgs(oop scope, oop args); |
|
|
oop evalArgs(oop scope, oop args); |
|
|
|
|
|
|
|
|
oop apply(oop scope, oop this, oop func, oop args, oop ast) |
|
|
oop apply(oop scope, oop this, oop func, oop args, oop ast) |
|
@ -1150,28 +1175,32 @@ oop apply(oop scope, oop this, oop func, oop args, oop ast) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
oop param = get(func, Function, param); |
|
|
oop param = get(func, Function, param); |
|
|
oop localScope = map_zip(param, args); |
|
|
|
|
|
|
|
|
oop localScope = newScope(get(func, Function, parentScope)); |
|
|
|
|
|
map_zip(localScope, param, args); |
|
|
map_set(localScope, this_symbol, this); |
|
|
map_set(localScope, this_symbol, this); |
|
|
map_set(localScope, __arguments___symbol, args); |
|
|
map_set(localScope, __arguments___symbol, args); |
|
|
map_set(localScope, __proto___symbol, get(func, Function, parentScope)); |
|
|
|
|
|
jbRecPush(); |
|
|
jbRecPush(); |
|
|
trace(ast, func); |
|
|
trace(ast, func); |
|
|
int jbt = sigsetjmp(jbs->jb, 0); |
|
|
int jbt = sigsetjmp(jbs->jb, 0); |
|
|
switch (jbt) { |
|
|
switch (jbt) { |
|
|
case j_return: { |
|
|
case j_return: { |
|
|
untrace(ast); |
|
|
untrace(ast); |
|
|
|
|
|
delScope(localScope); |
|
|
oop result = jbs->result; |
|
|
oop result = jbs->result; |
|
|
jbRecPop(); |
|
|
jbRecPop(); |
|
|
return result; |
|
|
return result; |
|
|
} |
|
|
} |
|
|
case j_break: { |
|
|
case j_break: { |
|
|
|
|
|
delScope(localScope); |
|
|
runtimeError("break outside of a loop or switch"); |
|
|
runtimeError("break outside of a loop or switch"); |
|
|
} |
|
|
} |
|
|
case j_continue: { |
|
|
case j_continue: { |
|
|
|
|
|
delScope(localScope); |
|
|
runtimeError("continue outside of a loop"); |
|
|
runtimeError("continue outside of a loop"); |
|
|
} |
|
|
} |
|
|
case j_throw: { |
|
|
case j_throw: { |
|
|
untrace(ast); |
|
|
untrace(ast); |
|
|
|
|
|
delScope(localScope); |
|
|
oop res= jbs->result; |
|
|
oop res= jbs->result; |
|
|
jbRecPop(); |
|
|
jbRecPop(); |
|
|
jbs->result= res; |
|
|
jbs->result= res; |
|
@ -1180,6 +1209,7 @@ oop apply(oop scope, oop this, oop func, oop args, oop ast) |
|
|
} |
|
|
} |
|
|
oop result= eval(localScope, get(func, Function, body)); |
|
|
oop result= eval(localScope, get(func, Function, body)); |
|
|
untrace(ast); |
|
|
untrace(ast); |
|
|
|
|
|
delScope(localScope); |
|
|
jbRecPop(); |
|
|
jbRecPop(); |
|
|
return result; |
|
|
return result; |
|
|
} |
|
|
} |
|
@ -1313,13 +1343,14 @@ oop eval(oop scope, oop ast) |
|
|
oop update = map_get(ast, update_symbol ); |
|
|
oop update = map_get(ast, update_symbol ); |
|
|
oop body = map_get(ast, body_symbol); |
|
|
oop body = map_get(ast, body_symbol); |
|
|
oop result = null; |
|
|
oop result = null; |
|
|
oop localScope = newObject(scope); |
|
|
|
|
|
|
|
|
oop localScope = newScope(scope); |
|
|
|
|
|
|
|
|
jbRecPush(); |
|
|
jbRecPush(); |
|
|
int jbt = sigsetjmp(jbs->jb, 0); |
|
|
int jbt = sigsetjmp(jbs->jb, 0); |
|
|
switch (jbt) { |
|
|
switch (jbt) { |
|
|
case j_return: |
|
|
case j_return: |
|
|
case j_throw: { |
|
|
case j_throw: { |
|
|
|
|
|
delScope(localScope); |
|
|
oop result = jbs->result; |
|
|
oop result = jbs->result; |
|
|
jbRecPop(); |
|
|
jbRecPop(); |
|
|
assert(jbs); |
|
|
assert(jbs); |
|
@ -1328,6 +1359,7 @@ oop eval(oop scope, oop ast) |
|
|
assert(0); |
|
|
assert(0); |
|
|
} |
|
|
} |
|
|
case j_break: { |
|
|
case j_break: { |
|
|
|
|
|
delScope(localScope); |
|
|
jbRecPop(); |
|
|
jbRecPop(); |
|
|
return result; |
|
|
return result; |
|
|
} |
|
|
} |
|
@ -1340,6 +1372,7 @@ oop eval(oop scope, oop ast) |
|
|
result= eval(localScope, body); |
|
|
result= eval(localScope, body); |
|
|
restart_for:; |
|
|
restart_for:; |
|
|
} |
|
|
} |
|
|
|
|
|
delScope(localScope); |
|
|
jbRecPop(); |
|
|
jbRecPop(); |
|
|
return result; |
|
|
return result; |
|
|
} |
|
|
} |
|
@ -1348,12 +1381,13 @@ oop eval(oop scope, oop ast) |
|
|
oop name = map_get(ast, name_symbol ) ; |
|
|
oop name = map_get(ast, name_symbol ) ; |
|
|
oop body = map_get(ast, body_symbol ) ; |
|
|
oop body = map_get(ast, body_symbol ) ; |
|
|
oop result = null; |
|
|
oop result = null; |
|
|
oop localScope = newObject(scope); |
|
|
|
|
|
|
|
|
oop localScope = newScope(scope); |
|
|
jbRecPush(); |
|
|
jbRecPush(); |
|
|
int jbt = sigsetjmp(jbs->jb, 0); |
|
|
int jbt = sigsetjmp(jbs->jb, 0); |
|
|
switch (jbt) { |
|
|
switch (jbt) { |
|
|
case j_return: |
|
|
case j_return: |
|
|
case j_throw: { |
|
|
case j_throw: { |
|
|
|
|
|
delScope(localScope); |
|
|
oop result = jbs->result; |
|
|
oop result = jbs->result; |
|
|
jbRecPop(); |
|
|
jbRecPop(); |
|
|
assert(jbs); |
|
|
assert(jbs); |
|
@ -1362,6 +1396,7 @@ oop eval(oop scope, oop ast) |
|
|
assert(0); |
|
|
assert(0); |
|
|
} |
|
|
} |
|
|
case j_break: { |
|
|
case j_break: { |
|
|
|
|
|
delScope(localScope); |
|
|
jbRecPop(); |
|
|
jbRecPop(); |
|
|
return result; |
|
|
return result; |
|
|
} |
|
|
} |
|
@ -1374,6 +1409,7 @@ oop eval(oop scope, oop ast) |
|
|
result= eval(localScope, body); |
|
|
result= eval(localScope, body); |
|
|
restart_forin:; |
|
|
restart_forin:; |
|
|
} |
|
|
} |
|
|
|
|
|
delScope(localScope); |
|
|
jbRecPop(); |
|
|
jbRecPop(); |
|
|
return result; |
|
|
return result; |
|
|
} |
|
|
} |
|
@ -1435,7 +1471,7 @@ oop eval(oop scope, oop ast) |
|
|
oop param = map_get(ast, param_symbol); |
|
|
oop param = map_get(ast, param_symbol); |
|
|
oop body = map_get(ast, body_symbol); |
|
|
oop body = map_get(ast, body_symbol); |
|
|
oop fixed = map_get(ast, fixed_symbol); |
|
|
oop fixed = map_get(ast, fixed_symbol); |
|
|
oop func = makeFunction(NULL, name, param, body, scope, fixed); |
|
|
|
|
|
|
|
|
oop func = makeFunction(NULL, name, param, body, fixScope(scope), fixed); |
|
|
if (opt_v > 4) { |
|
|
if (opt_v > 4) { |
|
|
printf("funcscope: "); |
|
|
printf("funcscope: "); |
|
|
println(scope); |
|
|
println(scope); |
|
@ -1516,16 +1552,18 @@ oop eval(oop scope, oop ast) |
|
|
if (null == catch) { |
|
|
if (null == catch) { |
|
|
return eval(scope, finally); |
|
|
return eval(scope, finally); |
|
|
} |
|
|
} |
|
|
oop localScope= newObject(scope); |
|
|
|
|
|
|
|
|
oop localScope= newScope(scope); |
|
|
setVariable(localScope, exception, res); |
|
|
setVariable(localScope, exception, res); |
|
|
|
|
|
|
|
|
jbRecPush(); |
|
|
jbRecPush(); |
|
|
jbt= sigsetjmp(jbs->jb, 0); |
|
|
jbt= sigsetjmp(jbs->jb, 0); |
|
|
if (0 == jbt) { |
|
|
if (0 == jbt) { |
|
|
eval(localScope, catch); |
|
|
eval(localScope, catch); |
|
|
|
|
|
delScope(localScope); |
|
|
jbRecPop(); |
|
|
jbRecPop(); |
|
|
return eval(scope, finally); |
|
|
return eval(scope, finally); |
|
|
} |
|
|
} |
|
|
|
|
|
delScope(localScope); |
|
|
// something happend in the catch block |
|
|
// something happend in the catch block |
|
|
res= jbs->result; |
|
|
res= jbs->result; |
|
|
jbRecPop(); |
|
|
jbRecPop(); |
|
@ -1540,12 +1578,13 @@ oop eval(oop scope, oop ast) |
|
|
int i = 0; |
|
|
int i = 0; |
|
|
oop index; |
|
|
oop index; |
|
|
oop statement, res; |
|
|
oop statement, res; |
|
|
oop localScope = newObject(scope); |
|
|
|
|
|
|
|
|
oop localScope = newScope(scope); |
|
|
while ((index = makeInteger(i)), map_hasKey(statements, index)) { |
|
|
while ((index = makeInteger(i)), map_hasKey(statements, index)) { |
|
|
statement = map_get(statements, index); |
|
|
statement = map_get(statements, index); |
|
|
res = eval(localScope, statement); |
|
|
res = eval(localScope, statement); |
|
|
i++; |
|
|
i++; |
|
|
} |
|
|
} |
|
|
|
|
|
delScope(localScope); |
|
|
return res; |
|
|
return res; |
|
|
} |
|
|
} |
|
|
case t_GetVariable: { |
|
|
case t_GetVariable: { |
|
@ -1910,9 +1949,15 @@ oop prim_import(oop scope, oop params) |
|
|
return null; |
|
|
return null; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
oop prim_String(oop scope, oop params) |
|
|
|
|
|
{ |
|
|
|
|
|
if (!map_hasIntegerKey(params, 0)) return null; |
|
|
|
|
|
return makeString(printString(get(params, Map, elements)[0].value)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
oop prim_scope(oop scope, oop params) |
|
|
oop prim_scope(oop scope, oop params) |
|
|
{ |
|
|
{ |
|
|
return scope; |
|
|
|
|
|
|
|
|
return fixScope(scope); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
#include <sys/resource.h> |
|
|
#include <sys/resource.h> |
|
@ -1943,6 +1988,7 @@ int main(int argc, char **argv) |
|
|
map_set(globals, intern("clone" ), makeFunction(prim_clone, intern("clone" ), 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("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("microseconds"), makeFunction(prim_microseconds, intern("microseconds"), null, null, globals, null)); |
|
|
|
|
|
map_set(globals, intern("String" ), makeFunction(prim_String , intern("String" ), 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)); |
|
|
|
|
|
|
|
@ -1964,10 +2010,13 @@ int main(int argc, char **argv) |
|
|
DO_PROTOS() |
|
|
DO_PROTOS() |
|
|
#undef _DO |
|
|
#undef _DO |
|
|
|
|
|
|
|
|
|
|
|
fixScope(globals); |
|
|
|
|
|
|
|
|
int repled = 0; |
|
|
int repled = 0; |
|
|
while (argc-- > 1) { |
|
|
while (argc-- > 1) { |
|
|
++argv; |
|
|
++argv; |
|
|
if (!strcmp(*argv, "-v")) ++opt_v; |
|
|
|
|
|
|
|
|
if (!strcmp(*argv, "-g")) ++opt_g; |
|
|
|
|
|
else if (!strcmp(*argv, "-v")) ++opt_v; |
|
|
else if (!strcmp(*argv, "-")) { |
|
|
else if (!strcmp(*argv, "-")) { |
|
|
readEvalPrint(globals, NULL); |
|
|
readEvalPrint(globals, NULL); |
|
|
repled= 1; |
|
|
repled= 1; |
|
@ -1981,6 +2030,13 @@ int main(int argc, char **argv) |
|
|
readEvalPrint(globals, NULL); |
|
|
readEvalPrint(globals, NULL); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (opt_g) { |
|
|
|
|
|
if (nalloc < 1024) printf("[GC: %lli bytes allocated]\n", nalloc ); |
|
|
|
|
|
else if (nalloc < 1024*1024) printf("[GC: %lli kB allocated]\n", nalloc / 1024 ); |
|
|
|
|
|
else if (nalloc < 1024*1024*1024) printf("[GC: %.2f MB allocated]\n", (double)nalloc / ( 1024*1024)); |
|
|
|
|
|
else printf("[GC: %.2f GB allocated]\n", (double)nalloc / (1024*1024*1024)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
return 0; |
|
|
return 0; |
|
|
|
|
|
|
|
|
(void)yyAccept; |
|
|
(void)yyAccept; |
|
|