Ver código fonte

Add for loop and switch statement

master
mtardy 4 anos atrás
pai
commit
6d20596796
3 arquivos alterados com 367 adições e 174 exclusões
  1. +20
    -13
      object.c
  2. +288
    -161
      parse.leg
  3. +59
    -0
      test.txt

+ 20
- 13
object.c Ver arquivo

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

+ 288
- 161
parse.leg Ver arquivo

@ -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:

+ 59
- 0
test.txt Ver arquivo

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

Carregando…
Cancelar
Salvar