-
Notifications
You must be signed in to change notification settings - Fork 3
/
scopes.c
115 lines (91 loc) · 3.27 KB
/
scopes.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wcc.h"
Scope *global_scope;
static List *allocated_scopes;
static List *allocated_tags;
// Initialize the global scope
void init_scopes(void) {
allocated_scopes = new_list(128);
allocated_tags = new_list(32);
global_scope = wcalloc(1, sizeof(Scope));
append_to_list(allocated_scopes, global_scope);
global_scope->symbol_list = new_list(128);
global_scope->symbols = new_strmap();
global_scope->tags = new_strmap();
global_scope->parent = 0;
cur_scope = global_scope;
}
void free_scopes(void) {
for (int i = 0; i < allocated_scopes->length; i++) {
Scope *scope = allocated_scopes->elements[i];
for (int j = 0; j < scope->symbol_list->length; j++) {
Symbol *symbol = scope->symbol_list->elements[j];
List *initializers = symbol->initializers;
if (initializers) {
for (int j = 0; j < initializers->length; j++) {
Initializer *in = initializers->elements[j];
if (in->data) wfree(in->data);
wfree(in);
}
free_list(initializers);
}
wfree(symbol);
}
free_list(scope->symbol_list);
free_strmap(scope->symbols);
free_strmap(scope->tags);
wfree(scope);
}
free_list(allocated_scopes);
for (int i = 0; i < allocated_tags->length; i++) wfree(allocated_tags->elements[i]);
free_list(allocated_tags);
}
// Initialize a local scope and set cur_scope as the parent
void enter_scope(void) {
Scope *scope = wcalloc(1, sizeof(Scope));
append_to_list(allocated_scopes, scope);
scope->symbol_list = new_list(128);
scope->symbols = new_strmap();
scope->tags = new_strmap();
scope->parent = cur_scope;
cur_scope = scope;
}
// Leave the current scope and go back up to the parent scope
void exit_scope(void) {
cur_scope = cur_scope->parent;
if (!cur_scope) panic("Attempt to exit the global scope");
}
// Add a symbol to the current scope
Symbol *new_symbol(char *identifier) {
Symbol *symbol = wcalloc(1, sizeof(Symbol));
symbol->identifier = identifier;
append_to_list(cur_scope->symbol_list, symbol);
strmap_put(cur_scope->symbols, identifier, symbol);
symbol->scope = cur_scope;
return symbol;
}
// Search for a symbol in a scope and recurse to parents if not found.
// Returns zero if not found in any parents
Symbol *lookup_symbol(char *name, Scope *scope, int recurse) {
Symbol *symbol = strmap_get(scope->symbols, name);
if (symbol) return symbol;
else if (recurse && scope->parent) return lookup_symbol(name, scope->parent, recurse);
else return 0;
}
Tag *new_tag(char *identifier) {
Tag *tag = wcalloc(1, sizeof(Tag));
append_to_list(allocated_tags, tag);
tag->identifier = identifier;
strmap_put(cur_scope->tags, identifier, tag);
return tag;
}
// Search for a tag in a scope and recurse to parents if not found.
// Returns zero if not found in any parents
Tag *lookup_tag(char *name, Scope *scope, int recurse) {
Tag *tag = strmap_get(scope->tags, name);
if (tag) return tag;
else if (recurse && scope->parent) return lookup_tag(name, scope->parent, recurse);
else return 0;
}