git » jacl.git » commit b04a1d9

Fix %tagbody/%go analysis, added withTags to Env class

author Alan Dipert
2019-11-10 14:05:44 UTC
committer Alan Dipert
2019-11-10 14:05:44 UTC
parent 2d12963505dba09d76533c08e8255e12aa8de63b

Fix %tagbody/%go analysis, added withTags to Env class

jacl.js +16 -5

diff --git a/jacl.js b/jacl.js
index 2a84251..c058183 100644
--- a/jacl.js
+++ b/jacl.js
@@ -1179,26 +1179,27 @@ const analyzeSpecials = new Map([
     // after the tag
 
     // First pass: gather tags and statements, don't analyze
-    const newEnv = env.withContext('statement');
     const tags = new Map();
     let currentTag = null, currentStmts = [];
     for (const x of tagsStmts) {
       if (isTag(x)) {
         tags.set(currentTag, currentStmts);
-        if (currentTag !== null) newEnv.tagbodyTags.add(currentTag);
         currentTag = asTagName(x);
         currentStmts = [];
       } else {
         currentStmts.push(x);
       }
     }
-    if (currentTag !== null) newEnv.tagbodyTags.add(currentTag);
     tags.set(currentTag, currentStmts);
 
     const node = makeNode('tagbody', { env: env, parent: parent, form: form });
 
+    const childEnv = env
+      .withContext('statement')
+      .withTags(Array.from(tags.keys()).filter(x => x !== null));
+
     // Second pass: analyze statements
-    const ana = analyze.bind(null, newEnv, node);
+    const ana = analyze.bind(null, childEnv, node);
     for (const [tag, stmts] of tags) tags.set(tag, stmts.map(ana));
     node.prelude = tags.get(null);
     tags.delete(null);
@@ -1210,7 +1211,7 @@ const analyzeSpecials = new Map([
     const [, tag] = form;
     if (!isTag(tag)) throw new Error(`Invalid GO tag`);
     const tagName = asTagName(tag);
-    if (!env.tagbodyTags.has(tagName))
+    if (!env.hasTag(tagName))
       throw new Error(`Non-existent GO tag: ${tagName}`);
     return makeNode('go', {
       env: env,
@@ -1296,12 +1297,14 @@ class Env {
   }
   static init(env) {
     env.locals = new Set();
+    env.tags = new Set();
     env.context = 'sval';
     return env;
   }
   clone() {
     const newEnv = new Env(false);
     newEnv.locals = new Set(this.locals);
+    newEnv.tags = new Set(this.tags);
     newEnv.context = this.context;
     return newEnv;
   }
@@ -1310,9 +1313,17 @@ class Env {
     newEnv.locals = new Set([...this.locals, ...syms]);
     return newEnv;
   }
+  withTags(syms) {
+    const newEnv = this.clone();
+    newEnv.tags = new Set([...this.tags, ...syms]);
+    return newEnv;
+  }
   hasLocal(sym) {
     return this.locals.has(sym);
   }
+  hasTag(sym) {
+    return this.tags.has(sym);
+  }
   withContext(context) {
     const newEnv = this.clone();
     newEnv.context = context;