fix interpolated string stack discipline

This commit is contained in:
Scott Richmond 2025-06-22 21:15:17 -04:00
parent f0cf43b486
commit 9d798e5e58
3 changed files with 53 additions and 32 deletions

View File

@ -275,22 +275,45 @@ fn print! {
} }
} }
& fn show { fn show {
& "Returns a text representation of a Ludus value as a string." "Returns a text representation of a Ludus value as a string."
& (x) -> base :show (x) (x) -> base :show (x)
& } }
& fn report! { fn report! {
& "Prints a value, then returns it." "Prints a value, then returns it."
& (x) -> { (x) -> {
& print! (x) print! (x)
& x x
& } }
& (msg as :string, x) -> { (msg as :string, x) -> {
& print! (concat ("{msg} ", show (x))) print! (concat ("{msg} ", show (x)))
& x x
& } }
& } }
fn doc! {
"Prints the documentation of a function to the console."
(f as :fn) -> do f > base :doc! > print!
(_) -> :none
}
&&& strings: harder than they look!
fn string? {
"Returns true if a value is a string."
(x as :string) -> true
(_) -> false
}
fn string {
"Converts a value to a string by using `show`. If it is a string, returns it unharmed. Use this to build up strings of different kinds of values."
(x as :string) -> x
(x) -> show (x)
(x, ...xs) -> loop (string (x), xs) with {
(out, [y]) -> concat (out, show (y))
(out, [y, ...ys]) -> recur (concat (out, show (y)), ys)
}
}
#{ #{
type type
@ -327,6 +350,9 @@ fn print! {
concat concat
contains? contains?
print! print!
& show show
& report! report!
doc!
string
string?
} }

View File

@ -1,13 +1,4 @@
fn arity {
() -> 0
(_) -> 1
(_, _) -> 2
(_, _, ...) -> {
and (1, 2, 3)
:many
}
}
arity(:foo, :bar, :baz)

View File

@ -476,6 +476,11 @@ impl<'a> Compiler<'a> {
// reset the scope // reset the scope
self.leave_scope(); self.leave_scope();
// reset the stack // reset the stack
self.report_depth("leaving block before pop");
self.msg(format!(
"popping back from {} to {}",
self.stack_depth, stack_depth,
));
self.pop_n(self.stack_depth - stack_depth); self.pop_n(self.stack_depth - stack_depth);
// load the value from the return register // load the value from the return register
self.load(); self.load();
@ -943,13 +948,12 @@ impl<'a> Compiler<'a> {
self.stack_depth -= 1; self.stack_depth -= 1;
} }
Arguments(args) => { Arguments(args) => {
self.emit_op(Op::Stash); self.store();
self.pop();
let arity = args.len(); let arity = args.len();
for arg in args { for arg in args {
self.visit(arg); self.visit(arg);
} }
self.emit_op(Op::Load); self.load();
if tail_pos && i == num_rest_terms - 1 { if tail_pos && i == num_rest_terms - 1 {
self.emit_op(Op::TailCall) self.emit_op(Op::TailCall)
} else { } else {
@ -1382,7 +1386,6 @@ impl<'a> Compiler<'a> {
let allocated = Value::String(Rc::new(str.clone())); let allocated = Value::String(Rc::new(str.clone()));
self.emit_constant(allocated); self.emit_constant(allocated);
self.emit_op(Op::ConcatStrings); self.emit_op(Op::ConcatStrings);
self.stack_depth -= 1;
} }
StringPart::Word(word) => { StringPart::Word(word) => {
self.resolve_binding(word); self.resolve_binding(word);
@ -1390,6 +1393,7 @@ impl<'a> Compiler<'a> {
self.emit_op(Op::ConcatStrings); self.emit_op(Op::ConcatStrings);
} }
} }
self.stack_depth -= 1;
} }
} }
Do(terms) => { Do(terms) => {