git » jacl.git » commit 18c77bf

Apply lexenv fix to flocal; fix Env counter

author Alan Dipert
2020-08-05 04:29:15 UTC
committer Alan Dipert
2020-08-05 04:29:15 UTC
parent 062a0aac6120777ffe9ff863e1d7a330313a12f7

Apply lexenv fix to flocal; fix Env counter

jacl.js +15 -8

diff --git a/jacl.js b/jacl.js
index c9577e6..afe4d32 100644
--- a/jacl.js
+++ b/jacl.js
@@ -1579,6 +1579,7 @@ const parseCall = (env, parent, form) => {
   } else if (env.hasLocalFunction(func)) {
     node.f = makeNode('flocal', {
       env: env.withContext('expr'),
+      envId: env.functionEnvId(func),
       parent: node,
       form: func,
       children: []
@@ -1644,7 +1645,7 @@ class Env {
   static init(env) {
     // sym => envId
     env.locals = new Map();
-    env.localFunctions = new Set();
+    env.localFunctions = new Map();
     // sym => tagbodyName
     env.tags = new Map();
     env.context = 'expr';
@@ -1654,7 +1655,7 @@ class Env {
   clone() {
     const newEnv = new Env(false);
     newEnv.locals = new Map(this.locals);
-    newEnv.localFunctions = new Set(this.localFunctions);
+    newEnv.localFunctions = new Map(this.localFunctions);
     newEnv.tags = new Map(this.tags);
     newEnv.context = this.context;
     newEnv.counter = this.counter;
@@ -1668,9 +1669,12 @@ class Env {
     ]);
     return newEnv;
   }
-  withLocalFunctions(syms) {
+  withLocalFunctions(syms, envId = this.counter()) {
     const newEnv = this.clone();
-    newEnv.localFunctions = new Set([...this.localFunctions, ...syms]);
+    newEnv.localFunctions = new Map([
+      ...this.localFunctions,
+      ...syms.map(sym => [sym, envId])
+    ]);
     return newEnv;
   }
   newId() {
@@ -1690,6 +1694,9 @@ class Env {
   hasLocal(sym) {
     return this.locals.has(sym);
   }
+  functionEnvId(sym) {
+    return this.locals.get(sym);
+  }
   hasLocalFunction(sym) {
     return this.localFunctions.has(sym);
   }
@@ -1703,7 +1710,7 @@ class Env {
   }
 }
 
-const emptyEnv = new Env();
+const emptyEnv = () => new Env(true);
 
 const analyze = (env, parent, form) => {
   if (form instanceof LispSymbol) {
@@ -1870,7 +1877,7 @@ const emitNode = (print, node) => {
       break;
     case 'flocal':
       if (context === 'return') print('return ');
-      print(mungeSym(form, 'flocal'));
+      print(mungeSym(form, `flocal_${node.envId}`));
       if (context !== 'expr') print(';\n');
       break;
     case 'global':
@@ -2363,7 +2370,7 @@ const startRepl = async () => {
   try {
     for await(const obj of replReader) {
       console.log("read", obj);
-      const node = optimize(analyze(emptyEnv, null, obj));
+      const node = optimize(analyze(emptyEnv(), null, obj));
       // console.log(node)
       const sb = new StringBuffer();
       emitNode(sb.append.bind(sb), node);
@@ -2386,7 +2393,7 @@ const fetchLoad = async (src) => {
         rdr = new Reader(ss);
   for await(const obj of rdr) {
     if (obj === EOF) break;
-    const node = optimize(analyze(emptyEnv.withContext('return'), null, obj)),
+    const node = optimize(analyze(emptyEnv().withContext('return'), null, obj)),
           sb = new StringBuffer();
     emitNode(sb.append.bind(sb), node);
     await (new Function(sb.toString())());