daonode: 一个函数式逻辑求解器
我发布了daonode,可通过npm安装,版本库在https://github.com/chaosim/daonode 安装daonode: npm install daonode
Dao是一个函数式逻辑求解器, 具有统一代码和数据,语法和程序,逻辑与函数,编译与执行的能力。 Daonode是原python项目daot用coffescript移植、重写后的升级版本。因为coffeescript可编译到javascript,因此daonode同时也直接就是javascript。 当lisp在javascript遇见prolog,世界将会怎样?
一些例子 (摘录的用coffeescript写的daonode测试代码):
"test builtin function": (test) ->
add = fun(2, (x, y) -> x+y)
test.equal solve(add(1, add(1,1)), 3
"test macro": (test) ->
orpm = macro((x, y) -> orp(x, y))
test.equal solve(orpm(fail, print_(2))), null
"test macro tofun": (test) ->
orpm = macro(2, (x, y) -> orp(x, y))
test.equal solve(orpm(print_(1), print_(2))), null
test.equal solve(tofun(orpm)(print_(1), print_(2))), null
test.equal solve(tofun(orpm)(quote(print_(1)), quote(print_(2)))), null
"test proc,aka online function in dao": (test) ->
a = proc(0, 'a', () ->
i = 0
add(1, 2))
test.equal solve(a()), 3
"test eval_ quote": (test) ->
exp = if_(1, 2, 3)
test.equal solve(quote(exp)), exp
test.equal solve(eval_(quote(exp))), 2
"test lisp style catch/throw ": (test) ->
test.equal solve(catch_(1, 2)), 2
test.equal solve(catch_(1, throw_(1, 2), 3)), 2
test.equal(solve(block('foo', protect(break_('foo', 1), print_(2)))), 1)
test.equal(solve(block('foo', protect(break_('foo', 1), print_(2), print_(3)))), 1)
"test callcc2": (test) ->
a = null
solve(begin(callcc((k) -> a = k), add(1, 2)))
test.equal a(null), 3
"test callfc": (test) ->
a = null
x = vari('x')
x.binding = 5
solve(orp(callfc((k) -> a = k), add(x, 2)))
test.equal a(null), 7
"test quasiquote": (test) ->
test.equal solve(qq(1)), 1
a = add(1, 2)
test.deepEqual solve(qq(a)), a
test.deepEqual solve(qq(uq(a))), 3
test.deepEqual solve(qq(uqs([1,2]))), new UnquoteSliceValue([1,2])
test.deepEqual solve(qq(add(uqs([1,2])))), a
"test block break continue": (test) ->
test.equal solve(block('a', 1)), 1
test.equal solve(block('a', break_('a', 2), 1)), 2
test.equal solve(block('a', block('b', break_('b', 2), 1), 3)), 3
a = vari('a')
test.equal solve(begin(assign(a, 1), block('a', if_(eq(a, 5), break_('a', a)), inc(a), continue_('a')))), 5
"test logic predicate": (test) ->
test.equal(solve(andp(unify(a, 1))), true)
test.equal (solve(andp(unify(a, 1), unify(a, 2))), false)
test.equal solve(orp(andp(unify(a, 1), unify(a, 2)), unify(a, 2))), true
test.equal (solve(orp(findall(orp(print_(1), print_(2))),)
print_(3))), null
test.equal (solve(findall(once(orp(print_(1), (print_(2)))))), null)
"test logic rule": (test) ->
r = rule(2, (x, y) ->
[[x,y], 1, null])
test.equal solve(r(1,1)), 1
"test parser builtins": (test) ->
test.deepEqual (solve(begin(settext('ab'), any(char(_), result, _), eoi, result)), ['a', 'b'])
test.equal (solve(parsetext(begin(some(char(_)), char('c'), eoi), 'abc')), true)
test.deepEqual (solve(begin(parsetext(seplist(char(_), {sep:char(','), times:n, result:result, template:_}), 'a,b,c'), result)), ['a', 'b','c'])
test.deepEqual (solve(begin(parsetext(andp(seplist(char(_), {sep:char(','), times:n, result:result, template:_}), char(','), char('b'), char(','), char('c')),
‘a,b,c’), result)), [‘a’])