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