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
|
& turtle_commands is a list of commands, expressed as tuples
|
||||||
box turtle_commands = []
|
box turtle_commands = []
|
||||||
box turtle_state = turtle_init
|
box turtle_state = turtle_init
|
||||||
|
box turtle_states = #{:turtle_0 turtle_init}
|
||||||
box command_id = 0
|
box command_id = 0
|
||||||
|
|
||||||
fn apply_command
|
fn apply_command
|
||||||
|
|
||||||
fn add_command! (command) -> {
|
fn add_command! (turtle_id, command) -> {
|
||||||
let idx = unbox (command_id)
|
let idx = unbox (command_id)
|
||||||
update! (command_id, inc)
|
update! (command_id, inc)
|
||||||
update! (turtle_commands, append (_, (:turtle_0, idx, command)))
|
update! (turtle_commands, append (_, (turtle_id, idx, command)))
|
||||||
let prev = unbox (turtle_state)
|
let prev = do turtle_states > unbox > turtle_id
|
||||||
let curr = apply_command (prev, command)
|
let curr = apply_command (prev, command)
|
||||||
store! (turtle_state, curr)
|
update! (turtle_states, assoc (_, turtle_id, curr))
|
||||||
:ok
|
:ok
|
||||||
}
|
}
|
||||||
|
|
||||||
fn forward! {
|
fn forward! {
|
||||||
"Moves the turtle forward by a number of steps. Alias: fd!"
|
"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!
|
let fd! = forward!
|
||||||
|
|
||||||
fn back! {
|
fn back! {
|
||||||
"Moves the turtle backward by a number of steps. Alias: bk!"
|
"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!
|
let bk! = back!
|
||||||
|
|
||||||
fn left! {
|
fn left! {
|
||||||
"Rotates the turtle left, measured in turns. Alias: lt!"
|
"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!
|
let lt! = left!
|
||||||
|
|
||||||
fn right! {
|
fn right! {
|
||||||
"Rotates the turtle right, measured in turns. Alias: rt!"
|
"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!
|
let rt! = right!
|
||||||
|
|
||||||
fn penup! {
|
fn penup! {
|
||||||
"Lifts the turtle's pen, stopping it from drawing. Alias: pu!"
|
"Lifts the turtle's pen, stopping it from drawing. Alias: pu!"
|
||||||
() -> add_command! ((:penup))
|
() -> add_command! (:turtle_0, (:penup))
|
||||||
}
|
}
|
||||||
|
|
||||||
let pu! = penup!
|
let pu! = penup!
|
||||||
|
|
||||||
fn pendown! {
|
fn pendown! {
|
||||||
"Lowers the turtle's pen, causing it to draw. Alias: pd!"
|
"Lowers the turtle's pen, causing it to draw. Alias: pd!"
|
||||||
() -> add_command! ((:pendown))
|
() -> add_command! (:turtle_0, (:pendown))
|
||||||
}
|
}
|
||||||
|
|
||||||
let pd! = pendown!
|
let pd! = pendown!
|
||||||
|
|
||||||
fn pencolor! {
|
fn pencolor! {
|
||||||
"Changes the turtle's pen color. Takes a single grayscale value, an rgb tuple, or an rgba tuple. Alias: pc!"
|
"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))
|
(color as :keyword) -> add_command! (:turtle_0, (:pencolor, color))
|
||||||
(gray as :number) -> add_command! ((:pencolor, (gray, gray, gray, 255)))
|
(gray as :number) -> add_command! (:turtle_0, (: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)) -> add_command! (:turtle_0, (:pencolor, (r, g, b, 255)))
|
||||||
((r as :number, g as :number, b as :number, a as :number)) -> add_command! ((:pencolor, (r, g, b, a)))
|
((r as :number, g as :number, b as :number, a as :number)) -> add_command! (:turtle_0, (:pencolor, (r, g, b, a)))
|
||||||
}
|
}
|
||||||
|
|
||||||
let pc! = pencolor!
|
let pc! = pencolor!
|
||||||
|
|
||||||
fn penwidth! {
|
fn penwidth! {
|
||||||
"Sets the width of the turtle's pen, measured in pixels. Alias: pw!"
|
"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!
|
let pw! = penwidth!
|
||||||
|
|
||||||
fn background! {
|
fn background! {
|
||||||
"Sets the background color behind the turtle and path. Alias: bg!"
|
"Sets the background color behind the turtle and path. Alias: bg!"
|
||||||
(color as :keyword) -> add_command! ((:background, color))
|
(color as :keyword) -> add_command! (:turtle_0, (:background, color))
|
||||||
(gray as :number) -> add_command! ((:background, (gray, gray, gray, 255)))
|
(gray as :number) -> add_command! (:turtle_0, (: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)) -> add_command! (:turtle_0, (:background, (r, g, b, 255)))
|
||||||
((r as :number, g as :number, b as :number, a as :number)) -> add_command! ((:background, (r, g, b, a)))
|
((r as :number, g as :number, b as :number, a as :number)) -> add_command! (:turtle_0, (:background, (r, g, b, a)))
|
||||||
}
|
}
|
||||||
|
|
||||||
let bg! = background!
|
let bg! = background!
|
||||||
|
|
||||||
fn home! {
|
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."
|
"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! {
|
fn clear! {
|
||||||
"Clears the canvas and sends the turtle home."
|
"Clears the canvas and sends the turtle home."
|
||||||
() -> add_command! ((:clear))
|
() -> add_command! (:turtle_0, (:clear))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn goto! {
|
fn goto! {
|
||||||
"Sends the turtle to (x, y) coordinates. If the pen is down, the turtle will draw a path to its new location."
|
"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)
|
((x, y)) -> goto! (x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setheading! {
|
fn setheading! {
|
||||||
"Sets the turtle's heading. The angle is specified in turns, with 0 pointing up. Increasing values rotate the turtle counter-clockwise."
|
"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! {
|
fn showturtle! {
|
||||||
"If the turtle is hidden, shows the turtle. If the turtle is already visible, does nothing."
|
"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! {
|
fn hideturtle! {
|
||||||
"If the turtle is visible, hides it. If the turtle is already hidden, does nothing."
|
"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! {
|
fn loadstate! {
|
||||||
"Sets the turtle state to a previously saved state."
|
"Sets the turtle state to a previously saved state."
|
||||||
(state) -> {
|
(state) -> {
|
||||||
let #{position, heading, pendown?, pencolor, penwidth, visible?} = 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)
|
& position () -> (x, y)
|
||||||
fn position {
|
fn position {
|
||||||
"Returns the turtle's current position."
|
"Returns the turtle's current position."
|
||||||
() -> do turtle_state > unbox > :position
|
() -> do turtle_states > unbox > :turtle_0 > :position
|
||||||
}
|
}
|
||||||
|
|
||||||
fn heading {
|
fn heading {
|
||||||
"Returns the turtle's current heading."
|
"Returns the turtle's current heading."
|
||||||
() -> do turtle_state > unbox > :heading
|
() -> do turtle_states > unbox > :turtle_0 > :heading
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pendown? {
|
fn pendown? {
|
||||||
"Returns the turtle's pen state: true if the pen is down."
|
"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 {
|
fn pencolor {
|
||||||
"Returns the turtle's pen color as an (r, g, b, a) tuple or keyword."
|
"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 {
|
fn penwidth {
|
||||||
"Returns the turtle's pen width in pixels."
|
"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
|
&&& 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.
|
And now, we build capacity for building projects.
|
||||||
|
|
||||||
* [ ] allow for multiple turtles
|
* [ ] 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
|
- [ ] write ludus code to spawn & manipulate turtle actors
|
||||||
* [ ] do some sample multiturtle sketches
|
* [ ] 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.call_stack.push(frame);
|
||||||
self.ip = 0;
|
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()))
|
return self.panic_with(format!("{} is not a function", called.show()))
|
||||||
}
|
}
|
||||||
|
@ -1229,6 +1237,15 @@ impl Creature {
|
||||||
self.call_stack.push(frame);
|
self.call_stack.push(frame);
|
||||||
self.ip = 0;
|
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()))
|
return self.panic_with(format!("{} is not a function", called.show()))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user