[chore] Lint-picked versions that pass all unit tests.

This commit is contained in:
Elf M. Sternberg 2015-07-08 15:14:05 -07:00
parent 111ad5d8dc
commit abf6c4ec50
9 changed files with 80 additions and 68 deletions

View File

@ -1,7 +1,11 @@
{listToString, listToVector, pairp, cons, car, cdr, caar, cddr, cdar, cadr, caadr, cadar, caddr, nilp, nil, setcdr, metacadr} = require "cons-lists/lists"
{listToString, listToVector, pairp, cons, car, cdr, caar, cddr, cdar,
cadr, caadr, cadar, caddr, nilp, nil, setcdr, metacadr} = require "cons-lists/lists"
readline = require "readline"
{inspect} = require "util"
print = require "../chapter1/print"
class LispInterpreterError extends Error
name: 'LispInterpreterError'
constructor: (@message) ->
env_init = nil
env_global = env_init
@ -19,7 +23,7 @@ defprimitive = (name, nativ, arity) ->
if (vmargs.length == arity)
callback nativ.apply null, vmargs
else
throw "Incorrect arity")
throw new LispInterpreterError "Incorrect arity")
the_false_value = (cons "false", "boolean")
@ -50,9 +54,9 @@ extend = (env, variables, values) ->
(cons (cons (car variables), (car values)),
(extend env, (cdr variables), (cdr values)))
else
throw "Too few values"
throw new LispInterpreterError "Too few values"
else if (nilp variables)
if (nilp values) then env else throw "Too many values"
if (nilp values) then env else throw new LispInterpreterError "Too many values"
else
if (symbolp variables)
(cons (cons variables, values), env)
@ -87,7 +91,7 @@ evlis = (exps, env, callback) ->
callback cons calc, rest
else
callback nil
lookup = (id, env) ->
if (pairp env)
if (caar env) == id
@ -113,12 +117,12 @@ update = (id, env, value, callback) ->
astSymbolsToLispSymbols = (node) ->
return nil if nilp node
throw "Not a list of variable names" if not (ntype(node) is 'list')
throw (new LispInterpreterError "Not a list of variable names") if not (ntype(node) is 'list')
handler = (node) ->
return nil if nilp node
cons (nvalu car node), (handler cdr node)
handler(nvalu node)
# Takes an AST node and evaluates it and its contents. A node may be
# ("list" (... contents ...)) or ("number" 42) or ("symbol" x), etc.
@ -157,6 +161,6 @@ evaluate = (e, env, callback) ->
evlis (cdr exp), env, (args) ->
invoke fn, args, callback
else
throw new Error("Can't handle a #{type}")
throw new LispInterpreterError ("Can't handle a #{type}")
module.exports = (c, cb) -> evaluate c, env_global, cb

View File

@ -1,4 +1,5 @@
{car, cdr, cons, listp, nilp, nil, list, pairp, listToString} = require 'cons-lists/lists'
{car, cdr, cons, listp, nilp, nil,
list, pairp, listToString} = require 'cons-lists/lists'
{aSymbol, aValue, astObject} = require './astAccessors'
# RICH_AST -> LISP_AST
@ -12,13 +13,13 @@ normalizeForm = (form) ->
l = cdr cdr l
null
o
listToVector1 = (l) ->
while(l != nil) then p = normalizeForm(car l); l = cdr l; p
id = (a) -> a
methods =
methods =
'list': normalizeForms
'vector': (atom) -> listToVector1(atom)
'record': (atom) -> listToRecord1(atom)
@ -28,7 +29,7 @@ normalizeForm = (form) ->
'number': id
'string': (atom) -> atom
'nil': (atom) -> nil
# Values inherited from the VM.
'true': (atom) -> true
'false': (atom) -> false
@ -47,10 +48,8 @@ normalizeForms = (forms) ->
if (astObject forms)
return normalizeForm(forms)
cons(normalizeForm(car forms), normalizeForms(cdr forms))
module.exports =
normalizeForm: normalizeForm
normalizeForms: normalizeForms

