author | Alan Dipert
<alan@dipert.org> 2019-11-11 18:11:05 UTC |
committer | Alan Dipert
<alan@dipert.org> 2019-11-11 18:11:05 UTC |
parent | ee2f395a152702415fe82a3d2a56206786fb6b6c |
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)