Name Resolution
A step prior to type-checking.
Symbol Table
- Symbol table = a hash table containing the info about the symbols.
- For each declaration, create a symbol and enter into table.
- For each expression node in the AST, look up the symbol table to ensure the type consistency.
- Multiple hash tables (called “scopes”) in a stack are needed to keep track of the current scope.
- Look for symbols in each scope in the stack.
/* symbol.h */
typedef enum {
SYMBOL_LOCAL;
SYMBOL_PARAM;
SYMBOL_GLOBAL;
} kind;
struct symbol {
symbol_t kind;
struct type *type;
char *name;
int which; // local 0, local 1, param 0, param 1, etc...
}
struct symbol *symbol_create( ... );
void symbol_print(struct symbol * s);Name Resolution
- Walk the AST
- For each decl, insert the symbol.
- For every use, lookup the symbol.
void decl_resolve(struct decl *d) {
struct symbol s = symbol_create(SYMBOL_GLOBAL, d->type);
scope_bind(d->name, s);
d->symbol = s;
if(d->code) {
scope_enter();
param_list_resolve(d->type->params);
stmt_resolve(d->code);
scope_exit();
}
decl_resolve(d->next);
}
void expr_resolve(struct expr *e) {
if(e->kind == EXPR_IDENT) {
e->symbol = scope_lookup(e->name);
} else {
expr_resolve(e->left);
expr_resolve(e->right);
}
}