diff --git a/examples/lazyseqs.dst b/examples/lazyseqs.dst index fa621802..f90090dd 100644 --- a/examples/lazyseqs.dst +++ b/examples/lazyseqs.dst @@ -17,7 +17,7 @@ (defmacro delay "Macro for lazy evaluation" - [x] (tuple mem0 (tuple 'fn [] x))) + [& forms] (tuple mem0 (apply tuple (array-concat ['fn []] forms)))) # Use tuples instead of structs to save memory (def HEAD :private 0) @@ -32,6 +32,11 @@ [h t] (delay (tuple h t))) +(defn cons1 + "Create a new sequence cons by prepending a value to the original sequence." + [h t] + (tuple h t)) + (defn empty? "Check if a sequence is empty." [s] @@ -47,17 +52,24 @@ [s] (get (s) TAIL)) -(defn range +(defn range2 "Return a sequence of integers [start, end)." [start end] (if (< start end) (cons start (range (+ 1 start) end)) empty-seq)) +(defn range + "Return a sequence of integers [0, end)." + [end] + (range2 0 end)) + (defn map "Return a sequence that is the result of apply f to each value in s." [f s] - (if (s) (cons (f (head s)) (map f (tail s))) empty-seq)) + (delay + (def x (s)) + (if x (tuple (f (get x HEAD)) (map f (get x TAIL)))))) (defn realize "Force evaluation of a lazy sequence." @@ -71,7 +83,9 @@ (defn drop "Ignores the first n values of the sequence and returns the rest." [n s] - (if (s) (if (zero? n) s (drop (- n 1) (tail s))) empty-seq)) + (delay + (def x (s)) + (if (s) (if (zero? n) s (drop (- n 1) (tail s))) empty-seq)) (defn take "Returns at most the first n values of s." @@ -80,3 +94,8 @@ (cons (head s) (take (- n 1) (tail s))) empty-seq)) +(defn take-while + "Returns a sequence of values until the predicate is false." + [pred s] + (delay (if (s) ))) + diff --git a/src/compiler/boot.dst b/src/compiler/boot.dst index febe1572..d053e791 100644 --- a/src/compiler/boot.dst +++ b/src/compiler/boot.dst @@ -1,11 +1,6 @@ # Bootstrap the dst environment # Copyright 2018 (C) Calvin Rose -# Capture the current env -(var *env* - "A var that points to the current environment." - _env) - (def defn :macro "Define a function" (fn [name & more] @@ -82,16 +77,20 @@ are matched. If there are no matches, return nil." (aux (+ i 2)))))) (aux 0)) -(defn doc - "Shows documentation for the given symbol." - [sym] - (def x (get *env* sym)) +(defn doc* + [env sym] + (def x (get env sym)) (if (not x) (print "symbol " x " not found.") (do (def d (get x 'doc)) (print "\n" (if d d "no documentation found.") "\n")))) +(defmacro doc + "Shows documentation for the given symbol." + [sym] + (tuple doc* '_env sym)) + (defmacro select "Select the body that equals the dispatch value. When pairs has an odd number of arguments, the last is the default expression. @@ -141,13 +140,13 @@ If no match is found, returns nil" (def iters { :array array-iter :tuple array-iter - :struct (fn [x] x)}) + :struct identity}) (fn [x] (def makei (get iters (type x))) (if makei (makei x) (error "expected sequence"))))) -(defn range [top] - (var i 0) +(defn range2 [bottom top] + (var i bottom) { :more (fn [] (< i top)) :next (fn [] @@ -156,6 +155,8 @@ If no match is found, returns nil" ret) }) +(defn range [top] (range2 0 top)) + (defn doiter [itr] (def {:more more :next next} (iter itr)) (while (more) (next))) @@ -337,6 +338,7 @@ If no match is found, returns nil" (defn make-env [parent] (def parent (if parent parent _env)) (def newenv (setproto @{} parent)) + (put newenv '_env @{'value newenv}) newenv) # Remove the reference to the default _env @@ -401,10 +403,7 @@ onvalue." (if (= (fiber-status f) :error) (onerr "runtime" res) (onvalue res))) - (def oldenv *env*) - (varset! *env* env) (foreach (val-stream chunks onerr) doone) - (varset! *env* oldenv) env))) (def require (do @@ -426,14 +425,17 @@ onvalue." (put loading path nil) newenv))))) -(defn import [path & args] - (def env (require path)) +(defn import* [env path & args] + (def newenv (require path)) (def { :prefix prefix } (apply table args)) - (foreach (pairs env) (fn [[k v]] + (foreach (pairs newenv) (fn [[k v]] (when (not (get v :private)) - (put *env* (symbol (if prefix prefix "") k) v))))) + (put env (symbol (if prefix prefix "") k) v))))) + +(defmacro import [path & args] + (apply tuple (array-concat [import* '_env path] args))) (defn repl [getchunk] (def newenv (make-env))