From 5738f6c8b1833255455e31bd7df73caca7f2b239 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Thu, 15 Mar 2018 17:19:31 -0400 Subject: [PATCH] Rename seq abstraction to iterator. Add random functions. --- examples/3sum.dst | 6 +-- examples/frequencies.dst | 7 ++-- src/compiler/boot.dst | 72 ++++++++++++++++++------------------ src/core/math.c | 32 ++++++++++------ src/include/dst/dstcorelib.h | 2 + 5 files changed, 64 insertions(+), 55 deletions(-) diff --git a/examples/3sum.dst b/examples/3sum.dst index 2cc75a6f..9c57cac7 100644 --- a/examples/3sum.dst +++ b/examples/3sum.dst @@ -2,7 +2,7 @@ "Solve the 3SUM problem O(n^2) time." [s] (def tab @{}) - (def solutions []) + (def solutions @{}) (def len (length s)) (for [k 0 len] (put tab (get s k) k)) @@ -10,5 +10,5 @@ (for [j 0 len] (def k (get tab (- 0 (get s i) (get s j)))) (when (and k (not= k i) (not= k j) (not= i j)) - (array-push solutions [i j k])))) - solutions) + (put solutions {i true j true k true} true)))) + (iter2array (map (fn [x] (iter2array (keys x))) (keys solutions)))) diff --git a/examples/frequencies.dst b/examples/frequencies.dst index c4444ef2..2f62dfdc 100644 --- a/examples/frequencies.dst +++ b/examples/frequencies.dst @@ -4,8 +4,7 @@ "Get the number of occurences of each value in a sequence." [s] (let [freqs @{} - fop (fn [x] - (let [n (get freqs x)] - (put freqs x (if n (+ 1 n) 1)))) - _ (domap fop s)] + _ (foreach s (fn [x] + (let [n (get freqs x)] + (put freqs x (if n (+ 1 n) 1)))))] freqs)) diff --git a/src/compiler/boot.dst b/src/compiler/boot.dst index 43f47c31..67e96b9e 100644 --- a/src/compiler/boot.dst +++ b/src/compiler/boot.dst @@ -39,6 +39,14 @@ (defn one? [x] (== x 1)) (defn inc [x] (+ x 1)) (defn dec [x] (- x 1)) +(def atomic? (do + (def non-atomic-types { + :array true + :tuple true + :table true + :struct true + }) + (fn [x] (not (get non-atomic-types (type x)))))) (defmacro comment "Ignores the body of the comment." @@ -109,8 +117,8 @@ If no match is found, returns nil" "A function that returns its first argument." [x] x) -(def seq (do - (defn array-seq [x] +(def iter (do + (defn array-iter [x] (def len (length x)) (var i 0) { @@ -120,22 +128,13 @@ If no match is found, returns nil" (varset! i (+ i 1)) ret) }) - (defn fiber-seq [x] - { - :more (fn [] (or - (= (fiber-status x) :pending) - (= (fiber-status x) :new))) - :next (fn [] - (resume x)) - }) - (def seqs { - :array array-seq - :tuple array-seq - :fiber fiber-seq + (def iters { + :array array-iter + :tuple array-iter :struct (fn [x] x)}) (fn [x] - (def makeseq (get seqs (type x))) - (if makeseq (makeseq x) (error "expected sequence"))))) + (def makei (get iters (type x))) + (if makei (makei x) (error "expected sequence"))))) (defn range [top] (var i 0) @@ -147,34 +146,34 @@ If no match is found, returns nil" ret) }) -(defn doseq [s] - (def {:more more :next next} (seq s)) +(defn doiter [itr] + (def {:more more :next next} (iter itr)) (while (more) (next))) -(defn domap [f s] - (def {:more more :next next} (seq s)) +(defn foreach [itr f] + (def {:more more :next next} (iter itr)) (while (more) (f (next)))) -(defn seq-array [s] - (def {:more more :next next} (seq s)) +(defn iter2array [itr] + (def {:more more :next next} (iter itr)) (def a []) (while (more) (array-push a (next))) a) -(defn map [f s] - (def {:more more :next next} (seq s)) +(defn map [f itr] + (def {:more more :next next} (iter itr)) {:more more :next (fn [] (f (next)))}) -(defn reduce [f start s] - (def s (seq s)) - (def {:more more :next next} s) +(defn reduce [f start itr] + (def itr (iter itr)) + (def {:more more :next next} itr) (if (more) - (reduce f (f start (next)) s) + (reduce f (f start (next)) itr) start)) -(defn filter [pred s] - (def s (seq s)) - (def {:more more :next next} s) +(defn filter [pred itr] + (def itr (iter itr)) + (def {:more more :next next} itr) (var alive true) (var temp nil) (var isnew true) @@ -322,13 +321,15 @@ If no match is found, returns nil" (defn unique [s] (def tab @{}) - (domap (fn [x] (put tab x true)) s) + (foreach s (fn [x] (put tab x true))) (keys tab)) (defn make-env [parent] (def parent (if parent parent _env)) (def newenv (setproto @{} parent)) newenv) + +# Remove the reference to the default _env (put _env '_env nil) (def run-context @@ -392,7 +393,7 @@ onvalue." (onvalue res))) (def oldenv *env*) (varset! *env* env) - (doseq (map doone (val-stream chunks onerr))) + (foreach (val-stream chunks onerr) doone) (varset! *env* oldenv) env))) @@ -420,10 +421,9 @@ onvalue." (def { :prefix prefix } (apply table args)) - (defn one [[k v]] + (foreach (pairs env) (fn [[k v]] (when (not (get v :private)) - (put *env* (symbol (if prefix prefix "") k) v))) - (doseq (map one (pairs env)))) + (put *env* (symbol (if prefix prefix "") k) v))))) (defn repl [getchunk] (def newenv (make-env)) diff --git a/src/core/math.c b/src/core/math.c index e1f21130..65628ef4 100644 --- a/src/core/math.c +++ b/src/core/math.c @@ -23,16 +23,26 @@ #include #include +/* Get a random number */ +int dst_rand(DstArgs args) { + double r = (rand() % RAND_MAX) / ((double) RAND_MAX); + return dst_return(args, dst_wrap_real(r)); +} + +/* Seed the random number generator */ +int dst_srand(DstArgs args) { + if (args.n != 1 || !dst_checktype(args.v[0], DST_INTEGER)) + return dst_throw(args, "expected integer"); + srand((unsigned) dst_unwrap_integer(args.v[0])); + return 0; +} + /* Convert a number to an integer */ int dst_int(DstArgs args) { - if (args.n != 1) { - *args.ret = dst_cstringv("expected 1 argument"); - return 1; - } + if (args.n != 1) return dst_throw(args, "expected one argument"); switch (dst_type(args.v[0])) { default: - *args.ret = dst_cstringv("could not convert to integer"); - return 1; + return dst_throw(args, "could not convert to integer"); case DST_REAL: *args.ret = dst_wrap_integer((int32_t) dst_unwrap_real(args.v[0])); break; @@ -45,14 +55,10 @@ int dst_int(DstArgs args) { /* Convert a number to a real number */ int dst_real(DstArgs args) { - if (args.n != 1) { - *args.ret = dst_cstringv("expected 1 argument"); - return 1; - } + if (args.n != 1) return dst_throw(args, "expected one argument"); switch (dst_type(args.v[0])) { default: - *args.ret = dst_cstringv("could not convert to real"); - return 1; + return dst_throw(args, "could not convert to real"); case DST_REAL: *args.ret = args.v[0]; break; @@ -379,6 +385,8 @@ DEF_NUMERIC_COMP(eq, ==) DEF_NUMERIC_COMP(neq, !=) static const DstReg cfuns[] = { + {"random", dst_rand}, + {"seedrandom", dst_srand}, {"int", dst_int}, {"real", dst_real}, {"+", dst_add}, diff --git a/src/include/dst/dstcorelib.h b/src/include/dst/dstcorelib.h index 77c74268..fb91417e 100644 --- a/src/include/dst/dstcorelib.h +++ b/src/include/dst/dstcorelib.h @@ -40,6 +40,8 @@ int dst_subtract(DstArgs args); int dst_multiply(DstArgs args); int dst_divide(DstArgs args); int dst_modulo(DstArgs args); +int dst_rand(DstArgs args); +int dst_srand(DstArgs args); int dst_strict_equal(DstArgs args); int dst_strict_notequal(DstArgs args); int dst_ascending(DstArgs args);