112 lines
3.9 KiB
Plaintext
112 lines
3.9 KiB
Plaintext
;;;; Generic structs, end to end: type parameters and length parameters.
|
|
;;;;
|
|
;;;; A defstruct whose fields introduce $t is a template, and each set of
|
|
;;;; arguments it is given is a copy — an ordinary struct. A parameter is a
|
|
;;;; length when it stands in an array's length slot, and a type anywhere else;
|
|
;;;; the arguments are written in the order the fields first introduce them.
|
|
;;;;
|
|
;;;; Small is Odin's Small_Array: a fixed-capacity array with a count, and no
|
|
;;;; allocation anywhere.
|
|
|
|
(defstruct Small [items [$n $t] count i32])
|
|
|
|
;; A generic function over a generic struct binds both of its parameters from
|
|
;; the argument, and reads the length back as a value.
|
|
(defn small-append [s (Ptr (Small $n $t)) x $t] bool
|
|
(if (< (.count s) n)
|
|
(do (set (at (.items s) (.count s)) x)
|
|
(set (.count s) (+ (.count s) 1))
|
|
true)
|
|
false))
|
|
|
|
;; One generic over the struct calling another at its own variables.
|
|
(defn small-append-all [s (Ptr (Small $n $t)) xs [$t]] ()
|
|
(dotimes [i (length xs)]
|
|
(small-append s (at xs i))))
|
|
|
|
(defn small-pop [s (Ptr (Small $n $t))] (Option $t)
|
|
(if (= (.count s) 0)
|
|
None
|
|
(do (set (.count s) (- (.count s) 1))
|
|
(Some (at (.items s) (.count s))))))
|
|
|
|
(defn capacity [s (Ptr (Small $n $t))] i32 n)
|
|
|
|
(defn total [s (Ptr (Small $n $t))] $t {:where (is-numeric $t)}
|
|
(let [acc (the $t 0)]
|
|
(dotimes [i (.count s)]
|
|
(set acc (+ acc (at (.items s) i))))
|
|
acc))
|
|
|
|
;; A type parameter alone, built positionally with the type read off the
|
|
;; fields, and returned under a variable.
|
|
(defstruct Pair [a $t b $t])
|
|
|
|
(defn swapped [p (Pair $t)] (Pair $t) (Pair (.b p) (.a p)))
|
|
|
|
;; A copy that names itself through a pointer, and a literal field that
|
|
;; takes its width from the one beside it.
|
|
(defstruct Node [v $t next (Option (Ptr (Node $t)))])
|
|
|
|
(defn sum-list [n (Ptr (Node i64))] i64
|
|
(let [at n acc (the i64 0)]
|
|
(while true
|
|
(set acc (+ acc (.v at)))
|
|
(match (.next at)
|
|
(Some p) (set at p)
|
|
None (break)))
|
|
acc))
|
|
|
|
;; A template naming another at its own parameters.
|
|
(defstruct Twice [x (Small $m $u) y (Small $m $u)])
|
|
|
|
;; A copy as a map key, and a named function over one handed where a
|
|
;; function value is wanted.
|
|
(defn pair-sum [p (Pair i32)] i32 (+ (.a p) (.b p)))
|
|
(defn apply-to [f (Fn [(Pair i32)] i32) p (Pair i32)] i32 (f p))
|
|
|
|
;; A length variable straight on an array parameter.
|
|
(defn len-of [a [$k $e]] i32 k)
|
|
|
|
(defconst cap 3)
|
|
|
|
(defn main [] i32
|
|
(let [s (the (Small 4 i32) (zeroed))
|
|
f (the (Small cap f64) (zeroed))]
|
|
(small-append (addr s) 10)
|
|
(small-append (addr s) 20)
|
|
(small-append (addr s) 30)
|
|
(println (total (addr s)) (.count s) (capacity (addr s)))
|
|
(small-append (addr f) 1.5)
|
|
(small-append (addr f) 2.5)
|
|
(small-append (addr f) 3.5)
|
|
(println (small-append (addr f) 4.5) (total (addr f)) (capacity (addr f)))
|
|
(println (small-pop (addr f)) (small-pop (addr f)) (.count f))
|
|
(let [p (Pair 1 2)
|
|
q (swapped p)
|
|
r (swapped (Pair {.a 1.5 .b 2.5}))]
|
|
(println (.a q) (.b q) (.a r) (.b r))
|
|
(println q (Pair 1 2.5)))
|
|
(let [c (the (Node i64) {.v 3})
|
|
b (Node 2 (Some (addr c)))
|
|
a (Node 1 (Some (addr b)))]
|
|
(println (sum-list (addr a))))
|
|
(let [w (the (Twice 2 u8) (zeroed))]
|
|
(small-append (addr (.y w)) 7)
|
|
(println (.count (.x w)) (.count (.y w)) (capacity (addr (.x w)))))
|
|
(println (len-of [1 2 3]) (len-of [1.5 2.5]))
|
|
(let [v (vec-new (Pair i32))]
|
|
(push v (Pair 5 6))
|
|
(println (.b (at v 0)))
|
|
(free v))
|
|
(let [t (the (Small 5 i64) (zeroed))
|
|
xs (the [3 i64] [1 2 3])]
|
|
(small-append-all (addr t) (slice xs))
|
|
(println (total (addr t)) (.count t)))
|
|
(let [m (map-new (Pair i32) i32)]
|
|
(put m (Pair 1 2) 12)
|
|
(put m (Pair 3 4) 34)
|
|
(println (get m (Pair 3 4)) (get m (Pair 2 1)) (apply-to pair-sum (Pair 7 8)))
|
|
(free m))
|
|
0))
|