LexFile* file;
Tok tok;
Module* imports;
- Symbol* scope;
char* name;
int curr_reg;
- int level;
+ size_t msyms;
+ size_t nsyms;
+ Symbol* syms;
} Parser;
// src/stdlib.c
int consume(Parser* p);
// src/sym.c
-Symbol* symbol_new(Parser* p, char* name, int class, bool export);
+Symbol* symbol_new(Parser* p, size_t scope, char* name, int class, bool export);
Symbol* symbol_addfield(Parser* p, Symbol* parent, char* name, int class, bool export);
-Symbol* symbol_get(Parser* p, int class, char* name);
-void symbol_openscope(Parser* p);
-void symbol_closescope(Parser* p);
+Symbol* symbol_get(Parser* p, char* name, int class);
+size_t symbol_openscope(Parser* p);
+void symbol_closescope(Parser* p, size_t scope);
// src/type_checks.c
void check_int(Parser* p, Item* item);
RULE(qualident)
{
char* name = expect_text(p, IDENT);
- Symbol* sym = symbol_get(p, -1, name);
+ Symbol* sym = symbol_get(p, name, -1);
init_item(item, sym);
// if (accept(p, '.'))
designator(p, item);
if (accept(p, '('))
{
- Symbol* proc = symbol_get(p, SYM_PROC, item->imm.s);
+ Symbol* proc = symbol_get(p, item->imm.s, SYM_PROC);
Symbol* args = proc->desc;
Item arglist = {0};
Item** currarg = &(arglist.next);
if (matches(p, IDENT))
{
char* text = expect_text(p, IDENT);
- Symbol* sym = symbol_get(p, SYM_TYPE, text);
+ Symbol* sym = symbol_get(p, text, SYM_TYPE);
item->type = sym->type;
}
else if (accept(p, ARRAY))
{
name = expect_text(p, IDENT);
export = accept(p, '*');
- sym = symbol_new(p, name, SYM_VAR, export);
+ sym = symbol_new(p, 0, name, SYM_VAR, export);
first = (nsyms == 0 ? sym : first);
sym->global = (p->level <= 1 ? 1 : 0);
nsyms++;
{
name = expect_text(p, IDENT);
export = accept(p, '*');
- sym = symbol_new(p, name, SYM_TYPE, export);
+ sym = symbol_new(p, 0, name, SYM_TYPE, export);
expect(p, '=');
type(p, item);
sym->type = item->type;
{
name = expect_text(p, IDENT);
export = accept(p, '*');
- sym = symbol_new(p, name, SYM_CONST, export);
+ sym = symbol_new(p, 0, name, SYM_CONST, export);
expect(p, '=');
expression(p, item);
expect(p, PROCEDURE);
char* name = expect_text(p, IDENT);
bool export = accept(p, '*');
- Symbol* proc = symbol_new(p, name, SYM_PROC, export);
+ Symbol* proc = symbol_new(p, 0, name, SYM_PROC, export);
/* construct the proc type */
expect(p, '(');
}
codegen_startproc(p, proc);
- symbol_openscope(p);
+ size_t scope = symbol_openscope(p);
/* parse the declarations */
if (accept(p, CONST))
expect(p, END);
codegen_endproc(p);
- symbol_closescope(p);
+ symbol_closescope(p, scope);
}
RULE(import_list)
RULE(module)
{
- symbol_openscope(p);
+ size_t scope = symbol_openscope(p);
expect(p, MODULE);
p->name = expect_text(p, IDENT);
error(p, "expected end of file");
}
- symbol_closescope(p);
+ symbol_closescope(p, scope);
}
static inline char* file_load(char* path)
#include "cerise.h"
+#define NIL_SYMBOL ((size_t)-1)
+
static int sym_matches(Parser* p, int class, char* name, Symbol* sym)
{
-// printf(" %s == %s\n", name, sym->name);
-
if (name && sym->name && !strcmp(sym->name, name))
{
if (class >= 0 && (int)sym->class != class)
return 0;
}
-static Symbol* lookup(Parser* p, int class, char* name)
+static size_t lookup(Parser* p, size_t scope, char* name, int class)
{
- for (Symbol* scope = p->scope; scope; scope = scope->next)
+ size_t ret = NIL_SYMBOL;
+ size_t count = p->nsyms - scope;
+ size_t curr = p->nsyms - 1u;
+
+ for (size_t i = 0; i < count; i++, curr--)
{
-// printf("SCOPE(n: %p):\n", scope->next);
- if (sym_matches(p, class, name, scope))
+ if (sym_matches(p, class, name, &p->syms[curr]))
{
- return scope;
- }
-
- for (Symbol* sym = scope->desc; sym; sym = sym->next)
- {
-// printf(" %s == %s %d\n", name, sym->name, sym_matches(p, class, name, scope));
- if (sym_matches(p, class, name, sym))
- {
- return sym;
- }
+ ret = curr;
+ break;
}
}
- return NULL;
-}
+ return ret;
+}
-Symbol* symbol_new(Parser* p, char* name, int class, bool export)
+Symbol* symbol_new(Parser* p, size_t scope, char* name, int class, bool export)
{
- Symbol* prev = NULL;
- Symbol* curr = p->scope->desc;
+ if (p->nsyms == p->msyms)
+ {
+ p->msyms = (p->msyms ? (p->msyms << 1) : 512u);
+ p->syms = realloc(p->syms, p->msyms * sizeof(Symbol));
+ }
-// printf("\nsymbol_new(%s)\n", name);
- while (curr)
+ /* verify we're not redefining it in the current scope */
+ if (NIL_SYMBOL != lookup(p, scope, name, class))
{
-// printf(" %s <- %s\n", curr->name, name);
- if (curr->name && !strcmp(curr->name, name))
- {
- error(p, "multiple definitions of '%s' in scope", name);
- }
- prev = curr;
- curr = curr->next;
+ error(p, "symbol '%s' is multiply defined in the current scope", name);
}
-// Symbol* existing = lookup(p, SYM_VAR, name);
-// printf("%s : %p\n", name, existing);
-// if ((class == SYM_VAR) && existing && !existing->global)
-// {
-// error(p, "local definition '%s' makes procedure argument inaccessible", name);
-// }
+ /* insert */
+ p->syms[p->nsyms].name = name;
+ p->syms[p->nsyms].class = class;
+ p->syms[p->nsyms].export = export;
+ p->nsyms++;
- Symbol* sym = calloc(1, sizeof(Symbol));
- sym->name = name;
- sym->class = class;
- sym->export = export;
- if (prev)
+ return &(p->syms[p->nsyms-1]);
+}
+
+Symbol* symbol_get(Parser* p, char* name, int class)
+{
+ Symbol* sym = NULL;
+ size_t index = lookup(p, 0, name, class);
+
+ if (NIL_SYMBOL != index)
{
- prev->next = sym;
+ error(p, "unknown symbol '%s'", name);
}
else
{
- p->scope->desc = sym;
+ sym = &(p->syms[index]);
}
+
return sym;
}
+size_t symbol_openscope(Parser* p)
+{
+ return p->nsyms;
+}
+
+void symbol_closescope(Parser* p, size_t scope)
+{
+ p->nsyms = scope;
+}
+
Symbol* symbol_addfield(Parser* p, Symbol* parent, char* name, int class, bool export)
{
Symbol* prev = NULL;
return sym;
}
-Symbol* symbol_get(Parser* p, int class, char* name)
-{
- Symbol* sym = lookup(p, class, name);
- if (!sym)
- {
- error(p, "unknown identifier '%s'", name);
- }
- return sym;
-}
-
-void symbol_openscope(Parser* p)
-{
- Symbol* scope = calloc(1, sizeof(Symbol));
- scope->class = SYM_SCOPE;
- scope->desc = NULL;
- scope->next = p->scope;
- p->scope = scope;
- p->level++;
-}
-
-void symbol_closescope(Parser* p)
-{
- p->scope = p->scope->next;
- p->level--;
-}
-
/* Symbol Table Unit Tests
*****************************************************************************/
#ifdef CERISE_TESTS