View File

@ -1,8 +1,11 @@
{listToString, listToVector, pairp, cons, car, cdr, caar, cddr, cdar, cadr, caadr, cadar, caddr, nilp, nil, setcdr, metacadr} = require "cons-lists/lists"
{listToString, listToVector, pairp, cons, car, cdr, caar, cddr,
cdar, cadr, caadr, cadar, caddr, nilp, nil, setcdr, metacadr} = require "cons-lists/lists"
readline = require "readline"
{inspect} = require "util"
print = require "./print"
class LispInterpreterError extends Error
name: 'LispInterpreterError'
constructor: (@message) ->
env_init = nil
env_global = env_init
@ -20,7 +23,7 @@ defprimitive = (name, nativ, arity) ->
if (vmargs.length == arity)
nativ.apply null, vmargs
else
throw "Incorrect arity")
throw (new LispInterpreterError "Incorrect arity"))
the_false_value = (cons "false", "boolean")
@ -51,9 +54,9 @@ extend = (env, variables, values) ->
(cons (cons (car variables), (car values)),
(extend env, (cdr variables), (cdr values)))
else
throw "Too few values"
throw new LispInterpreterError "Too few values"
else if (nilp variables)
if (nilp values) then env else throw "Too many values"
if (nilp values) then env else throw new LispInterpreterError "Too many values"
else
if (symbolp variables)
(cons (cons variables, values), env)
@ -112,7 +115,7 @@ update = (id, env, value) ->
astSymbolsToLispSymbols = (node) ->
return nil if nilp node
throw "Not a list of variable names" if not (ntype(node) is 'list')
throw (new LispInterpreterError "Not a list of variable names") if not (ntype(node) is 'list')
handler = (node) ->
return nil if nilp node
cons (nvalu car node), (handler cdr node)
@ -147,6 +150,6 @@ evaluate = (e, env) ->
else
invoke (evaluate (car exp), env), (evlis (cdr exp), env)
else
throw new Error("Can't handle a #{type}")
throw new LispInterpreterError "Can't handle a #{type}"
module.exports = (c) -> evaluate c, env_global

View File

