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