Add slice, fix bugs

This commit is contained in:
Scott Richmond 2023-12-03 21:48:53 -05:00
parent 30fa4e9d97
commit 14862c3ba9
3 changed files with 69 additions and 10 deletions

View File

@ -137,6 +137,10 @@
::data/type ::data/clj ::data/type ::data/clj
:body nth}) :body nth})
(def slice {:name "slice"
::data/type ::data/clj
:body subvec})
(def types { (def types {
:keyword :keyword
#?( #?(
@ -402,6 +406,7 @@
:extern extern :extern extern
:rest rest- :rest rest-
:nth nth- :nth nth-
:slice slice
:count count- :count count-
:into into- :into into-
:to_vec to_vec :to_vec to_vec

View File

@ -648,7 +648,7 @@
(let [data (:data ast) (let [data (:data ast)
word (first data) word (first data)
ns (resolve-word word ctx)] ns (resolve-word word ctx)]
(println "use: " ns) ; (println "use: " ns)
(if (not (= (::data/type ns) ::data/ns)) (if (not (= (::data/type ns) ::data/ns))
(throw (ex-info (str "`use` may only use namespaces; " (-> word :data first) " is not a namespace") {:ast ast})) (throw (ex-info (str "`use` may only use namespaces; " (-> word :data first) " is not a namespace") {:ast ast}))
(let [ns-entries (dissoc ns ::data/type ::data/name ::data/struct) (let [ns-entries (dissoc ns ::data/type ::data/name ::data/struct)

View File

@ -14,13 +14,20 @@ fn inc {
fn dec { fn dec {
"Decrements a number." "Decrements a number."
(x as :number) -> base :dec (x) (x as :number) -> base :dec (x)
(x) -> report (x)
} }
fn nth { fn nth {
"Returns the element at index n of a list or tuple. Zero-indexed: the first element is at index 0." "Returns the element at index n of a list or tuple. Zero-indexed: the first element is at index 0."
(xs as :list, n as :number) -> base :nth (xs, inc(n)) (xs as :list, n as :number) -> when {
(xs as :tuple, n as :number) -> base :nth (xs, inc (n)) neg? (n) -> nil
gte? (n, count (xs)) -> nil
else -> base :nth (xs, inc (n))
}
(xs as :tuple, n as :number) -> when {
neg? (n) -> nil
gte? (n, count (xs)) -> nil
else -> base :nth (xs, inc (n))
}
} }
fn first { fn first {
@ -33,9 +40,33 @@ fn second {
(xs) -> nth (xs, 1) (xs) -> nth (xs, 1)
} }
fn last {
"Returns the last element of a list or tuple."
(xs) -> nth (xs, sub (count (xs), 1))
}
fn butlast {
"Returns a list, omitting the last element."
(xs as :list) -> base :slice (xs, sub (count (xs), 1))
}
fn slice {
"Returns a slice of a list, representing a sub-list."
(xs as :list, end as :number) -> slice (xs, 0, end)
(xs as :list, start as :number, end as :number) -> when {
gte? (start, end) -> []
gt? (end, count (xs)) -> slice (xs, start, count (xs))
neg? (start) -> slice (xs, 0, end)
else -> {
let slice = base :slice (xs, inc (start), inc (end))
base :into ([], slice)
}
}
}
fn count { fn count {
"Returns the number of elements in a collection (including string)." "Returns the number of elements in a collection (including string)."
(xs as :list) -> dec (base :count (report(xs))) (xs as :list) -> dec (base :count (xs))
(xs as :tuple) -> dec (base :count (xs)) (xs as :tuple) -> dec (base :count (xs))
(xs as :dict) -> base :count (xs) (xs as :dict) -> base :count (xs)
(xs as :string) -> base :count (xs) (xs as :string) -> base :count (xs)
@ -118,14 +149,14 @@ fn concat {
(xs, ys, ...zs) -> fold (concat, zs, concat(xs, ys)) (xs, ys, ...zs) -> fold (concat, zs, concat(xs, ys))
} }
fn report { fn report! {
"Prints a value, then returns it." "Prints a value, then returns it."
(x) -> { (x) -> {
print (x) print! (x)
x x
} }
(msg as :string, x) -> { (msg as :string, x) -> {
print (concat (msg, show (x))) print! (concat (msg, show (x)))
x x
} }
} }
@ -615,18 +646,38 @@ let turtle_init = #{
& the first member of each tuple is the command & the first member of each tuple is the command
ref turtle_commands = [] ref turtle_commands = []
ref last_command = ()
& give ourselves a ref for current turtle state & give ourselves a ref for current turtle state
ref turtle_state = turtle_init ref turtle_state = turtle_init
& and a list of turtle states & and a list of turtle states
ref turtle_states = [turtle_init] ref turtle_states = [turtle_init]
ref p5_calls = [
(:background, 0)
]
fn add_call! (call) -> update! (p5_calls, conj (_, call))
fn add_command! (command) -> { fn add_command! (command) -> {
update! (turtle_commands, append (_, command)) update! (turtle_commands, append (_, command))
make! (last_command, command)
let current_state = deref (turtle_state) let current_state = deref (turtle_state)
let new_state = apply_command (current_state, command) let new_state = apply_command (current_state, command)
update! (turtle_states, append (_, new_state)) update! (turtle_states, append (_, new_state))
make! (turtle_state, new_state) make! (turtle_state, new_state)
render_command! ()
:ok
}
fn render_command! () -> {
let cmd = first (command)
let state = deref (turtle_state)
let #{position, heading, pendown, color, penwidth, visible} = state
match cmd with {
:forward -> :todo
}
} }
fn forward! { fn forward! {
@ -748,7 +799,7 @@ fn apply_command {
fn turtle/p5 { fn turtle/p5 {
"Takes a list of turtle states and returns a list of p5 calls that will render the turtle states." "Takes a list of turtle states and returns a list of p5 calls that will render the turtle states."
() -> :todo () -> :todo
} }
@ -763,6 +814,9 @@ ns prelude {
second second
rest rest
nth nth
last
butlast
slice
count count
append append
fold fold
@ -775,7 +829,7 @@ ns prelude {
show show
prn! prn!
type type
report report!
concat concat
deref deref
make! make!