@ -5,8 +5,8 @@
NEWLINES = ["\n", "\r", "\x0B", "\x0C"]
WHITESPACE = [" ", "\t"].concat(NEWLINES)
EOF = new (class)
EOO = new (class)
EOF = new (class Eof)()
EOO = new (class Eoo)()
class Source
constructor: (@inStream) ->
@ -29,7 +29,7 @@ class Source
done: -> @index > @max
# IO -> IO
skipWS = (inStream) ->
skipWS = (inStream) ->
while inStream.peek() in WHITESPACE then inStream.next()
# (type, value, line, column) -> (node {type, value, line, column)}
@ -88,7 +88,7 @@ readSymbol = (inStream, tableKeys) ->
if number?
return makeObj 'number', number, line, column
makeObj 'symbol', symbol, line, column
# (Delim, TypeName) -> IO -> (IO, node) | Error
makeReadPair = (delim, type) ->
@ -143,7 +143,7 @@ readMacros =
'[': makeReadPair ']', 'vector'
']': handleError "Closing bracket encountered"
'{': makeReadPair('}', 'record', (res) ->
res.length % 2 == 0 and true or mkerr "record key without value")
res.length % 2 == 0 and true or mkerr "record key without value")
'}': handleError "Closing curly without corresponding opening."
"`": prefixReader 'back-quote'
"'": prefixReader 'quote'
@ -188,19 +188,19 @@ read = (inStream, eofErrorP = false, eofError = EOF, recursiveP = false, inReadM
# IO -> (Form* | Error)
readForms = (inStream) ->
inStream = if inStream instanceof Source then inStream else new Source inStream
return nil if inStream.done()
inStream = if inStream instanceof Source then inStream else new Source inStream
return nil if inStream.done()
# IO -> (FORM*, IO) | Error
[line, column] = inStream.position()
readEach = (inStream) ->
obj = read inStream, true, null, false
return nil if (nilp obj)
return obj if (car obj) == 'error'
cons obj, readEach inStream
# IO -> (FORM*, IO) | Error
[line, column] = inStream.position()
readEach = (inStream) ->
obj = read inStream, true, null, false
return nil if (nilp obj)
return obj if (car obj) == 'error'
cons obj, readEach inStream
obj = readEach inStream
if (car obj) == 'error' then obj else makeObj "list", obj, line, column
obj = readEach inStream
if (car obj) == 'error' then obj else makeObj "list", obj, line, column
exports.read = read
exports.readForms = readForms

View File

@ -1,7 +1,13 @@
{listToString, listToVector, pairp, cons, car, cdr, caar, cddr, cdar, cadr, caadr, cadar, caddr, nilp, nil, setcdr, metacadr, setcar} = require "cons-lists/lists"
{listToString, listToVector, pairp, cons, car, cdr, caar, cddr, cdar,
cadr, caadr, cadar, caddr, nilp, nil, setcdr,
metacadr, setcar} = require "cons-lists/lists"
readline = require "readline"
{inspect} = require "util"
class LispInterpreterError extends Error
name: 'LispInterpreterError'
constructor: (@message) ->
ntype = (node) -> car node
nvalu = (node) -> cadr node
@ -12,33 +18,33 @@ class Value
# Represents the base class of a continuation. Calls to invoke resume
# the contained continuation, which is typecast to one of the specific
# continuation needs of conditional, sequence, etc...
class Continuation
constructor: (@k) ->
invoke: (v, env, kont) ->
if nilp cdr v
@k.resume (car v)
else
throw "Continuations expect one argument"
throw new LispInterpreterError "Continuations expect one argument"
# Abstract class representing the environment
class Environment
lookup: -> throw "Nonspecific invocation"
update: -> throw "Nonspecific invocation"
lookup: -> throw new LispInterpreterError "Nonspecific invocation"
update: -> throw new LispInterpreterError "Nonspecific invocation"
# Base of the environment stack. If you hit this, your variable was
# never found for lookup/update. Note that at this time in the
# class, you have not
# class, you have not
class NullEnv extends Environment
lookup: (e) -> throw "Unknown variable #{e}"
update: (e) -> throw "Unknown variable #{e}"
lookup: (e) -> throw new LispInterpreterError "Unknown variable #{e}"
update: (e) -> throw new LispInterpreterError "Unknown variable #{e}"
# This appears to be an easy and vaguely abstract handle to the
# environment. The book is not clear on the distinction between the
# FullEnv and the VariableEnv.
class FullEnv extends Environment
constructor: (@others, @name) ->
@_type = "FullEnv"
@ -116,7 +122,7 @@ evaluateVariable = (name, env, kont) ->
# called after an update has been performed.
evaluateSet = (name, exp, env, kont) ->
evaluate exp, env, (new SetCont(kont, name, env))
evaluate exp, env, (new SetCont(kont, name, env))
class SetCont extends Continuation
constructor: (@k, @name, @env) ->
@ -149,7 +155,7 @@ extend = (env, names, values) ->
if (pairp names) and (pairp values)
new VariableEnv (extend env, (cdr names), (cdr values)), (car names), (car values)
else if (nilp names)
if (nilp values) then env else throw "Arity mismatch"
if (nilp values) then env else throw new LispInterpreterError "Arity mismatch"
else
new VariableEnv env, names, values
@ -195,7 +201,7 @@ class GatherCont extends Continuation
@k.resume (cons @v, v)
# Upon resumption, invoke the function.
class ApplyCont extends Continuation
constructor: (@k, @fn, @env) ->
@_type = "ApplyCont"
@ -205,13 +211,13 @@ class ApplyCont extends Continuation
# A special continuation that represents what we want the interpreter
# to do when it's done processing.
class BottomCont extends Continuation
constructor: (@k, @f) ->
@_type = "BottomCont"
resume: (v) ->
@f(v)
class Primitive extends Value
constructor: (@name, @nativ) ->
@_type = "Primitive"
@ -220,7 +226,7 @@ class Primitive extends Value
astSymbolsToLispSymbols = (node) ->
return nil if nilp node
throw "Not a list of variable names" if not (ntype(node) is 'list')
throw (new LispInterpreterError "Not a list of variable names") if not (ntype(node) is 'list')
handler = (node) ->
return nil if nilp node
cons (nvalu car node), (handler cdr node)
@ -245,7 +251,7 @@ evaluate = (e, env, kont) ->
else
evaluateApplication (car exp), (cdr exp), env, kont
else
throw new Error("Can't handle a '#{type}'")
throw new LispInterpreterError("Can't handle a '#{type}'")
env_init = new NullEnv()
@ -259,7 +265,7 @@ defprimitive = (name, nativ, arity) ->
if (vmargs.length == arity)
kont.resume (nativ.apply null, vmargs)
else
throw "Incorrect arity"
throw new LispInterpreterError "Incorrect arity"
defpredicate = (name, nativ, arity) ->
defprimitive name, ((a, b) -> if nativ.call(null, a, b) then true else the_false_value), arity
@ -294,7 +300,7 @@ definitial "call/cc", new Primitive "call/cc", (values, env, kont) ->
if nilp cdr values
(car values).invoke (cons kont), env, kont
else
throw ["Incorrect arity for call/cc", [r, k]]
throw new LispInterpreterError "Incorrect arity for call/cc"
definitial "apply", new Primitive "apply", (values, env, kont) ->
if pairp cdr values
@ -309,5 +315,5 @@ definitial "list", new Primitive "list", (values, env, kont) ->
interpreter = (ast, kont) ->
evaluate ast, env_init, new BottomCont null, kont
module.exports = interpreter

View File

@ -1,6 +1,6 @@
chai = require 'chai'
chai.should()
expect = chai.expect
expect = chai.expect
{cons} = require "cons-lists/lists"
olisp = require '../chapter-lambda-1/interpreter'
@ -27,7 +27,7 @@ describe "Core interpreter #3", ->
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)
expect(lisp read '(begin (* 5 5))').to.equal(25)
@ -51,4 +51,4 @@ describe "Core interpreter #3", ->
it "Should handle an IIFE", ->
expect(lisp read '(begin ((lambda () (+ 5 5))))').to.equal(10)

