git » jacl.git » commit fab91a5

added real tests, even fixed a bug

author Alan Dipert
2019-08-22 06:08:33 UTC
committer Alan Dipert
2019-08-22 06:08:33 UTC
parent cc3687511e8118645700f45a6a49ac639f05906e

added real tests, even fixed a bug

jacl-tests.js +69 -94
jacl.js +6 -4

diff --git a/jacl-tests.js b/jacl-tests.js
index 0897fb6..cc71552 100644
--- a/jacl-tests.js
+++ b/jacl-tests.js
@@ -1,101 +1,76 @@
 QUnit.config.testTimeout = 100; // milliseconds
 
-QUnit.module("reader");
+QUnit.module('Reader');
+
+const makeRead1 = (rdr, it) => {
+  return async str => {
+    const done = it.async();
+    rdr.tokenizer.stream.writeEach(str);
+    const obj = await rdr.read();
+    done();
+    return obj;
+  }
+};
+
+QUnit.test('Integers', async is => {
+	const rdr = Reader.of(Tokenizer.of(new BufferedStream())),
+        read1 = makeRead1(rdr, is);
+
+	is.strictEqual(await read1('123 '), 123, 'single integer');
+	is.strictEqual(await read1('+9912 '), 9912, 'integer with leading +');
+	is.strictEqual(await read1('0 '), 0, 'zero');
+	is.strictEqual(await read1('-32 '), -32, 'negative number');
+	is.strictEqual(await read1('1. '), 1, 'number with trailing dot');
+});
+
+QUnit.test('Symbols', async is => {
+	const rdr = Reader.of(Tokenizer.of(new BufferedStream())),
+        read1 = makeRead1(rdr, is);
+  var sym;
+
+  sym = await read1('defun ');
+  is.strictEqual(sym.name, 'DEFUN', 'simple symbol name');
+  is.strictEqual(sym.packageName, 'COMMON-LISP', 'simple symbol package');
+
+  sym = await read1('|Alan| ');
+  is.strictEqual(sym.name, 'Alan', 'simple symbol name');
+
+  sym = await read1(String.raw`\alan `);
+  is.strictEqual(sym.name, 'aLAN', 'simple symbol with escape');
+
+  Package.makePackage('TEST-PACKAGE');
+
+  sym = await read1('test-package::+ ');
+  is.strictEqual(sym.name, '+', 'exported symbol');
+  is.strictEqual(sym.packageName, 'TEST-PACKAGE', 'exported symbol');
+
+  // TODO external vs internal
+  sym = await read1('|TEST-PACKAGE::some symbol| ');
+  is.strictEqual(sym.name, 'some symbol', 'pipe/qualified symbol');
+  is.strictEqual(sym.packageName, 'TEST-PACKAGE', 'pipe/qualified symbol');
+
+  sym = await read1(':some-lil-kw ');
+  is.strictEqual(sym.name, 'SOME-LIL-KW', 'kw name');
+  is.strictEqual(sym.packageName, 'KEYWORD', 'kw package');
 
-QUnit.test("works", is => {
-  is.ok(true);
 });
 
-//QUnit.test("single integer", is => {
-//  const done = is.async();
-//  new Reader(x => {
-//    is.ok(x instanceof Number);
-//    is.equal(x, 123);
-//    done();
-//  }).readString("123 ");
-//});
-//
-//QUnit.test("single integer with multiple readString", is => {
-//  const done = is.async();
-//  const rdr = new Reader(x => {
-//    is.ok(x instanceof Number);
-//    is.equal(x, 123);
-//    done();
-//  });
-//  rdr.readString("1");
-//  rdr.readString("23");
-//  rdr.readString(" ");
-//});
-//
-//QUnit.test("whitespace is ignored", is => {
-//  const done = is.async();
-//  const rdr = new Reader(x => {
-//    is.ok(x instanceof Number);
-//    is.equal(x, 123);
-//    done();
-//  });
-//  rdr.readString("\n \n\t ");
-//  rdr.readString("123");
-//  rdr.readString("(\t \n ");
-//});
-//
-//QUnit.test("() is nil", is => {
-//  const done = is.async();
-//  new Reader(x => {
-//    is.strictEqual(x, null);
-//    done();
-//  }).readString("()");
-//});
-//
-//QUnit.test("nested lists", is => {
-//  const done = is.async();
-//  new Reader(x => {
-//    is.ok(x instanceof Cons);
-//    is.strictEqual(x.car, null);
-//    is.equal(x.cdr.car.car, 1);
-//    is.strictEqual(x.cdr.cdr.car.car.car, null);
-//    done();
-//  }).readString("(() (1) ((())))");
-//});
-//
-//QUnit.test("Array.from proper lists", is => {
-//  const done = is.async();
-//  new Reader(x => {
-//    is.deepEqual(Array.from(x), [1, 2, 3]);
-//    done();
-//  }).readString("(1 2 3)");
-//});
-//
-//QUnit.test("Array.from pairs", is => {
-//  const done = is.async();
-//  new Reader(x => {
-//    is.deepEqual(Array.from(x), [1, 2]);
-//    done();
-//  }).readString("(1 . 2)");
-//});
-//
-//QUnit.test("unexpected after dot", is => {
-//  const done = is.async();
-//  new Reader(x => {}, err => {
-//    is.ok(err.match(/Unexpected element after dot/));
-//    done();
-//  }).readString("(1 . 2 3)");
-//});
-//
-//QUnit.only("nothing after dot", is => {
-//  const done = is.async();
-//  new Reader(x => {}, err => {
-//    is.ok(err.match(/No element after dot/));
-//    done();
-//  }).readString("(1 . )");
-//});
-//
-//QUnit.test("Array.from compound structure", is => {
-//  const done = is.async();
-//  new Reader(x => {
-//    is.deepEqual(Array.from(x), [[1, 2], [3, 4]]);
-//    done();
-//  }).readString("((1 . 2) (3 . 4))");
-//});
+QUnit.test('Conses', async is => {
+	const rdr = Reader.of(Tokenizer.of(new BufferedStream())),
+        read1 = makeRead1(rdr, is);
+  var cons;
 
+  cons = await read1('()');
+  is.strictEqual(cons, null, 'nil');
 
+  cons = await read1('(1)');
+  is.strictEqual(cons.car, 1, 'car of cons');
+  is.strictEqual(cons.cdr, null, 'cdr of cons');
+
+  cons = await read1('(1 . 2)');
+  is.strictEqual(cons.car, 1, 'car of dot cons');
+  is.strictEqual(cons.cdr, 2, 'cdr of dot cons');
+
+  // TODO dot syntax parse error tests
+
+});
diff --git a/jacl.js b/jacl.js
index c9ba5e8..db77f35 100644
--- a/jacl.js
+++ b/jacl.js
@@ -63,9 +63,9 @@ class LispSymbol {
     this.value = this.stack.pop();
   }
   static intern(packageName, name) {
-    if (readInteger(packageName))
+    if (readInteger(packageName)[0])
       throw new Error(`Symbol package must not be number: '${packageName}'`);
-    if (readInteger(name))
+    if (readInteger(name)[0])
       throw new Error(`Symbol name must not be number: '${name}'`);
     return Package.get(packageName, true).intern(name);
   }
@@ -127,7 +127,8 @@ const PACKAGES = new Map();
 
 class Token extends String {
   interpret() {
-    return readInteger(this) || LispSymbol.fromString(this);
+    const [isInteger, i] = readInteger(this);
+    return isInteger ? i : LispSymbol.fromString(this);
   }
   static is(x, y) {
     return (x instanceof Token) && x.valueOf() === y;
@@ -348,8 +349,9 @@ const readMultiEscaped = async function(stream, token) {
 
 const readInteger = token => {
   if (/^[+-]?[0-9]+\.?$/.test(token)) {
-    return window.parseInt(token);
+    return new Values(true, window.parseInt(token));
   }
+  return new Values(false);
 };
 
 const readSingleEscaped = async function(stream, token) {