aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/data/coll/array.lux
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/source/lux/data/coll/array.lux')
-rw-r--r--stdlib/source/lux/data/coll/array.lux225
1 files changed, 225 insertions, 0 deletions
diff --git a/stdlib/source/lux/data/coll/array.lux b/stdlib/source/lux/data/coll/array.lux
new file mode 100644
index 000000000..f95754262
--- /dev/null
+++ b/stdlib/source/lux/data/coll/array.lux
@@ -0,0 +1,225 @@
+## Copyright (c) Eduardo Julian. All rights reserved.
+## This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+## If a copy of the MPL was not distributed with this file,
+## You can obtain one at http://mozilla.org/MPL/2.0/.
+
+(;module:
+ lux
+ (lux (control monoid
+ functor
+ applicative
+ monad
+ eq
+ fold)
+ (data error
+ (coll [list "List/" Fold<List>])
+ [product])
+ ))
+
+## [Types]
+(type: #export (Array a)
+ {#;doc "Mutable arrays."}
+ (#;HostT "#Array" (#;Cons a #;Nil)))
+
+## [Functions]
+(def: #export (new size)
+ (All [a] (-> Nat (Array a)))
+ (_lux_proc ["array" "new"] [size]))
+
+(def: #export (size xs)
+ (All [a] (-> (Array a) Nat))
+ (_lux_proc ["array" "size"] [xs]))
+
+(def: #export (get i xs)
+ (All [a]
+ (-> Nat (Array a) (Maybe a)))
+ (_lux_proc ["array" "get"] [xs i]))
+
+(def: #export (put i x xs)
+ (All [a]
+ (-> Nat a (Array a) (Array a)))
+ (_lux_proc ["array" "put"] [xs i x]))
+
+(def: #export (remove i xs)
+ (All [a]
+ (-> Nat (Array a) (Array a)))
+ (_lux_proc ["array" "remove"] [xs i]))
+
+(def: #export (copy length src-start src-array dest-start dest-array)
+ (All [a] (-> Nat Nat (Array a) Nat (Array a)
+ (Array a)))
+ (if (n.= +0 length)
+ dest-array
+ (List/fold (lambda [offset target]
+ (case (get (n.+ offset src-start) src-array)
+ #;None
+ target
+
+ (#;Some value)
+ (put (n.+ offset dest-start) value target)))
+ dest-array
+ (list;n.range +0 (n.dec length)))))
+
+(def: #export (occupied array)
+ {#;doc "Finds out how many cells in an array are occupied."}
+ (All [a] (-> (Array a) Nat))
+ (List/fold (lambda [idx count]
+ (case (get idx array)
+ #;None
+ count
+
+ (#;Some _)
+ (n.inc count)))
+ +0
+ (list;indices (size array))))
+
+(def: #export (vacant array)
+ {#;doc "Finds out how many cells in an array are vacant."}
+ (All [a] (-> (Array a) Nat))
+ (n.- (occupied array) (size array)))
+
+(def: #export (filter p xs)
+ (All [a]
+ (-> (-> a Bool) (Array a) (Array a)))
+ (List/fold (: (-> Nat (Array ($ +0)) (Array ($ +0)))
+ (lambda [idx xs']
+ (case (get idx xs)
+ #;None
+ xs'
+
+ (#;Some x)
+ (if (p x)
+ xs'
+ (remove idx xs')))))
+ xs
+ (list;indices (size xs))))
+
+(def: #export (find p xs)
+ (All [a]
+ (-> (-> a Bool) (Array a) (Maybe a)))
+ (let [arr-size (size xs)]
+ (loop [idx +0]
+ (if (n.< arr-size idx)
+ (case (get idx xs)
+ #;None
+ (recur (n.inc idx))
+
+ (#;Some x)
+ (if (p x)
+ (#;Some x)
+ (recur (n.inc idx))))
+ #;None))))
+
+(def: #export (find+ p xs)
+ {#;doc "Just like 'find', but with access to the index of each value."}
+ (All [a]
+ (-> (-> Nat a Bool) (Array a) (Maybe [Nat a])))
+ (let [arr-size (size xs)]
+ (loop [idx +0]
+ (if (n.< arr-size idx)
+ (case (get idx xs)
+ #;None
+ (recur (n.inc idx))
+
+ (#;Some x)
+ (if (p idx x)
+ (#;Some [idx x])
+ (recur (n.inc idx))))
+ #;None))))
+
+(def: #export (clone xs)
+ (All [a] (-> (Array a) (Array a)))
+ (let [arr-size (size xs)]
+ (List/fold (lambda [idx ys]
+ (case (get idx xs)
+ #;None
+ ys
+
+ (#;Some x)
+ (put idx x ys)))
+ (new arr-size)
+ (list;indices arr-size))))
+
+(def: #export (from-list xs)
+ (All [a] (-> (List a) (Array a)))
+ (product;right (List/fold (lambda [x [idx arr]]
+ [(n.inc idx) (put idx x arr)])
+ [+0 (new (list;size xs))]
+ xs)))
+
+(def: #export (to-list array)
+ (All [a] (-> (Array a) (List a)))
+ (let [_size (size array)]
+ (product;right (List/fold (lambda [_ [idx tail]]
+ (case (get idx array)
+ (#;Some head)
+ [(n.dec idx) (#;Cons head tail)]
+
+ #;None
+ [(n.dec idx) tail]))
+ [(n.dec _size) #;Nil]
+ (list;repeat _size [])
+ ))))
+
+## [Structures]
+(struct: #export (Eq<Array> Eq<a>)
+ (All [a] (-> (Eq a) (Eq (Array a))))
+ (def: (= xs ys)
+ (let [sxs (size xs)
+ sxy (size ys)]
+ (and (n.= sxy sxs)
+ (List/fold (lambda [idx prev]
+ (and prev
+ (case [(get idx xs) (get idx ys)]
+ [#;None #;None]
+ true
+
+ [(#;Some x) (#;Some y)]
+ (:: Eq<a> = x y)
+
+ _
+ false)))
+ true
+ (list;n.range +0 (n.dec sxs)))))
+ ))
+
+(struct: #export Monoid<Array> (All [a]
+ (Monoid (Array a)))
+ (def: unit (new +0))
+
+ (def: (append xs ys)
+ (let [sxs (size xs)
+ sxy (size ys)]
+ (|> (new (n.+ sxy sxs))
+ (copy sxs +0 xs +0)
+ (copy sxy +0 ys sxs)))))
+
+(struct: #export _ (Functor Array)
+ (def: (map f ma)
+ (let [arr-size (size ma)]
+ (if (n.= +0 arr-size)
+ (new arr-size)
+ (List/fold (: (-> Nat (Array ($ +1)) (Array ($ +1)))
+ (lambda [idx mb]
+ (case (get idx ma)
+ #;None
+ mb
+
+ (#;Some x)
+ (put idx (f x) mb))))
+ (new arr-size)
+ (list;n.range +0 (n.dec arr-size)))))))
+
+(struct: #export _ (Fold Array)
+ (def: (fold f init xs)
+ (let [arr-size (size xs)]
+ (loop [so-far init
+ idx +0]
+ (if (n.< arr-size idx)
+ (case (get idx xs)
+ #;None
+ (recur so-far (n.inc idx))
+
+ (#;Some value)
+ (recur (f value so-far) (n.inc idx)))
+ so-far)))))