From e2c9619fa6cd77c004f46b9ce2da6d0074b56dd0 Mon Sep 17 00:00:00 2001 From: Scott Richmond Date: Sun, 22 Jun 2025 20:43:51 -0400 Subject: [PATCH] update block stack work --- assets/test_prelude.ld | 67 ++++++++++++++++++++++++++++++++++-------- sandbox.ld | 20 ++++++------- src/compiler.rs | 18 +----------- 3 files changed, 65 insertions(+), 40 deletions(-) diff --git a/assets/test_prelude.ld b/assets/test_prelude.ld index 4455377..0bacc82 100644 --- a/assets/test_prelude.ld +++ b/assets/test_prelude.ld @@ -51,11 +51,11 @@ fn some { & ...and if two things are the same fn eq? { "Returns true if all arguments have the same value." - & (x) -> true + (x) -> true (x, y) -> base :eq? (x, y) (x, y, ...zs) -> if eq? (x, y) then loop (y, zs) with { - (a, []) -> eq? (a, x) + (a, [b]) -> and (eq? (a, x), eq? (b, x)) (a, [b, ...cs]) -> if eq? (a, x) then recur (b, cs) else false @@ -115,19 +115,19 @@ fn fn? { fn first { "Retrieves the first element of an ordered collection--a tuple or a list. If the collection is empty, returns nil." ([]) -> nil - & (()) -> nil + (()) -> nil & ("") -> nil (xs as :list) -> base :first (xs) - & (xs as :tuple) -> base :first (xs) + (xs as :tuple) -> base :first (xs) & (str as :string) -> base :slice (str, 0, 1) } fn rest { "Returns all but the first element of a list or tuple, as a list." ([]) -> [] - & (()) -> () + (()) -> () (xs as :list) -> base :rest (xs) - & (xs as :tuple) -> base :rest (xs) + (xs as :tuple) -> base :rest (xs) & (str as :string) -> base :rest (str) } @@ -203,18 +203,33 @@ fn fold { } } +fn foldr { + "Folds a list, right-associatively." + (f as :fn, []) -> [] + (f as :fn, xs as :list) -> foldr(f, xs, f ()) + (f as :fn, [], root) -> [] + (f as :fn, xs as :list, root) -> loop (root, first (xs), rest (xs)) with { + (prev, curr, []) -> f (curr, prev) + (prev, curr, remaining) -> recur ( + f (curr, prev) + first (remaining) + rest (remaining) + ) + } +} + fn map { "Maps a function over a list: returns a new list with elements that are the result of applying the function to each element in the original list. E.g., `map ([1, 2, 3], inc) &=> [2, 3, 4]`. With one argument, returns a function that is a mapper over lists; with two, it executes the mapping function right away." - & (f as :fn) -> map (f, _) - & (kw as :keyword) -> map (kw, _) + (f as :fn) -> map (f, _) + (kw as :keyword) -> map (kw, _) (f as :fn, xs) -> { fn mapper (prev, curr) -> append (prev, f (curr)) fold (mapper, xs, []) } - & (kw as :keyword, xs) -> { - & fn mapper (prev, curr) -> append (prev, kw (curr)) - & fold (mapper, xs, []) - & } + (kw as :keyword, xs) -> { + fn mapper (prev, curr) -> append (prev, kw (curr)) + fold (mapper, xs, []) + } } fn filter { @@ -252,6 +267,30 @@ fn contains? { } } +& fn print! { +& "Sends a text representation of Ludus values to the console." +& (...args) -> { +& base :print! (args) +& :ok +& } +& } + +& 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 +& } +& } #{ type @@ -280,10 +319,14 @@ fn contains? { list first fold + foldr append map filter keep concat contains? + & print! + & show + & report! } diff --git a/sandbox.ld b/sandbox.ld index d123411..4b07805 100644 --- a/sandbox.ld +++ b/sandbox.ld @@ -1,15 +1,13 @@ -fn my_eq? { - (x, y, ...zs) -> if eq? (x, y) - then loop (y, zs) with { - (a, [b]) -> and (eq? (a, x), eq? (b, x)) - (a, [b, ...cs]) -> if eq? (a, x) - then recur (b, cs) - else false - } - else false +fn arity { + () -> 0 + (_) -> 1 + (_, _) -> 2 + (_, _, ...) -> { + and (1, 2, 3) + :many + } } -my_eq? (1, 1, 3) - +arity(:foo, :bar, :baz) diff --git a/src/compiler.rs b/src/compiler.rs index 468bcc2..3d3dfbb 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -433,7 +433,6 @@ impl<'a> Compiler<'a> { self.tail_pos = false; // increase the scope self.enter_scope(); - // self.scope_depth += 1; // stash the stack depth let stack_depth = self.stack_depth; // evaluate all the lines but the last @@ -454,7 +453,6 @@ impl<'a> Compiler<'a> { // we do this by pretending it's a binding (Let(patt, expr), _) => { // self.match_depth = 0; - // self.emit_op(Op::ResetMatch); self.visit(expr); let expr_pos = self.stack_depth - 1; self.report_ast("let binding: matching".to_string(), patt); @@ -472,28 +470,15 @@ impl<'a> Compiler<'a> { } } - // we've made a new value, so increase the stack level in the compiler - self.stack_depth += 1; - // store the value in the return register - // self.emit_op(Op::Store); self.store(); // reset the scope self.leave_scope(); - // self.scope_depth -= 1; - // while let Some(binding) = self.bindings.last() { - // if binding.depth > self.scope_depth { - // self.bindings.pop(); - // } else { - // break; - // } - // } // reset the stack - self.pop_n(self.stack_depth - stack_depth - 1); + self.pop_n(self.stack_depth - stack_depth); // load the value from the return register self.load(); - // self.emit_op(Op::Load); } If(cond, then, r#else) => { let tail_pos = self.tail_pos; @@ -1156,7 +1141,6 @@ impl<'a> Compiler<'a> { } compiler.tail_pos = true; compiler.visit(clause_body); - // compiler.emit_op(Op::Store); compiler.store(); compiler.scope_depth -= 1; while let Some(binding) = compiler.bindings.last() {