Skip to content

Commit

Permalink
Documentation and load_book
Browse files Browse the repository at this point in the history
  • Loading branch information
vkobinski committed Jul 7, 2024
1 parent 7cc5300 commit 7d41d42
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 28 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
[Bend]: https://github.com/HigherOrderCo/bend

Read the Docs:<br>
[FFI](https://github.com/vkobinski/benda-main/tree/master/docs/FFI.md)
[FFI](/docs/FFI.md)

This is in MVP stage.

Expand Down Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions crates/benda/src/benda_ffi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -18,7 +18,7 @@ pub fn run(book: &Book) -> Option<(Term, String, Diagnostics)> {
compile_opts,
diagnostics_cfg,
args,
"run",
cmd,
)
.unwrap()
}
20 changes: 8 additions & 12 deletions crates/benda/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
use std::fs::File;
use std::io::Write;
use std::path::Path;

use num_traits::ToPrimitive;
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;
Expand All @@ -22,16 +20,13 @@ fn switch() -> PyResult<String> {

#[pyfunction]
fn load_book(py: Python, code: Py<PyString>) -> PyResult<Py<Book>> {
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());

Expand Down Expand Up @@ -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::<BendCommand>()?;
m.add_class::<PyBjit>()?;
m.add_class::<U24>()?;
m.add_class::<Tree>()?;
Expand Down
2 changes: 1 addition & 1 deletion crates/benda/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
43 changes: 39 additions & 4 deletions crates/benda/src/types/book.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -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<BendCommand>,
}

#[pymethods]
Expand Down Expand Up @@ -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);

Expand All @@ -375,6 +399,7 @@ impl Definition {
#[derive(Clone, Debug, Default)]
pub struct Definitions {
defs: IndexMap<String, Definition>,
cmd: Option<BendCommand>,
}

#[pymethods]
Expand All @@ -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))
}
Expand Down Expand Up @@ -426,6 +453,7 @@ impl Adts {
pub struct Book {
adts: Adts,
defs: Definitions,
cmd: Option<BendCommand>,
}

impl Book {
Expand Down Expand Up @@ -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);
}
Expand All @@ -591,6 +620,7 @@ impl Book {
let benda_book = Self {
adts,
defs: definitions,
cmd: None,
};
GLOBAL_BENDA_BOOK.set(Some(benda_book.clone()));

Expand All @@ -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<PyObject> {
Python::with_gil(|py| {
Expand All @@ -611,8 +645,9 @@ impl Book {
#[getter]
fn defs(&self) -> PyResult<PyObject> {
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))
})
}

Expand Down
40 changes: 32 additions & 8 deletions docs/FFI.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,46 @@

## 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

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()`;
<br>
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.<br>
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.<br>
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.<br>
Example:

Expand All @@ -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`.<br>
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.<br>

## Definitions

Expand Down Expand Up @@ -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.<br>
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.<br>

Example:
```python
import benda
Expand Down

0 comments on commit 7d41d42

Please sign in to comment.