find a bug in function bindings; TCO is maybe complete?; things are in a shambles

This commit is contained in:
Scott Richmond 2025-06-19 21:47:58 -04:00
parent 7e4ddd3dc4
commit 8b004b45fa
3 changed files with 33 additions and 15 deletions

View File

@ -250,8 +250,8 @@ To reiterate the punch list that *I would have needed for Computer Class 1*:
- [ ] Identify others
* [x] add guards to loop forms
* [x] check loop forms against function calls: do they still work the way we want them to?
* [ ] tail call elimination
* [ ] stack traces in panics
* [x] tail call elimination
* [x] stack traces in panics
* [ ] actually good error messages
- [ ] parsing
- [ ] my memory is that validator messages are already good?
@ -277,3 +277,14 @@ Just trying to get a sense of what needs to happen for CC2:
- [ ] Makey makey for alternate input?
* [ ] Saving and loading data into Ludus (perceptrons, dissociated press)
* [ ] Finding corpuses for Dissociated Press
### Final touches on semantics, or lots of bugs
#### 2025-06-19
* Main code is fucking up bindings in functions
* Why?
* In the middle of doing TCO, looks like it works for `do` forms based on the bytecode, but I ran into these weird binding problems while trying to test that in the vm
* Once that's put to bed, I believe TCO fully works
* But then I need to test it actually works in its intended use case: recursive calls
* Which means I need to test recursive calls
* And, once that's done, I think I have a COMPLETE SEMANTICALLY CORRECT INTERPRETER.
* After that, jesus, it's time for base > prelude > test cases

View File

@ -1095,10 +1095,7 @@ impl<'a> Compiler<'a> {
}
self.resolve_binding(fn_name);
// if we're in tail position AND there aren't any rest args, this should be a tail call (I think)
if rest.is_empty() {
self.tail_pos = tail_pos;
}
if self.tail_pos {
if rest.is_empty() && tail_pos {
self.emit_op(Op::TailCall);
} else {
self.emit_op(Op::Call);
@ -1112,7 +1109,8 @@ impl<'a> Compiler<'a> {
_ => unreachable!(),
}
// the last term in rest should be in tail position if we are in tail position
for (term, _) in rest {
let num_rest_terms = rest.len();
for (i, (term, _)) in rest.iter().enumerate() {
match term {
Keyword(str) => {
self.emit_constant(Value::Keyword(str));
@ -1127,13 +1125,18 @@ impl<'a> Compiler<'a> {
self.visit(arg);
}
self.emit_op(Op::Load);
if tail_pos && i == num_rest_terms - 1 {
self.emit_op(Op::TailCall)
} else {
self.emit_op(Op::Call);
}
self.emit_byte(arity);
self.stack_depth -= arity;
}
_ => unreachable!(),
}
}
self.tail_pos = tail_pos;
}
When(clauses) => {
let tail_pos = self.tail_pos;
@ -1497,10 +1500,14 @@ impl<'a> Compiler<'a> {
self.emit_byte(1);
self.stack_depth -= 1;
}
self.tail_pos = tail_pos;
self.visit(last);
if tail_pos {
self.emit_op(Op::TailCall)
} else {
self.emit_op(Op::Call);
}
self.emit_byte(1);
self.tail_pos = tail_pos;
self.stack_depth -= 1;
}
Placeholder => {

View File

@ -75,12 +75,12 @@ pub fn run(src: &'static str) {
pub fn main() {
env::set_var("RUST_BACKTRACE", "1");
let src = "
fn recursive {
(0) -> :done
(n) -> recursive (0)
}
fn add_one (x) -> add (x, 1)
fn double (x) -> add (x, x)
fn square (x) -> mult (x, x)
double (2)
recursive (1)
";
run(src);
}