summaryrefslogtreecommitdiff
path: root/symbol.c
diff options
context:
space:
mode:
authorglenda <glenda@cirno>2022-09-11 09:17:43 +0000
committerglenda <glenda@cirno>2022-09-11 09:17:43 +0000
commit759d2d541d943fe95138789477fa6faddf6e3e08 (patch)
treefc579523c78d4e073dc058777c9ab6a335087bde /symbol.c
parenta1a9641baeab04b954420122b6fd1c9428a757b5 (diff)
Clone all symbols in scope when spawning a new thread (closures), since the scope may get freed.
Diffstat (limited to 'symbol.c')
-rw-r--r--symbol.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/symbol.c b/symbol.c
index 8e51ba9..626a2db 100644
--- a/symbol.c
+++ b/symbol.c
@@ -319,4 +319,32 @@ void
setsyntaxerr(Datum *)
{
throwerror(nil, ESyntax);
+}
+
+DfnFrame *
+dupscope(DfnFrame *dfn)
+{
+ if(dfn == nil)
+ return nil;
+
+ DfnFrame *new = emallocz(sizeof(DfnFrame), 1);
+ new->symtab = newsymtab();
+
+ /* copy ALL symbols which are in scope, into the new symtab */
+ for(DfnFrame *d = dfn; d != nil; d = d->chain){
+ /* Add all new symbols */
+ for(int i = 0; i < d->symtab->nsyms; i++){
+ Symbol *sym = d->symtab->syms[i];
+ int found = 0;
+ for(int j = 0; j < new->symtab->nsyms && !found; j++)
+ if(runestrcmp(new->symtab->syms[i]->name, d->symtab->syms[j]->name) == 0)
+ found = 1;
+ if(!found){
+ new->symtab->nsyms++;
+ new->symtab->syms = erealloc(new->symtab->syms, sizeof(Symbol *) * new->symtab->nsyms);
+ new->symtab->syms[new->symtab->nsyms-1] = dupsymbol(sym);
+ }
+ }
+ }
+ return new;
} \ No newline at end of file