From 3bcda6668c5515d950f289c8ac18930b34376766 Mon Sep 17 00:00:00 2001 From: Kelvin Steiner Date: Mon, 17 Jun 2024 20:25:52 -0300 Subject: [PATCH 1/3] add vscode recommended extensions; cleaning --- .vscode/extensions.json | 8 +++++++- crates/placeholder/Cargo.toml | 6 ------ crates/placeholder/src/main.rs | 3 --- result | 1 - 4 files changed, 7 insertions(+), 11 deletions(-) delete mode 100644 crates/placeholder/Cargo.toml delete mode 100644 crates/placeholder/src/main.rs delete mode 120000 result diff --git a/.vscode/extensions.json b/.vscode/extensions.json index b3c9d51..170387d 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,5 +1,11 @@ { "recommendations": [ - "rust-lang.rust-analyzer" + "rust-lang.rust-analyzer", + "editorconfig.editorconfig", + "streetsidesoftware.code-spell-checker", + "mkhl.direnv", + "tamasfe.even-better-toml", + "jnoortheen.nix-ide", + "foxundermoon.shell-format" ] } diff --git a/crates/placeholder/Cargo.toml b/crates/placeholder/Cargo.toml deleted file mode 100644 index 7a669c7..0000000 --- a/crates/placeholder/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "placeholder" -version = "0.1.0" -edition = "2021" - -[dependencies] diff --git a/crates/placeholder/src/main.rs b/crates/placeholder/src/main.rs deleted file mode 100644 index e7a11a9..0000000 --- a/crates/placeholder/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} diff --git a/result b/result deleted file mode 120000 index 11a79e9..0000000 --- a/result +++ /dev/null @@ -1 +0,0 @@ -/nix/store/azwmb2sjg9zz83ybcfgh2l4yz2jgx163-rust-workspace-unknown \ No newline at end of file From fd30af7596e5cb05e2d6eb125628395b36f0721e Mon Sep 17 00:00:00 2001 From: Kelvin Steiner Date: Tue, 18 Jun 2024 07:37:41 -0300 Subject: [PATCH 2/3] moving transpilation examples --- Cargo.lock | 4 ---- examples/future/README.md | 4 ++++ examples/{ => future}/fib.py | 22 +++++----------------- examples/{ => future}/simple.py | 2 +- examples/{ => future}/tree.py | 12 ++++++++---- 5 files changed, 18 insertions(+), 26 deletions(-) create mode 100644 examples/future/README.md rename examples/{ => future}/fib.py (63%) rename examples/{ => future}/simple.py (86%) rename examples/{ => future}/tree.py (71%) diff --git a/Cargo.lock b/Cargo.lock index 5417237..a5fa6df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -559,10 +559,6 @@ dependencies = [ "siphasher", ] -[[package]] -name = "placeholder" -version = "0.1.0" - [[package]] name = "portable-atomic" version = "1.6.0" diff --git a/examples/future/README.md b/examples/future/README.md new file mode 100644 index 0000000..3a20ad8 --- /dev/null +++ b/examples/future/README.md @@ -0,0 +1,4 @@ +# benda/examples/future + +Examples of code that we intend to support in the future. Mainly about translating +a subset of Python code to Bend/HVM. diff --git a/examples/fib.py b/examples/future/fib.py similarity index 63% rename from examples/fib.py rename to examples/future/fib.py index 1eabe47..7b0c05e 100644 --- a/examples/fib.py +++ b/examples/future/fib.py @@ -1,21 +1,10 @@ from typing import TypeVar -# from benda import bjit +from benda import bjit, bend T = TypeVar("T") -def bend(fn: T) -> T: - """ - Decorator that hints the transpiler that a call to the recursive function - should be translated to an inline `bend` block. - - This decorator is intended to be defined internally by the benda library. - """ - return fn - -# @bjit - - +@bjit def fib_recursive(n: int) -> int: """ Calculates the nth Fibonacci number using a recursive approach. @@ -28,16 +17,15 @@ def fib_recursive(n: int) -> int: case _: return fib_recursive(n - 2) + fib_recursive(n - 1) -# @bjit - +@bjit def fib_iterative(n: int) -> int: """ Calculates the nth Fibonacci number using an iterative (tail-recursive) approach. """ - # This decorator does nothing, it just hints the benda transpiler to - # use a `bend` block for the recursive computation. + # This decorator hints the Benda transpiler to use a `bend` block for the + # recursive computation. @bend def go(a: int, b: int, n: int) -> int: if n == 0: diff --git a/examples/simple.py b/examples/future/simple.py similarity index 86% rename from examples/simple.py rename to examples/future/simple.py index ada81ce..1bed79b 100644 --- a/examples/simple.py +++ b/examples/future/simple.py @@ -11,4 +11,4 @@ def simple() -> u24: if __name__ == "__main__": translated_simple = bjit(simple) print(simple()) - print(translated_simple()) \ No newline at end of file + print(translated_simple()) diff --git a/examples/tree.py b/examples/future/tree.py similarity index 71% rename from examples/tree.py rename to examples/future/tree.py index fb59eca..9c43dad 100644 --- a/examples/tree.py +++ b/examples/future/tree.py @@ -1,6 +1,9 @@ from dataclasses import dataclass +import random + from benda import bjit, u24 + @dataclass class MyLeaf: value: u24 @@ -24,14 +27,15 @@ def sum_tree(tree: MyTree) -> u24: return sum_tree(left) + sum_tree(right) -def gen_tree(depth: int, n: int) -> MyTree: +def gen_tree(depth: int) -> MyTree: + n = random.randint(0, 1000) if depth == 0: return MyLeaf(value=n) else: - return MyNode(left=gen_tree(depth-1, n-1), right=gen_tree(depth-1, n+1)) + return MyNode(left=gen_tree(depth-1), right=gen_tree(depth-1)) if __name__ == "__main__": - tree = gen_tree(4, 10) + tree = gen_tree(4) print(tree) - print(sum_tree(tree)) \ No newline at end of file + print(sum_tree(tree)) From dc209059e5a708763c195966305cd654e590b1e3 Mon Sep 17 00:00:00 2001 From: Kelvin Steiner Date: Tue, 18 Jun 2024 08:40:06 -0300 Subject: [PATCH 3/3] update quicksort.py example --- Makefile | 3 + examples/future/__init__.py | 0 examples/quicksort.bend | 27 +++++---- examples/quicksort.py | 115 +++++++++++++----------------------- examples/quicksort_mock.py | 74 +++++++++++++++++++++++ 5 files changed, 134 insertions(+), 85 deletions(-) create mode 100644 examples/future/__init__.py create mode 100644 examples/quicksort_mock.py diff --git a/Makefile b/Makefile index 89a19e2..68e3868 100644 --- a/Makefile +++ b/Makefile @@ -17,3 +17,6 @@ rust-fmt: build: cd crates/benda; \ maturin develop + +run_examples: + python -m examples.quicksort diff --git a/examples/future/__init__.py b/examples/future/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/quicksort.bend b/examples/quicksort.bend index 84f0296..fa2dfba 100644 --- a/examples/quicksort.bend +++ b/examples/quicksort.bend @@ -1,20 +1,26 @@ type MyTree = Leaf | (Node lft val rgt) # Parallel QuickSort -(Sort List/Nil) = MyTree/Leaf +(Sort List/Nil) = List/Nil (Sort (List/Cons head tail)) = ((Part head tail) λmin λmax let lft = (Sort min) let rgt = (Sort max) - (MyTree/Node lft head rgt)) + (Concat lft (List/Cons head rgt))) - # Partitions a list in two halves, less-than-p and greater-than-p - (Part p List/Nil) = λt (t List/Nil List/Nil) - (Part p (List/Cons head tail)) = (Push (> head p) head (Part p tail)) +# Partitions a list in two halves, less-than-p and greater-than-p +(Part p List/Nil) = λt (t List/Nil List/Nil) +(Part p (List/Cons head tail)) = (Push (> head p) head (Part p tail)) - # Pushes a value to the first or second list of a pair - (Push 0 x pair) = (pair λmin λmax λp (p (List/Cons x min) max)) - (Push _ x pair) = (pair λmin λmax λp (p min (List/Cons x max))) +# Pushes a value to the first or second list of a pair +(Push 0 x pair) = (pair λmin λmax λp (p (List/Cons x min) max)) +(Push _ x pair) = (pair λmin λmax λp (p min (List/Cons x max))) + +(Concat List/Nil tail) = tail +(Concat (List/Cons head tail) xs2) = + (List/Cons head (Concat tail xs2)) + +# --- Test --- # Generates a random list with xorshift (Rnd 0 state) = List/Nil @@ -25,10 +31,11 @@ type MyTree = Leaf | (Node lft val rgt) (List/Cons state (Rnd (- n 1) state)) # Sums all elements in a concatenation tree -(Sum MyTree/Leaf) = 0 -(Sum (MyTree/Node lft val rgt)) = (+ val (+ (Sum lft) (Sum rgt))) +(Sum List/Nil) = 0 +(Sum (List/Cons head tail)) = (+ head (Sum tail)) # Sorts and sums n random numbers +# Result: 12741879 (Main) = (Sum (Sort (Rnd 0x100 1))) diff --git a/examples/quicksort.py b/examples/quicksort.py index 33c8414..1f34d0c 100644 --- a/examples/quicksort.py +++ b/examples/quicksort.py @@ -1,104 +1,69 @@ -from typing import TypeVar, Generic -from dataclasses import dataclass +from typing import TypeVar import random +from .quicksort_mock import u24, List, List_Cons, List_Nil, mock_sort + T = TypeVar("T") -# --> Our Target # import benda # from benda import u24 - # book = benda.load_book_from_file("./quicksort.bend") # List_Nil = book.adts.List.Nil # List_Cons = book.adts.List.Cons -# MyTree_Leaf = book.adts.MyTree.Leaf -# MyTree_Node = book.adts.MyTree.Node - - -# -> Mock - -u24 = int - - -@dataclass -class List_Nil: - pass - - -@dataclass -class List_Cons(Generic[T]): - value: T - tail: "List[T]" - - -List = List_Nil | List_Cons[T] - - -@dataclass -class MyTree_Leaf: - pass - - -@dataclass -class MyTree_Node(Generic[T]): - value: T - left: "MyTree[T]" - right: "MyTree[T]" - -MyTree = MyTree_Leaf | MyTree_Node[T] +def gen_list(n: int, max_value: int = 0xffffff) -> list[u24]: + """Generates an array of random u24 numbers with the `random` package""" + result: list[u24] = [] + for _ in range(n): + result.append(u24(random.randint(0, max_value))) + return result -def gen_list(n: int, max_value: int) -> List[u24]: - if n <= 0: - return List_Nil() - else: - value = random.randint(0, max_value) - return List_Cons(u24(value), gen_list(n-1, max_value)) +def to_cons_list(xs: list[int]) -> List[u24]: + """Converts a Python list to a Bend cons-list""" + result = List_Nil() -def print_tree(tree: MyTree[u24]): - match tree: - case MyTree_Leaf(): - pass - case MyTree_Node(value, left, right): - print(value) - print_tree(left) - print_tree(right) + hi = len(xs) + if hi == 0: + return result + while hi > 0: + hi -= 1 + result = List_Cons(u24(xs[hi]), result) -def list_to_tree(list: List[u24]) -> MyTree[u24]: - match list: - case List_Nil(): - return MyTree_Leaf() - case List_Cons(value, tail): - return MyTree_Node(value, MyTree_Leaf(), list_to_tree(tail)) + return result -def mock_sum(tree: MyTree[u24]) -> u24: - match tree: - case MyTree_Leaf(): - return u24(0) - case MyTree_Node(value, left, right): - return value + mock_sum(left) + mock_sum(right) +def from_cons_list(xs: List[u24]) -> list[u24]: + """Converts a Bend cons-list to a Python list""" + result: list[u24] = [] + while True: + match xs: + case List_Nil(): + return result + case List_Cons(value, tail): + result.append(value) + xs = tail def main(): - numbers = gen_list(7, 1000) - print(numbers) + data = gen_list(10, 1000) + print("Data: ", data) - # tree = benda.run(book.defs.Sort, [numbers]) - # tree = book.defs.Sort(numbers) + expected = sorted(data) + print("Expected:", expected) - tree = list_to_tree(numbers) - print("Values:") - print_tree(tree) + cons_list = to_cons_list(data) - # result = book.run(book.defs.Sum, [tree]) + # sorted_res = book.defs.Sort(cons_list) + # sorted_arr = from_cons_list(sorted_res) + # print("Result: ", sorted_arr) - result = mock_sum(tree) - print("Result:", result) + mocked_sorted = mock_sort(cons_list) + mocked_sorted_arr = from_cons_list(mocked_sorted) + print("Mocked: ", mocked_sorted_arr) if __name__ == "__main__": diff --git a/examples/quicksort_mock.py b/examples/quicksort_mock.py new file mode 100644 index 0000000..1911cab --- /dev/null +++ b/examples/quicksort_mock.py @@ -0,0 +1,74 @@ +from typing import TypeVar, Generic +from dataclasses import dataclass + +T = TypeVar("T") + + +u24 = int + +# Explain + + +@dataclass +class List_Nil: + pass + + +@dataclass +class List_Cons(Generic[T]): + value: T + tail: "List[T]" + + +List = List_Nil | List_Cons[T] + + +@dataclass +class MyTree_Leaf: + pass + + +@dataclass +class MyTree_Node(Generic[T]): + value: T + left: "MyTree[T]" + right: "MyTree[T]" + + +MyTree = MyTree_Leaf | MyTree_Node[T] + + +def partition(list: List[u24], p: u24) -> tuple[List[u24], List[u24]]: + left = List_Nil() + right = List_Nil() + + while True: + match list: + case List_Nil(): + return left, right + case List_Cons(value, tail): + if value <= p: + left = List_Cons(value, left) + else: + right = List_Cons(value, right) + list = tail + + +def concat(xs1: List[u24], xs2: List[u24]) -> List[u24]: + while True: + match xs1: + case List_Nil(): + return xs2 + case List_Cons(value, tail): + return List_Cons(value, concat(tail, xs2)) + + +def mock_sort(list: List[u24]) -> List[u24]: + match list: + case List_Nil(): + return List_Nil() + case List_Cons(value, tail): + [left, right] = partition(tail, value) + left = mock_sort(left) + right = mock_sort(right) + return concat(left, List_Cons(value, right))