From d22f2647e2f850879f0bdb9db196b5a4130bbf97 Mon Sep 17 00:00:00 2001 From: Rigidity Date: Mon, 24 Jun 2024 08:52:54 -0400 Subject: [PATCH 1/2] Functional programming utilities --- .../rue-compiler/src/database/type_system.rs | 8 ++++--- std/stdlib.rue | 24 +++++++++++++++++++ tests/stdlib/fp_utils.rue | 4 ++++ 3 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 tests/stdlib/fp_utils.rue diff --git a/crates/rue-compiler/src/database/type_system.rs b/crates/rue-compiler/src/database/type_system.rs index ab36c6d..e59e918 100644 --- a/crates/rue-compiler/src/database/type_system.rs +++ b/crates/rue-compiler/src/database/type_system.rs @@ -220,7 +220,7 @@ impl Database { (Type::Alias(..), _) | (_, Type::Alias(..)) => unreachable!(), // We need to infer `Generic` types, and return `Unrelated` if incompatible. - (_, Type::Generic) if ctx.infer_generics => { + (_, Type::Generic) => { let mut found = None; for generics in ctx.generic_type_stack.iter().rev() { @@ -231,9 +231,11 @@ impl Database { if let Some(found) = found { self.compare_type_visitor(lhs, found, ctx) - } else { + } else if ctx.infer_generics { ctx.generic_type_stack.last_mut().unwrap().insert(rhs, lhs); Comparison::Assignable + } else { + Comparison::Unrelated } } @@ -264,7 +266,7 @@ impl Database { // `Generic` types are unrelated to everything else except their specific instance. // The only exception is the `Any` type above. - (Type::Generic, _) | (_, Type::Generic) => Comparison::Unrelated, + (Type::Generic, _) => Comparison::Unrelated, // You have to explicitly convert between other atom types. // This is because the compiled output can change depending on the type. diff --git a/std/stdlib.rue b/std/stdlib.rue index 0b0f01c..108ca2d 100644 --- a/std/stdlib.rue +++ b/std/stdlib.rue @@ -196,3 +196,27 @@ export fun calculate_coin_id( assert puzzle_hash is Bytes32; sha256(parent_coin_id + puzzle_hash + amount as Bytes) } + +export fun map(list: T[], fn: fun(T) -> U) -> U[] { + if list is Nil { + return nil; + } + [fn(list.first), ...map(list.rest, fn)] +} + +export fun filter(list: T[], fn: fun(T) -> Bool) -> T[] { + if list is Nil { + return nil; + } + if fn(list.first) { + return [list.first, ...filter(list.rest, fn)]; + } + filter(list.rest, fn) +} + +export fun fold(list: T[], initial: U, fn: fun(U, T) -> U) -> U { + if list is Nil { + return initial; + } + fold(list.rest, fn(initial, list.first), fn) +} diff --git a/tests/stdlib/fp_utils.rue b/tests/stdlib/fp_utils.rue new file mode 100644 index 0000000..5fd07a6 --- /dev/null +++ b/tests/stdlib/fp_utils.rue @@ -0,0 +1,4 @@ +fun main() -> Nil { + assert tree_hash(map([1, 2, 3], fun(num: Int) => num * 2)) == tree_hash([2, 4, 6]); + nil +} From b8f5fed035e2cbfdb19b3b3f85ed0bfdf20e9492 Mon Sep 17 00:00:00 2001 From: Rigidity Date: Mon, 24 Jun 2024 08:56:30 -0400 Subject: [PATCH 2/2] Rest of test --- tests.toml | 7 +++++++ tests/stdlib/fp_utils.rue | 2 ++ 2 files changed, 9 insertions(+) diff --git a/tests.toml b/tests.toml index c2bb852..0838dea 100644 --- a/tests.toml +++ b/tests.toml @@ -216,3 +216,10 @@ cost = 24974 input = "(0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 () (q . ((51 0x291e4594b43d58e833cab95e4b165c5fac6b4d8391c81ebfd20efdd8d58b92d8 1000))) 1)" output = "((g1_multiply 0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0x3d7e1145b5969c12f4889f4f1f66bde0e4d3ba54b91784cf604294d162b44b69) (g1_negate 0x291e4594b43d58e833cab95e4b165c5fac6b4d8391c81ebfd20efdd8d58b92d8 1000))" hash = "670f06e052dedc68788dd17acb7d100203a1533d11f9c679d0f23bd3d555f122" + +[fp_utils] +bytes = 873 +cost = 92626 +input = "()" +output = "()" +hash = "5f8d285dbefef4c4c7ccfcc4f204710c21f46ea45bfe6d5b4e81562ef183adde" diff --git a/tests/stdlib/fp_utils.rue b/tests/stdlib/fp_utils.rue index 5fd07a6..0df9528 100644 --- a/tests/stdlib/fp_utils.rue +++ b/tests/stdlib/fp_utils.rue @@ -1,4 +1,6 @@ fun main() -> Nil { assert tree_hash(map([1, 2, 3], fun(num: Int) => num * 2)) == tree_hash([2, 4, 6]); + assert tree_hash(filter([1, 2, 3, 4, 5], fun(num: Int) => num < 4)) == tree_hash([1, 2, 3]); + assert tree_hash(fold([1, 2, 3], 0, fun(acc: Int, num: Int) => acc + num)) == tree_hash(6); nil }