; [q X] -> q(X) ; [q :x] -> q(x) ; [q #(+ 1 2)] -> q(3) (fn clause [c] (match c (where [escape expr] (list? c) (= (tostring escape) :unquote)) expr (where [escape expr] (list? c) (= (tostring escape) :hashfn)) `[:const ,expr] (where [name & params] (sequence? c)) `[:literal ,(tostring name) ,(icollect [_ param (ipairs params)] (clause param))] (where [head & args] (list? c) (sym? head)) (icollect [_ expr (ipairs args) :into [(tostring head)]] (clause expr)) (where c (list? c)) (icollect [_ val (ipairs c)] (clause val)) (where v (sym? c)) `[:var ,(tostring v)] _ `[:const ,c])) (fn clauses [...] (icollect [_ c (ipairs [...]) :into `(values)] (clause c))) (fn defrule [s ...] `(: ,s :defrule ,(clauses ...))) (fn defrules [s ...] (icollect [_ rule (ipairs [...]) :into `(do)] (defrule s (table.unpack rule)))) (fn query [s ...] `(: ,s :query ,(clauses ...))) (fn insert [s ...] `(: ,s :insert ,(clauses ...))) (fn delete [s ...] `(: ,s :delete ,(clauses ...))) (fn update [s ...] `(: ,s :update ,(clauses ...))) (fn specify [s ...] `(: ,s :specify ,(clauses ...))) {: clause : clauses :$ clauses : defrule : defrules : query : insert : delete : update : specify}