From 9d9624632a76f903ef192b8ec6fa7f448dc018fa Mon Sep 17 00:00:00 2001 From: "Elf M. Sternberg" Date: Tue, 30 Jun 2015 08:05:58 -0700 Subject: [PATCH] Fixed test pass. Almost have CPS running. --- .gitignore | 2 +- Makefile | 4 +- chapter1/reader.coffee | 6 +- chapter3/interpreter.coffee | 88 +++++++++++------------ test-reports.xml | 139 ------------------------------------ test/test_chapter3.coffee | 28 ++++++-- 6 files changed, 73 insertions(+), 194 deletions(-) delete mode 100644 test-reports.xml diff --git a/.gitignore b/.gitignore index effebfb..70bdd02 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,4 @@ bin/_mocha bin/mocha bin/coffee bin/cake - +./test-reports.xml diff --git a/Makefile b/Makefile index 71448fa..3ad704b 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,9 @@ node_modules: package.json test: clean node_modules @JUNIT_REPORT_PATH=test-reports.xml JUNIT_REPORT_STACK=1 ./node_modules/.bin/mocha \ --reporter mocha-jenkins-reporter --compilers coffee:coffee-script/register || true -# @node_modules/.bin/mocha + +ltest: node_modules + @node_modules/.bin/mocha --compilers coffee:coffee-script/register clean: rm -f report.xml test-reports.xml diff --git a/chapter1/reader.coffee b/chapter1/reader.coffee index 152938d..e2b349f 100644 --- a/chapter1/reader.coffee +++ b/chapter1/reader.coffee @@ -1,4 +1,6 @@ -{car, cdr, cons, nil, nilp, pairp, vectorToList} = require 'cons-lists/lists' +{car, cdr, cons, nil, nilp, pairp, vectorToList, list} = require 'cons-lists/lists' +{inspect} = require "util" + NEWLINES = ["\n", "\r", "\x0B", "\x0C"] WHITESPACE = [" ", "\t"].concat(NEWLINES) @@ -32,7 +34,7 @@ skipWS = (inStream) -> # (type, value, line, column) -> (node {type, value, line, column)} makeObj = (type, value, line, column) -> - cons(type, cons(value, cons(line, cons(column, nil)))) + list(type, value, line, column) # msg -> (IO -> Node => Error) handleError = (message) -> diff --git a/chapter3/interpreter.coffee b/chapter3/interpreter.coffee index 89c5742..03e4c1e 100644 --- a/chapter3/interpreter.coffee +++ b/chapter3/interpreter.coffee @@ -3,7 +3,6 @@ readline = require "readline" {inspect} = require "util" print = require "../chapter1/print" - env_init = nil env_global = env_init @@ -15,10 +14,10 @@ definitial = (name, value = nil) -> name defprimitive = (name, nativ, arity) -> - definitial name, ((args) -> + definitial name, ((args, callback) -> vmargs = listToVector(args) if (vmargs.length == arity) - nativ.apply null, vmargs + callback nativ.apply null, vmargs else throw "Incorrect arity") @@ -60,43 +59,43 @@ extend = (env, variables, values) -> else nil -make_function = (variables, body, env, continuation) -> - continuation (values, cb) -> eprogn body, (extend env, variables, values), cb +make_function = (variables, body, env, callback) -> + callback (values) -> eprogn body, (extend env, variables, values) -invoke = (fn, args, cb) -> - fn args, cb +invoke = (fn, args, callback) -> + fn args, callback # Takes a list of nodes and calls evaluate on each one, returning the # last one as the value of the total expression. In this example, we # are hard-coding what ought to be a macro, namely the threading # macros, "->" -eprogn = (exps, env, cb) -> +eprogn = (exps, env, callback) -> if (pairp exps) if pairp (cdr exps) evaluate (car exps), env, (next) -> - eprogn (cdr exps), env, cb + eprogn (cdr exps), env, callback else - evaluate (car exps), env, cb + evaluate (car exps), env, callback else - cb nil + callback nil -evlis = (exps, env, cb) -> +evlis = (exps, env, callback) -> if (pairp exps) - evaluate (car exps), env, (stepv) -> - evlis (cdr exps), env, (next) -> - cb cons stepv, next + evlis (cdr exps), env, (rest) -> + evaluate (car exps), env, (calc) -> + callback cons calc, rest else - cb(nil) + callback nil -lookup = (id, env, continuation) -> +lookup = (id, env) -> if (pairp env) if (caar env) == id - continuation (cdar env) + cdar env else - lookup id, (cdr env), continuation + lookup id, (cdr env) else - continuation nil + nil update = (id, env, value, callback) -> if (pairp env) @@ -106,7 +105,7 @@ update = (id, env, value, callback) -> else update id, (cdr env), value, callback else - nil + callback nil # This really ought to be the only place where the AST meets the # interpreter core. I can't help but think that this design precludes @@ -126,37 +125,38 @@ astSymbolsToLispSymbols = (node) -> cadddr = metacadr('cadddr') -evaluate = (e, env, continuation) -> +evaluate = (e, env, callback) -> [type, exp] = [(ntype e), (nvalu e)] - if type in ["number", "string", "boolean", "vector"] - return continuation exp - else if type == "symbol" - return lookup exp, env, continuation + if type == "symbol" + return callback lookup exp, env + else if type in ["number", "string", "boolean", "vector"] + return callback exp else if type == "list" head = car exp if (ntype head) == 'symbol' - switch (nvalu head) - when "quote" then continuation cdr exp + return switch (nvalu head) + when "quote" + callback cdr exp when "if" - evaluate (cadr exp), env, (result) -> - unless result == the_false_value - evaluate (caddr exp), env, continuation - else - evaluate (cadddr exp), env, continuation - when "begin" then eprogn (cdr exp), env, continuation - when "set!" then evaluate (caddr exp), env, (value) -> - update (nvalu cadr exp), env, value, continuation + evaluate (cadr exp), env, (res) -> + w = unless res == the_false_value then caddr else cadddr + evaluate (w exp), env, callback + when "begin" + eprogn (cdr exp), env, callback + when "set!" + evaluate (caddr exp), env, (newvalue) -> + update (nvalu cadr exp), env, newvalue, callback when "lambda" - make_function (astSymbolsToLispSymbols cadr exp), (cddr exp), env, continuation + make_function (astSymbolsToLispSymbols cadr exp), (cddr exp), env, callback else - evlis (cdr exp), env, (args) -> - evaluate (car exp), env, (fn) -> - invoke fn, args, continuation + evaluate (car exp), env, (fn) -> + evlis (cdr exp), env, (args) -> + invoke fn, args, callback else - evlis (cdr exp), env, (args) -> - evaluate (car exp), env, (fn) -> - invoke fn, args, continuation + evaluate (car exp), env, (fn) -> + evlis (cdr exp), env, (args) -> + invoke fn, args, callback else throw new Error("Can't handle a #{type}") -module.exports = (c, continuation) -> evaluate c, env_global, continuation +module.exports = (c, cb) -> evaluate c, env_global, cb diff --git a/test-reports.xml b/test-reports.xml deleted file mode 100644 index ff13886..0000000 --- a/test-reports.xml +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - - - - - - - - - at nvalu (chapter1/interpreter.coffee:11:19) - at handler (chapter1/interpreter.coffee:118:11) - at astSymbolsToLispSymbols (chapter1/interpreter.coffee:119:3) - at evaluate (chapter1/interpreter.coffee:145:43) - at evaluate (chapter1/interpreter.coffee:144:57) - at eprogn (chapter1/interpreter.coffee:77:7) - at evaluate (chapter1/interpreter.coffee:143:27) - at module.exports (chapter1/interpreter.coffee:152:25) - at Context.<anonymous> (test/test_chapter1.coffee:38:12) - - - - - - - - at nvalu (chapter1/interpreter.coffee:11:19) - at handler (chapter1/interpreter.coffee:118:11) - at astSymbolsToLispSymbols (chapter1/interpreter.coffee:119:3) - at evaluate (chapter1/interpreter.coffee:145:43) - at evaluate (chapter1/interpreter.coffee:148:15) - at eprogn (chapter1/interpreter.coffee:80:7) - at evaluate (chapter1/interpreter.coffee:143:27) - at module.exports (chapter1/interpreter.coffee:152:25) - at Context.<anonymous> (test/test_chapter1.coffee:47:12) - - - - - - - - at Context.<anonymous> (test/test_chapter3.coffee:11:56) - - - - - - - at evaluate (chapter3/interpreter.coffee:160:15) - at eprogn (chapter3/interpreter.coffee:77:7) - at evaluate (chapter3/interpreter.coffee:146:27) - at module.exports (chapter3/interpreter.coffee:162:39) - at Context.<anonymous> (test/test_chapter3.coffee:24:12) - - - - - - at lookup (chapter3/interpreter.coffee:95:7) - at lookup (chapter3/interpreter.coffee:97:7) - at lookup (chapter3/interpreter.coffee:97:7) - at lookup (chapter3/interpreter.coffee:97:7) - at lookup (chapter3/interpreter.coffee:97:7) - at lookup (chapter3/interpreter.coffee:97:7) - at lookup (chapter3/interpreter.coffee:97:7) - at lookup (chapter3/interpreter.coffee:97:7) - at lookup (chapter3/interpreter.coffee:97:7) - at lookup (chapter3/interpreter.coffee:97:7) - at evaluate (chapter3/interpreter.coffee:134:12) - at eprogn (chapter3/interpreter.coffee:80:7) - at chapter3/interpreter.coffee:78:9 - at update (chapter3/interpreter.coffee:105:7) - at update (chapter3/interpreter.coffee:107:7) - at update (chapter3/interpreter.coffee:107:7) - at update (chapter3/interpreter.coffee:107:7) - at update (chapter3/interpreter.coffee:107:7) - at update (chapter3/interpreter.coffee:107:7) - at update (chapter3/interpreter.coffee:107:7) - at update (chapter3/interpreter.coffee:107:7) - at update (chapter3/interpreter.coffee:107:7) - at update (chapter3/interpreter.coffee:107:7) - at chapter3/interpreter.coffee:148:11 - at evaluate (chapter3/interpreter.coffee:132:12) - at evaluate (chapter3/interpreter.coffee:147:26) - at eprogn (chapter3/interpreter.coffee:77:7) - at evaluate (chapter3/interpreter.coffee:146:27) - at module.exports (chapter3/interpreter.coffee:162:39) - at Context.<anonymous> (test/test_chapter3.coffee:27:12) - - - - - - at nvalu (chapter3/interpreter.coffee:11:19) - at handler (chapter3/interpreter.coffee:120:11) - at astSymbolsToLispSymbols (chapter3/interpreter.coffee:121:3) - at evaluate (chapter3/interpreter.coffee:150:26) - at evaluate (chapter3/interpreter.coffee:147:26) - at eprogn (chapter3/interpreter.coffee:77:7) - at evaluate (chapter3/interpreter.coffee:146:27) - at module.exports (chapter3/interpreter.coffee:162:39) - at Context.<anonymous> (test/test_chapter3.coffee:30:12) - - - - - - -Index: string -=================================================================== ---- string -+++ string - - at Context.<anonymous> (test/test_chapter3.coffee:36:108) - - - - - - at nvalu (chapter3/interpreter.coffee:11:19) - at handler (chapter3/interpreter.coffee:120:11) - at astSymbolsToLispSymbols (chapter3/interpreter.coffee:121:3) - at evaluate (chapter3/interpreter.coffee:150:26) - at chapter3/interpreter.coffee:157:9 - at evlis (chapter3/interpreter.coffee:90:5) - at evaluate (chapter3/interpreter.coffee:156:7) - at eprogn (chapter3/interpreter.coffee:80:7) - at evaluate (chapter3/interpreter.coffee:146:27) - at module.exports (chapter3/interpreter.coffee:162:39) - at Context.<anonymous> (test/test_chapter3.coffee:39:12) - - - - - diff --git a/test/test_chapter3.coffee b/test/test_chapter3.coffee index 8db777d..97f85d1 100644 --- a/test/test_chapter3.coffee +++ b/test/test_chapter3.coffee @@ -2,17 +2,31 @@ chai = require 'chai' chai.should() expect = chai.expect -lisp = require '../chapter3/interpreter' +{cons} = require "cons-lists/lists" +olisp = require '../chapter3/interpreter' {read, readForms} = require '../chapter1/reader' +the_false_value = (cons "false", "boolean") + +lisp = (ast) -> + ret = undefined + olisp ast, (i) -> ret = i + return ret + + describe "Core interpreter #3", -> - it "Should handle if statements", -> + it "Should handle true statements", -> expect(lisp read "(begin (if (lt 0 1) #t #f))").to.equal(true) - expect(lisp read "(begin (if (lt 1 0) #t #f))").to.equal(false) - expect(lisp read '(begin (if (lt 1 0) "y" "n"))').to.equal("n") + it "Should handle false statements", -> + expect(lisp read "(begin (if (lt 1 0) #t #f))").to.deep.equal(the_false_value) + it "Should handle return strings", -> expect(lisp read '(begin (if (lt 0 1) "y" "n"))').to.equal("y") - expect(lisp read '(begin (if (eq "y" "y") "y" "n"))').to.equal("y") - expect(lisp read '(begin (if (eq "y" "x") "y" "n"))').to.equal("n") + it "Should handle return strings when false", -> + expect(lisp read '(begin (if (lt 1 0) "y" "n"))').to.equal("n") + it "Should handle equivalent objects that are not intrinsically truthy", -> + expect(lisp read '(begin (if (eq? "y" "y") "y" "n"))').to.equal("y") + it "Should handle inequivalent objects that are not intrinsically truthy", -> + expect(lisp read '(begin (if (eq? "y" "x") "y" "n"))').to.equal("n") it "Should handle basic arithmetic", -> expect(lisp read '(begin (+ 5 5))').to.equal(10) @@ -21,7 +35,7 @@ describe "Core interpreter #3", -> expect(lisp read '(begin (- 9 5))').to.equal(4) it "Should handle some algebra", -> - expect(lisp read '(begin (* (+ 5 5) (* 2 3))').to.equal(60) + expect(lisp read '(begin (* (+ 5 5) (* 2 3)))').to.equal(60) it "Should handle a basic setting", -> expect(lisp read '(begin (set! fact 4) fact)').to.equal(4)