diff --git a/bootstrap.txt b/bootstrap.txt new file mode 100644 index 0000000..5edf95c --- /dev/null +++ b/bootstrap.txt @@ -0,0 +1,16 @@ +var __requires__ = {} + +fun require(__fileName__) { + if (__requires__[__fileName__] != null) { + return __requires__[__fileName__] + } + import(__fileName__); + __requires__[__fileName__]= scope(); + return scope(); +} + +fun println() { + apply(print, __arguments__); + print("\n"); + __arguments__; +} \ No newline at end of file diff --git a/object.c b/object.c index c70adc0..051bb60 100644 --- a/object.c +++ b/object.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -85,7 +86,7 @@ struct Symbol { #endif //SYMBOL_PAYLOAD }; -typedef oop (*primitive_t)(oop params); +typedef oop (*primitive_t)(oop scope, oop params); struct Function { type_t type; @@ -177,7 +178,7 @@ DECLARE_STRING_BUFFER(char, StringBuffer); void print(oop ast); void println(oop ast); -void printOn(StringBuffer *buf, oop obj); +void printOn(StringBuffer *buf, oop obj, int indent); int getInteger(oop obj) { @@ -458,6 +459,40 @@ oop map_values(oop map) return values; } +DECLARE_BUFFER(oop, OopStack); +OopStack printing = BUFFER_INITIALISER; + +#define OopStack_push(s, o) OopStack_append(s, o) +oop OopStack_pop(OopStack *s) +{ + if (s->position < 1) { + return null; + } + return s->contents[--(s->position)]; +} + +int OopStack_includes(OopStack *s, oop map) +{ + for (size_t i=0; i < s->position; ++i) { + if (s->contents[i] == map) { + return 1; + } + } + return 0; +} + +void indentOn(StringBuffer *buf, int indent) +{ + for (size_t i = 0; i < indent; i++) { + if (isatty(fileno(stdout))) { + StringBuffer_appendString(buf, "\033[90m|\033[0m"); + } else { + StringBuffer_appendString(buf, "|"); + } + StringBuffer_appendString(buf, " "); + } +} + void map_printOn(StringBuffer *buf, oop map, int ident) { assert(is(Map, map)); @@ -467,31 +502,30 @@ void map_printOn(StringBuffer *buf, oop map, int ident) StringBuffer_append(buf, '}'); return; } + if (OopStack_includes(&printing, map)) { + StringBuffer_appendString(buf, ""); + return; + } + OopStack_push(&printing, map); for (size_t i = 0; i < map_size(map); i++) { StringBuffer_append(buf, '\n'); - for (size_t i = 0; i < ident; i++) { - if (isatty(fileno(stdout))) { - StringBuffer_appendString(buf, "\033[90m|\033[0m"); - } else { - StringBuffer_appendString(buf, "|"); - } - StringBuffer_appendString(buf, " "); - } + indentOn(buf, ident); // todo: a key could be a map itself - printOn(buf, get(map, Map, elements)[i].key); + printOn(buf, get(map, Map, elements)[i].key, ident); StringBuffer_appendString(buf, ": "); oop rhs = get(map, Map, elements)[i].value; if (getType(rhs) == Map) { map_printOn(buf, rhs, ident + 1); } else { - printOn(buf, rhs); + printOn(buf, rhs, ident); } if (i < map_size(map) - 1) StringBuffer_append(buf, ','); if (ident == 1 && i == map_size(map) - 1) StringBuffer_append(buf, '\n'); } + OopStack_pop(&printing); } -void printOn(StringBuffer *buf, oop obj) +void printOn(StringBuffer *buf, oop obj, int indent) { assert(obj); switch (getType(obj)) { @@ -520,14 +554,18 @@ void printOn(StringBuffer *buf, oop obj) } else { StringBuffer_appendString(buf, "Primitive:"); } - printOn(buf, get(obj, Function, name)); + printOn(buf, get(obj, Function, name), indent); StringBuffer_append(buf, '('); - printOn(buf, get(obj, Function, param)); + printOn(buf, get(obj, Function, param), indent + 1); + if (get(obj, Function, param) != null) { + StringBuffer_append(buf, '\n'); + indentOn(buf, indent); + } StringBuffer_append(buf, ')'); return; } case Map: { - map_printOn(buf, obj, 0); + map_printOn(buf, obj, indent); return; } } @@ -538,7 +576,7 @@ char *printString(oop obj) { static StringBuffer buf= BUFFER_INITIALISER; StringBuffer_clear(&buf); - printOn(&buf, obj); + printOn(&buf, obj, 0); return StringBuffer_contents(&buf); } diff --git a/parse.leg b/parse.leg index a423b73..471b56a 100644 --- a/parse.leg +++ b/parse.leg @@ -485,7 +485,7 @@ oop newFunc(oop name, oop param, oop body, oop fixed) return func; } -oop apply(oop func, oop args); +oop apply(oop scope, oop func, oop args); oop getSyntaxId(int n, oop key) { @@ -625,7 +625,7 @@ exp = VAR l:ident ASSIGN e:exp { $$ = newDeclarati | 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) } - | l:syntax2 a:argumentList s:block { $$ = (map_append(a, s), apply(l, a)) } + | l:syntax2 a:argumentList s:block { $$ = (map_append(a, s), apply(globals, l, a)) } | c:cond { $$ = c } ident = l:IDENT { $$ = l } @@ -724,7 +724,7 @@ prefix = PLUS n:prefix { $$= n } postfix = i:value ( DOT s:IDENT a:argumentList { i = newInvoke(i, s, a) } | DOT s:IDENT !assignOp { i = newGetMap(GetMember_proto, i, s) } | LBRAC p:exp RBRAC !assignOp { i = newGetMap(GetIndex_proto, i, p) } - | a:argumentList { i = (null != getSyntax(1, i)) ? apply(getSyntax(1, i), a) : newCall(i, a) } + | a:argumentList { i = (null != getSyntax(1, i)) ? apply(globals, getSyntax(1, i), a) : newCall(i, a) } | PLUSPLUS { i = newPostIncrement(i) } | MINUSMINUS { i = newPostDecrement(i) } ) * { $$ = i } @@ -1114,7 +1114,7 @@ oop eval(oop scope, oop ast) oop condition = map_get(ast, condition_symbol ); oop consequent = map_get(ast, consequent_symbol); oop alternate = map_get(ast, alternate_symbol ); - return eval(scope, isTrue(eval(scope, condition)) ? consequent : alternate); + return eval(scope, isTrue(eval(scope, condition)) ? consequent : alternate); } case t_While: { oop condition = map_get(ast, condition_symbol ); @@ -1335,7 +1335,7 @@ oop eval(oop scope, oop ast) jbRecPop(); return result; } - return get(func, Function, primitive)(args); + return get(func, Function, primitive)(scope, args); } case t_Invoke: { // this is what differs from t_call @@ -1349,7 +1349,7 @@ oop eval(oop scope, oop ast) oop args = evalArgs(scope, map_get(ast, args_symbol)); if (NULL != get(func, Function, primitive)) { - return get(func, Function, primitive)(args); + return get(func, Function, primitive)(scope, args); } oop param = get(func, Function, param); oop localScope = map_zip(param, args); @@ -1547,8 +1547,18 @@ oop eval(oop scope, oop ast) BINARY(Bitor, | ); BINARY(Bitxor, ^ ); BINARY(Bitand, & ); - BINARY(Equal, ==); - BINARY(Noteq, !=); +// BINARY(Equal, ==); +// BINARY(Noteq, !=); + 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, >=); @@ -1676,7 +1686,7 @@ oop eval(oop scope, oop ast) return null; } -oop prim_exit(oop params) +oop prim_exit(oop scope, oop params) { int status= 0; if (map_hasIntegerKey(params, 0)) { @@ -1686,7 +1696,7 @@ oop prim_exit(oop params) exit(status); } -oop prim_keys(oop params) +oop prim_keys(oop scope, oop params) { if (map_hasIntegerKey(params, 0)) { oop arg= get(params, Map, elements)[0].value; @@ -1695,7 +1705,7 @@ oop prim_keys(oop params) return null; } -oop prim_values(oop params) +oop prim_values(oop scope, oop params) { if (map_hasIntegerKey(params, 0)) { oop arg= get(params, Map, elements)[0].value; @@ -1704,7 +1714,7 @@ oop prim_values(oop params) return null; } -oop prim_length(oop params) +oop prim_length(oop scope, oop params) { if (map_hasIntegerKey(params, 0)) { oop arg= get(params, Map, elements)[0].value; @@ -1726,7 +1736,7 @@ oop prim_length(oop params) // ISSUE2: how can I tackle the 2 fprintf(stderr, "\nbreak/continue oustide of a loop\n") in prim_invoke and prim_apply // in this situation it seems that I don't have access to any AST -oop prim_invoke(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 func= null; if (map_hasIntegerKey(params, 1)) func= get(params, Map, elements)[1].value; @@ -1737,7 +1747,7 @@ oop prim_invoke(oop params) exit(1); } if (NULL != get(func, Function, primitive)) { - return get(func, Function, primitive)(args); + return get(func, Function, primitive)(scope, args); } oop param = get(func, Function, param); oop localScope = map_zip(param, args); @@ -1770,7 +1780,7 @@ oop prim_invoke(oop params) return result; } -oop apply(oop func, oop args) +oop apply(oop scope, oop func, oop args) { if (!is(Function, func)) { printf("cannot apply "); @@ -1778,7 +1788,7 @@ oop apply(oop func, oop args) exit(1); } if (NULL != get(func, Function, primitive)) { - return get(func, Function, primitive)(args); + return get(func, Function, primitive)(scope, args); } oop param = get(func, Function, param); oop localScope = map_zip(param, args); @@ -1810,19 +1820,19 @@ oop apply(oop func, oop args) return result; } -oop prim_apply(oop params) { +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(func, args); + return apply(scope, func, args); } -oop prim_clone(oop params) +oop prim_clone(oop scope, oop params) { if (map_hasIntegerKey(params, 0)) return clone(get(params, Map, elements)[0].value); return null; } -oop prim_print(oop params) +oop prim_print(oop scope, oop params) { assert(is(Map, params)); for (int i= 0; map_hasIntegerKey(params, i); ++i) { @@ -1831,13 +1841,6 @@ oop prim_print(oop params) return params; } -oop prim_println(oop params) -{ - oop res= prim_print(params); - printf("\n"); - return res; -} - oop evalArgs(oop scope, oop args) { int i = 0; @@ -1852,7 +1855,7 @@ oop evalArgs(oop scope, oop args) oop AST= NULL; -void readEvalPrint(char *fileName) +void readEvalPrint(oop scope, char *fileName) { inputStackPush(fileName); input_t *top= inputStack; @@ -1871,7 +1874,7 @@ void readEvalPrint(char *fileName) continue; } // EOF if (opt_v > 1) println(yylval); - oop res = eval(globals, yylval); + oop res = eval(scope, yylval); if (opt_v > 0) println(res); assert(jbs == jtop); } @@ -1898,7 +1901,7 @@ void readEvalPrint(char *fileName) } } -oop prim_import(oop params) +oop prim_import(oop scope, oop params) { if (map_hasIntegerKey(params, 0)) { char *file= get(get(params, Map, elements)[0].value, String, value); @@ -1906,14 +1909,19 @@ oop prim_import(oop params) yyctx->__limit--; ungetc(yyctx->__buf[yyctx->__limit], inputStack->file); } - readEvalPrint(file); + readEvalPrint(scope, file); } return null; } +oop prim_scope(oop scope, oop params) +{ + return scope; +} + #include -oop prim_millis(oop params) +oop prim_millis(oop scope, oop params) { struct rusage ru; getrusage(RUSAGE_SELF, &ru); @@ -1934,13 +1942,14 @@ int main(int argc, char **argv) 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("println"), makeFunction(prim_println, intern("println"), 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("scope"), makeFunction(prim_scope, intern("scope"), null, null, globals, null)); + #define _DO(NAME) NAME##_symbol=intern(#NAME); DO_SYMBOLS() #undef _DO @@ -1964,16 +1973,16 @@ int main(int argc, char **argv) ++argv; if (!strcmp(*argv, "-v")) ++opt_v; else if (!strcmp(*argv, "-")) { - readEvalPrint(NULL); + readEvalPrint(globals, NULL); repled= 1; } else { - readEvalPrint(*argv); + readEvalPrint(globals, *argv); repled= 1; } } if (!repled) { - readEvalPrint(NULL); + readEvalPrint(globals, NULL); } return 0; diff --git a/test-module.txt b/test-module.txt new file mode 100644 index 0000000..2f88091 --- /dev/null +++ b/test-module.txt @@ -0,0 +1,6 @@ +var pi = 3 + +fun sum(a, b) { + return a+b; +} +println("Hello from test-module.txt"); \ No newline at end of file diff --git a/test-require.txt b/test-require.txt new file mode 100644 index 0000000..d76d436 --- /dev/null +++ b/test-require.txt @@ -0,0 +1,6 @@ +// keep a reference to that function local scope that might otherwise been garbage collected +var mod = require("test-module.txt"); +println(mod.sum(40, 2)); +println(mod.pi); +var mod2 = require("test-module.txt"); +println(mod2.pi); \ No newline at end of file diff --git a/test3.txt b/test3.txt deleted file mode 100644 index 6332136..0000000 --- a/test3.txt +++ /dev/null @@ -1,3 +0,0 @@ -println(666) -import "test-proto.txt" -println(12) \ No newline at end of file