From 7d41d42be0e059ae4f4484fe72aadc30a304f3b8 Mon Sep 17 00:00:00 2001 From: vkobinski Date: Sun, 7 Jul 2024 20:39:01 -0300 Subject: [PATCH] Documentation and load_book --- README.md | 3 ++- crates/benda/src/benda_ffi/mod.rs | 4 +-- crates/benda/src/lib.rs | 20 ++++++-------- crates/benda/src/parser/mod.rs | 2 +- crates/benda/src/types/book.rs | 43 ++++++++++++++++++++++++++++--- docs/FFI.md | 40 ++++++++++++++++++++++------ 6 files changed, 84 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 72ce205..465caa4 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [Bend]: https://github.com/HigherOrderCo/bend Read the Docs:
-[FFI](https://github.com/vkobinski/benda-main/tree/master/docs/FFI.md) +[FFI](/docs/FFI.md) This is in MVP stage. @@ -72,6 +72,7 @@ def print_cons_list(list): data = gen_list(5, 1000) cons_list = to_cons_list(data) +book.set_cmd(benda.BendCommand.Cuda) sorted_list = book.defs.Sort(cons_list) sorted_list = sorted_list.to_adt(book.adts.List) print_cons_list(sorted_list) diff --git a/crates/benda/src/benda_ffi/mod.rs b/crates/benda/src/benda_ffi/mod.rs index 28c39d0..c897983 100644 --- a/crates/benda/src/benda_ffi/mod.rs +++ b/crates/benda/src/benda_ffi/mod.rs @@ -6,7 +6,7 @@ use bend::{CompileOpts, RunOpts}; * TODO: move to another module * TODO: docstring */ -pub fn run(book: &Book) -> Option<(Term, String, Diagnostics)> { +pub fn run(book: &Book, cmd: &str) -> Option<(Term, String, Diagnostics)> { let run_opts = RunOpts::default(); let compile_opts = CompileOpts::default().set_all(); let diagnostics_cfg = DiagnosticsConfig::default(); @@ -18,7 +18,7 @@ pub fn run(book: &Book) -> Option<(Term, String, Diagnostics)> { compile_opts, diagnostics_cfg, args, - "run", + cmd, ) .unwrap() } diff --git a/crates/benda/src/lib.rs b/crates/benda/src/lib.rs index b47d38a..acd37e9 100644 --- a/crates/benda/src/lib.rs +++ b/crates/benda/src/lib.rs @@ -1,5 +1,3 @@ -use std::fs::File; -use std::io::Write; use std::path::Path; use num_traits::ToPrimitive; @@ -7,7 +5,7 @@ use parser::Parser; use pyo3::prelude::*; use pyo3::types::{PyDict, PyFunction, PyString, PyTuple}; use rustpython_parser::{parse, Mode}; -use types::book::Book; +use types::book::{BendCommand, Book}; use types::fan::Fan; use types::tree::{Leaf, Node, Tree}; use types::u24::U24; @@ -22,16 +20,13 @@ fn switch() -> PyResult { #[pyfunction] fn load_book(py: Python, code: Py) -> PyResult> { - let mut tmp_file = File::create_new("./tmp/bend_book.tmp") - .expect("Could not create temporary file."); - - let _ = tmp_file.write_all(code.to_string().as_bytes()); - let _ = tmp_file.flush(); - + let builtins = bend::fun::Book::builtins(); let path = Path::new("./tmp/bend_book.tmp"); - let bend_book = bend::load_file_to_book(path); - - let _ = std::fs::remove_file(path); + let bend_book = bend::fun::load_book::do_parse_book( + code.to_string().as_str(), + path, + builtins, + ); let book = Book::new(&mut bend_book.unwrap()); @@ -150,6 +145,7 @@ fn benda(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(switch, m)?)?; m.add_function(wrap_pyfunction!(load_book_from_file, m)?)?; m.add_function(wrap_pyfunction!(load_book, m)?)?; + m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; diff --git a/crates/benda/src/parser/mod.rs b/crates/benda/src/parser/mod.rs index 6a58472..eac290b 100644 --- a/crates/benda/src/parser/mod.rs +++ b/crates/benda/src/parser/mod.rs @@ -885,7 +885,7 @@ impl<'py> Parser<'py> { //println!("BEND:\n {}", self.book.display_pretty()); - let return_val = run(&self.book); + let return_val = run(&self.book, "run"); match return_val { Some(val) => val.0.to_string(), diff --git a/crates/benda/src/types/book.rs b/crates/benda/src/types/book.rs index b557773..44324bb 100644 --- a/crates/benda/src/types/book.rs +++ b/crates/benda/src/types/book.rs @@ -1,5 +1,6 @@ use core::panic; use std::cell::RefCell; +use std::fmt::Display; use std::vec; use bend::fun::{self, Book as BendBook, Name, Rule}; @@ -259,11 +260,31 @@ impl Ctrs { } } +#[pyclass] +#[derive(Clone, Debug, Default)] +pub enum BendCommand { + #[default] + Rust, + C, + Cuda, +} + +impl Display for BendCommand { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + BendCommand::Rust => f.write_str("run"), + BendCommand::C => f.write_str("run-c"), + BendCommand::Cuda => f.write_str("run-cu"), + } + } +} + #[pyclass(name = "Definition")] #[derive(Clone, Debug, Default)] pub struct Definition { arity: usize, name: String, + cmd: Option, } #[pymethods] @@ -356,7 +377,10 @@ impl Definition { b.defs .insert(Name::new("main"), main_def.to_fun(true).unwrap()); - let res = benda_ffi::run(&b.clone()); + let res = benda_ffi::run( + &b.clone(), + &self.cmd.clone().unwrap_or_default().to_string(), + ); GLOBAL_BOOK.set(bend_book); @@ -375,6 +399,7 @@ impl Definition { #[derive(Clone, Debug, Default)] pub struct Definitions { defs: IndexMap, + cmd: Option, } #[pymethods] @@ -385,7 +410,9 @@ impl Definitions { let py = object.py(); if let Some(def) = self.defs.get(field) { - Ok(Py::new(py, def.clone())?) + let mut def = def.clone(); + def.cmd = self.cmd.clone(); + Ok(Py::new(py, def)?) } else { new_err(format!("Could not find attr {}", object)) } @@ -426,6 +453,7 @@ impl Adts { pub struct Book { adts: Adts, defs: Definitions, + cmd: Option, } impl Book { @@ -579,6 +607,7 @@ impl Book { let new_def = Definition { arity: def.arity(), name: def.name.to_string(), + cmd: None, }; definitions.defs.insert(nam.to_string(), new_def); } @@ -591,6 +620,7 @@ impl Book { let benda_book = Self { adts, defs: definitions, + cmd: None, }; GLOBAL_BENDA_BOOK.set(Some(benda_book.clone())); @@ -600,6 +630,10 @@ impl Book { #[pymethods] impl Book { + fn set_cmd(&mut self, cmd: BendCommand) { + self.cmd = Some(cmd); + } + #[getter] fn adts(&self) -> PyResult { Python::with_gil(|py| { @@ -611,8 +645,9 @@ impl Book { #[getter] fn defs(&self) -> PyResult { Python::with_gil(|py| { - let defs = &self.defs; - Ok(defs.clone().into_py(py)) + let mut defs = self.defs.clone(); + defs.cmd = self.cmd.clone(); + Ok(defs.into_py(py)) }) } diff --git a/docs/FFI.md b/docs/FFI.md index e8498b7..b056ee1 100644 --- a/docs/FFI.md +++ b/docs/FFI.md @@ -10,13 +10,20 @@ ## Introduction -If there is some part of your Python code that needs speed and you have a Bend function that does the job, you can use the Benda FFI to call that function from Python. Use the power of Bend to speed up your Python code. +When you need to optimize performance-critical sections of your Python code, Benda FFI allows you to seamlessly integrate high-performance Bend functions. By leveraging Bend's capabilities, you can significantly enhance the speed and efficiency of your Python applications. ## Functions -The `benda ffi` has the following functions: +The `benda ffi` module provides the following key function: -- `load_book_from_file()` - Load a book from a file, returns a book object; +- `load_book_from_file(file_path: str) -> Book`: Loads a Bend book from the specified file path and returns a Book object. + +Example usage: +```python +from benda import load_book_from_file + +book = load_book_from_file("./path/to/your/bendbook.bend") +``` ## Book @@ -24,10 +31,25 @@ A book object has the following uses: - `book.adts` - Get the adts of the book. Example: `book.adts.List`; - `book.defs` - Get the definitions, or bend functions, of the book. Example: `book.defs.Sort()`; +
+You can modify the Book's runtime environment using the `book.set_cmd()` function. This function accepts an argument of type `BendCommand`, an Enum that specifies the desired runtime. Available options include: + +- `BendCommand.Rust`: Use the Rust runtime +- `BendCommand.C`: Use the C runtime +- `BendCommand.Cuda`: Use the CUDA runtime for GPU acceleration + +Example usage: +```python +from benda import BendCommand + +book.set_cmd(BendCommand.Cuda) # Set the runtime to Cuda +``` + +Choose the appropriate runtime based on your performance requirements and available hardware ## ADTs -A ADT is a way to define a data structure in Bend. The Benda FFI can load the ADTs defined in a Book and expose them in Python. All the builtin ADTs of Bend are in any book loaded.
+Abstract Data Types (ADTs) in Bend provide a powerful way to define complex data structures. The Benda FFI seamlessly loads ADTs defined in a Bend Book and makes them accessible in Python. Every loaded Book includes all of Bend's built-in ADTs, ensuring you have access to a rich set of data structures out of the box.
The way to use a ADT is to access it from a `adts` object. Every ADT is composed of a set of `Constructors`, and each of these represent a instance of the ADT.
Example: @@ -53,19 +75,20 @@ These ADTs can be accessed using `match` statements to extract the values from t ``` python my_list = to_cons_list([1, 2, 3, 4, 5]) +List = book.adts.List while True: match my_list: - case book.adts.List.tCons(value, tail): + case List.Cons.type(value, tail): print(value) my_list = tail - case book.adts.List.tNil(): + case List.Nil.type(): print("End") break ``` -Notice that the Constructors in this case are prefixed with a `t` to indicate that you are matching the `types` of the constructors. Every time you want to pattern match a ADT, you need to prefix the constructor with a `t`.
+Notice that you're matching against the `type` attribute of a Constructor, so everytime you need to use a `match` with an ADT, you need to use this attribute. This is due to [pyo3](https://pyo3.rs/v0.22.1/br) limitation of creating types at runtime.
## Definitions @@ -101,7 +124,8 @@ This way you can convert the `Term` object into a ADT to use complex data struct ## Superpositions -Use [superpositions](https://gist.github.com/VictorTaelin/9061306220929f04e7e6980f23ade615) to boost your code performance. Superpositions are a way to call a Bend function multiple times using a `Tuple` of values.
+Leverage [superpositions](https://gist.github.com/VictorTaelin/9061306220929f04e7e6980f23ade615) to significantly enhance your code's performance. Superpositions allow you to efficiently apply a Bend function to multiple input values simultaneously, exploiting parallelism and reducing overall computation time.
+ Example: ```python import benda