View File

@ -1,6 +1,6 @@
chai = require 'chai'
chai.should()
expect = chai.expect
expect = chai.expect
{cons} = require "cons-lists/lists"
lisp = require '../chapter1/interpreter'
@ -21,7 +21,7 @@ describe "Core interpreter #1", ->
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)
expect(lisp read '(begin (* 5 5))').to.equal(25)
@ -45,4 +45,4 @@ describe "Core interpreter #1", ->
it "Should handle an IIFE", ->
expect(lisp read '(begin ((lambda () (+ 5 5))))').to.equal(10)

View File

@ -1,6 +1,6 @@
chai = require 'chai'
chai.should()
expect = chai.expect
expect = chai.expect
{cons} = require "cons-lists/lists"
olisp = require '../chapter3/interpreter'
@ -27,7 +27,7 @@ describe "Core interpreter #3", ->
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)
expect(lisp read '(begin (* 5 5))').to.equal(25)
@ -51,5 +51,5 @@ describe "Core interpreter #3", ->
it "Should handle an IIFE", ->
expect(lisp read '(begin ((lambda () (+ 5 5))))').to.equal(10)

View File

@ -1,6 +1,6 @@
chai = require 'chai'
chai.should()
expect = chai.expect
expect = chai.expect
{cons, nil, nilp} = require "cons-lists/lists"
{read, readForms} = require '../chapter1/reader'