git » jacl.git » commit 10a9129

Basic static tagbody working

author Alan Dipert
2019-11-11 18:11:05 UTC
committer Alan Dipert
2019-11-11 18:11:05 UTC
parent ee2f395a152702415fe82a3d2a56206786fb6b6c

Basic static tagbody working

jacl.js +26 -9
notes.txt +22 -0

diff --git a/jacl.js b/jacl.js
index 6336f65..988d906 100644
--- a/jacl.js
+++ b/jacl.js
@@ -311,6 +311,12 @@ Package.makePackage('KEYWORD');
 // Temporary definitions for testing
 JACLPKG.intern('!LOG').fvalue = console.log;
 JACLPKG.intern('!ARRAY').fvalue = (...xs) => [...xs];
+JACLPKG.intern('!<').fvalue = (x, y) => x < y ? true : null;
+JACLPKG.intern('!>').fvalue = (x, y) => x > y ? true : null;
+JACLPKG.intern('!+').fvalue = (x, y) => x+y;
+JACLPKG.intern('!-').fvalue = (x, y) => x-y;
+JACLPKG.intern('!EQL').fvalue = (x, y) => x === y ? true : null;
+JACLPKG.intern('!*').fvalue = (x, y) => x*y;
 
 // CL package constants
 // TODO update this, look into constants
@@ -757,7 +763,8 @@ const SPECIAL_FORMS = [
   '%DOT',
   '%LAMBDA',
   '%SET',
-  '%TAGBODY'
+  '%TAGBODY',
+  '%GO'
 ];
 
 for (const s of SPECIAL_FORMS) JACLPKG.intern(s);
@@ -1418,6 +1425,10 @@ const emitKeyCheck = (print, lambdaList) => {
   }
 };
 
+const formatTag = x => typeof x === 'number' 
+  ? x.toString() 
+  : `'${escapeSingle(x)}'`;
+
 const emitNode = (print, node) => {
   const { op, env: { context }, parent, form } = node;
   switch (op) {
@@ -1663,17 +1674,17 @@ const emitNode = (print, node) => {
       break;
     case 'if':
       if (context === 'sval' || context === 'return') {
-        print('(truth(');
+        print('(');
         emitNode(print, node.testNode);
-        print(')?')
+        print('!==null)?')
         emitNode(print, node.thenNode);
         print(':');
         emitNode(print, node.elseNode);
         print(')');
       } else {
-        print('if(truth(');
+        print('if(');
         emitNode(print, node.testNode);
-        print('))\n\t');
+        print('!==null)\n\t');
         emitNode(print, node.thenNode);
         print('else\n\t');
         emitNode(print, node.elseNode);
@@ -1689,9 +1700,6 @@ const emitNode = (print, node) => {
           emitNode(print, stmt);
         }
         if (node.tags.size) {
-          const formatTag = x => typeof x === 'number' 
-            ? x.toString() 
-            : `'${escapeSingle(x)}'`;
           const firstTag = formatTag(node.tags.entries().next().value[0]);
           print(`tagbody_${node.id}_to=${firstTag};\n`);
           print(`tagbody_${node.id}:while(true){\n`);
@@ -1708,7 +1716,16 @@ const emitNode = (print, node) => {
       //if (context !== 'sval') print(';\n');
       break;
     } case 'go': {
-      throw new Error('TODO emit go');
+      if (context === 'return') print('return ');
+      if (context === 'sval' || context === 'return') {
+        throw new Error('TODO go IIFE');
+      } else {
+        print('{\n');
+        print(`tagbody_${node.tagbodyId}_to=${formatTag(node.tagName)};\n`);
+        print(`continue tagbody_${node.tagbodyId};\n`);
+        print('}\n');
+      }
+      break;
     } default:
       throw new Error(`Unknown op: ${op}`);
   }
diff --git a/notes.txt b/notes.txt
index c8c0051..c176372 100644
--- a/notes.txt
+++ b/notes.txt
@@ -42,3 +42,25 @@ window
 
 ((dot (global |window|) |alert|)
  (to-js "hello, world!"))
+
+;; factorial
+(%lambda (n &aux (prod 1))
+  (%tagbody
+    t0
+    (%if (!eql n 0) (%go done) nil)
+    (%set prod (!* prod n))
+    (%set n (!- n 1))
+    (%go t0)
+    done)
+  prod)
+
+(%let ((x 0))
+  (%tagbody
+    t0
+    (%if (> x 10) (%go t1) nil)
+    (!log x)
+    (%set x (+ x 1))
+    (%go t0)
+    t1
+    (!log "done"))
+  0)