From 0ebc95aa2b6536e93c77a16d849cb8e2be6655bf Mon Sep 17 00:00:00 2001 From: Gavlooth Date: Fri, 23 Mar 2018 15:18:04 +0200 Subject: [PATCH 1/5] Improve lazy2iter and fix a typo in specials.c --- examples/lazyseqs.dst | 12 +++++------- src/compiler/specials.c | 26 +++++++++++++------------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/examples/lazyseqs.dst b/examples/lazyseqs.dst index f7d49284..6fe30434 100644 --- a/examples/lazyseqs.dst +++ b/examples/lazyseqs.dst @@ -109,15 +109,14 @@ body once, and then memoizes the result." #Iterators is a conscept that looks a lot like lazy seq #The following functions turn iterators to lazy seq and vice versa -(defn- iter-self - [next] - (delay (tuple (next) (iter-self next)))) (defn iter2lazy -"Create a lazy sequence froma an iterator" +"Create a lazy sequence from an iterator" [iter] (def {:more more :next next} iter) - (iter-self next)) + (if (more) + (delay (tuple (next) (iter2lazy iter))) + empty-seq)) (defn lazy2iter "turn a lazy-seq to an iterator" @@ -138,8 +137,7 @@ body once, and then memoizes the result." #data structures as their values are references to this #data structures. Same is true for iterators -(defn filter2 [pred coll] - (tail (iter2lazy (filter pred coll)))) +(defn filter2 [pred coll] (iter2lazy (filter pred coll))) (def arr [0 -1 -2 33 -3 0 302 -3 2 8 54 3 -2 0]) diff --git a/src/compiler/specials.c b/src/compiler/specials.c index 86209adc..17d6f21b 100644 --- a/src/compiler/specials.c +++ b/src/compiler/specials.c @@ -45,7 +45,7 @@ DstSlot dstc_astquote(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) } static void destructure(DstCompiler *c, Dst left, DstSlot right, - void (*leaf)(DstCompiler *c, + void (*leaf)(DstCompiler *c, DstAst *ast, const uint8_t *sym, DstSlot s, @@ -72,7 +72,7 @@ static void destructure(DstCompiler *c, Dst left, DstSlot right, localright = dstc_preread(c, ast, 0xFF, 1, right); localsub = dstc_lslotn(c, 0xFF, 3); if (i < 0x100) { - dstc_emit(c, ast, + dstc_emit(c, ast, (i << 24) | (localright << 16) | (localsub << 8) | @@ -80,7 +80,7 @@ static void destructure(DstCompiler *c, Dst left, DstSlot right, } else { DstSlot islot = dstc_cslot(dst_wrap_integer(i)); int32_t locali = dstc_preread(c, ast, 0xFF, 2, islot); - dstc_emit(c, ast, + dstc_emit(c, ast, (locali << 24) | (localright << 16) | (localsub << 8) | @@ -111,7 +111,7 @@ static void destructure(DstCompiler *c, Dst left, DstSlot right, localright = dstc_preread(c, ast, 0xFF, 1, right); localsub = dstc_lslotn(c, 0xFF, 3); int32_t localk = dstc_preread(c, ast, 0xFF, 2, kslot); - dstc_emit(c, ast, + dstc_emit(c, ast, (localk << 24) | (localright << 16) | (localsub << 8) | @@ -211,7 +211,7 @@ static DstSlot namelocal(DstCompiler *c, DstAst *ast, Dst head, int32_t flags, D ret = localslot; } ret.flags |= flags; - dstc_nameslot(c, dst_unwrap_symbol(head), ret); + dstc_nameslot(c, dst_unwrap_symbol(head), ret); return ret; } @@ -276,7 +276,7 @@ static void defleaf( tableindex = dstc_preread(c, ast, 0xFF, 1, tabslot); valsymindex = dstc_preread(c, ast, 0xFF, 2, valsym); valueindex = dstc_preread(c, ast, 0xFF, 3, s); - dstc_emit(c, ast, + dstc_emit(c, ast, (valueindex << 24) | (valsymindex << 16) | (tableindex << 8) | @@ -352,7 +352,7 @@ DstSlot dstc_if(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) { } /* Set target for compilation */ - target = (drop || tail) + target = (drop || tail) ? dstc_cslot(dst_wrap_nil()) : dstc_gettarget(opts); @@ -366,7 +366,7 @@ DstSlot dstc_if(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) { /* Condition left body */ dstc_scope(c, 0); left = dstc_value(bodyopts, truebody); - if (!drop && !tail) dstc_copy(c, ast, target, left); + if (!drop && !tail) dstc_copy(c, ast, target, left); dstc_popscope(c); /* Compile jump to done */ @@ -377,7 +377,7 @@ DstSlot dstc_if(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) { labelr = dst_v_count(c->buffer); dstc_scope(c, 0); right = dstc_value(bodyopts, falsebody); - if (!drop && !tail) dstc_copy(c, ast, target, right); + if (!drop && !tail) dstc_copy(c, ast, target, right); dstc_popscope(c); /* Write jumps - only add jump lengths if jump actually emitted */ @@ -584,7 +584,7 @@ DstSlot dstc_fn(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) { dstc_freeslot(c, s); if (dstc_iserr(&opts)) return dstc_cslot(dst_wrap_nil()); } - + /* Build function */ def = dstc_pop_funcdef(c); def->arity = arity; @@ -603,9 +603,9 @@ DstSlot dstc_fn(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) { (defindex << 16) | (localslot << 8) | DOP_CLOSURE); - + if (ret.index != localslot) { - dstc_emit(c, ast, + dstc_emit(c, ast, (ret.index << 16) | (localslot << 8) | DOP_MOVE_FAR); @@ -614,7 +614,7 @@ DstSlot dstc_fn(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) { return ret; } -/* Keep in lexographic order */ +/* Keep in lexicographic order */ static const DstSpecial dstc_specials[] = { {":=", dstc_varset}, {"ast-quote", dstc_astquote}, From 9f90dc1e1fe9acf17b12892d4355ccac165a1f38 Mon Sep 17 00:00:00 2001 From: Gavlooth Date: Sat, 24 Mar 2018 07:44:17 +0200 Subject: [PATCH 2/5] Fix some typos --- src/compiler/boot.dst | 64 +++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/compiler/boot.dst b/src/compiler/boot.dst index 9dae4faa..bd0cc82b 100644 --- a/src/compiler/boot.dst +++ b/src/compiler/boot.dst @@ -1,13 +1,13 @@ # Bootstrap the dst environment # Copyright 2018 (C) Calvin Rose -(var *env* +(var *env* "The current environment." _env) (def defn :macro "Define a function" - (fn [name & more] + (fn [name & more] (def fstart (fn recur [i] (def ith (ast-unwrap1 (get more i))) (def t (type ith)) @@ -23,7 +23,7 @@ "Define a macro." (do (def defn* (get (get _env 'defn) :value)) - (fn [name & more] + (fn [name & more] (def args (array-concat [] name :macro more)) (apply1 defn* args)))) @@ -86,7 +86,7 @@ (defmacro when "Evaluates the body when the condition is true. Otherwise returns nil." - [cond & body] + [cond & body] (tuple 'if cond (tuple-prepend body 'do))) (defmacro cond @@ -140,21 +140,21 @@ If no match is found, returns nil" (tuple 'def sym dispatch) (aux 0))) -(defmacro and [& forms] +(defmacro and [& forms] (def len (length forms)) (if (= len 0) true ((fn aux [i] (cond (>= (inc i) len) (get forms i) (tuple 'if (get forms i) (aux (inc i)) false))) 0))) -(defmacro or [& forms] +(defmacro or [& forms] (def len (length forms)) (if (= len 0) false ((fn aux [i] (cond (>= (inc i) len) (get forms i) (tuple 'if (get forms i) true (aux (inc i))))) 0))) -(defn identity +(defn identity "A function that returns its first argument." [x] x) @@ -167,7 +167,7 @@ If no match is found, returns nil" :next (fn [] (def ret (get x i)) (:= i (+ i 1)) - ret) + ret) }) (def iters { :array array-iter @@ -184,20 +184,20 @@ If no match is found, returns nil" :next (fn [] (def ret i) (:= i (+ i 1)) - ret) + ret) }) (defn range [top] (range2 0 top)) -(defn doiter [itr] +(defn doiter [itr] (def {:more more :next next} (iter itr)) (while (more) (next))) -(defn foreach [itr f] +(defn foreach [itr f] (def {:more more :next next} (iter itr)) (while (more) (f (next)))) -(defn iter2array [itr] +(defn iter2array [itr] (def {:more more :next next} (iter itr)) (def a []) (while (more) (array-push a (next))) @@ -237,7 +237,7 @@ If no match is found, returns nil" (def len (length head)) (var [i accum] [0 ['do]]) (while (< i len) - (array-push accum (tuple 'def + (array-push accum (tuple 'def (get head i) (get head (+ 1 i)))) (:= i (+ i 2))) @@ -379,7 +379,7 @@ If no match is found, returns nil" (defmacro when-let "Takes the first one or two forms in vector and if true binds - all the forms with let and evaluates body" + all the forms with let and evaluates the body" [bindings & body] (def head (ast-unwrap1 bindings)) (tuple 'let head @@ -403,21 +403,21 @@ If no match is found, returns nil" (array-slice functions 5 -1))))) (defn zipcoll -"Creates an table or tuple from two arrays/tuples. Result is table if no -third argument is given" +"Creates an table or tuple from two arrays/tuples. If a third argument of + :struct is givent resault is struct else is table." [coll-1 coll-2 the-type] (var zipping-table @{}) (def {:more more1 :next next1} (iter coll-1)) (def {:more more2 :next next2} (iter coll-2)) (while (and (more1) (more2)) (put zipping-table (next1) (next2))) - (if (= :struct the-type) + (if (struct? the-type) (table-to-struct zipping-table) zipping-table)) (defn update -"Accepts a key argument and passes its associated value to a function. - The key, then is associated to that value" +"Accepts a key argument and passes its' associated value to a function. + The key then, is associated to the function's return value" [coll a-key a-function & args] (def old-value (get coll a-key) ) (put coll a-key (apply a-function old-value args))) @@ -476,8 +476,8 @@ third argument is given" :struct (fn [pp seen buf x] (pp-dict pp seen buf x "{" "}")) }) - (defn- default_printer [pp seen buf x] - (buffer-push-string buf (describe x)) + (defn- default_printer [pp seen buf x] + (buffer-push-string buf (describe x)) buf) (defn- pp1 [seen buf x] @@ -497,10 +497,10 @@ third argument is given" "Expand macros in a form, but do not recursively expand macros." [x] - (defn doarray [a] + (defn doarray [a] (def len (length a)) (def newa []) - (for [i 0 len] + (for [i 0 len] (array-push newa (macroexpand1 (get a i)))) newa) @@ -535,7 +535,7 @@ third argument is given" 'quote identity 'var expandlast 'while expandall - }) + }) (defn dotup [t] (def h (get t 0)) @@ -584,7 +584,7 @@ third argument is given" (put newenv '_env @{:value newenv})) newenv) -(def run-context +(def run-context "Run a context. This evaluates expressions of dst in an environment, and is encapsulates the parsing, compilation, and evaluation of dst. env is the environment to evaluate the code in, chunks is a function @@ -592,7 +592,7 @@ that returns strings or buffers of source code (from a repl, file, network connection, etc. onvalue and onerr are callbacks that are invoked when a result is returned and when an error is produced, respectively. - + This function can be used to implemement a repl very easily, simply pass a function that reads line from stdin to chunks, and print to onvalue." @@ -605,7 +605,7 @@ onvalue." (var len 1) (while (< 0 len) (buffer-clear buf) - (chunks buf) + (chunks buf) (:= len (length buf)) (for [i 0 len] (yield (get buf i)))) @@ -614,7 +614,7 @@ onvalue." (var tempval nil) # Stream of values (def f (fiber (fn [] - (def p (parser 1)) + (def p (parser 1)) (while going (select (parser-status p) :full (yield (parser-produce p)) @@ -626,8 +626,8 @@ onvalue." (when (not= :root (parser-status p)) (onerr "parse" "unexpected end of source")) nil))) - (defn more [] (if temp true - (do + (defn more [] (if temp true + (do (:= temp true) (:= tempval (resume f)) going))) @@ -670,7 +670,7 @@ onvalue." } (get st i)) (file-write stdout " in") (when c (file-write stdout " cfunction")) - (when name (file-write stdout (string " " name))) + (when name (file-write stdout (string " " name))) (when func (file-write stdout (string " " func))) (when pc (file-write stdout (string " (pc=" pc ")"))) (when tail (file-write stdout " (tailcall)")) @@ -707,7 +707,7 @@ onvalue." (put env (symbol (if prefix prefix "") k) v))))) (defmacro import [path & args] - (apply tuple import* '_env path args)) + (apply tuple import* '_env path args)) (defn repl [getchunk] (def newenv (make-env)) From 1bc57056674556114b51fd636599f76aaba64406 Mon Sep 17 00:00:00 2001 From: Gavlooth Date: Sun, 25 Mar 2018 11:30:30 +0300 Subject: [PATCH 3/5] Fix if-let when-let and add put-in (assoc-in) --- src/compiler/boot.dst | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/compiler/boot.dst b/src/compiler/boot.dst index bd0cc82b..ab6ed174 100644 --- a/src/compiler/boot.dst +++ b/src/compiler/boot.dst @@ -367,13 +367,16 @@ If no match is found, returns nil" (tuple 'when (tuple not condition) exp-1)) (defmacro if-let -"Takes the first one or two forms in a vector and if true binds +"Takes the first one or two forms in a vector and if both are true binds all the forms with let and evaluates the first expression else evaluates the second" [bindings then else] - (def head (ast-unwrap1 bindings)) - (tuple 'let head - (tuple 'if (and (get head 1) (if (get head 2) (get head 3) true)) + #(tuple 'print (tuple '> (tuple 'length bindings) 2)) + (tuple 'let bindings + (tuple 'if (tuple 'and (tuple 'get bindings 1) + (tuple 'if + (tuple '> (tuple 'length bindings) 2) + (tuple 'get bindings 3) 'true)) then else))) @@ -385,7 +388,10 @@ If no match is found, returns nil" (tuple 'let head (tuple 'when - (and (get head 1) (if (get head 2) (get head 3) true)) + (tuple 'and (tuple 'get bindings 1) + (tuple 'if + (tuple '> (tuple 'length bindings) 2) + (tuple 'get bindings 3) 'true)) (apply1 tuple (array-concat ['do] (ast-unwrap1 body)))))) (defn comp From 5ff0367d0f546c5db0bd17b12fcff15f8663d1d5 Mon Sep 17 00:00:00 2001 From: Gavlooth Date: Sun, 25 Mar 2018 11:30:30 +0300 Subject: [PATCH 4/5] Fix if-let when-let and add put-in (assoc-in) --- examples/utils.dst | 22 ++++++++++++++++++++++ src/compiler/boot.dst | 4 +--- 2 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 examples/utils.dst diff --git a/examples/utils.dst b/examples/utils.dst new file mode 100644 index 00000000..8f252e33 --- /dev/null +++ b/examples/utils.dst @@ -0,0 +1,22 @@ + +(defn put-in [coll keys val] + (defn assoc [the-coll n] + (if-let [current-key (get keys n) + current-val (get the-coll current-key)] + (put the-coll current-key (assoc current-val (inc n))) + val)) + (assoc coll 0)) + + +(defn update-in [coll keys an-fn] + (def new-keys (array-slice coll 0 -2) ) + (def last-key (get (array-slice coll -1 -2) 0)) + (defn assoc [the-coll n] + (if-let [current-key (get keys n) + current-val (get the-coll current-key)] + (put the-coll current-key (assoc current-val (inc n))) + ( update the-coll last-key an-fn ))) + (assoc coll new-keys 0)) + + +;; (defn update-in-test [ ] (update-in @{:a "x" :b {:y {"pipa" 3}}} [:b :y "pipa"] type)) diff --git a/src/compiler/boot.dst b/src/compiler/boot.dst index ab6ed174..1ee72f11 100644 --- a/src/compiler/boot.dst +++ b/src/compiler/boot.dst @@ -371,7 +371,6 @@ If no match is found, returns nil" all the forms with let and evaluates the first expression else evaluates the second" [bindings then else] - #(tuple 'print (tuple '> (tuple 'length bindings) 2)) (tuple 'let bindings (tuple 'if (tuple 'and (tuple 'get bindings 1) (tuple 'if @@ -384,8 +383,7 @@ If no match is found, returns nil" "Takes the first one or two forms in vector and if true binds all the forms with let and evaluates the body" [bindings & body] - (def head (ast-unwrap1 bindings)) - (tuple 'let head + (tuple 'let bindings (tuple 'when (tuple 'and (tuple 'get bindings 1) From 080caf31a71f3addee3aa36d43fd4057067e28f9 Mon Sep 17 00:00:00 2001 From: bakpakin Date: Sun, 25 Mar 2018 18:51:31 -0400 Subject: [PATCH 5/5] Add triangles examples. --- examples/maxtriangle.dst | 39 +++++++++++++++++++++++++++++++++++++++ src/core/tuple.c | 18 +++++++++--------- 2 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 examples/maxtriangle.dst diff --git a/examples/maxtriangle.dst b/examples/maxtriangle.dst new file mode 100644 index 00000000..dcb7d4a3 --- /dev/null +++ b/examples/maxtriangle.dst @@ -0,0 +1,39 @@ +(defn vmap2 [f m1 m2] + (def len (length m1)) + (def arr []) + (for [i 0 len] (array-push arr (f (get m1 i) (get m2 i)))) + arr) + +(defn reduce [s f c] + (var res s) + (for [i 0 (length c)] + (:= res (f res (get c i)))) + res) + +(defn max1 [l r] (if (< l r) r l)) + +(defn myfold [xs ys] + (def xs1 (tuple-prepend xs 0)) + (def xs2 (tuple-append xs 0)) + (def m1 (vmap2 + xs1 ys)) + (def m2 (vmap2 + xs2 ys)) + (vmap2 max1 m1 m2)) + +(defn max [a] + (var m (get a 0)) + (for [i 0 (length a)] + (if (< m (get a i)) + (:= m (get a i)))) + m) + +(defn maxpath [t] + (max (reduce [] myfold t))) + +(def triangle [ + [3] + [7 10] + [4 3 7] +[8 9 1 3] +]) + +(print (maxpath triangle)) diff --git a/src/core/tuple.c b/src/core/tuple.c index 358a8363..b851f639 100644 --- a/src/core/tuple.c +++ b/src/core/tuple.c @@ -127,25 +127,25 @@ static int cfun_slice(DstArgs args) { static int cfun_prepend(DstArgs args) { const Dst *t; + int32_t len; Dst *n; if (args.n != 2) return dst_throw(args, "expected 2 arguments"); - if (!dst_checktype(args.v[0], DST_TUPLE)) return dst_throw(args, "expected tuple"); - t = dst_unwrap_tuple(args.v[0]); - n = dst_tuple_begin(dst_tuple_length(t) + 1); - memcpy(n + 1, t, sizeof(Dst) * dst_tuple_length(t)); + if (!dst_seq_view(args.v[0], &t, &len)) return dst_throw(args, "expected tuple/array"); + n = dst_tuple_begin(len + 1); + memcpy(n + 1, t, sizeof(Dst) * len); n[0] = args.v[1]; return dst_return(args, dst_wrap_tuple(dst_tuple_end(n))); } static int cfun_append(DstArgs args) { const Dst *t; + int32_t len; Dst *n; if (args.n != 2) return dst_throw(args, "expected 2 arguments"); - if (!dst_checktype(args.v[0], DST_TUPLE)) return dst_throw(args, "expected tuple"); - t = dst_unwrap_tuple(args.v[0]); - n = dst_tuple_begin(dst_tuple_length(t) + 1); - memcpy(n, t, sizeof(Dst) * dst_tuple_length(t)); - n[dst_tuple_length(t)] = args.v[1]; + if (!dst_seq_view(args.v[0], &t, &len)) return dst_throw(args, "expected tuple/array"); + n = dst_tuple_begin(len + 1); + memcpy(n, t, sizeof(Dst) * len); + n[len] = args.v[1]; return dst_return(args, dst_wrap_tuple(dst_tuple_end(n))); }