fix upvalue resolution for forward-declared functions

This commit is contained in:
Scott Richmond 2025-06-23 20:26:26 -04:00
parent 42a5f599f7
commit 772c56a6df
3 changed files with 86 additions and 36 deletions

View File

@ -1029,10 +1029,16 @@ box turtle_state = turtle_init
fn apply_command fn apply_command
fn add_command! (command) -> { fn add_command! (command) -> {
print! ("adding {command}")
update! (turtle_commands, append (_, command)) update! (turtle_commands, append (_, command))
print! ("added command to commands")
print! (turtle_commands)
let prev = unbox (turtle_state) let prev = unbox (turtle_state)
print! ("previous state: {prev}")
let curr = apply_command (prev, command) let curr = apply_command (prev, command)
print! ("new state: {curr}")
store! (turtle_state, curr) store! (turtle_state, curr)
print! ("stored state: {turtle_state}")
:ok :ok
} }
@ -1146,38 +1152,40 @@ fn loadstate! {
fn apply_command { fn apply_command {
"Takes a turtle state and a command and calculates a new state." "Takes a turtle state and a command and calculates a new state."
(state, command) -> match command with { (state, command) -> {
(:goto, (x, y)) -> assoc (state, :position, (x, y)) print!("apply_command:\n{state}\n{command}")
(:home) -> do state > match command with {
assoc (_, :position, (0, 0)) > (:goto, (x, y)) -> assoc (state, :position, (x, y))
assoc (_, :heading, 0) (:home) -> do state >
(:clear) -> do state > assoc (_, :position, (0, 0)) >
assoc (state, :position, (0, 0)) > assoc (_, :heading, 0)
assoc (_, :heading, 0) & (:clear) -> do state >
(:right, turns) -> update (state, :heading, add (_, turns)) & assoc (state, :position, (0, 0)) >
(:left, turns) -> update (state, :heading, sub (_, turns)) & assoc (_, :heading, 0)
(:forward, steps) -> { (:right, turns) -> update (state, :heading, add (_, turns))
let #{heading, position, ...} = state (:left, turns) -> update (state, :heading, sub (_, turns))
let unit = heading/vector (heading) (:forward, steps) -> {
let vect = mult (steps, unit) let #{heading, position, ...} = state
update (state, :position, add (vect, _)) let unit = heading/vector (heading)
} let vect = mult (steps, unit)
(:back, steps) -> { update (state, :position, add (vect, _))
let #{heading, position, ...} = state }
let unit = heading/vector (heading) (:back, steps) -> {
let vect = mult (steps, unit) let #{heading, position, ...} = state
update (state, :position, sub (_, vect)) let unit = heading/vector (heading)
} let vect = mult (steps, unit)
(:penup) -> assoc (state, :pendown?, false) update (state, :position, sub (_, vect))
(:pendown) -> assoc (state, :pendown?, true) }
(:penwidth, pixels) -> assoc (state, :penwidth, pixels) (:penup) -> assoc (state, :pendown?, false)
(:pencolor, color) -> assoc (state, :pencolor, color) (:pendown) -> assoc (state, :pendown?, true)
(:setheading, heading) -> assoc (state, :heading, heading) (:penwidth, pixels) -> assoc (state, :penwidth, pixels)
(:loadstate, position, heading, visible?, pendown?, penwidth, pencolor) -> #{position, heading, visible?, pendown?, penwidth, pencolor} (:pencolor, color) -> assoc (state, :pencolor, color)
(:show) -> assoc (state, :visible?, true) (:setheading, heading) -> assoc (state, :heading, heading)
(:hide) -> assoc (state, :visible?, false) (:loadstate, position, heading, visible?, pendown?, penwidth, pencolor) -> #{position, heading, visible?, pendown?, penwidth, pencolor}
(:background, _) -> state (:show) -> assoc (state, :visible?, true)
} (:hide) -> assoc (state, :visible?, false)
(:background, _) -> state
}}
} }
& position () -> (x, y) & position () -> (x, y)

View File

@ -1,2 +1,37 @@
let state = unbox (turtle_state) fn apply_command {
apply_command(state, (:penup)) "Takes a turtle state and a command and calculates a new state."
(state, command) -> match command with {
(:goto, (x, y)) -> assoc (state, :position, (x, y))
(:home) -> do state >
assoc (_, :position, (0, 0)) >
assoc (_, :heading, 0)
(:clear) -> do state >
assoc (state, :position, (0, 0)) >
assoc (_, :heading, 0)
(:right, turns) -> update (state, :heading, add (_, turns))
(:left, turns) -> update (state, :heading, sub (_, turns))
(:forward, steps) -> {
let #{heading, position, ...} = state
let unit = heading/vector (heading)
let vect = mult (steps, unit)
update (state, :position, add (vect, _))
}
(:back, steps) -> {
let #{heading, position, ...} = state
let unit = heading/vector (heading)
let vect = mult (steps, unit)
update (state, :position, sub (_, vect))
}
(:penup) -> assoc (state, :pendown?, false)
(:pendown) -> assoc (state, :pendown?, true)
(:penwidth, pixels) -> assoc (state, :penwidth, pixels)
(:pencolor, color) -> assoc (state, :pencolor, color)
(:setheading, heading) -> assoc (state, :heading, heading)
(:loadstate, position, heading, visible?, pendown?, penwidth, pencolor) -> #{position, heading, visible?, pendown?, penwidth, pencolor}
(:show) -> assoc (state, :visible?, true)
(:hide) -> assoc (state, :visible?, false)
(:background, _) -> state
}
}
apply_command (turtle_init, (:penup))

View File

@ -606,8 +606,15 @@ impl Vm {
} }
LoadDictValue => { LoadDictValue => {
let dict_idx = self.chunk().bytecode[self.ip + 1] as usize; let dict_idx = self.chunk().bytecode[self.ip + 1] as usize;
let Value::Dict(dict) = self.stack[dict_idx].clone() else { let dict = match self.stack[dict_idx].clone() {
unreachable!("expected dict, got something else") Value::Dict(dict) => dict,
value => {
println!(
"internal Ludus error in function {}",
self.frame.function.as_fn().name()
);
unreachable!("expected dict, got {value}")
}
}; };
let Value::Keyword(key) = self.pop() else { let Value::Keyword(key) = self.pop() else {
unreachable!("expected keyword, got something else") unreachable!("expected keyword, got something else")