A bunch of prerequisites before we can do arrays, part 3.1, using the pool pointer in calls (removes the cursed test case)

This commit is contained in:
2023-11-13 00:44:26 -06:00
parent 325288d7ba
commit 749b11adfa
3 changed files with 26 additions and 11 deletions
+5 -9
View File
@@ -16,13 +16,10 @@ impl Compilable for Call {
arg.process(state, Some(sig), loc)?; arg.process(state, Some(sig), loc)?;
} }
// Now we increment the frame ptr to right after the current frame: // Whatever shall we send as a frame pointer to the new fn? Our pool pointer, because we
// see cursed test case in vtest/forge_tests.rs // know that's free, even if we've alloced anything, it'll increment it:
sig.emit("peekr"); sig.emit("popr"); sig.emit("peekr"); // take the frame ptr off and copy the pool off
let frame_size = sig.frame_size(); sig.emit("swap"); sig.emit("pushr"); // swap the pool under the frame and put the frame back on
if frame_size > 0 {
sig.emit_arg("add", frame_size);
}
// Eval the target // Eval the target
self.target.0.process(state, Some(sig), loc)?; self.target.0.process(state, Some(sig), loc)?;
@@ -51,8 +48,7 @@ mod test {
vec![ vec![
"push 2", // evaluating args, in order "push 2", // evaluating args, in order
"push 3", "push 3",
"peekr", // The new fn's frame ptr: "popr", "peekr", "swap", "pushr", // Pool ptr to send to the new call
"add 6",
"push _forge_gensym_1", // evaluating target (this fn) "push _forge_gensym_1", // evaluating target (this fn)
"call", // Actually make the call "call", // Actually make the call
"pop", // expr-as-statement drops the evaluated value "pop", // expr-as-statement drops the evaluated value
+1 -1
View File
@@ -140,7 +140,7 @@ mod test {
"_forge_gensym_3:", // fn main() "_forge_gensym_3:", // fn main()
"dup", "pushr", // capture pool ptr "dup", "pushr", // capture pool ptr
"pushr", // capture frame ptr "pushr", // capture frame ptr
"peekr", // prep frame ptr to send to foo "popr", "peekr", "swap", "pushr", // Grab pool ptr to send to foo
"push _forge_gensym_1", // load foo "push _forge_gensym_1", // load foo
"call", // call it "call", // call it
"pop", // Throw away its return value "pop", // Throw away its return value
+20 -1
View File
@@ -86,7 +86,26 @@ fn scope_test() {
} }
#[test] #[test]
fn cursed_call_test() { fn recursion_test() {
// Recursive call with some stuff in it
assert_eq!(
main_return(
"fn sum(n) {
if (n > 0) {
return n + sum(n - 1);
} else {
return 0;
}
}
fn main() { return sum(5); }"),
15
)
}
//#[test]
// This is no longer cursed, or a test. The revised calling convention with the pool pointer makes
// it now perfectly sane. Left here for posterity.
fn _cursed_call_test() {
// This is a cursed subtlety of block scoping and the way calls are compiled. It's not actually // This is a cursed subtlety of block scoping and the way calls are compiled. It's not actually
// a bug. It's explained below: // a bug. It's explained below:
let src = " let src = "