From 9d798e5e586a99fbe8787d6d1160b72919e304df Mon Sep 17 00:00:00 2001 From: Scott Richmond Date: Sun, 22 Jun 2025 21:15:17 -0400 Subject: [PATCH] fix interpolated string stack discipline --- assets/test_prelude.ld | 60 ++++++++++++++++++++++++++++++------------ sandbox.ld | 13 ++------- src/compiler.rs | 12 ++++++--- 3 files changed, 53 insertions(+), 32 deletions(-) diff --git a/assets/test_prelude.ld b/assets/test_prelude.ld index b9db177..7c4a5c5 100644 --- a/assets/test_prelude.ld +++ b/assets/test_prelude.ld @@ -275,22 +275,45 @@ fn print! { } } -& fn show { -& "Returns a text representation of a Ludus value as a string." -& (x) -> base :show (x) -& } +fn show { + "Returns a text representation of a Ludus value as a string." + (x) -> base :show (x) +} -& fn report! { -& "Prints a value, then returns it." -& (x) -> { -& print! (x) -& x -& } -& (msg as :string, x) -> { -& print! (concat ("{msg} ", show (x))) -& x -& } -& } +fn report! { + "Prints a value, then returns it." + (x) -> { + print! (x) + x + } + (msg as :string, x) -> { + print! (concat ("{msg} ", show (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 @@ -327,6 +350,9 @@ fn print! { concat contains? print! - & show - & report! + show + report! + doc! + string + string? } diff --git a/sandbox.ld b/sandbox.ld index 4b07805..fd40910 100644 --- a/sandbox.ld +++ b/sandbox.ld @@ -1,13 +1,4 @@ -fn arity { - () -> 0 - (_) -> 1 - (_, _) -> 2 - (_, _, ...) -> { - and (1, 2, 3) - :many - } -} - -arity(:foo, :bar, :baz) + + diff --git a/src/compiler.rs b/src/compiler.rs index 3d3dfbb..64cd1ab 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -476,6 +476,11 @@ impl<'a> Compiler<'a> { // reset the scope self.leave_scope(); // 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); // load the value from the return register self.load(); @@ -943,13 +948,12 @@ impl<'a> Compiler<'a> { self.stack_depth -= 1; } Arguments(args) => { - self.emit_op(Op::Stash); - self.pop(); + self.store(); let arity = args.len(); for arg in args { self.visit(arg); } - self.emit_op(Op::Load); + self.load(); if tail_pos && i == num_rest_terms - 1 { self.emit_op(Op::TailCall) } else { @@ -1382,7 +1386,6 @@ impl<'a> Compiler<'a> { let allocated = Value::String(Rc::new(str.clone())); self.emit_constant(allocated); self.emit_op(Op::ConcatStrings); - self.stack_depth -= 1; } StringPart::Word(word) => { self.resolve_binding(word); @@ -1390,6 +1393,7 @@ impl<'a> Compiler<'a> { self.emit_op(Op::ConcatStrings); } } + self.stack_depth -= 1; } } Do(terms) => {