Use hashmap for block-scope lookup

This commit is contained in:
Rui Ueyama 2020-10-07 11:13:22 +09:00
parent 30520e5a7c
commit 655954e301
1 changed files with 23 additions and 39 deletions

62
parse.c
View File

@ -20,23 +20,12 @@
// Scope for local variables, global variables, typedefs
// or enum constants
typedef struct VarScope VarScope;
struct VarScope {
VarScope *next;
char *name;
typedef struct {
Obj *var;
Type *type_def;
Type *enum_ty;
int enum_val;
};
// Scope for struct, union or enum tags
typedef struct TagScope TagScope;
struct TagScope {
TagScope *next;
char *name;
Type *ty;
};
} VarScope;
// Represents a block scope.
typedef struct Scope Scope;
@ -45,8 +34,8 @@ struct Scope {
// C has two block scopes; one is for variables/typedefs and
// the other is for struct/union/enum tags.
VarScope *vars;
TagScope *tags;
HashMap vars;
HashMap tags;
};
// Variable attributes such as typedef or extern.
@ -183,18 +172,20 @@ static void leave_scope(void) {
// Find a variable by name.
static VarScope *find_var(Token *tok) {
for (Scope *sc = scope; sc; sc = sc->next)
for (VarScope *sc2 = sc->vars; sc2; sc2 = sc2->next)
if (equal(tok, sc2->name))
return sc2;
for (Scope *sc = scope; sc; sc = sc->next) {
VarScope *sc2 = hashmap_get2(&sc->vars, tok->loc, tok->len);
if (sc2)
return sc2;
}
return NULL;
}
static Type *find_tag(Token *tok) {
for (Scope *sc = scope; sc; sc = sc->next)
for (TagScope *sc2 = sc->tags; sc2; sc2 = sc2->next)
if (equal(tok, sc2->name))
return sc2->ty;
for (Scope *sc = scope; sc; sc = sc->next) {
Type *ty = hashmap_get2(&sc->tags, tok->loc, tok->len);
if (ty)
return ty;
}
return NULL;
}
@ -263,9 +254,7 @@ Node *new_cast(Node *expr, Type *ty) {
static VarScope *push_scope(char *name) {
VarScope *sc = calloc(1, sizeof(VarScope));
sc->name = name;
sc->next = scope->vars;
scope->vars = sc;
hashmap_put(&scope->vars, name, sc);
return sc;
}
@ -366,11 +355,7 @@ static Type *find_typedef(Token *tok) {
}
static void push_tag_scope(Token *tok, Type *ty) {
TagScope *sc = calloc(1, sizeof(TagScope));
sc->name = strndup(tok->loc, tok->len);
sc->ty = ty;
sc->next = scope->tags;
scope->tags = sc;
hashmap_put2(&scope->tags, tok->loc, tok->len, ty);
}
// declspec = ("void" | "_Bool" | "char" | "short" | "int" | "long"
@ -2559,11 +2544,10 @@ static Type *struct_union_decl(Token **rest, Token *tok) {
if (tag) {
// If this is a redefinition, overwrite a previous type.
// Otherwise, register the struct type.
for (TagScope *sc = scope->tags; sc; sc = sc->next) {
if (equal(tag, sc->name)) {
*sc->ty = *ty;
return sc->ty;
}
Type *ty2 = hashmap_get2(&scope->tags, tag->loc, tag->len);
if (ty2) {
*ty2 = *ty;
return ty2;
}
push_tag_scope(tag, ty);
@ -3053,9 +3037,9 @@ static Obj *find_func(char *name) {
while (sc->next)
sc = sc->next;
for (VarScope *sc2 = sc->vars; sc2; sc2 = sc2->next)
if (!strcmp(sc2->name, name) && sc2->var && sc2->var->is_function)
return sc2->var;
VarScope *sc2 = hashmap_get(&sc->vars, name);
if (sc2 && sc2->var && sc2->var->is_function)
return sc2->var;
return NULL;
}