git » jacl.git » commit 7dddd20

Constants, bindspecial

author Alan Dipert
2019-10-18 13:20:41 UTC
committer Alan Dipert
2019-10-18 13:20:41 UTC
parent 488651d32f1dbea7a7c35fbf48007345de6bebc9

Constants, bindspecial

jacl.js +32 -54

diff --git a/jacl.js b/jacl.js
index 3dabc5d..2a8f00f 100644
--- a/jacl.js
+++ b/jacl.js
@@ -70,6 +70,7 @@ class LispSymbol {
     this.fvalue = UNDEFINED;
     this.stack = [];
     this.isMacro = false;
+    this.isConstant = false;
   }
   val() {
     if (this.value === UNDEFINED)
@@ -85,6 +86,10 @@ class LispSymbol {
     this.isMacro = true;
     return this;
   }
+  setConstant() {
+    this.isConstant = true;
+    return this;
+  }
   pushBinding(v) {
     this.stack.push(this.value);
     this.value = v;
@@ -95,6 +100,23 @@ class LispSymbol {
   getPackage() {
     return Package.get(this.packageName);
   }
+  static bindSpecial(syms, vals, thunk) {
+    try {
+      for (let i = 0; i < syms.length; i++) {
+        const sym = syms[i];
+        if (sym.isConstant) {
+          throw new Error(`Can't bind constant`);
+        }
+        sym.stack.push(sym.value);
+        sym.value = vals[i];
+      }
+      return thunk();
+    } finally {
+      for (let i = 0; i < syms.length; i++) {
+        syms[i].value = syms[i].stack.pop();
+      }
+    }
+  }
   static intern(packageName, name) {
     if (readInteger(packageName)[0])
       throw new Error(`Symbol package must not be number: '${packageName}'`);
@@ -269,12 +291,12 @@ Package.makePackage('KEYWORD');
 // CL package constants
 // TODO update this, look into constants
 const CLCONSTS = new Map([
-  ['T', 'true'],
-  ['NIL', 'null']
+  ['T', true],
+  ['NIL', null]
 ]);
 
 for (const [k,v] of CLCONSTS) {
-  CLPKG.intern(k);
+  CLPKG.intern(k).setConstant().value = v;
   CLPKG.exportSymbol(k);
 }
 
@@ -292,16 +314,16 @@ for (const [k,v] of CLFUNCS) {
 
 // JS package constants
 const JSCONSTS = new Map([
-  ['+FALSE+', 'false'],
-  ['+NAN+', 'NaN'],
-  ['+NULL+', 'null'],
-  ['+TRUE+', 'true'],
-  ['+UNDEFINED+', 'undefined'],
-  ['+THIS+', 'this']
+  ['+FALSE+', false],
+  ['+NAN+', NaN],
+  ['+NULL+', null],
+  ['+TRUE+', true],
+  ['+UNDEFINED+', undefined],
+  ['+THIS+', this]
 ]);
 
 for (const [k,v] of JSCONSTS) {
-  JSPKG.intern(k);
+  JSPKG.intern(k).setConstant().value = v;
   JSPKG.exportSymbol(k);
 }
 
@@ -694,35 +716,6 @@ for (const s of ['%DOT', '%CALL', '%LAMBDA']) {
   JACLPKG.intern(s);
 }
 
-// Primitive functions related to interop
-JACLPKG.intern('TO-JS').fvalue = x => {
-  if (x instanceof LispString) {
-    return x.toString();
-  } else {
-    throw new Error(`Don't know how to convert ${x} to a JS value`);
-  }
-};
-JACLPKG.exportSymbol('TO-JS');
-
-JACLPKG.intern('.').setMacro().fvalue = function(topic, ...ops) {
-  if (arguments.length < 2) throw new Error(`\. requires at least two arguments`);
-  return ops.reduce((prev, op) => {
-    if (op instanceof LispSymbol) {
-      return Cons.listOf(JACLPKG.intern('%DOT'), prev, op);
-    } else if (op instanceof Cons) {
-      const [method, ...args] = op;
-      return Cons.listOf(
-        JACLPKG.intern('%CALL'),
-        Cons.listOf(JACLPKG.intern('%DOT'), prev, method),
-        ...args
-      );
-    } else {
-      throw new Error(`Invalid \. syntax: ${op}`);
-    }
-  }, topic);
-};
-JACLPKG.exportSymbol('.');
-
 CLPKG.intern('QUOTE').setMacro().fvalue = function(env, form, x) {
   return Cons.listOf(JACLPKG.intern('%QUOTE'), x);
 };
@@ -791,21 +784,6 @@ JACLPKG.intern('QUASIQUOTE').setMacro().fvalue = function(env, form) {
   return expand(form);
 };
 
-const readJsString = async stream => {
-  // TODO make this a real JS string reader
-  const [clStr] = await readString(stream);
-  return new Values(clStr.toString());
-};
-
-JACLPKG.intern('ENABLE-JS-SYNTAX').fvalue = () => {
-  READTABLE
-    .val()
-    .makeDispatchMacroChar('@', true)
-    .setDispatchMacroChar('@', '"', readJsString)
-  return null;
-};
-JACLPKG.exportSymbol('ENABLE-JS-SYNTAX');
-
 const isMacroForm = form => {
   return form instanceof Cons
     && form.car