2018-01-31 22:39:18 +00:00
|
|
|
(def defmacro macro
|
|
|
|
(fn [name & more] (tuple 'def name 'macro (tuple-prepend (tuple-prepend more name) 'fn))))
|
|
|
|
|
|
|
|
(defmacro defn
|
|
|
|
[name & more]
|
|
|
|
(tuple 'def name (tuple-prepend (tuple-prepend more name) 'fn)))
|
|
|
|
|
|
|
|
(defmacro when
|
|
|
|
[cond & body]
|
|
|
|
(tuple 'if cond (tuple-prepend body 'do)))
|
|
|
|
|
2018-02-07 18:19:34 +00:00
|
|
|
(defmacro or [x y] (tuple 'if x true y))
|
|
|
|
(defmacro and [x y] (tuple 'if x y false))
|
|
|
|
|
2018-02-07 05:44:51 +00:00
|
|
|
(def identity (fn [x] x))
|
|
|
|
|
2018-01-31 22:39:18 +00:00
|
|
|
(def seq (do
|
|
|
|
(defn array-seq [x]
|
|
|
|
(def len (length x))
|
|
|
|
(var i 0)
|
|
|
|
{
|
|
|
|
:more (fn [] (< i len))
|
|
|
|
:next (fn []
|
|
|
|
(def ret (get x i))
|
|
|
|
(varset! i (+ i 1))
|
|
|
|
ret)
|
|
|
|
})
|
|
|
|
(def seqs {
|
|
|
|
:array array-seq
|
|
|
|
:tuple array-seq
|
|
|
|
:struct (fn [x] x)})
|
|
|
|
(fn [x]
|
|
|
|
(def makeseq (get seqs (type x)))
|
|
|
|
(if makeseq (makeseq x) (error "expected sequence")))))
|
|
|
|
|
|
|
|
(defn range [top]
|
|
|
|
(var i 0)
|
|
|
|
{
|
|
|
|
:more (fn [] (< i top))
|
|
|
|
:next (fn []
|
|
|
|
(def ret i)
|
|
|
|
(varset! i (+ i 1))
|
|
|
|
ret)
|
|
|
|
})
|
|
|
|
|
|
|
|
(defn doseq [s]
|
|
|
|
(def s (seq s))
|
|
|
|
(def more? (get s :more))
|
|
|
|
(def getnext (get s :next))
|
|
|
|
(while (more?)
|
|
|
|
(getnext)))
|
|
|
|
|
|
|
|
(defn map [f s]
|
|
|
|
(def s (seq s))
|
|
|
|
(def more (get s :more))
|
|
|
|
(def getnext (get s :next))
|
|
|
|
{
|
|
|
|
:more more
|
|
|
|
:next (fn [] (f (getnext)))
|
|
|
|
})
|
|
|
|
|
|
|
|
(defn reduce [f start s]
|
|
|
|
(def s (seq s))
|
|
|
|
(def more? (get s :more))
|
|
|
|
(def getnext (get s :next))
|
|
|
|
(var ret start)
|
|
|
|
(while (more?)
|
|
|
|
(varset! ret (f ret (getnext))))
|
|
|
|
ret)
|
|
|
|
|
|
|
|
(defmacro for [head & body]
|
2018-02-03 22:22:04 +00:00
|
|
|
(def head (ast-unwrap1 head))
|
2018-01-31 22:39:18 +00:00
|
|
|
(def sym (get head 0))
|
|
|
|
(def start (get head 1))
|
|
|
|
(def end (get head 2))
|
|
|
|
(def _inc (get head 3))
|
|
|
|
(def inc (if _inc _inc 1))
|
2018-02-12 16:49:10 +00:00
|
|
|
(def endsym (gensym))
|
2018-01-31 22:39:18 +00:00
|
|
|
(tuple 'do
|
|
|
|
(tuple 'var sym start)
|
2018-02-12 16:49:10 +00:00
|
|
|
(tuple 'def endsym end)
|
|
|
|
(tuple 'while (tuple '< sym endsym)
|
2018-01-31 22:39:18 +00:00
|
|
|
(tuple-prepend body 'do)
|
|
|
|
(tuple 'varset! sym (tuple '+ sym 1))
|
|
|
|
)))
|
2018-02-03 22:22:04 +00:00
|
|
|
|
2018-02-06 15:31:42 +00:00
|
|
|
(defn pairs [x]
|
|
|
|
(var lastkey (next x nil))
|
|
|
|
{
|
|
|
|
:more (fn [] lastkey)
|
|
|
|
:next (fn []
|
|
|
|
(def ret (tuple lastkey (get x lastkey)))
|
|
|
|
(varset! lastkey (next x lastkey))
|
|
|
|
ret)
|
|
|
|
})
|
|
|
|
|
|
|
|
(defn keys [x]
|
|
|
|
(var lastkey (next x nil))
|
|
|
|
{
|
|
|
|
:more (fn [] lastkey)
|
|
|
|
:next (fn []
|
|
|
|
(def ret lastkey)
|
|
|
|
(varset! lastkey (next x lastkey))
|
|
|
|
ret)
|
|
|
|
})
|
|
|
|
|
|
|
|
(defn values [x]
|
|
|
|
(var lastkey (next x nil))
|
|
|
|
{
|
|
|
|
:more (fn [] lastkey)
|
|
|
|
:next (fn []
|
|
|
|
(def ret (get x lastkey))
|
|
|
|
(varset! lastkey (next x lastkey))
|
|
|
|
ret)
|
|
|
|
})
|
2018-02-07 05:44:51 +00:00
|
|
|
|
|
|
|
(defn onerr [t e]
|
|
|
|
(print (string t " error: " e)))
|
|
|
|
|
|
|
|
(var *read* nil)
|
|
|
|
(var *onvalue* identity)
|
|
|
|
|
|
|
|
(def require-loading @{})
|
|
|
|
|
|
|
|
(defn char-stream [getchunk ondone]
|
|
|
|
(fiber (fn [parent]
|
|
|
|
(def buf @"")
|
|
|
|
(var len 1)
|
|
|
|
(while (< 0 len)
|
|
|
|
(buffer-clear buf)
|
|
|
|
(getchunk buf)
|
|
|
|
(varset! len (length buf))
|
|
|
|
(for [i 0 len]
|
|
|
|
(transfer parent (get buf i))))
|
|
|
|
(ondone))))
|
|
|
|
|
|
|
|
(defn val-stream [chars]
|
|
|
|
(fiber (fn [parent]
|
|
|
|
(var up parent)
|
|
|
|
(def me (fiber-current))
|
2018-02-12 16:49:10 +00:00
|
|
|
(def p (parser 1))
|
2018-02-07 05:44:51 +00:00
|
|
|
(while true
|
|
|
|
(def s (parser-status p))
|
|
|
|
(if (= s :full)
|
|
|
|
(varset! up (transfer up (parser-produce p)))
|
|
|
|
(if (= s :error)
|
|
|
|
(onerr "parse" (parser-error p))
|
|
|
|
(parser-byte p (transfer chars me))))))))
|
|
|
|
|
|
|
|
(defn require [path]
|
|
|
|
(when (get require-loading path)
|
|
|
|
(error (string "circular dependency: module " path "is already loading")))
|
|
|
|
(def oldread *read*)
|
|
|
|
(def oldonvalue *onvalue*)
|
|
|
|
(def f (file-open path))
|
2018-02-07 18:19:34 +00:00
|
|
|
(def getter (fn [buf] (file-read f 1024 buf) buf))
|
2018-02-07 05:44:51 +00:00
|
|
|
(def cs (char-stream getter (fn []
|
|
|
|
(put require-loading path nil)
|
|
|
|
(file-close f)
|
|
|
|
(varset! *read* oldread)
|
|
|
|
(varset! *onvalue* oldonvalue)
|
|
|
|
nil)))
|
|
|
|
(def vs (val-stream cs))
|
|
|
|
(varset! *onvalue* identity)
|
|
|
|
(varset! *read* (fn [] (transfer vs (fiber-current))))
|
|
|
|
nil)
|
|
|
|
|
|
|
|
(defn dorepl []
|
|
|
|
(def oldread *read*)
|
|
|
|
(def cs (char-stream (fn [buf]
|
|
|
|
(file-write stdout ">> ")
|
|
|
|
(file-read stdin :line buf))
|
|
|
|
(fn []
|
|
|
|
(varset! *read* oldread)
|
|
|
|
nil)))
|
|
|
|
(def vs (val-stream cs))
|
|
|
|
(varset! *onvalue* (fn [ret]
|
|
|
|
(put _env '_ @{'value ret})
|
|
|
|
(describe ret)))
|
|
|
|
(varset! *read* (fn [] (transfer vs (fiber-current)))))
|
|
|
|
|
2018-02-07 18:19:34 +00:00
|
|
|
(defn dostring [str]
|
|
|
|
(def oldread *read*)
|
|
|
|
(def cs (char-stream (fn [buf]
|
|
|
|
(buffer-push-string buf str)
|
|
|
|
(buffer-push-string buf "\n")
|
|
|
|
buf)
|
|
|
|
(fn []
|
|
|
|
(varset! *read* oldread)
|
|
|
|
nil)))
|
|
|
|
(def vs (val-stream cs))
|
|
|
|
(varset! *onvalue* identity)
|
|
|
|
(varset! *read* (fn [] (transfer vs (fiber-current)))))
|
|
|
|
|
2018-02-07 05:44:51 +00:00
|
|
|
(defn init-loop []
|
|
|
|
(while *read*
|
|
|
|
(def wrapper (fiber (fn []
|
|
|
|
(while *read*
|
|
|
|
(def source (*read*))
|
|
|
|
(def res (compile source _env))
|
|
|
|
(if (= (type res) :function)
|
|
|
|
(*onvalue* (res))
|
|
|
|
(onerr "compile" (get res :error)))))))
|
|
|
|
(def eb (transfer wrapper))
|
|
|
|
(if (= (fiber-status wrapper) :error) (onerr "runtime" eb))))
|
|
|
|
|
|
|
|
(defn init-repl [] (dorepl) (init-loop))
|