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 add_command! (command) -> {
print! ("adding {command}")
update! (turtle_commands, append (_, command))
print! ("added command to commands")
print! (turtle_commands)
let prev = unbox (turtle_state)
print! ("previous state: {prev}")
let curr = apply_command (prev, command)
print! ("new state: {curr}")
store! (turtle_state, curr)
print! ("stored state: {turtle_state}")
:ok
}
@ -1146,38 +1152,40 @@ fn loadstate! {
fn apply_command {
"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
}
(state, command) -> {
print!("apply_command:\n{state}\n{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
}}
}
& position () -> (x, y)

View File

@ -1,2 +1,37 @@
let state = unbox (turtle_state)
apply_command(state, (:penup))
fn apply_command {
"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 => {
let dict_idx = self.chunk().bytecode[self.ip + 1] as usize;
let Value::Dict(dict) = self.stack[dict_idx].clone() else {
unreachable!("expected dict, got something else")
let dict = match self.stack[dict_idx].clone() {
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 {
unreachable!("expected keyword, got something else")