Skip to content

Commit 7d41d42

Browse files
committed
Documentation and load_book
1 parent 7cc5300 commit 7d41d42

File tree

6 files changed

+84
-28
lines changed

6 files changed

+84
-28
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
[Bend]: https://github.com/HigherOrderCo/bend
88

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

1212
This is in MVP stage.
1313

@@ -72,6 +72,7 @@ def print_cons_list(list):
7272

7373
data = gen_list(5, 1000)
7474
cons_list = to_cons_list(data)
75+
book.set_cmd(benda.BendCommand.Cuda)
7576
sorted_list = book.defs.Sort(cons_list)
7677
sorted_list = sorted_list.to_adt(book.adts.List)
7778
print_cons_list(sorted_list)

crates/benda/src/benda_ffi/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use bend::{CompileOpts, RunOpts};
66
* TODO: move to another module
77
* TODO: docstring
88
*/
9-
pub fn run(book: &Book) -> Option<(Term, String, Diagnostics)> {
9+
pub fn run(book: &Book, cmd: &str) -> Option<(Term, String, Diagnostics)> {
1010
let run_opts = RunOpts::default();
1111
let compile_opts = CompileOpts::default().set_all();
1212
let diagnostics_cfg = DiagnosticsConfig::default();
@@ -18,7 +18,7 @@ pub fn run(book: &Book) -> Option<(Term, String, Diagnostics)> {
1818
compile_opts,
1919
diagnostics_cfg,
2020
args,
21-
"run",
21+
cmd,
2222
)
2323
.unwrap()
2424
}

crates/benda/src/lib.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
use std::fs::File;
2-
use std::io::Write;
31
use std::path::Path;
42

53
use num_traits::ToPrimitive;
64
use parser::Parser;
75
use pyo3::prelude::*;
86
use pyo3::types::{PyDict, PyFunction, PyString, PyTuple};
97
use rustpython_parser::{parse, Mode};
10-
use types::book::Book;
8+
use types::book::{BendCommand, Book};
119
use types::fan::Fan;
1210
use types::tree::{Leaf, Node, Tree};
1311
use types::u24::U24;
@@ -22,16 +20,13 @@ fn switch() -> PyResult<String> {
2220

2321
#[pyfunction]
2422
fn load_book(py: Python, code: Py<PyString>) -> PyResult<Py<Book>> {
25-
let mut tmp_file = File::create_new("./tmp/bend_book.tmp")
26-
.expect("Could not create temporary file.");
27-
28-
let _ = tmp_file.write_all(code.to_string().as_bytes());
29-
let _ = tmp_file.flush();
30-
23+
let builtins = bend::fun::Book::builtins();
3124
let path = Path::new("./tmp/bend_book.tmp");
32-
let bend_book = bend::load_file_to_book(path);
33-
34-
let _ = std::fs::remove_file(path);
25+
let bend_book = bend::fun::load_book::do_parse_book(
26+
code.to_string().as_str(),
27+
path,
28+
builtins,
29+
);
3530

3631
let book = Book::new(&mut bend_book.unwrap());
3732

@@ -150,6 +145,7 @@ fn benda(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
150145
m.add_function(wrap_pyfunction!(switch, m)?)?;
151146
m.add_function(wrap_pyfunction!(load_book_from_file, m)?)?;
152147
m.add_function(wrap_pyfunction!(load_book, m)?)?;
148+
m.add_class::<BendCommand>()?;
153149
m.add_class::<PyBjit>()?;
154150
m.add_class::<U24>()?;
155151
m.add_class::<Tree>()?;

crates/benda/src/parser/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -885,7 +885,7 @@ impl<'py> Parser<'py> {
885885

886886
//println!("BEND:\n {}", self.book.display_pretty());
887887

888-
let return_val = run(&self.book);
888+
let return_val = run(&self.book, "run");
889889

890890
match return_val {
891891
Some(val) => val.0.to_string(),

crates/benda/src/types/book.rs

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use core::panic;
22
use std::cell::RefCell;
3+
use std::fmt::Display;
34
use std::vec;
45

56
use bend::fun::{self, Book as BendBook, Name, Rule};
@@ -259,11 +260,31 @@ impl Ctrs {
259260
}
260261
}
261262

263+
#[pyclass]
264+
#[derive(Clone, Debug, Default)]
265+
pub enum BendCommand {
266+
#[default]
267+
Rust,
268+
C,
269+
Cuda,
270+
}
271+
272+
impl Display for BendCommand {
273+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
274+
match self {
275+
BendCommand::Rust => f.write_str("run"),
276+
BendCommand::C => f.write_str("run-c"),
277+
BendCommand::Cuda => f.write_str("run-cu"),
278+
}
279+
}
280+
}
281+
262282
#[pyclass(name = "Definition")]
263283
#[derive(Clone, Debug, Default)]
264284
pub struct Definition {
265285
arity: usize,
266286
name: String,
287+
cmd: Option<BendCommand>,
267288
}
268289

269290
#[pymethods]
@@ -356,7 +377,10 @@ impl Definition {
356377
b.defs
357378
.insert(Name::new("main"), main_def.to_fun(true).unwrap());
358379

359-
let res = benda_ffi::run(&b.clone());
380+
let res = benda_ffi::run(
381+
&b.clone(),
382+
&self.cmd.clone().unwrap_or_default().to_string(),
383+
);
360384

361385
GLOBAL_BOOK.set(bend_book);
362386

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

380405
#[pymethods]
@@ -385,7 +410,9 @@ impl Definitions {
385410
let py = object.py();
386411

387412
if let Some(def) = self.defs.get(field) {
388-
Ok(Py::new(py, def.clone())?)
413+
let mut def = def.clone();
414+
def.cmd = self.cmd.clone();
415+
Ok(Py::new(py, def)?)
389416
} else {
390417
new_err(format!("Could not find attr {}", object))
391418
}
@@ -426,6 +453,7 @@ impl Adts {
426453
pub struct Book {
427454
adts: Adts,
428455
defs: Definitions,
456+
cmd: Option<BendCommand>,
429457
}
430458

431459
impl Book {
@@ -579,6 +607,7 @@ impl Book {
579607
let new_def = Definition {
580608
arity: def.arity(),
581609
name: def.name.to_string(),
610+
cmd: None,
582611
};
583612
definitions.defs.insert(nam.to_string(), new_def);
584613
}
@@ -591,6 +620,7 @@ impl Book {
591620
let benda_book = Self {
592621
adts,
593622
defs: definitions,
623+
cmd: None,
594624
};
595625
GLOBAL_BENDA_BOOK.set(Some(benda_book.clone()));
596626

@@ -600,6 +630,10 @@ impl Book {
600630

601631
#[pymethods]
602632
impl Book {
633+
fn set_cmd(&mut self, cmd: BendCommand) {
634+
self.cmd = Some(cmd);
635+
}
636+
603637
#[getter]
604638
fn adts(&self) -> PyResult<PyObject> {
605639
Python::with_gil(|py| {
@@ -611,8 +645,9 @@ impl Book {
611645
#[getter]
612646
fn defs(&self) -> PyResult<PyObject> {
613647
Python::with_gil(|py| {
614-
let defs = &self.defs;
615-
Ok(defs.clone().into_py(py))
648+
let mut defs = self.defs.clone();
649+
defs.cmd = self.cmd.clone();
650+
Ok(defs.into_py(py))
616651
})
617652
}
618653

docs/FFI.md

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,46 @@
1010

1111
## Introduction
1212

13-
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.
13+
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.
1414

1515
## Functions
1616

17-
The `benda ffi` has the following functions:
17+
The `benda ffi` module provides the following key function:
1818

19-
- `load_book_from_file()` - Load a book from a file, returns a book object;
19+
- `load_book_from_file(file_path: str) -> Book`: Loads a Bend book from the specified file path and returns a Book object.
20+
21+
Example usage:
22+
```python
23+
from benda import load_book_from_file
24+
25+
book = load_book_from_file("./path/to/your/bendbook.bend")
26+
```
2027

2128
## Book
2229

2330
A book object has the following uses:
2431

2532
- `book.adts` - Get the adts of the book. Example: `book.adts.List`;
2633
- `book.defs` - Get the definitions, or bend functions, of the book. Example: `book.defs.Sort()`;
34+
<br>
35+
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:
36+
37+
- `BendCommand.Rust`: Use the Rust runtime
38+
- `BendCommand.C`: Use the C runtime
39+
- `BendCommand.Cuda`: Use the CUDA runtime for GPU acceleration
40+
41+
Example usage:
42+
```python
43+
from benda import BendCommand
44+
45+
book.set_cmd(BendCommand.Cuda) # Set the runtime to Cuda
46+
```
47+
48+
Choose the appropriate runtime based on your performance requirements and available hardware
2749

2850
## ADTs
2951

30-
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>
52+
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>
3153
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>
3254
Example:
3355

@@ -53,19 +75,20 @@ These ADTs can be accessed using `match` statements to extract the values from t
5375
``` python
5476

5577
my_list = to_cons_list([1, 2, 3, 4, 5])
78+
List = book.adts.List
5679

5780
while True:
5881
match my_list:
59-
case book.adts.List.tCons(value, tail):
82+
case List.Cons.type(value, tail):
6083
print(value)
6184
my_list = tail
62-
case book.adts.List.tNil():
85+
case List.Nil.type():
6386
print("End")
6487
break
6588

6689
```
6790

68-
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>
91+
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>
6992

7093
## Definitions
7194

@@ -101,7 +124,8 @@ This way you can convert the `Term` object into a ADT to use complex data struct
101124

102125
## Superpositions
103126

104-
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>
127+
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>
128+
105129
Example:
106130
```python
107131
import benda

0 commit comments

Comments
 (0)