# Name Resolution
A step prior to [[type-checking]].
## Symbol Table
- Symbol table = a [[hash-table|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|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.
```c
/* 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|AST]]
- For each decl, insert the symbol.
- For every use, lookup the symbol.
```c
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);
}
}
```