test.lua
Branches > main > de7e2b0 > files / test.lua
local LIST = require("org.faddle.lang.list")
local is_list = LIST.is_list
local first = LIST.first
local rest = LIST.rest
local cons = LIST.cons
local count = LIST.count
local list = LIST.list
local apply = LIST.apply
local lisp_print = require("org.faddle.lang.print").print
--- Returns whether 2 objects are structurally equal at the point of calling, even if they are mutable (i.e. tables)
local function eq(x,y)
if x == y then return true end
if is_list(x) and is_list(y) then
if count(x) ~= count(y) then return false end
while count(x) > 0 do
if not eq(first(x), first(y)) then return false end
x = rest(x)
y = rest(y)
end
return true
end
if type(x) == "table" and type(y) == "table" then
if #x ~= #y then return false end
for k, v in pairs(x) do
if not eq(y[k], v) then return false end
end
return true
end
return false
end
local function teq(x, y)
if not eq(x, y) then
error("Test failed! " .. lisp_print(x) .. " and " .. lisp_print(y) .. " are not equal!", 2)
end
end
local function tneq(x, y)
if eq(x, y) then
error("Test failed! " .. lisp_print(x) .. " and " .. lisp_print(y) .. " are equal!", 2)
end
end
---
print("Running tests...")
--- eq
teq({}, {})
teq({1, true}, {1, true})
teq({1, nil}, {1, nil})
teq({nil, 1}, {nil, 1})
tneq(42, 43)
tneq({1}, {"1"})
tneq(0/0, 0/0)
--- Lists
teq(cons(1, nil), cons(1, nil))
tneq(cons(2, nil), cons(1, nil))
tneq(nil, rest(cons(1, nil)))
teq(count(cons(1, nil)), 1)
teq(count(rest(cons(1, nil))), 0)
teq(first(cons({1}, nil)), {1})
teq(list(1, 2, 3), cons(1, cons(2, cons(3, nil))))
teq(list(), LIST.empty)
teq(apply(list, list(1, 2, 3)), list(1, 2,3))
teq(apply(function(x, y, z) return x + y + z end, list(1, 2, 3)), 6)
tneq(list(1, 2, 3, nil), list(1, 2, 3))
tneq(list(1, 2, 3, nil, nil), list(1, 2, 3, nil))
--- Reader
local read = require("org.faddle.lang.read").read
local function read_one(s) return read(s)[1] end
local intern = require("org.faddle.lang.symbol").intern
teq(read(""), {})
teq(read("1 2 3"), {1, 2, 3})
teq(read("1 2 3")[1], read_one("1 2 3"))
teq(read_one(""), nil)
teq(read_one("42"), 42)
teq(read_one("3.14"), 3.14)
teq(read_one("true"), true)
teq(read_one("false"), false)
tneq(read_one("nil"), nil)
teq(read_one("(1)"), cons(1, nil))
teq(read_one("[]"), {})
teq(read_one("{}"), {})
teq(read_one("foo"), intern("foo"))
teq(read_one("()"), list())
-- Symbol with a table/module... Not sure of the syntax.
teq(read_one('"foo"'), "foo")
teq(read_one(":foo"), "foo")
--- Print
teq(lisp_print(42), "42")
teq(lisp_print(nil), ".")
teq(lisp_print(), ".")
teq(lisp_print(1, 2, 3), "1, 2, 3")
teq(lisp_print({}), "{}")
teq(lisp_print({1, 2, 3}), "[1 2 3]")
teq(lisp_print(intern("foo")), "foo")
teq(lisp_print(list()), "()")
--- Eval
local eval_eval = require("org.faddle.lang.eval").eval
local create_env = require("org.faddle.lang.eval").create_env
local env = create_env("user")
local function eval(form)
return eval_eval(form, env)
end
teq(eval(42), 42)
teq(eval(nil), nil)
teq(eval(rest(cons(1, nil))), LIST.empty)
teq(eval(read_one("[1 2 3]")), {1, 2, 3})
-- teq(eval(list(list(intern("fn"), {}, 42))), 42)
teq(eval({}), {})
-- Something to call to make sure lists actually work
teq(eval(list(2, {"a", "b", "c"})), "b")
teq(eval(list("a", {a = 42, b = 43})), 42)
-- do
local plus = intern("plus")
-- teq(eval(list(plus)), 0)
-- teq(eval(list(plus, 1)), 1)
-- teq(eval(list(plus, 1, 2)), 3)
-- teq(eval(list(plus, 1, 2, 3)), 6)
-- end
local function read_eval(s)
return eval(read_one(s))
end
teq(read_eval("1"), 1)
teq(read_eval("[:a :b :c]"), {"a", "b", "c"})
teq(read_eval("()"), list())
teq(read_eval("[]"), {})
teq(read_eval("(quote x)"), intern("x"))
-- teq(read_eval("'x"), intern("x"))
teq(read_eval("(plus)"), 0)
teq(read_eval("(plus 1 2 3)"), 6)
-- local compiler = require("org.faddle.lang.compile")
-- local execute = compiler.execute
-- local compile = compiler.compile
teq(read_eval("(let [x 42] 42)"), 42)
teq(read_eval("(let [x 42] x)"), 42)
teq(read_eval("((fn [] 42))"), 42)
teq(read_eval("(let [f (fn [] 42)] (f))"), 42)
teq(read_eval("(let [x ()] x)"), list())
-- Later
-- teq(read_eval("(let [x 1 y 2] [x y])"), {1, 2})
teq(read_eval("((fn [x] x) :abc)"), "abc")
-- Add more arities?
teq(read_eval("((fn [x y] [x y]) [1 2])"), {1, 2})
teq(read_eval("((fn [x y z] [x y z]) [1 2 3])"), {1, 2, 3})
-- teq(read_eval("((fn []))"), nil)
-- teq(read_eval("((let []))"), nil)
-- teq(read_eval("((fn [] 1 2 3))"), 3)
-- teq(read_eval("((let [] 1 2 3))"), 3)
-- Feels like do could be implemented in terms of let or fn idk.
-- teq(read_eval("(do)"), nil)
-- teq(read_eval("(do 1)"), 1)
-- teq(read_eval("(do 1 2 3)"), 3)
---
print("Yay it worked")