mirror of
https://github.com/janet-lang/janet
synced 2024-11-16 13:44:48 +00:00
Change primary looping macro to 'loop' instead of 'for'.
This commit is contained in:
parent
644219a8a5
commit
b09bf72490
@ -1,16 +1,13 @@
|
|||||||
(import examples.iterators :as "")
|
|
||||||
|
|
||||||
(defn sum3
|
(defn sum3
|
||||||
"Solve the 3SUM problem in O(n^2) time."
|
"Solve the 3SUM problem in O(n^2) time."
|
||||||
[s]
|
[s]
|
||||||
(def tab @{})
|
(def tab @{})
|
||||||
(def solutions @{})
|
(def solutions @{})
|
||||||
(def len (length s))
|
(def len (length s))
|
||||||
(for [k 0 len]
|
(loop [k :range [0 len]]
|
||||||
(put tab (get s k) k))
|
(put tab (get s k) k))
|
||||||
(for [i 0 len]
|
(loop [i :range [0 len], j :range [0 len]]
|
||||||
(for [j 0 len]
|
|
||||||
(def k (get tab (- 0 (get s i) (get s j))))
|
(def k (get tab (- 0 (get s i) (get s j))))
|
||||||
(when (and k (not= k i) (not= k j) (not= i j))
|
(when (and k (not= k i) (not= k j) (not= i j))
|
||||||
(put solutions {i true j true k true} true))))
|
(put solutions {i true j true k true} true)))
|
||||||
(iter2array (map (fn [x] (iter2array (keys x))) (keys solutions))))
|
(map keys (keys solution)))
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
(defn fizzbuzz
|
(defn fizzbuzz
|
||||||
"Prints the fizzbuzz problem."
|
"Prints the fizzbuzz problem."
|
||||||
[]
|
[]
|
||||||
(for [i 1 101]
|
(loop [i :range [1 101]]
|
||||||
(let [fizz (zero? (% i 3))
|
(let [fizz (zero? (% i 3))
|
||||||
buzz (zero? (% i 5))]
|
buzz (zero? (% i 5))]
|
||||||
(print (cond
|
(print (cond
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
"Get the number of occurences of each value in a indexed structure."
|
"Get the number of occurences of each value in a indexed structure."
|
||||||
[ind]
|
[ind]
|
||||||
(def freqs @{})
|
(def freqs @{})
|
||||||
(each (fn [x]
|
(loop
|
||||||
(let [n (get freqs x)]
|
[x :in ind]
|
||||||
(put freqs x (if n (+ 1 n) 1)))) ind)
|
(def n (get freqs x))
|
||||||
|
(put freqs x (if n (+ 1 n) 1)))
|
||||||
freqs)
|
freqs)
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
# Prints hello
|
# Prints hello
|
||||||
|
|
||||||
|
(import examples.3sum)
|
||||||
|
|
||||||
(print "hello, world!")
|
(print "hello, world!")
|
||||||
|
@ -4,10 +4,10 @@
|
|||||||
"Returns a list of prime numbers less than n."
|
"Returns a list of prime numbers less than n."
|
||||||
[n]
|
[n]
|
||||||
(def list @[])
|
(def list @[])
|
||||||
(for [i 2 n]
|
(loop [i :range [2 n]]
|
||||||
(var isprime? true)
|
(var isprime? true)
|
||||||
(def len (length list))
|
(def len (length list))
|
||||||
(for [j 0 len]
|
(loop [j :range [0 len]]
|
||||||
(def trial (get list j))
|
(def trial (get list j))
|
||||||
(if (zero? (% i trial)) (:= isprime? false)))
|
(if (zero? (% i trial)) (:= isprime? false)))
|
||||||
(if isprime? (array.push list i)))
|
(if isprime? (array.push list i)))
|
||||||
|
@ -218,18 +218,63 @@ value."
|
|||||||
(array.concat accum body)
|
(array.concat accum body)
|
||||||
(apply1 tuple accum))
|
(apply1 tuple accum))
|
||||||
|
|
||||||
|
(defmacro loop
|
||||||
|
"A general purpose loop macro."
|
||||||
|
[head & body]
|
||||||
|
(def head1 (ast.unwrap1 head))
|
||||||
|
(def len (length head1))
|
||||||
|
(defn doone
|
||||||
|
[i]
|
||||||
|
(if (>= i len)
|
||||||
|
(tuple.prepend body 'do)
|
||||||
|
(do
|
||||||
|
(def bindings (get head1 i))
|
||||||
|
(def verb (ast.unwrap1 (get head1 (+ i 1))))
|
||||||
|
(def object (ast.unwrap1 (get head1 (+ i 2))))
|
||||||
|
(switch verb
|
||||||
|
:range (do
|
||||||
|
(def [start end _inc] (ast.unwrap1 object))
|
||||||
|
(def inc (if _inc _inc 1))
|
||||||
|
(def endsym (gensym))
|
||||||
|
(tuple 'do
|
||||||
|
(tuple 'var bindings start)
|
||||||
|
(tuple 'def endsym end)
|
||||||
|
(tuple 'while (tuple < bindings endsym)
|
||||||
|
(doone (+ i 3))
|
||||||
|
(tuple ':= bindings (tuple + bindings inc)))))
|
||||||
|
:keys (do
|
||||||
|
(def $dict (gensym "dict"))
|
||||||
|
(tuple 'do
|
||||||
|
(tuple 'def $dict object)
|
||||||
|
(tuple 'var bindings (tuple next $dict nil))
|
||||||
|
(tuple 'while (tuple not= nil bindings)
|
||||||
|
(doone (+ i 3))
|
||||||
|
(tuple ':= bindings (tuple next $dict bindings)))))
|
||||||
|
:in (do
|
||||||
|
(def $len (gensym "len"))
|
||||||
|
(def $i (gensym "i"))
|
||||||
|
(def $indexed (gensym "indexed"))
|
||||||
|
(tuple 'do
|
||||||
|
(tuple 'def $indexed object)
|
||||||
|
(tuple 'def $len (tuple length $indexed))
|
||||||
|
(tuple 'var $i 0)
|
||||||
|
(tuple 'while (tuple < $i $len)
|
||||||
|
(tuple 'def bindings (tuple get $indexed $i))
|
||||||
|
(doone (+ i 3))
|
||||||
|
(tuple ':= $i (tuple + 1 $i)))))
|
||||||
|
(error ("unexpected loop verb: " verb))))))
|
||||||
|
(doone 0))
|
||||||
|
|
||||||
(defmacro for
|
(defmacro for
|
||||||
"An imperative for loop over an integer range. Use with caution and discretion."
|
"Similar to loop, but accumulates the loop body into an array and returns that."
|
||||||
[head & body]
|
[head & body]
|
||||||
(def [sym start end _inc] (ast.unwrap1 head))
|
(def $accum (gensym "accum"))
|
||||||
(def inc (if _inc _inc 1))
|
|
||||||
(def endsym (gensym))
|
|
||||||
(tuple 'do
|
(tuple 'do
|
||||||
(tuple 'var sym start)
|
(tuple 'def $accum @[])
|
||||||
(tuple 'def endsym end)
|
(tuple 'loop head
|
||||||
(tuple 'while (tuple < sym endsym)
|
(tuple array.push $accum
|
||||||
(tuple.prepend body 'do)
|
(tuple.prepend body 'do)))
|
||||||
(tuple ':= sym (tuple + sym inc)))))
|
$accum))
|
||||||
|
|
||||||
(defmacro and
|
(defmacro and
|
||||||
"Evaluates to the last argument if all preceding elements are true, otherwise
|
"Evaluates to the last argument if all preceding elements are true, otherwise
|
||||||
@ -332,7 +377,7 @@ Returns nil if args is empty."
|
|||||||
(def len (length args))
|
(def len (length args))
|
||||||
(when (pos? len)
|
(when (pos? len)
|
||||||
(var ret (get args 0))
|
(var ret (get args 0))
|
||||||
(for [i 0 len]
|
(loop [i :range [0 len]]
|
||||||
(def v (get args i))
|
(def v (get args i))
|
||||||
(if (order v ret) (:= ret v)))
|
(if (order v ret) (:= ret v)))
|
||||||
ret))
|
ret))
|
||||||
@ -356,7 +401,7 @@ Returns nil if args is empty."
|
|||||||
[a lo hi by]
|
[a lo hi by]
|
||||||
(def pivot (get a hi))
|
(def pivot (get a hi))
|
||||||
(var i lo)
|
(var i lo)
|
||||||
(for [j lo hi]
|
(loop [j :range [lo hi]]
|
||||||
(def aj (get a j))
|
(def aj (get a j))
|
||||||
(when (by aj pivot)
|
(when (by aj pivot)
|
||||||
(def ai (get a i))
|
(def ai (get a i))
|
||||||
@ -391,8 +436,8 @@ Returns nil if args is empty."
|
|||||||
an indexed type (array, tuple) with a function to produce a value."
|
an indexed type (array, tuple) with a function to produce a value."
|
||||||
[f init ind]
|
[f init ind]
|
||||||
(var res init)
|
(var res init)
|
||||||
(for [i 0 (length ind)]
|
(loop [x :in ind]
|
||||||
(:= res (f res (get ind i))))
|
(:= res (f res x)))
|
||||||
res)
|
res)
|
||||||
|
|
||||||
(defn map
|
(defn map
|
||||||
@ -402,19 +447,19 @@ the same type as the input sequence."
|
|||||||
(def ninds (length inds))
|
(def ninds (length inds))
|
||||||
(if (= 0 ninds) (error "expected at least 1 indexed collection."))
|
(if (= 0 ninds) (error "expected at least 1 indexed collection."))
|
||||||
(var limit (length (get inds 0)))
|
(var limit (length (get inds 0)))
|
||||||
(for [i 0 ninds]
|
(loop [i :range [0 ninds]]
|
||||||
(def l (length (get inds i)))
|
(def l (length (get inds i)))
|
||||||
(if (< l limit) (:= limit l)))
|
(if (< l limit) (:= limit l)))
|
||||||
(def [i1 i2 i3 i4] inds)
|
(def [i1 i2 i3 i4] inds)
|
||||||
(def res (array.new limit))
|
(def res (array.new limit))
|
||||||
(switch ninds
|
(switch ninds
|
||||||
1 (for [i 0 limit] (array.push res (f (get i1 i))))
|
1 (loop [i :range [0 limit]] (array.push res (f (get i1 i))))
|
||||||
2 (for [i 0 limit] (array.push res (f (get i1 i) (get i2 i))))
|
2 (loop [i :range [0 limit]] (array.push res (f (get i1 i) (get i2 i))))
|
||||||
3 (for [i 0 limit] (array.push res (f (get i1 i) (get i2 i) (get i3 i))))
|
3 (loop [i :range [0 limit]] (array.push res (f (get i1 i) (get i2 i) (get i3 i))))
|
||||||
4 (for [i 0 limit] (array.push res (f (get i1 i) (get i2 i) (get i3 i) (get i4 i))))
|
4 (loop [i :range [0 limit]] (array.push res (f (get i1 i) (get i2 i) (get i3 i) (get i4 i))))
|
||||||
(for [i 0 limit]
|
(loop [i :range [0 limit]]
|
||||||
(def args (array.new ninds))
|
(def args (array.new ninds))
|
||||||
(for [j 0 ninds] (array.push args (get (get inds j) i)))
|
(loop [j :range [0 ninds]] (array.push args (get (get inds j) i)))
|
||||||
(array.push res (apply1 f args))))
|
(array.push res (apply1 f args))))
|
||||||
res)
|
res)
|
||||||
|
|
||||||
@ -425,18 +470,18 @@ return a new indexed type."
|
|||||||
(def ninds (length inds))
|
(def ninds (length inds))
|
||||||
(if (= 0 ninds) (error "expected at least 1 indexed collection."))
|
(if (= 0 ninds) (error "expected at least 1 indexed collection."))
|
||||||
(var limit (length (get inds 0)))
|
(var limit (length (get inds 0)))
|
||||||
(for [i 0 ninds]
|
(loop [i :range [0 ninds]]
|
||||||
(def l (length (get inds i)))
|
(def l (length (get inds i)))
|
||||||
(if (< l limit) (:= limit l)))
|
(if (< l limit) (:= limit l)))
|
||||||
(def [i1 i2 i3 i4] inds)
|
(def [i1 i2 i3 i4] inds)
|
||||||
(switch ninds
|
(switch ninds
|
||||||
1 (for [i 0 limit] (f (get i1 i)))
|
1 (loop [i :range [0 limit]] (f (get i1 i)))
|
||||||
2 (for [i 0 limit] (f (get i1 i) (get i2 i)))
|
2 (loop [i :range [0 limit]] (f (get i1 i) (get i2 i)))
|
||||||
3 (for [i 0 limit] (f (get i1 i) (get i2 i) (get i3 i)))
|
3 (loop [i :range [0 limit]] (f (get i1 i) (get i2 i) (get i3 i)))
|
||||||
4 (for [i 0 limit] (f (get i1 i) (get i2 i) (get i3 i) (get i4 i)))
|
4 (loop [i :range [0 limit]] (f (get i1 i) (get i2 i) (get i3 i) (get i4 i)))
|
||||||
(for [i 0 limit]
|
(loop [i :range [0 limit]]
|
||||||
(def args (array.new ninds))
|
(def args (array.new ninds))
|
||||||
(for [j 0 ninds] (array.push args (get (get inds j) i)))
|
(loop [j :range [0 ninds]] (array.push args (get (get inds j) i)))
|
||||||
(apply1 f args))))
|
(apply1 f args))))
|
||||||
|
|
||||||
(defn mapcat
|
(defn mapcat
|
||||||
@ -445,8 +490,8 @@ use array to concatenate the results. Returns the same
|
|||||||
type as the input sequence."
|
type as the input sequence."
|
||||||
[f ind t]
|
[f ind t]
|
||||||
(def res @[])
|
(def res @[])
|
||||||
(for [i 0 (length ind)]
|
(loop [x :in ind]
|
||||||
(array.concat res (f (get ind i))))
|
(array.concat res (f x)))
|
||||||
(if (= :tuple (type (or t ind)))
|
(if (= :tuple (type (or t ind)))
|
||||||
(apply1 tuple res)
|
(apply1 tuple res)
|
||||||
res))
|
res))
|
||||||
@ -455,10 +500,8 @@ type as the input sequence."
|
|||||||
"Given a predicate, take only elements from an array or tuple for
|
"Given a predicate, take only elements from an array or tuple for
|
||||||
which (pred element) is truthy. Returns the same type as the input sequence."
|
which (pred element) is truthy. Returns the same type as the input sequence."
|
||||||
[pred ind t]
|
[pred ind t]
|
||||||
(def len (length ind))
|
(def res @[])
|
||||||
(def res (array.new len))
|
(loop [item :in ind]
|
||||||
(for [i 0 len]
|
|
||||||
(def item (get ind i))
|
|
||||||
(if (pred item)
|
(if (pred item)
|
||||||
(array.push res item)))
|
(array.push res item)))
|
||||||
(if (= :tuple (type (or t ind)))
|
(if (= :tuple (type (or t ind)))
|
||||||
@ -469,7 +512,7 @@ which (pred element) is truthy. Returns the same type as the input sequence."
|
|||||||
"Create an array of values [0, n)."
|
"Create an array of values [0, n)."
|
||||||
[n]
|
[n]
|
||||||
(def arr (array.new n))
|
(def arr (array.new n))
|
||||||
(for [i 0 n] (put arr i i))
|
(loop [i :range [0 n]] (put arr i i))
|
||||||
arr)
|
arr)
|
||||||
|
|
||||||
(defn find-index
|
(defn find-index
|
||||||
@ -521,19 +564,18 @@ the predicate, and abort on first failure."
|
|||||||
|
|
||||||
(defn juxt*
|
(defn juxt*
|
||||||
[& funs]
|
[& funs]
|
||||||
(def len (length funs))
|
|
||||||
(fn [& args]
|
(fn [& args]
|
||||||
(def ret @[])
|
(def ret @[])
|
||||||
(for [i 0 len]
|
(loop [f :in funs]
|
||||||
(array.push ret (apply1 (get funs i) args)))
|
(array.push ret (apply1 f args)))
|
||||||
(apply1 tuple ret)))
|
(apply1 tuple ret)))
|
||||||
|
|
||||||
(defmacro juxt
|
(defmacro juxt
|
||||||
[& funs]
|
[& funs]
|
||||||
(def parts @['tuple])
|
(def parts @['tuple])
|
||||||
(def $args (gensym))
|
(def $args (gensym))
|
||||||
(for [i 0 (length funs)]
|
(loop [f :in funs]
|
||||||
(array.push parts (tuple apply1 (get funs i) $args)))
|
(array.push parts (tuple apply1 f $args)))
|
||||||
(tuple 'fn (tuple '& $args) (apply1 tuple parts)))
|
(tuple 'fn (tuple '& $args) (apply1 tuple parts)))
|
||||||
|
|
||||||
(defmacro ->
|
(defmacro ->
|
||||||
@ -611,7 +653,7 @@ in the same manner, and so on. Useful for expressing pipelines of data."
|
|||||||
(def lk (length keys))
|
(def lk (length keys))
|
||||||
(def lv (length vals))
|
(def lv (length vals))
|
||||||
(def len (if (< lk lv) lk lv))
|
(def len (if (< lk lv) lk lv))
|
||||||
(for [i 0 len]
|
(loop [i :range [0 len]]
|
||||||
(put res (get keys i) (get vals i)))
|
(put res (get keys i) (get vals i)))
|
||||||
(if (= :struct t)
|
(if (= :struct t)
|
||||||
(table.to-struct res)
|
(table.to-struct res)
|
||||||
@ -631,18 +673,15 @@ in the same manner, and so on. Useful for expressing pipelines of data."
|
|||||||
collection"
|
collection"
|
||||||
[& colls]
|
[& colls]
|
||||||
(def container @{})
|
(def container @{})
|
||||||
(for [i 0 (length colls)]
|
(loop [c :in colls
|
||||||
(def c (get colls i))
|
key :keys c]
|
||||||
(var key (next c nil))
|
(put container key (get c key)))
|
||||||
(while (not= nil key)
|
|
||||||
(put container key (get c key))
|
|
||||||
(:= key (next c key))))
|
|
||||||
(if (table? (get colls 0)) container (table.to-struct container)))
|
(if (table? (get colls 0)) container (table.to-struct container)))
|
||||||
|
|
||||||
(defn keys
|
(defn keys
|
||||||
"Get the keys of an associative data structure."
|
"Get the keys of an associative data structure."
|
||||||
[x]
|
[x]
|
||||||
(def arr @[])
|
(def arr (array.new (length x)))
|
||||||
(var k (next x nil))
|
(var k (next x nil))
|
||||||
(while (not= nil k)
|
(while (not= nil k)
|
||||||
(array.push arr k)
|
(array.push arr k)
|
||||||
@ -652,7 +691,7 @@ in the same manner, and so on. Useful for expressing pipelines of data."
|
|||||||
(defn values
|
(defn values
|
||||||
"Get the values of an associative data structure."
|
"Get the values of an associative data structure."
|
||||||
[x]
|
[x]
|
||||||
(def arr @[])
|
(def arr (array.new (length x)))
|
||||||
(var k (next x nil))
|
(var k (next x nil))
|
||||||
(while (not= nil k)
|
(while (not= nil k)
|
||||||
(array.push arr (get x k))
|
(array.push arr (get x k))
|
||||||
@ -662,7 +701,7 @@ in the same manner, and so on. Useful for expressing pipelines of data."
|
|||||||
(defn pairs
|
(defn pairs
|
||||||
"Get the values of an associative data structure."
|
"Get the values of an associative data structure."
|
||||||
[x]
|
[x]
|
||||||
(def arr @[])
|
(def arr (array.new (length x)))
|
||||||
(var k (next x nil))
|
(var k (next x nil))
|
||||||
(while (not= nil k)
|
(while (not= nil k)
|
||||||
(array.push arr (tuple k (get x k)))
|
(array.push arr (tuple k (get x k)))
|
||||||
@ -706,12 +745,12 @@ to call on any table. Does not print table prototype information."
|
|||||||
(def len (length y))
|
(def len (length y))
|
||||||
(if (< len 5)
|
(if (< len 5)
|
||||||
(do
|
(do
|
||||||
(for [i 0 len]
|
(loop [i :range [0 len]]
|
||||||
(when (not= i 0) (buffer.push-string buf " "))
|
(when (not= i 0) (buffer.push-string buf " "))
|
||||||
(recur (get y i))))
|
(recur (get y i))))
|
||||||
(do
|
(do
|
||||||
(buffer.push-string indent " ")
|
(buffer.push-string indent " ")
|
||||||
(for [i 0 len]
|
(loop [i :range [0 len]]
|
||||||
(when (not= i len) (buffer.push-string buf indent))
|
(when (not= i len) (buffer.push-string buf indent))
|
||||||
(recur (get y i)))
|
(recur (get y i)))
|
||||||
(buffer.popn indent 2)
|
(buffer.popn indent 2)
|
||||||
@ -719,9 +758,7 @@ to call on any table. Does not print table prototype information."
|
|||||||
|
|
||||||
(defn pp-dict-nested [y]
|
(defn pp-dict-nested [y]
|
||||||
(buffer.push-string indent " ")
|
(buffer.push-string indent " ")
|
||||||
(def ps (sort (pairs y)))
|
(loop [[k v] :in (sort (pairs y))]
|
||||||
(for [i 0 (length ps)]
|
|
||||||
(def [k v] (get ps i))
|
|
||||||
(buffer.push-string buf indent)
|
(buffer.push-string buf indent)
|
||||||
(recur k)
|
(recur k)
|
||||||
(buffer.push-string buf " ")
|
(buffer.push-string buf " ")
|
||||||
@ -730,10 +767,9 @@ to call on any table. Does not print table prototype information."
|
|||||||
(buffer.push-string buf indent))
|
(buffer.push-string buf indent))
|
||||||
|
|
||||||
(defn pp-dict-simple [y]
|
(defn pp-dict-simple [y]
|
||||||
(def ps (sort (pairs y)))
|
(var i -1)
|
||||||
(for [i 0 (length ps)]
|
(loop [[k v] :in (sort (pairs y))]
|
||||||
(def [k v] (get ps i))
|
(if (pos? (++ i)) (buffer.push-string buf " "))
|
||||||
(if (pos? i) (buffer.push-string buf " "))
|
|
||||||
(recur k)
|
(recur k)
|
||||||
(buffer.push-string buf " ")
|
(buffer.push-string buf " ")
|
||||||
(recur v)))
|
(recur v)))
|
||||||
@ -772,11 +808,7 @@ to call on any table. Does not print table prototype information."
|
|||||||
[x]
|
[x]
|
||||||
|
|
||||||
(defn doarray [a]
|
(defn doarray [a]
|
||||||
(def len (length a))
|
(map macroexpand-1 a))
|
||||||
(def newa @[])
|
|
||||||
(for [i 0 len]
|
|
||||||
(array.push newa (macroexpand-1 (get a i))))
|
|
||||||
newa)
|
|
||||||
|
|
||||||
(defn dotable [t]
|
(defn dotable [t]
|
||||||
(def newt @{})
|
(def newt @{})
|
||||||
@ -891,7 +923,7 @@ onvalue."
|
|||||||
(buffer.clear buf)
|
(buffer.clear buf)
|
||||||
(chunks buf p)
|
(chunks buf p)
|
||||||
(:= len (length buf))
|
(:= len (length buf))
|
||||||
(for [i 0 len]
|
(loop [i :range [0 len]]
|
||||||
(fiber.yield (get buf i))))
|
(fiber.yield (get buf i))))
|
||||||
0))
|
0))
|
||||||
|
|
||||||
@ -943,15 +975,13 @@ onvalue."
|
|||||||
(pp x))
|
(pp x))
|
||||||
(when f
|
(when f
|
||||||
(def st (fiber.stack f))
|
(def st (fiber.stack f))
|
||||||
(def len (length st))
|
(loop [{
|
||||||
(for [i 0 len]
|
|
||||||
(def {
|
|
||||||
:function func
|
:function func
|
||||||
:tail tail
|
:tail tail
|
||||||
:pc pc
|
:pc pc
|
||||||
:c c
|
:c c
|
||||||
:name name
|
:name name
|
||||||
} (get st i))
|
} :in st]
|
||||||
(file.write stdout " in")
|
(file.write stdout " in")
|
||||||
(when c (file.write stdout " cfunction"))
|
(when c (file.write stdout " cfunction"))
|
||||||
(when name (file.write stdout (string " " name)))
|
(when name (file.write stdout (string " " name)))
|
||||||
@ -1067,7 +1097,8 @@ returned from compiling and running the file."
|
|||||||
(while k
|
(while k
|
||||||
(def v (get newenv k))
|
(def v (get newenv k))
|
||||||
(when (not (get v :private))
|
(when (not (get v :private))
|
||||||
(put env (symbol prefix k) v))
|
(def newv (table.setproto @{:private true} v))
|
||||||
|
(put env (symbol prefix k) newv))
|
||||||
(:= k (next newenv k))))
|
(:= k (next newenv k))))
|
||||||
|
|
||||||
(defmacro import [path & args]
|
(defmacro import [path & args]
|
||||||
|
@ -830,7 +830,6 @@ recur:
|
|||||||
DstSignal status = dst_call(f, dst_tuple_length(tup) - 1, tup + 1, &x);
|
DstSignal status = dst_call(f, dst_tuple_length(tup) - 1, tup + 1, &x);
|
||||||
dst_gcunlock(lock);
|
dst_gcunlock(lock);
|
||||||
if (status != DST_SIGNAL_OK) {
|
if (status != DST_SIGNAL_OK) {
|
||||||
printf("Status: %d\n", status);
|
|
||||||
const uint8_t *es = dst_formatc("error in macro expansion: %V", x);
|
const uint8_t *es = dst_formatc("error in macro expansion: %V", x);
|
||||||
dstc_error(c, ast, es);
|
dstc_error(c, ast, es);
|
||||||
}
|
}
|
||||||
|
@ -885,6 +885,47 @@ static int cfun_checkset(DstArgs args) {
|
|||||||
DST_RETURN_TRUE(args);
|
DST_RETURN_TRUE(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cfun_join(DstArgs args) {
|
||||||
|
const Dst *parts;
|
||||||
|
const uint8_t *joiner;
|
||||||
|
uint8_t *buf, *out;
|
||||||
|
int32_t joinerlen, partslen, finallen, i;
|
||||||
|
DST_MINARITY(args, 1);
|
||||||
|
DST_MAXARITY(args, 2);
|
||||||
|
DST_ARG_INDEXED(parts, partslen, args, 0);
|
||||||
|
if (args.n == 2) {
|
||||||
|
DST_ARG_BYTES(joiner, joinerlen, args, 1);
|
||||||
|
} else {
|
||||||
|
joiner = NULL;
|
||||||
|
joinerlen = 0;
|
||||||
|
}
|
||||||
|
/* Check args */
|
||||||
|
finallen = 0;
|
||||||
|
for (i = 0; i < partslen; i++) {
|
||||||
|
const uint8_t *chunk;
|
||||||
|
int32_t chunklen = 0;
|
||||||
|
if (!dst_chararray_view(parts[i], &chunk, &chunklen)) {
|
||||||
|
DST_THROW(args, "expected string|symbol|buffer");
|
||||||
|
}
|
||||||
|
if (i) finallen += joinerlen;
|
||||||
|
finallen += chunklen;
|
||||||
|
}
|
||||||
|
out = buf = dst_string_begin(finallen);
|
||||||
|
for (i = 0; i < partslen; i++) {
|
||||||
|
const uint8_t *chunk = NULL;
|
||||||
|
int32_t chunklen = 0;
|
||||||
|
if (i) {
|
||||||
|
memcpy(out, joiner, joinerlen);
|
||||||
|
out += joinerlen;
|
||||||
|
}
|
||||||
|
dst_chararray_view(parts[i], &chunk, &chunklen);
|
||||||
|
memcpy(out, chunk, chunklen);
|
||||||
|
out += chunklen;
|
||||||
|
}
|
||||||
|
DST_RETURN_STRING(args, dst_string_end(buf));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static const DstReg cfuns[] = {
|
static const DstReg cfuns[] = {
|
||||||
{"string.slice", cfun_slice},
|
{"string.slice", cfun_slice},
|
||||||
{"string.repeat", cfun_repeat},
|
{"string.repeat", cfun_repeat},
|
||||||
@ -899,6 +940,7 @@ static const DstReg cfuns[] = {
|
|||||||
{"string.replace-all", cfun_replaceall},
|
{"string.replace-all", cfun_replaceall},
|
||||||
{"string.split", cfun_split},
|
{"string.split", cfun_split},
|
||||||
{"string.check-set", cfun_checkset},
|
{"string.check-set", cfun_checkset},
|
||||||
|
{"string.join", cfun_join},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -274,6 +274,13 @@ int dst_typeabstract_err(DstArgs args, int32_t n, const DstAbstractType *at);
|
|||||||
}\
|
}\
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define DST_ARG_INDEXED(DESTVALS, DESTLEN, A, N) do {\
|
||||||
|
if ((A).n <= (N)) return dst_typemany_err(A, N, DST_TFLAG_INDEXED);\
|
||||||
|
if (!dst_seq_view((A).v[(N)], &(DESTVALS), &(DESTLEN))) {\
|
||||||
|
return dst_typemany_err(A, N, DST_TFLAG_INDEXED);\
|
||||||
|
}\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define _DST_ARG(TYPE, NAME, DEST, A, N) do { \
|
#define _DST_ARG(TYPE, NAME, DEST, A, N) do { \
|
||||||
DST_CHECK(A, N, TYPE);\
|
DST_CHECK(A, N, TYPE);\
|
||||||
DEST = dst_unwrap_##NAME((A).v[(N)]); \
|
DEST = dst_unwrap_##NAME((A).v[(N)]); \
|
||||||
|
Loading…
Reference in New Issue
Block a user