1 /*
2 Copyright 2002-2004 John Plevyak, All Rights Reserved
3 */
4 #include "d.h"
5
6 #define INITIAL_SYMHASH_SIZE 3137
7
8 typedef struct D_SymHash {
9 int index;
10 int grow;
11 Vec(D_Sym *) syms;
12 } D_SymHash;
13
14 /*
15 How this works. In a normal symbol table there is simply
16 a stack of scopes representing the scoping structure of
17 the program. Because of speculative parsing, this symbol table
18 also has a tree of all 'updates' representing different
19 views of the state of scoped variables by each speculative
20 parse state. Periodically, when the parse state collapses
21 to a single state (we are nolonger speculating), these changes
22 are can be 'committed' and the changes pushed into the top
23 level hash table.
24
25 All D_Scope's except the top level just have a 'll' of symbols, the
26 top level has a 'hash'.
27
28 'updates' is a list of changes to symbols in other scopes. It is
29 searched to find the current version of a symbol with respect to the
30 speculative parse path represented by D_Scope.
31
32 'up' points to the enclosing scope, it isn't used much.
33
34 'up_updates' is the prior scope in speculative parsing, it is used find
35 the next D_Scope to look in for 'updates' after the current one has been
36 searched.
37
38 'down' and 'down_next' are used to hold enclosing scopes, or in the
39 case of the top level, sibling scopes (created by commmit).
40 */
41
symhash_add(D_SymHash * sh,D_Sym * s)42 static void symhash_add(D_SymHash *sh, D_Sym *s) {
43 uint i, h = s->hash % sh->syms.n, n;
44 D_Sym **v = sh->syms.v, *x;
45 Vec(D_Sym *) vv, tv;
46
47 sh->index++;
48 s->next = v[h];
49 v[h] = s;
50
51 if (sh->index > sh->grow) {
52 vv.v = sh->syms.v;
53 vv.n = sh->syms.n;
54 sh->syms.n = sh->grow;
55 sh->grow = sh->grow * 2 + 1;
56 sh->syms.v = MALLOC(sh->syms.n * sizeof(void *));
57 memset(sh->syms.v, 0, sh->syms.n * sizeof(void *));
58 v = sh->syms.v;
59 n = sh->syms.n;
60 vec_clear(&tv);
61 for (i = 0; i < vv.n; i++) /* use temporary to preserve order */
62 while (vv.v[i]) {
63 x = vv.v[i];
64 vv.v[i] = x->next;
65 vec_add(&tv, x);
66 }
67 while (tv.v[i]) {
68 x = tv.v[i];
69 tv.v[i] = x->next;
70 h = x->hash % n;
71 x->next = v[h];
72 v[h] = x;
73 }
74 FREE(vv.v);
75 }
76 }
77
new_D_SymHash()78 static D_SymHash *new_D_SymHash() {
79 D_SymHash *sh = MALLOC(sizeof(D_SymHash));
80 memset(sh, 0, sizeof(D_SymHash));
81 sh->grow = INITIAL_SYMHASH_SIZE * 2 + 1;
82 sh->syms.n = INITIAL_SYMHASH_SIZE;
83 sh->syms.v = MALLOC(sh->syms.n * sizeof(void *));
84 memset(sh->syms.v, 0, sh->syms.n * sizeof(void *));
85 return sh;
86 }
87
free_D_SymHash(D_SymHash * sh)88 static void free_D_SymHash(D_SymHash *sh) {
89 uint i;
90 D_Sym *sym;
91 for (i = 0; i < sh->syms.n; i++)
92 for (; sh->syms.v[i]; sh->syms.v[i] = sym) {
93 sym = sh->syms.v[i]->next;
94 free_D_Sym(sh->syms.v[i]);
95 }
96 FREE(sh->syms.v);
97 FREE(sh);
98 }
99
new_D_Scope(D_Scope * parent)100 D_Scope *new_D_Scope(D_Scope *parent) {
101 D_Scope *st = MALLOC(sizeof(D_Scope));
102 memset(st, 0, sizeof(D_Scope));
103 if (parent) {
104 st->depth = parent->depth + 1;
105 st->kind = parent->kind;
106 st->search = parent;
107 st->up = parent;
108 st->up_updates = parent;
109 st->down_next = parent->down;
110 parent->down = st;
111 } else
112 st->hash = new_D_SymHash();
113 return st;
114 }
115
equiv_D_Scope(D_Scope * current)116 D_Scope *equiv_D_Scope(D_Scope *current) {
117 D_Scope *s = current, *last = current;
118 D_Sym *sy;
119 if (!s) return s;
120 while (s->depth >= current->depth) {
121 if (s->depth == last->depth) {
122 if (current->up == s->up)
123 last = s;
124 else
125 break;
126 }
127 if (s->ll || s->hash) break;
128 if (s->dynamic) break;
129 sy = s->updates;
130 while (sy) {
131 if (sy->scope->depth <= current->depth) break;
132 sy = sy->next;
133 }
134 if (sy) break;
135 if (!s->up_updates) break;
136 s = s->up_updates;
137 }
138 return last;
139 }
140
141 #if 0
142 D_Scope *
143 equiv_D_Scope(D_Scope *current) {
144 D_Scope *s = current;
145 while (s) {
146 if (s->ll || s->hash)
147 break;
148 if (s->dynamic) /* conservative */
149 break;
150 if (s->updates)
151 break;
152 if (!s->search)
153 break;
154 if (s->search->up != current->up)
155 break;
156 if (s->search->up_updates != current->up_updates)
157 break;
158 s = s->search;
159 }
160 return s;
161 }
162 #endif
163
enter_D_Scope(D_Scope * current,D_Scope * scope)164 D_Scope *enter_D_Scope(D_Scope *current, D_Scope *scope) {
165 D_Scope *st = MALLOC(sizeof(D_Scope)), *parent = scope->up;
166 memset(st, 0, sizeof(D_Scope));
167 st->depth = scope->depth;
168 st->up = parent;
169 st->kind = scope->kind;
170 st->search = scope;
171 #if 0
172 /* clear old updates */
173 {
174 D_Scope *update_scope = current;
175 while (update_scope) {
176 D_Sym *sy = update_scope->updates;
177 while (sy) {
178 if (sy->scope->depth <= current->depth)
179 goto Lfound;
180 sy = sy->next;
181 }
182 update_scope = update_scope->up_updates;
183 }
184 Lfound:
185 st->up_updates = update_scope;
186 }
187 #else
188 st->up_updates = current;
189 #endif
190 st->down_next = current->down;
191 current->down = st;
192 return st;
193 }
194
global_D_Scope(D_Scope * current)195 D_Scope *global_D_Scope(D_Scope *current) {
196 D_Scope *g = current;
197 while (g->up) g = g->search;
198 return enter_D_Scope(current, g);
199 }
200
scope_D_Scope(D_Scope * current,D_Scope * scope)201 D_Scope *scope_D_Scope(D_Scope *current, D_Scope *scope) {
202 D_Scope *st = MALLOC(sizeof(D_Scope)), *parent = current->up;
203 memset(st, 0, sizeof(D_Scope));
204 st->depth = current->depth;
205 st->up = parent;
206 st->kind = current->kind;
207 st->search = current;
208 st->dynamic = scope;
209 st->up_updates = current;
210 st->down_next = current->down;
211 current->down = st;
212 return st;
213 }
214
free_D_Scope(D_Scope * st,int force)215 void free_D_Scope(D_Scope *st, int force) {
216 D_Scope *s;
217 D_Sym *sym;
218 for (; st->down; st->down = s) {
219 s = st->down->down_next;
220 free_D_Scope(st->down, 0);
221 }
222 if (st->owned_by_user && !force) return;
223 if (st->hash)
224 free_D_SymHash(st->hash);
225 else
226 for (; st->ll; st->ll = sym) {
227 sym = st->ll->next;
228 free_D_Sym(st->ll);
229 }
230 for (; st->updates; st->updates = sym) {
231 sym = st->updates->next;
232 free_D_Sym(st->updates);
233 }
234 FREE(st);
235 }
236
commit_ll(D_Scope * st,D_SymHash * sh)237 static void commit_ll(D_Scope *st, D_SymHash *sh) {
238 D_Sym *sym;
239 if (st->search) {
240 commit_ll(st->search, sh);
241 for (; st->ll; st->ll = sym) {
242 sym = st->ll->next;
243 symhash_add(sh, st->ll);
244 }
245 }
246 }
247
248 /* make direct links to the latest update */
commit_update(D_Scope * st,D_SymHash * sh)249 static void commit_update(D_Scope *st, D_SymHash *sh) {
250 uint i;
251 D_Sym *s;
252
253 for (i = 0; i < sh->syms.n; i++)
254 for (s = sh->syms.v[i]; s; s = s->next) s->update_of = current_D_Sym(st, s);
255 }
256
257 /* currently only commit the top level scope */
commit_D_Scope(D_Scope * st)258 D_Scope *commit_D_Scope(D_Scope *st) {
259 D_Scope *x = st;
260 if (st->up) return st;
261 while (x->search) x = x->search;
262 commit_ll(st, x->hash);
263 commit_update(st, x->hash);
264 return x;
265 }
266
new_D_Sym(D_Scope * st,char * name,char * end,int sizeof_D_Sym)267 D_Sym *new_D_Sym(D_Scope *st, char *name, char *end, int sizeof_D_Sym) {
268 uint len = end ? end - name : name ? strlen(name) : 0;
269 D_Sym *s = MALLOC(sizeof_D_Sym);
270 memset(s, 0, sizeof_D_Sym);
271 s->name = name;
272 s->len = len;
273 s->hash = strhashl(name, len);
274 s->scope = st;
275 if (st) {
276 if (st->hash) {
277 symhash_add(st->hash, s);
278 } else {
279 s->next = st->ll;
280 st->ll = s;
281 }
282 }
283 return s;
284 }
285
free_D_Sym(D_Sym * s)286 void free_D_Sym(D_Sym *s) { FREE(s); }
287
current_D_Sym(D_Scope * st,D_Sym * sym)288 D_Sym *current_D_Sym(D_Scope *st, D_Sym *sym) {
289 D_Scope *sc;
290 D_Sym *uu;
291
292 if (sym->update_of) sym = sym->update_of;
293 /* return the last update */
294 for (sc = st; sc; sc = sc->up_updates) {
295 for (uu = sc->updates; uu; uu = uu->next)
296 if (uu->update_of == sym) return uu;
297 }
298 return sym;
299 }
300
find_D_Sym_in_Scope_internal(D_Scope * st,char * name,int len,uint h)301 static D_Sym *find_D_Sym_in_Scope_internal(D_Scope *st, char *name, int len, uint h) {
302 D_Sym *ll;
303 for (; st; st = st->search) {
304 if (st->hash)
305 ll = st->hash->syms.v[h % st->hash->syms.n];
306 else
307 ll = st->ll;
308 while (ll) {
309 if (ll->hash == h && ll->len == len && !strncmp(ll->name, name, len)) return ll;
310 ll = ll->next;
311 }
312 if (st->dynamic)
313 if ((ll = find_D_Sym_in_Scope_internal(st->dynamic, name, len, h))) return ll;
314 if (!st->search || st->search->up != st->up) break;
315 }
316 return NULL;
317 }
318
find_D_Sym_internal(D_Scope * cur,char * name,int len,uint h)319 static D_Sym *find_D_Sym_internal(D_Scope *cur, char *name, int len, uint h) {
320 D_Sym *ll;
321 if (!cur) return NULL;
322 if (cur->hash)
323 ll = cur->hash->syms.v[h % cur->hash->syms.n];
324 else
325 ll = cur->ll;
326 while (ll) {
327 if (ll->hash == h && ll->len == len && !strncmp(ll->name, name, len)) break;
328 ll = ll->next;
329 }
330 if (!ll) {
331 if (cur->dynamic)
332 if ((ll = find_D_Sym_in_Scope_internal(cur->dynamic, name, len, h))) return ll;
333 if (cur->search) return find_D_Sym_internal(cur->search, name, len, h);
334 return ll;
335 }
336 return ll;
337 }
338
find_D_Sym(D_Scope * st,char * name,char * end)339 D_Sym *find_D_Sym(D_Scope *st, char *name, char *end) {
340 uint len = end ? end - name : strlen(name);
341 uint h = strhashl(name, len);
342 D_Sym *s = find_D_Sym_internal(st, name, len, h);
343 if (s) return current_D_Sym(st, s);
344 return NULL;
345 }
346
find_global_D_Sym(D_Scope * st,char * name,char * end)347 D_Sym *find_global_D_Sym(D_Scope *st, char *name, char *end) {
348 D_Sym *s;
349 uint len = end ? end - name : strlen(name);
350 uint h = strhashl(name, len);
351 D_Scope *cur = st;
352 while (cur->up) cur = cur->search;
353 s = find_D_Sym_internal(cur, name, len, h);
354 if (s) return current_D_Sym(st, s);
355 return NULL;
356 }
357
find_D_Sym_in_Scope(D_Scope * st,D_Scope * cur,char * name,char * end)358 D_Sym *find_D_Sym_in_Scope(D_Scope *st, D_Scope *cur, char *name, char *end) {
359 uint len = end ? end - name : strlen(name);
360 uint h = strhashl(name, len);
361 D_Sym *s = find_D_Sym_in_Scope_internal(cur, name, len, h);
362 if (s) return current_D_Sym(st, s);
363 return NULL;
364 }
365
next_D_Sym_in_Scope(D_Scope ** scope,D_Sym ** sym)366 D_Sym *next_D_Sym_in_Scope(D_Scope **scope, D_Sym **sym) {
367 D_Sym *last_sym = *sym, *ll = last_sym;
368 D_Scope *st = *scope;
369 if (ll) {
370 ll = ll->next;
371 if (ll) goto Lreturn;
372 }
373 for (; st; st = st->search) {
374 if (st->hash) {
375 uint i = last_sym ? ((last_sym->hash + 1) % st->hash->syms.n) : 0;
376 if (!last_sym || i) ll = st->hash->syms.v[i];
377 } else {
378 if (!last_sym) ll = st->ll;
379 }
380 last_sym = 0;
381 if (ll) goto Lreturn;
382 if (!st->search || st->search->up != st->up) break;
383 }
384 Lreturn:
385 if (ll) *sym = ll;
386 *scope = st;
387 return ll;
388 }
389
update_additional_D_Sym(D_Scope * st,D_Sym * sym,int sizeof_D_Sym)390 D_Sym *update_additional_D_Sym(D_Scope *st, D_Sym *sym, int sizeof_D_Sym) {
391 D_Sym *s;
392
393 sym = current_D_Sym(st, sym);
394 s = MALLOC(sizeof_D_Sym);
395 memcpy(s, sym, sizeof(D_Sym));
396 if (sym->update_of) sym = sym->update_of;
397 s->update_of = sym;
398 s->next = st->updates;
399 st->updates = s;
400 return s;
401 }
402
update_D_Sym(D_Sym * sym,D_Scope ** pst,int sizeof_D_Sym)403 D_Sym *update_D_Sym(D_Sym *sym, D_Scope **pst, int sizeof_D_Sym) {
404 *pst = enter_D_Scope(*pst, *pst);
405 return update_additional_D_Sym(*pst, sym, sizeof_D_Sym);
406 }
407
print_sym(D_Sym * s)408 void print_sym(D_Sym *s) {
409 char *c = (char *)MALLOC(s->len + 1);
410 if (s->len) memcpy(c, s->name, s->len);
411 c[s->len] = 0;
412 printf("%s, ", c);
413 FREE(c);
414 }
415
print_scope(D_Scope * st)416 void print_scope(D_Scope *st) {
417 printf("SCOPE %p: ", (void *)st);
418 printf(" owned: %d, kind: %d, ", st->owned_by_user, st->kind);
419 if (st->ll) printf(" LL\n");
420 if (st->hash) printf(" HASH\n");
421 if (st->hash) {
422 uint i;
423 for (i = 0; i < st->hash->syms.n; i++)
424 if (st->hash->syms.v[i]) print_sym(st->hash->syms.v[i]);
425 } else {
426 D_Sym *ll = st->ll;
427 while (ll) {
428 print_sym(ll);
429 ll = ll->next;
430 }
431 }
432 printf("\n\n");
433 if (st->dynamic) print_scope(st->dynamic);
434 if (st->search) print_scope(st->search);
435 }
436