From 6d20596796d08dc45c31bc044018de63bc93490a Mon Sep 17 00:00:00 2001 From: mtardy Date: Thu, 6 Aug 2020 14:02:01 +0200 Subject: [PATCH] Add for loop and switch statement --- object.c | 33 ++-- parse.leg | 449 ++++++++++++++++++++++++++++++++++-------------------- test.txt | 59 +++++++ 3 files changed, 367 insertions(+), 174 deletions(-) diff --git a/object.c b/object.c index cbe4e31..894ad34 100644 --- a/object.c +++ b/object.c @@ -122,6 +122,8 @@ union object { union object _null = {.Undefined = {Undefined}}; oop null = &_null; +int is(type_t type, oop obj); + int isInteger(oop obj) { #if (USE_TAG) @@ -230,9 +232,14 @@ oop makeMap() return newMap; } +size_t map_size(oop map) +{ + return get(map, Map, size); +} + bool map_hasIntegerKey(oop map, size_t index) { - if (index >= get(map, Map, size)) return 0; + if (index >= map_size(map)) return 0; oop key= get(map, Map, elements)[index].key; if (!isInteger(key)) return 0; return index == getInteger(key); @@ -261,7 +268,7 @@ ssize_t map_search(oop map, oop key) assert(is(Map, map)); assert(key); - ssize_t r = get(map, Map, size) - 1; + ssize_t r = map_size(map) - 1; if (isInteger(key)) { ssize_t index = getInteger(key); @@ -307,25 +314,25 @@ oop map_insert(oop map, oop key, oop value, size_t pos) assert(is(Map, map)); assert(key); assert(value); - if (pos > get(map, Map, size)) { // don't need to check for pos < 0 because size_t is unsigned + if (pos > map_size(map)) { // don't need to check for pos < 0 because size_t is unsigned fprintf(stderr, "\nTrying to insert in a map out of bound\n"); assert(-1); } // check capacity and expand if needed - if (get(map, Map, size) >= get(map, Map, capacity)) { + if (map_size(map) >= get(map, Map, capacity)) { size_t newCapacity = get(map, Map, capacity) + MAP_CHUNK_SIZE; set(map, Map, elements, memcheck(realloc(get(map, Map, elements), sizeof(struct Pair) * newCapacity))); set(map, Map, capacity, newCapacity); } // insert - memmove(get(map, Map, elements) + pos + 1, get(map, Map, elements) + pos, sizeof(struct Pair) * (get(map, Map, size) - pos)); + memmove(get(map, Map, elements) + pos + 1, get(map, Map, elements) + pos, sizeof(struct Pair) * (map_size(map) - pos)); // Maybe this syntax is not very nice and I should access the Pair stuff differently? // I mean modifying something on a line that begin with "get"... :/ get(map, Map, elements)[pos].value = value; get(map, Map, elements)[pos].key = key; - set(map, Map, size, get(map, Map, size) + 1); + set(map, Map, size, map_size(map) + 1); return value; } @@ -351,16 +358,16 @@ oop map_del(oop map, oop key) assert(is(String, key)); ssize_t pos = map_search(map, key); if (pos < 0) return map; - if (pos < get(map, Map, size) - 1) { - memmove(get(map, Map, elements) + pos, get(map, Map, elements) + pos + 1, sizeof(struct Pair) * (get(map, Map, size) - pos)); + if (pos < map_size(map) - 1) { + memmove(get(map, Map, elements) + pos, get(map, Map, elements) + pos + 1, sizeof(struct Pair) * (map_size(map) - pos)); } - set(map, Map, size, get(map, Map, size) - 1); + set(map, Map, size, map_size(map) - 1); return map; } oop map_append(oop map, oop value) { - return map_set(map, makeInteger(get(map, Map, size)), value); + return map_set(map, makeInteger(map_size(map)), value); } void map_print(oop map, int ident) @@ -369,7 +376,7 @@ void map_print(oop map, int ident) if (ident > 1) { printf("\n"); } - for (size_t i = 0; i < get(map, Map, size); i++) { + for (size_t i = 0; i < map_size(map); i++) { for (size_t i = 0; i < ident; i++) { printf("|"); printf(" "); @@ -383,7 +390,7 @@ void map_print(oop map, int ident) } else { print(rhs); } - if (i < get(map, Map, size) - 1) printf(",\n"); + if (i < map_size(map) - 1) printf(",\n"); } return; } @@ -442,7 +449,7 @@ ssize_t map_intern_search(oop map, char* ident) { assert(is(Map, map)); assert(ident); - ssize_t l = 0, r = get(map, Map, size) - 1; + ssize_t l = 0, r = map_size(map) - 1; while (l <= r) { ssize_t mid = (l + r) / 2; int cmpres = strcmp(get(get(map, Map, elements)[mid].key, Symbol, name), ident); diff --git a/parse.leg b/parse.leg index f340ef0..f63375b 100644 --- a/parse.leg +++ b/parse.leg @@ -6,14 +6,13 @@ * run: echo "3+4" | ./parse */ -#define DO_PROTOS() \ - _DO(if) _DO(while) _DO(call) _DO(func) _DO(compoundStatement) _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(getMember) _DO(setMember) _DO(getIndex) _DO(setIndex) \ - _DO(return) +#define DO_PROTOS() \ + _DO(if) _DO(while) _DO(do) _DO(for) _DO(switch) _DO(call) _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(getMember) _DO(setMember) _DO(getIndex) _DO(setIndex) typedef enum { t_UNDEFINED=0, @@ -29,10 +28,10 @@ DO_PROTOS() // this is the global scope oop globals= 0; -#define DO_SYMBOLS() \ - DO_PROTOS() _DO(__proto__) _DO(__name__) \ - _DO(name) _DO(body) _DO(param) _DO(key) _DO(value) _DO(condition) _DO(consequent) _DO(alternate) \ - _DO(lhs) _DO(rhs) _DO(scope) _DO(args) _DO(statements) +#define DO_SYMBOLS() \ + DO_PROTOS() _DO(__proto__) _DO(__name__) _DO(__default__) \ + _DO(name) _DO(body) _DO(param) _DO(key) _DO(value) _DO(condition) _DO(consequent) _DO(alternate) \ + _DO(lhs) _DO(rhs) _DO(scope) _DO(args) _DO(expression) _DO(labels) _DO(statements) _DO(initialise) _DO(update) #define _DO(NAME) oop NAME##_symbol; DO_SYMBOLS() @@ -99,6 +98,33 @@ oop newWhile(oop cond, oop body) return obj; } +oop newDo(oop body, oop cond) +{ + oop obj= newObject(do_proto); + map_set(obj, body_symbol, body); + map_set(obj, condition_symbol, cond); + return obj; +} + +oop newFor(oop init, oop cond, oop step, oop body) +{ + oop obj= newObject(for_proto); + map_set(obj, initialise_symbol, init); + map_set(obj, condition_symbol, cond); + map_set(obj, update_symbol, step); + map_set(obj, body_symbol, body); + return obj; +} + +oop newSwitch(oop expression, oop labels, oop statements) +{ + oop obj= newObject(switch_proto); + map_set(obj, expression_symbol, expression); + map_set(obj, labels_symbol, labels); + map_set(obj, statements_symbol, statements); + return obj; +} + oop newAssign(oop lhs, oop rhs) { oop assign = newObject(assign_proto); @@ -123,56 +149,61 @@ oop newInteger(int value) return integer; } +int digitValue(int c) +{ + if (c < '0') return -1; + if ('a' <= c && c <= 'z') c -= ('a' - 'A'); // tolower(c) + if ('9' < c && c < 'A') return -1; + if ('Z' < c) return -1; + if (c >= 'A') c -= ('A' - 10); else c -= '0'; + return c; +} + int isradix(int r, int c) { - if (c < '0') return 0; - if (c >= 'a') c -= 'a' - 'A'; // tolower(c) - if ('9' < c && c < 'A') return 0; - if (c >= 'A') c -= 'A' - 10; - return c < r; + c= digitValue(c); + return 0 <= c && c < r; } char *unescape(char *s) { - char *t= strdup(s); // this is garbage collected + char *t= strdup(s); int in= 0, out= 0, c= 0; while (0 != (c= t[in++])) { - if ('\\' == c && 0 != (c= t[in++])) { - switch (c) { - case 'a': c= '\a'; break; - case 'b': c= '\b'; break; - case 'e': c= '\e'; break; - case 'f': c= '\f'; break; - case 'n': c= '\n'; break; - case 'r': c= '\r'; break; - case 't': c= '\t'; break; - case 'v': c= '\v'; break; - case '0'...'7': { - c= c - '0'; - ++in; - if (isradix(8, t[in])) c= c * 8 + t[in++] - '0'; - if (isradix(8, t[in])) c= c * 8 + t[in++] - '0'; - break; - } - case 'x': { - c= 0; - ++in; - if (isradix(16, t[in])) c= c * 16 + t[in++] - '0'; - if (isradix(16, t[in])) c= c * 16 + t[in++] - '0'; - break; - } - case 'u': { - c= 0; - ++in; - if (isradix(16, t[in])) c= c * 16 + t[in++] - '0'; - if (isradix(16, t[in])) c= c * 16 + t[in++] - '0'; - if (isradix(16, t[in])) c= c * 16 + t[in++] - '0'; - if (isradix(16, t[in])) c= c * 16 + t[in++] - '0'; - break; - } - } - } - t[out++]= c; + if ('\\' == c && 0 != (c= t[in])) { + ++in; + switch (c) { + case 'a': c= '\a'; break; + case 'b': c= '\b'; break; + case 'e': c= '\e'; break; + case 'f': c= '\f'; break; + case 'n': c= '\n'; break; + case 'r': c= '\r'; break; + case 't': c= '\t'; break; + case 'v': c= '\v'; break; + case '0'...'7': { + c -= '0'; + if (isradix(8, t[in])) c= c * 8 + t[in++] - '0'; + if (isradix(8, t[in])) c= c * 8 + t[in++] - '0'; + break; + } + case 'x': { + c= 0; + if (isradix(16, t[in])) c= c * 16 + digitValue(t[in++]); + if (isradix(16, t[in])) c= c * 16 + digitValue(t[in++]); + break; + } + case 'u': { + c= 0; + if (isradix(16, t[in])) c= c * 16 + digitValue(t[in++]); + if (isradix(16, t[in])) c= c * 16 + digitValue(t[in++]); + if (isradix(16, t[in])) c= c * 16 + digitValue(t[in++]); + if (isradix(16, t[in])) c= c * 16 + digitValue(t[in++]); + break; + } + } + } + t[out++]= c; } t[out]= 0; return t; @@ -253,20 +284,13 @@ oop newCall(oop func, oop args) return call; } -oop newCompoundStatement(oop statements) +oop newBlock(oop statements) { - oop obj = newObject(compoundStatement_proto); + oop obj = newObject(block_proto); map_set(obj, statements_symbol, statements); return obj; } -oop newReturn(oop exp) -{ - oop obj = newObject(return_proto); - map_set(obj, value_symbol, exp); - return obj; -} - // this always creates the key in "object" oop newVariable(oop object, oop key, oop value) { @@ -299,6 +323,8 @@ oop setVariable(oop object, oop key, oop value) return map_set(object, key, value); } +oop fold(oop ast); + #define YYSTYPE oop YYSTYPE yylval; @@ -308,7 +334,7 @@ YYSTYPE yylval; start = - e:stmt { yylval = e } stmt = e:exp SEMICOLON* { $$ = e } - | s:compoundStatement { $$ = newCompoundStatement(s) } + | s:block { $$ = newBlock(s) } exp = VAR l:IDENT ASSIGN e:exp { $$ = newDeclaration(l, e) } | VAR l:IDENT { $$ = newDeclaration(l, null) } @@ -316,18 +342,27 @@ exp = VAR l:IDENT ASSIGN e:exp { $$ = newDeclarati | FUN p:paramList e:stmt { $$ = newFunc(null, p, e) } | IF LPAREN c:exp RPAREN t:stmt ELSE f:stmt { $$ = newIf(c, t, f ) } | IF LPAREN c:exp RPAREN t:stmt { $$ = newIf(c, t, null) } - | WHILE LPAREN c:exp RPAREN e:stmt { $$ = newWhile(c, e) } - | RETURN e:exp { $$ = newReturn(e) } - | RETURN { $$ = newReturn(null) } + | WHILE LPAREN c:exp RPAREN s:stmt { $$ = newWhile(c, s) } + | 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 } | l:IDENT ASSIGN e:exp { $$ = newAssign(l, e) } | l:postfix DOT i:IDENT ASSIGN e:exp { $$ = newSetMember(l, i, e) } | l:postfix LBRAC i:exp RBRAC ASSIGN e:exp { $$ = newSetIndex(l, i, e) } | c:cond { $$ = c } -compoundStatement = LCB m:makeMap - ( s:stmt { map_append(m, s) } - ) * - RCB { $$ = m } +block = LCB m:makeMap + ( s:stmt { map_append(m, s) } + ) * + RCB { $$ = m } + +switch = SWITCH LPAREN e:exp RPAREN + LCB statements:makeMap labels:makeMap + ( CASE l:exp COLON { map_set(labels, fold(l), makeInteger(map_size(statements))) } + | DEFAULT COLON { map_set(labels, __default___symbol, makeInteger(map_size(statements))) } + | s:stmt { map_append(statements, s) } + )* + RCB { $$= newSwitch(e, labels, statements) } cond = c:logor QUERY t:exp COLON f:cond { $$ = newIf(c, t, f) } | logor @@ -440,53 +475,61 @@ blank = [ \t\n\r] comment = "//" ( ![\n\r] . )* | "/*" ( !"*/" . )* "*/" -IDENT = < [a-zA-Z][a-zA-Z0-9_]* > - { $$ = intern(yytext) } -NUMBER = '0b' < [01]+ > - { $$ = newInteger(strtol(yytext, 0, 2)) } - | '0x' < [0-9a-fA-F]+ > - { $$ = newInteger(strtol(yytext, 0, 16)) } - | '0' < [0-7]+ > - { $$ = newInteger(strtol(yytext, 0, 8)) } - | < [0-9]+ > - { $$ = newInteger(strtol(yytext, 0, 10)) } -FUN = 'fun' ![a-zA-Z0-9_] - -VAR = 'var' ![a-zA-Z0-9_] - -WHILE = 'while' ![a-zA-Z0-9_] - -IF = 'if' ![a-zA-Z0-9_] - -ELSE = 'else' ![a-zA-Z0-9_] - -NULL = 'null' ![a-zA-Z0-9_] - -RETURN = 'return' ![a-zA-Z0-9_] - -HASH = '#' - -LOGOR = '||' - -LOGAND = '&&' - -BITOR = '|' ![|=] - -BITXOR = '^' ![=] - -BITAND = '&' ![&=] - -EQUAL = '==' - -NOTEQ = '!=' - -LESS = '<' ![<=] - -LESSEQ = '<=' - -GREATEREQ = '>=' - -GREATER = '>' ![>=] - -SHLEFT = '<<' ![=] - -SHRIGHT = '>>' ![=] - -PLUS = '+' ![+=] - -MINUS = '-' ![-=] - -TILDE = '~' - -PLING = '!' ![=] - -MULTI = '*' ![=] - -DIVIDE = '/' ![/=] - -MODULO = '%' ![=] - -ASSIGN = '=' ![=] - -QUERY = '?' - -COLON = ':' - -SEMICOLON = ';' - -COMMA = ',' - -DOT = '.' - -LCB = '{' - -RCB = '}' - -LBRAC = '[' - -RBRAC = ']' - -LPAREN = '(' - -RPAREN = ')' - -DQUOTE = '"' - -SQUOTE = "'" - +keyword = FUN | VAR | SWITCH | CASE | DEFAULT | DO | FOR | WHILE | IF | ELSE | NULL + +IDENT = !keyword < [a-zA-Z_][a-zA-Z0-9_]* > - { $$ = intern(yytext) } + +NUMBER = '0b' < [01]+ > - { $$ = newInteger(strtol(yytext, 0, 2)) } + | '0x' < [0-9a-fA-F]+ > - { $$ = newInteger(strtol(yytext, 0, 16)) } + | '0' < [0-7]+ > - { $$ = newInteger(strtol(yytext, 0, 8)) } + | < [0-9]+ > - { $$ = newInteger(strtol(yytext, 0, 10)) } + +FUN = 'fun' ![a-zA-Z0-9_] - +VAR = 'var' ![a-zA-Z0-9_] - +SWITCH = 'switch' ![a-zA-Z0-9_] - +CASE = 'case' ![a-zA-Z0-9_] - +DEFAULT = 'default' ![a-zA-Z0-9_] - +DO = 'do' ![a-zA-Z0-9_] - +FOR = 'for' ![a-zA-Z0-9_] - +WHILE = 'while' ![a-zA-Z0-9_] - +IF = 'if' ![a-zA-Z0-9_] - +ELSE = 'else' ![a-zA-Z0-9_] - +NULL = 'null' ![a-zA-Z0-9_] - +HASH = '#' - +LOGOR = '||' - +LOGAND = '&&' - +BITOR = '|' ![|=] - +BITXOR = '^' ![=] - +BITAND = '&' ![&=] - +EQUAL = '==' - +NOTEQ = '!=' - +LESS = '<' ![<=] - +LESSEQ = '<=' - +GREATEREQ = '>=' - +GREATER = '>' ![>=] - +SHLEFT = '<<' ![=] - +SHRIGHT = '>>' ![=] - +PLUS = '+' ![+=] - +MINUS = '-' ![-=] - +TILDE = '~' - +PLING = '!' ![=] - +MULTI = '*' ![=] - +DIVIDE = '/' ![/=] - +MODULO = '%' ![=] - +ASSIGN = '=' ![=] - +QUERY = '?' - +COLON = ':' - +SEMICOLON = ';' - +COMMA = ',' - +DOT = '.' - +LCB = '{' - +RCB = '}' - +LBRAC = '[' - +RBRAC = ']' - +LPAREN = '(' - +RPAREN = ')' - +DQUOTE = '"' - +SQUOTE = "'" - %% ; @@ -501,28 +544,93 @@ int isTrue(oop obj) return !isFalse(obj); } -oop map_fromArrays(oop keys, oop values) +oop map_zip(oop keys, oop values) { assert(is(Map, keys)); assert(is(Map, values)); - int i = 0; - oop map = makeMap(); - oop key, value; - oop index; - while ((index = makeInteger(i)), map_hasKey(keys, index)) { - key = map_get(keys, index); - value = map_get(values, index); + oop map= makeMap(); + for (int i= 0; map_hasIntegerKey(keys, i) && map_hasIntegerKey(values, i); ++i) { + oop key = get(keys, Map, elements)[i].value; + oop value = get(values, Map, elements)[i].value; map_set(map, key, value); - i++; } return map; } +oop fold(oop ast) +{ + if (is(Map, ast)) { + oop proto= map_get(ast, __proto___symbol); + if (null != proto) { + proto_t proto_number= get(map_get(proto, __name___symbol), Symbol, prototype); + switch (proto_number) { + case t_integer: + case t_string: + case t_symbol: { + return map_get(ast, value_symbol); + } + case t_logor: { + oop lhs= map_get(ast, lhs_symbol); + oop rhs= map_get(ast, rhs_symbol); + if (isTrue(fold(lhs))) return makeInteger(1); + if (isTrue(fold(rhs))) return makeInteger(1); + return makeInteger(0); + } + case t_logand: { + oop lhs= map_get(ast, lhs_symbol); + oop rhs= map_get(ast, rhs_symbol); + if (isFalse(fold(lhs))) return makeInteger(0); + if (isFalse(fold(rhs))) return makeInteger(0); + return makeInteger(1); + } +# define BINARY(NAME, OPERATOR) \ + case t_##NAME: { \ + oop lhs= fold(map_get(ast, lhs_symbol)); \ + oop rhs= fold(map_get(ast, rhs_symbol)); \ + 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) \ + case t_##NAME: { \ + oop rhs = fold(map_get(ast, rhs_symbol)); \ + return makeInteger(OPERATOR getInteger(rhs)); \ + } + UNARY(not, !); + UNARY(neg, -); + UNARY(com, ~); +# undef UNARY + default: + break; + } + } + } + printf("illegal value in constant expression: "); + println(ast); + assert(0); + return null; +} + oop evalArgs(oop scope, oop args); oop eval(oop scope, oop ast) { - switch(ast->type) { + switch(getType(ast)) { case Undefined: case Integer: case String: @@ -568,6 +676,40 @@ oop eval(oop scope, oop ast) while (isTrue(eval(scope, condition))) result= eval(scope, body); return result; } + case t_do: { + oop body = map_get(ast, body_symbol); + oop condition = map_get(ast, condition_symbol ); + oop result = null; + do { result= eval(scope, body); } while (isTrue(eval(scope, condition))); + return result; + } + case t_for: { + oop initialise = map_get(ast, initialise_symbol ); + oop condition = map_get(ast, condition_symbol ); + oop update = map_get(ast, update_symbol ); + oop body = map_get(ast, body_symbol); + oop result = null; + oop localScope = newObject(scope); + for (eval(localScope, initialise); isTrue(eval(localScope, condition)); eval(localScope, update)) + result= eval(localScope, body); + return result; + } + case t_switch: { + oop expression = map_get(ast, expression_symbol ); + oop labels = map_get(ast, labels_symbol ); + oop statements = map_get(ast, statements_symbol ); + oop result = eval(scope, expression); + oop label = map_get(labels, result); + if (null == label) label= map_get(labels, __default___symbol); + if (null == label) return result; + assert(isInteger(label)); + int limit= map_size(statements); + for (int i= getInteger(label); i < limit; ++i) { + assert(map_hasIntegerKey(statements, i)); + result= eval(scope, get(statements, Map, elements)[i].value); + } + return result; + } case t_assign: { oop lhs = map_get(ast, lhs_symbol); oop rhs = eval(scope, map_get(ast, rhs_symbol)); @@ -588,15 +730,15 @@ oop eval(oop scope, oop ast) } case t_call: { oop func = eval(scope, map_get(ast, func_symbol)); - if (!is(Function, func)) { - printf("cannot call "); - println(func); - exit(1); - } + if (!is(Function, func)) { + printf("cannot call "); + println(func); + exit(1); + } oop args = evalArgs(scope, map_get(ast, args_symbol)); if (get(func, Function, primitive) == NULL) { oop param = get(func, Function, param); - oop localScope = map_fromArrays(param, args); + oop localScope = map_zip(param, args); map_set(localScope, __proto___symbol, get(func, Function, parentScope)); if (opt_v) { printf("localscope\n"); @@ -607,7 +749,7 @@ oop eval(oop scope, oop ast) } return get(func, Function, primitive)(args); } - case t_compoundStatement: { + case t_block: { oop statements = map_get(ast, statements_symbol); int i = 0; oop index; @@ -615,30 +757,11 @@ oop eval(oop scope, oop ast) oop localScope = newObject(scope); while ((index = makeInteger(i)), map_hasKey(statements, index)) { statement = map_get(statements, index); - - // RETURN STUFF - oop proto = map_get(statement, __proto___symbol); - proto_t proto_number = 0; - if (proto != null) { - proto_number = get(map_get(proto, __name___symbol), Symbol, prototype); - } - // we are doing the work twice because the eval cannot return a special case to signal that it's a return statement - res = eval(localScope, statement); - - // RETURN STUFF - if (proto_number == t_return) { - break; - } - i++; } return res; } - case t_return: { - oop exp = eval(scope, map_get(ast, value_symbol)); - return exp; - } case t_getMember: { oop map = eval(scope, map_get(ast, map_symbol)); oop key = map_get(ast, key_symbol); @@ -680,11 +803,11 @@ oop eval(oop scope, oop ast) if (isFalse(eval(scope, rhs))) return makeInteger(0); return makeInteger(1); } -# define BINARY(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(getInteger(lhs) OPERATOR getInteger(rhs)); \ +# define BINARY(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(getInteger(lhs) OPERATOR getInteger(rhs)); \ } BINARY(bitor, | ); BINARY(bitxor, ^ ); @@ -705,7 +828,7 @@ oop eval(oop scope, oop ast) # undef BINARY # define UNARY(NAME, OPERATOR) \ case t_##NAME: { \ - oop rhs = eval(scope ,map_get(ast, rhs_symbol)); \ + oop rhs = eval(scope, map_get(ast, rhs_symbol)); \ return makeInteger(OPERATOR getInteger(rhs)); \ } UNARY(not, !); @@ -732,7 +855,7 @@ oop prim_exit(oop params) oop prim_print(oop params) { assert(is(Map, params)); - for (int i= 0; map_hasIntegerKey(params, i); ++i) { + for (int i= 0; map_hasIntegerKey(params, i); ++i) { print(get(params, Map, elements)[i].value); } printf("\n"); @@ -792,3 +915,7 @@ int main(int argc, char **argv) (void)yyAccept; } + +// Local Variables: +// indent-tabs-mode: nil +// End: diff --git a/test.txt b/test.txt index 94cf3a9..d7c94a5 100644 --- a/test.txt +++ b/test.txt @@ -55,8 +55,67 @@ fun f(n) if (n < 2) 1 else 1 + f(n-1) + f(n-2) f(15) +fun f() { + var i = 0; + while (i < 10) print(i = i + 1); +} + /* multi line comment */ +var i = 0; +while (i < 1000000) i = i + 1; + +do print(i); while ((i = i + 1) < 10); +i= 5; +do print(i); while ((i = i + 1) < 10); + +for (var x= 100; x < 105; x= x + 1) print(x); + +print(x); + +for (i= 200; i < 205; i= i + 1) print(i); + +print(i); + +switch (3) { + case 0: print('zero'); + case 1: print('one'); + case 2: print('two'); + case 3: print('three'); + case 4: print('four'); + case 5: print('five'); +} + +switch (#three) { + case #zero: print(0); + case #one: print(1); + case #two: print(2); + case #three: print(3); + case #four: print(4); + case #five: print(5); +} + +switch (#nine) { + case #zero: print(0); + case #one: print(1); + case #two: print(2); + case #three: print(3); + case #four: print(4); + case #five: print(5); +} + +switch (#nine) { + case #zero: print(0); + case #one: print(1); + case #two: print(2); + case #three: print(3); + case #four: print(4); + default: print(666); + case #five: print(5); +} + +print('newline\nanother\012another\x0aanother\u000a') + print('\nmoriturus te saluto\n') && exit(0)