2 Copyright 2002-2003 John Plevyak, All Rights Reserved
6 #define INITIAL_SYMHASH_SIZE 3137
8 typedef struct D_SymHash
{
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
25 All D_Scope's except the top level just have a 'll' of symbols, the
26 top level has a 'hash'.
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.
32 'up' points to the enclosing scope, it isn't used much.
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
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).
44 symhash_add(D_SymHash
*sh
, D_Sym
*s
) {
45 uint i
, h
= s
->hash
% sh
->syms
.n
, n
;
46 D_Sym
**v
= sh
->syms
.v
, *x
;
53 if (sh
->index
> sh
->grow
) {
56 sh
->syms
.n
= sh
->grow
;
57 sh
->grow
= sh
->grow
* 2 + 1;
58 sh
->syms
.v
= MALLOC(sh
->syms
.n
* sizeof(void *));
59 memset(sh
->syms
.v
, 0, sh
->syms
.n
* sizeof(void *));
63 for (i
= 0; i
< vv
.n
; i
++)
64 /* use temporary to preserve order */
83 D_SymHash
*sh
= MALLOC(sizeof(D_SymHash
));
84 memset(sh
, 0, sizeof(D_SymHash
));
85 sh
->grow
= INITIAL_SYMHASH_SIZE
* 2 + 1;
86 sh
->syms
.n
= INITIAL_SYMHASH_SIZE
;
87 sh
->syms
.v
= MALLOC(sh
->syms
.n
* sizeof(void *));
88 memset(sh
->syms
.v
, 0, sh
->syms
.n
* sizeof(void *));
93 free_D_SymHash(D_SymHash
*sh
) {
96 for (i
= 0; i
< sh
->syms
.n
; i
++)
97 for (; sh
->syms
.v
[i
]; sh
->syms
.v
[i
] = sym
) {
98 sym
= sh
->syms
.v
[i
]->next
;
99 free_D_Sym(sh
->syms
.v
[i
]);
106 new_D_Scope(D_Scope
*parent
) {
107 D_Scope
*st
= MALLOC(sizeof(D_Scope
));
108 memset(st
, 0, sizeof(D_Scope
));
110 st
->kind
= parent
->kind
;
113 st
->up_updates
= parent
;
114 st
->down_next
= parent
->down
;
117 st
->hash
= new_D_SymHash();
122 enter_D_Scope(D_Scope
*current
, D_Scope
*scope
) {
123 D_Scope
*st
= MALLOC(sizeof(D_Scope
)), *parent
= scope
->up
;
124 memset(st
, 0, sizeof(D_Scope
));
126 st
->kind
= scope
->kind
;
128 st
->up_updates
= current
;
129 st
->down_next
= current
->down
;
135 free_D_Scope(D_Scope
*st
, int force
) {
138 for (; st
->down
; st
->down
= s
) {
139 s
= st
->down
->down_next
;
140 free_D_Scope(st
->down
, 0);
142 if (st
->owned_by_user
&& !force
)
145 free_D_SymHash(st
->hash
);
147 for (; st
->ll
; st
->ll
= sym
) {
151 for (; st
->updates
; st
->updates
= sym
) {
152 sym
= st
->updates
->next
;
153 free_D_Sym(st
->updates
);
159 commit_ll(D_Scope
*st
, D_SymHash
*sh
) {
162 commit_ll(st
->search
, sh
);
163 for (; st
->ll
; st
->ll
= sym
) {
165 symhash_add(sh
, st
->ll
);
170 /* make direct links to the latest update */
172 commit_update(D_Scope
*st
, D_SymHash
*sh
) {
176 for (i
= 0; i
< sh
->syms
.n
; i
++)
177 for (s
= sh
->syms
.v
[i
]; s
; s
= s
->next
)
178 s
->update_of
= current_D_Sym(st
, s
);
181 /* currently only commit the top level scope */
183 commit_D_Scope(D_Scope
*st
) {
187 while (x
->search
) x
= x
->search
;
188 commit_ll(st
, x
->hash
);
189 commit_update(st
, x
->hash
);
194 new_D_Sym(D_Scope
*st
, char *name
, char *end
, int sizeof_D_Sym
) {
195 int len
= end
- name
;
196 D_Sym
*s
= MALLOC(sizeof_D_Sym
);
197 memset(s
, 0, sizeof_D_Sym
);
200 s
->hash
= strhashl(name
, len
);
202 symhash_add(st
->hash
, s
);
211 free_D_Sym(D_Sym
*s
) {
216 current_D_Sym(D_Scope
*st
, D_Sym
*sym
) {
220 if (sym
->update_of
) sym
= sym
->update_of
;
221 /* return the last update */
222 for (sc
= st
; sc
; sc
= sc
->up_updates
) {
223 for (uu
= sc
->updates
; uu
; uu
= uu
->next
)
224 if (uu
->update_of
== sym
)
231 find_sym_internal(D_Scope
*top
, D_Scope
*cur
, char *name
, int len
, uint h
) {
237 ll
= cur
->hash
->syms
.v
[h
% cur
->hash
->syms
.n
];
241 if (ll
->hash
== h
&& ll
->len
== len
&& !strncmp(ll
->name
, name
, len
))
247 return find_sym_internal(top
, cur
->search
, name
, len
, h
);
250 return current_D_Sym(top
, ll
);
254 find_D_Sym(D_Scope
*st
, char *name
, char *end
) {
255 int len
= end
- name
;
256 uint h
= strhashl(name
, len
);
257 return find_sym_internal(st
, st
, name
, len
, h
);
261 find_D_Sym_in_Scope(D_Scope
*st
, char *name
, char *end
) {
263 int len
= end
- name
;
264 uint h
= strhashl(name
, len
);
265 for (;st
; st
= st
->search
) {
267 ll
= st
->hash
->syms
.v
[h
% st
->hash
->syms
.n
];
271 if (ll
->hash
== h
&& ll
->len
== len
&& !strncmp(ll
->name
, name
, len
))
275 if (!st
->search
|| st
->search
->up
!= st
->up
)
282 update_D_Sym(D_Scope
*st
, D_Sym
*sym
, int sizeof_D_Sym
) {
285 sym
= current_D_Sym(st
, sym
);
286 s
= MALLOC(sizeof_D_Sym
);
287 memcpy(s
, sym
, sizeof(D_Sym
));
288 if (sym
->update_of
) sym
= sym
->update_of
;
290 s
->next
= st
->updates
;
296 print_sym(D_Sym
*s
) {
297 char *c
= (char*)MALLOC(s
->len
+ 1);
298 memcpy(c
, s
->name
, s
->len
);
305 print_scope(D_Scope
*st
) {
306 printf("SCOPE %X: ", (long)st
);
307 printf(" owned: %d, kind: %d, ", st
->owned_by_user
, st
->kind
);
308 if (st
->ll
) printf(" LL\n");
309 if (st
->hash
) printf(" HASH\n");
312 for (i
= 0; i
< st
->hash
->syms
.n
; i
++)
313 if (st
->hash
->syms
.v
[i
])
314 print_sym(st
->hash
->syms
.v
[i
]);
323 if (st
->search
) print_scope(st
->search
);