oops: implement called keywords!
This commit is contained in:
parent
ff6aaf5cdf
commit
84101711f2
|
@ -1052,125 +1052,126 @@ let turtle_init = #{
|
|||
& turtle_commands is a list of commands, expressed as tuples
|
||||
box turtle_commands = []
|
||||
box turtle_state = turtle_init
|
||||
box turtle_states = #{:turtle_0 turtle_init}
|
||||
box command_id = 0
|
||||
|
||||
fn apply_command
|
||||
|
||||
fn add_command! (command) -> {
|
||||
fn add_command! (turtle_id, command) -> {
|
||||
let idx = unbox (command_id)
|
||||
update! (command_id, inc)
|
||||
update! (turtle_commands, append (_, (:turtle_0, idx, command)))
|
||||
let prev = unbox (turtle_state)
|
||||
update! (turtle_commands, append (_, (turtle_id, idx, command)))
|
||||
let prev = do turtle_states > unbox > turtle_id
|
||||
let curr = apply_command (prev, command)
|
||||
store! (turtle_state, curr)
|
||||
update! (turtle_states, assoc (_, turtle_id, curr))
|
||||
:ok
|
||||
}
|
||||
|
||||
fn forward! {
|
||||
"Moves the turtle forward by a number of steps. Alias: fd!"
|
||||
(steps as :number) -> add_command! ((:forward, steps))
|
||||
(steps as :number) -> add_command! (:turtle_0, (:forward, steps))
|
||||
}
|
||||
|
||||
let fd! = forward!
|
||||
|
||||
fn back! {
|
||||
"Moves the turtle backward by a number of steps. Alias: bk!"
|
||||
(steps as :number) -> add_command! ((:back, steps))
|
||||
(steps as :number) -> add_command! (:turtle_0, (:back, steps))
|
||||
}
|
||||
|
||||
let bk! = back!
|
||||
|
||||
fn left! {
|
||||
"Rotates the turtle left, measured in turns. Alias: lt!"
|
||||
(turns as :number) -> add_command! ((:left, turns))
|
||||
(turns as :number) -> add_command! (:turtle_0, (:left, turns))
|
||||
}
|
||||
|
||||
let lt! = left!
|
||||
|
||||
fn right! {
|
||||
"Rotates the turtle right, measured in turns. Alias: rt!"
|
||||
(turns as :number) -> add_command! ((:right, turns))
|
||||
(turns as :number) -> add_command! (:turtle_0, (:right, turns))
|
||||
}
|
||||
|
||||
let rt! = right!
|
||||
|
||||
fn penup! {
|
||||
"Lifts the turtle's pen, stopping it from drawing. Alias: pu!"
|
||||
() -> add_command! ((:penup))
|
||||
() -> add_command! (:turtle_0, (:penup))
|
||||
}
|
||||
|
||||
let pu! = penup!
|
||||
|
||||
fn pendown! {
|
||||
"Lowers the turtle's pen, causing it to draw. Alias: pd!"
|
||||
() -> add_command! ((:pendown))
|
||||
() -> add_command! (:turtle_0, (:pendown))
|
||||
}
|
||||
|
||||
let pd! = pendown!
|
||||
|
||||
fn pencolor! {
|
||||
"Changes the turtle's pen color. Takes a single grayscale value, an rgb tuple, or an rgba tuple. Alias: pc!"
|
||||
(color as :keyword) -> add_command! ((:pencolor, color))
|
||||
(gray as :number) -> add_command! ((:pencolor, (gray, gray, gray, 255)))
|
||||
((r as :number, g as :number, b as :number)) -> add_command! ((:pencolor, (r, g, b, 255)))
|
||||
((r as :number, g as :number, b as :number, a as :number)) -> add_command! ((:pencolor, (r, g, b, a)))
|
||||
(color as :keyword) -> add_command! (:turtle_0, (:pencolor, color))
|
||||
(gray as :number) -> add_command! (:turtle_0, (:pencolor, (gray, gray, gray, 255)))
|
||||
((r as :number, g as :number, b as :number)) -> add_command! (:turtle_0, (:pencolor, (r, g, b, 255)))
|
||||
((r as :number, g as :number, b as :number, a as :number)) -> add_command! (:turtle_0, (:pencolor, (r, g, b, a)))
|
||||
}
|
||||
|
||||
let pc! = pencolor!
|
||||
|
||||
fn penwidth! {
|
||||
"Sets the width of the turtle's pen, measured in pixels. Alias: pw!"
|
||||
(width as :number) -> add_command! ((:penwidth, width))
|
||||
(width as :number) -> add_command! (:turtle_0, (:penwidth, width))
|
||||
}
|
||||
|
||||
let pw! = penwidth!
|
||||
|
||||
fn background! {
|
||||
"Sets the background color behind the turtle and path. Alias: bg!"
|
||||
(color as :keyword) -> add_command! ((:background, color))
|
||||
(gray as :number) -> add_command! ((:background, (gray, gray, gray, 255)))
|
||||
((r as :number, g as :number, b as :number)) -> add_command! ((:background, (r, g, b, 255)))
|
||||
((r as :number, g as :number, b as :number, a as :number)) -> add_command! ((:background, (r, g, b, a)))
|
||||
(color as :keyword) -> add_command! (:turtle_0, (:background, color))
|
||||
(gray as :number) -> add_command! (:turtle_0, (:background, (gray, gray, gray, 255)))
|
||||
((r as :number, g as :number, b as :number)) -> add_command! (:turtle_0, (:background, (r, g, b, 255)))
|
||||
((r as :number, g as :number, b as :number, a as :number)) -> add_command! (:turtle_0, (:background, (r, g, b, a)))
|
||||
}
|
||||
|
||||
let bg! = background!
|
||||
|
||||
fn home! {
|
||||
"Sends the turtle home: to the centre of the screen, pointing up. If the pen is down, the turtle will draw a path to home."
|
||||
() -> add_command! ((:home))
|
||||
() -> add_command! (:turtle_0, (:home))
|
||||
}
|
||||
|
||||
fn clear! {
|
||||
"Clears the canvas and sends the turtle home."
|
||||
() -> add_command! ((:clear))
|
||||
() -> add_command! (:turtle_0, (:clear))
|
||||
}
|
||||
|
||||
fn goto! {
|
||||
"Sends the turtle to (x, y) coordinates. If the pen is down, the turtle will draw a path to its new location."
|
||||
(x as :number, y as :number) -> add_command! ((:goto, (x, y)))
|
||||
(x as :number, y as :number) -> add_command! (:turtle_0, (:goto, (x, y)))
|
||||
((x, y)) -> goto! (x, y)
|
||||
}
|
||||
|
||||
fn setheading! {
|
||||
"Sets the turtle's heading. The angle is specified in turns, with 0 pointing up. Increasing values rotate the turtle counter-clockwise."
|
||||
(heading as :number) -> add_command! ((:setheading, heading))
|
||||
(heading as :number) -> add_command! (:turtle_0, (:setheading, heading))
|
||||
}
|
||||
|
||||
fn showturtle! {
|
||||
"If the turtle is hidden, shows the turtle. If the turtle is already visible, does nothing."
|
||||
() -> add_command! ((:show))
|
||||
() -> add_command! (:turtle_0, (:show))
|
||||
}
|
||||
|
||||
fn hideturtle! {
|
||||
"If the turtle is visible, hides it. If the turtle is already hidden, does nothing."
|
||||
() -> add_command! ((:hide))
|
||||
() -> add_command! (:turtle_0, (:hide))
|
||||
}
|
||||
|
||||
fn loadstate! {
|
||||
"Sets the turtle state to a previously saved state."
|
||||
(state) -> {
|
||||
let #{position, heading, pendown?, pencolor, penwidth, visible?} = state
|
||||
add_command! ((:loadstate, position, heading, visible?, pendown?, penwidth, pencolor))
|
||||
add_command! (:turtle_0, (:loadstate, position, heading, visible?, pendown?, penwidth, pencolor))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1214,27 +1215,27 @@ fn apply_command {
|
|||
& position () -> (x, y)
|
||||
fn position {
|
||||
"Returns the turtle's current position."
|
||||
() -> do turtle_state > unbox > :position
|
||||
() -> do turtle_states > unbox > :turtle_0 > :position
|
||||
}
|
||||
|
||||
fn heading {
|
||||
"Returns the turtle's current heading."
|
||||
() -> do turtle_state > unbox > :heading
|
||||
() -> do turtle_states > unbox > :turtle_0 > :heading
|
||||
}
|
||||
|
||||
fn pendown? {
|
||||
"Returns the turtle's pen state: true if the pen is down."
|
||||
() -> do turtle_state > unbox > :pendown?
|
||||
() -> do turtle_states > unbox > :turtle_0 > :pendown?
|
||||
}
|
||||
|
||||
fn pencolor {
|
||||
"Returns the turtle's pen color as an (r, g, b, a) tuple or keyword."
|
||||
() -> do turtle_state > unbox > :pencolor
|
||||
() -> do turtle_states > unbox > :turtle_0 > :pencolor
|
||||
}
|
||||
|
||||
fn penwidth {
|
||||
"Returns the turtle's pen width in pixels."
|
||||
() -> do turtle_state > unbox > :penwidth
|
||||
() -> do turtle_states > unbox > :turtle_0 > :penwidth
|
||||
}
|
||||
|
||||
&&& fake some lispisms with tuples
|
||||
|
|
|
@ -1248,6 +1248,6 @@ We can revisit the idea of a special spawn form later.
|
|||
And now, we build capacity for building projects.
|
||||
|
||||
* [ ] allow for multiple turtles
|
||||
- [ ] rework p5 function in `ludus.js` to properly parse commands targeted at different turtles
|
||||
- [x] rework p5 function in `ludus.js` to properly parse commands targeted at different turtles
|
||||
- [ ] write ludus code to spawn & manipulate turtle actors
|
||||
* [ ] do some sample multiturtle sketches
|
||||
|
|
Binary file not shown.
17
src/vm.rs
17
src/vm.rs
|
@ -1117,6 +1117,14 @@ impl Creature {
|
|||
self.call_stack.push(frame);
|
||||
self.ip = 0;
|
||||
}
|
||||
Value::Keyword(key) => {
|
||||
let dict = self.pop();
|
||||
match dict {
|
||||
Value::Dict(d) => self
|
||||
.push(d.get(&Key::Keyword(key)).unwrap_or(&Value::Nil).clone()),
|
||||
_ => self.push(Value::Nil),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return self.panic_with(format!("{} is not a function", called.show()))
|
||||
}
|
||||
|
@ -1229,6 +1237,15 @@ impl Creature {
|
|||
self.call_stack.push(frame);
|
||||
self.ip = 0;
|
||||
}
|
||||
Value::Keyword(key) => {
|
||||
let dict = self.pop();
|
||||
match dict {
|
||||
Value::Dict(d) => self
|
||||
.push(d.get(&Key::Keyword(key)).unwrap_or(&Value::Nil).clone()),
|
||||
_ => self.push(Value::Nil),
|
||||
}
|
||||
}
|
||||
|
||||
_ => {
|
||||
return self.panic_with(format!("{} is not a function", called.show()))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user