TEST: Add tests for the reader (!), which I had forgotten.
This also adds a number of accesory functions necessary for rationalizing the record structure of an object in the lex/parse phase into something more lisp-like. There's a metadata issue here that I'm not quite wrapping my head around.
This commit is contained in:
parent
254c1c0f60
commit
1c4975067d
|
@ -0,0 +1,10 @@
|
||||||
|
{car, cdr} = require 'cons-lists/lists'
|
||||||
|
|
||||||
|
symbol = (form) -> (car form)
|
||||||
|
|
||||||
|
module.exports =
|
||||||
|
aSymbol: symbol
|
||||||
|
aValue: (form) -> (car cdr form)
|
||||||
|
isAList: (form) -> (symbol form) == 'list'
|
||||||
|
isARecord: (form) -> (symbol form) == 'record'
|
||||||
|
isAVector: (form) -> (symbol form) == 'vector'
|
|
@ -0,0 +1,51 @@
|
||||||
|
{car, cdr, cons, listp, nilp, nil, list, listToString} = require 'cons-lists/lists'
|
||||||
|
{aSymbol, aValue} = require './astAccessors'
|
||||||
|
|
||||||
|
# RICH_AST -> LISP_AST
|
||||||
|
normalizeForm = (form) ->
|
||||||
|
|
||||||
|
listToRecord1 = (l) ->
|
||||||
|
o = Object.create(null)
|
||||||
|
while(l != nil)
|
||||||
|
o[normalizeForm(car l)] = normalizeForm(car cdr l)
|
||||||
|
l = cdr cdr l
|
||||||
|
null
|
||||||
|
o
|
||||||
|
|
||||||
|
listToVector1 = (l) ->
|
||||||
|
while(l != nil) then p = normalizeForm(car l); l = cdr l; p
|
||||||
|
|
||||||
|
id = (a) -> a
|
||||||
|
|
||||||
|
methods =
|
||||||
|
'list': normalizeForms
|
||||||
|
'vector': (atom) -> listToVector1(atom)
|
||||||
|
'record': (atom) -> listToRecord1(atom)
|
||||||
|
|
||||||
|
# Basic native types. Meh.
|
||||||
|
'symbol': id
|
||||||
|
'number': id
|
||||||
|
'string': (atom) -> atom
|
||||||
|
'nil': (atom) -> nil
|
||||||
|
|
||||||
|
# Values inherited from the VM.
|
||||||
|
'true': (atom) -> true
|
||||||
|
'false': (atom) -> false
|
||||||
|
'null': (atom) -> null
|
||||||
|
'undefined': (atom) -> undefined
|
||||||
|
|
||||||
|
methods[(car form)](car cdr form)
|
||||||
|
|
||||||
|
|
||||||
|
normalizeForms = (forms) ->
|
||||||
|
# Yes, this reifies the expectation than an empty list and 'nil' are
|
||||||
|
# the same.
|
||||||
|
return nil if nilp forms
|
||||||
|
cons(normalizeForm(car forms), normalizeForms(cdr forms))
|
||||||
|
|
||||||
|
module.exports =
|
||||||
|
normalizeForm: normalizeForm
|
||||||
|
normalizeForms: normalizeForms
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
chai = require 'chai'
|
||||||
|
chai.should()
|
||||||
|
expect = chai.expect
|
||||||
|
|
||||||
|
{cons, nil, nilp} = require "cons-lists/lists"
|
||||||
|
{read, readForms} = require '../chapter1/reader'
|
||||||
|
{normalizeForm} = require '../chapter1/astToList'
|
||||||
|
|
||||||
|
describe "Core reader functions", ->
|
||||||
|
samples = [
|
||||||
|
['nil', nil]
|
||||||
|
['0', 0]
|
||||||
|
['1', 1]
|
||||||
|
['500', 500]
|
||||||
|
['0xdeadbeef', 3735928559]
|
||||||
|
['"Foo"', 'Foo']
|
||||||
|
['(1)', cons(1)]
|
||||||
|
['(1 2)', cons(1, (cons 2))]
|
||||||
|
['(1 2 )', cons(1, (cons 2))]
|
||||||
|
['( 1 2 )', cons(1, (cons 2))]
|
||||||
|
['( 1 2 )', cons(1, (cons 2))]
|
||||||
|
['("a" "b")', cons("a", (cons "b"))]
|
||||||
|
['("a" . "b")', cons("a", "b")]
|
||||||
|
['[]', []]
|
||||||
|
['{}', {}]
|
||||||
|
['[1 2 3]', [1, 2, 3]]
|
||||||
|
['{foo "bar"}', {foo: "bar"}]
|
||||||
|
]
|
||||||
|
|
||||||
|
for [t, v] in samples
|
||||||
|
do (t, v) ->
|
||||||
|
it "should interpret #{t} as #{v}", ->
|
||||||
|
res = normalizeForm read t
|
||||||
|
expect(res).to.deep.equal(v)
|
Loading…
Reference in New Issue