From 8957b242ad5231361454f7938e0afb3095bf23a7 Mon Sep 17 00:00:00 2001 From: mtardy Date: Thu, 23 Jul 2020 09:34:55 +0200 Subject: [PATCH] Fix symbol table --- calc.leg | 18 ++++++++---------- object.c | 52 ++++++++++++++++++++++++---------------------------- 2 files changed, 32 insertions(+), 38 deletions(-) diff --git a/calc.leg b/calc.leg index b3d300a..1ed7631 100644 --- a/calc.leg +++ b/calc.leg @@ -9,9 +9,7 @@ #include "object.c" // this is the global scope -// oop globals; - -// this should stay out of object.c because it manipulates Symbol members defined in this file +oop globals; oop apply(oop function, oop parameters) { @@ -26,7 +24,7 @@ YYSTYPE yylval; start = - e:exp { yylval = e } -exp = l:IDENT EQUAL p:exp { $$ = variableSet(l, p) } +exp = l:IDENT EQUAL p:exp { $$ = map_set(globals, l, p) } | l:postfix DOT i:IDENT EQUAL p:exp { $$ = map_set(l, i, p) } | l:postfix LBRAC i:exp RBRAC EQUAL p:exp { $$ = map_set(l, i, p) } | s:sum { $$ = s } @@ -46,7 +44,7 @@ prefix = MINUS n:prefix { set(n, Integer, value, -get(n, Integer | PLUS n:prefix { $$ = n } | n:postfix { $$ = n } -postfix = i:value ( DOT s:IDENT p:parameterList { map_set(p, intern(globals, "this"), i); i = apply(map_get(i, s), p) } +postfix = i:value ( DOT s:IDENT p:parameterList { map_set(p, intern("this"), i); i = apply(map_get(i, s), p) } | DOT s:IDENT !EQUAL { i = map_get(i, s) } | LBRAC p:exp RBRAC !EQUAL { i = map_get(i, p) } | p:parameterList { i = apply(i, p) } @@ -64,14 +62,14 @@ value = n:NUMBER { $$ = n } | s:symbol { $$ = s } | m:map { $$ = m } | NULL { $$ = null } - | i:IDENT { $$ = variableGet(i) } + | i:IDENT { $$ = map_get(globals, i) } | LPAREN i:exp RPAREN { $$ = i } string = SQUOTE < (!SQUOTE .)* > SQUOTE { $$ = makeString(yytext) } | DQUOTE < (!DQUOTE .)* > DQUOTE { $$ = makeString(yytext) } symbol = HASH ( i:IDENT { $$ = i } - | i:string { $$ = intern(globals, get(i, String, value)) } + | i:string { $$ = intern(get(i, String, value)) } ) map = LCB m:makeMap @@ -86,7 +84,7 @@ makeMap = { $$ = makeMap() } - = [ \t\n\r]* | "//" ( ![\n\r] . )* -IDENT = < [a-zA-Z][a-zA-Z0-9_]* > - { $$ = intern(globals, yytext) } +IDENT = < [a-zA-Z][a-zA-Z0-9_]* > - { $$ = intern(yytext) } NUMBER = < [0-9]+ > - { $$ = makeInteger(atoi(yytext)) } HASH = '#' - PLUS = '+' - @@ -120,10 +118,10 @@ oop prim_exit(oop params) int main(int argc, char **argv) { + symbol_table = makeMap(); globals = makeMap(); - variableSet(intern(globals, "exit"), makeFunction(prim_exit)); - // map_set(globals, intern("exit"), makeFunction(prim_exit)); + map_set(globals, intern("exit"), makeFunction(prim_exit)); while (yyparse()) { println(yylval); diff --git a/object.c b/object.c index dfaf765..6df578a 100644 --- a/object.c +++ b/object.c @@ -41,7 +41,6 @@ struct Symbol { typedef oop (*primitive_t)(oop params); -oop globals; struct Function { type_t type; @@ -158,7 +157,7 @@ int oopcmp(oop a, oop b) case String: return strcmp(get(a, String, value), get(b, String, value)); case Symbol: - return strcmp(get(a, Symbol, name), get(b, Symbol, name)); + return a - b; default: return (intptr_t)a - (intptr_t)b; } @@ -260,26 +259,6 @@ oop map_append(oop map, oop value) return map_set(map, makeInteger(get(map, Map, size)), value); } -bool variableIsDefined(oop aSymbol) -{ - assert(is(Symbol, aSymbol)); - return map_hasKey(globals, aSymbol); -} - -oop variableSet(oop aSymbol, oop value) -{ - assert(is(Symbol, aSymbol)); - assert(value); - map_set(globals, aSymbol, value); - return value; -} - -oop variableGet(oop aSymbol) -{ - assert(is(Symbol, aSymbol)); - return map_get(globals, aSymbol); -} - void print(oop ast) { assert(ast); @@ -323,14 +302,31 @@ void println(oop ast) printf("\n"); } -oop intern(oop scope, char *ident) +oop symbol_table; + +ssize_t map_intern_search(oop map, char* ident) { - assert(is(Map, scope)); - oop symbol = makeSymbol(memcheck(strdup(ident))); - ssize_t pos = map_search(scope, symbol); - if (pos >= 0) return get(scope, Map, elements)[pos].key; // So it this case, symbol will be garbage collected right? + assert(is(Map, map)); + assert(ident); + ssize_t l = 0, r = get(map, Map, size) - 1; + while (l <= r) { + ssize_t mid = (l + r) / 2; + int cmpres = strcmp(get(get(map, Map, elements)[mid].key, Symbol, name), ident); + if (cmpres > 0) r = mid - 1; + else if (cmpres < 0) l = mid + 1; + else return mid; // non-negative result => element found at this index + } + return -1 - l; // negative result => 'not found', reflected around -1 instead of 0 to allow 'not found' at index 0 +} + +oop intern(char *ident) +{ + assert(ident); + ssize_t pos = map_intern_search(symbol_table, ident); + if (pos >= 0) return get(symbol_table, Map, elements)[pos].key; pos = -1 - pos; // 'un-negate' the result by reflecting it around X=-1 - map_insert(scope, symbol, null, pos); + oop symbol = makeSymbol(memcheck(strdup(ident))); + map_insert(symbol_table, symbol, null, pos); return symbol; } \ No newline at end of file