Skip to content

Latest commit

 

History

History
144 lines (98 loc) · 5.23 KB

FFI.md

File metadata and controls

144 lines (98 loc) · 5.23 KB

Bend FFI for Python

Use Bend functions, data structures and capabilities in Python

Index

  1. Introduction
  2. Functions
  3. Book
  4. ADTs
  5. Definitions

Introduction

When you want to use Bend on your Python code, Benda allows you to integrate Bend into Python using its ADTs, functions and capabilities.

Functions

The benda ffi module provides the following key function:

  • load_book_from_file(file_path: str) -> Book: Loads a Bend book from the specified file path and returns a Book object.

Example usage:

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();

You can modify the Book's runtime environment using the `book.set_cmd()` function. This function accepts an argument of type `BendRuntime`, an Enum that specifies the desired runtime. Available options include:
  • BendRuntime.Rust: Use the Rust runtime
  • BendRuntime.C: Use the C runtime
  • BendRuntime.Cuda: Use the CUDA runtime for GPU acceleration

Example usage:

from benda import BendRuntime

book.set_cmd(BendRuntime.Cuda)  # Set the runtime to Cuda

Choose the appropriate runtime based on your performance requirements and available hardware

ADTs

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:

def to_cons_list(xs: list[int]):
    result = book.adts.List.Nil()

    hi = len(xs)
    if hi == 0:
        return result

    while hi > 0:
        hi -= 1
        result = book.adts.List.Cons(xs[hi], result)

    return result

In this example, we are creating a List ADT from a Python list. The List ADT has two constructors: Nil and Cons. We are using the Nil constructor to represent the end of the List and the Cons constructor to represent an element of the List.
These ADTs can be accessed using match statements to extract the values from the ADT. Example:

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

while True:
    match my_list:
        case List.Cons.type(value, tail):
            print(value)
            my_list = tail
        case List.Nil.type():
            print("End")
            break

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 limitation of creating types at runtime.

Definitions

A definition is a Bend function that can be called from Python. The Benda FFI can load the definitions defined in a Book and expose them in Python. All the builtin definitions of Bend are in any book loaded.
The way to use a definition is to access it from a book.defs object. Benda checks the number of arguments the Bend function needs.
Example:

import random
import benda

book = benda.load_book_from_file("./examples/quicksort.bend")

def gen_list(n: int, max_value: int):
    if n <= 0:
        return book.adts.List.Nil()
    else:
        value = random.randint(0, max_value)
        return book.adts.List.Cons(value, gen_list(n-1, max_value))

my_list = gen_list(400, 200)
sorted_list = book.defs.Sort(my_list)

In this example, we are generating a list of 400 random numbers and sorting it using the Sort definition. The Sort definition is a Bend function that takes a List and returns a sorted List Term.
Every definition call in Benda returns a Term object. This object represents the output of HVM in lambda encoding. To convert this object into a ADT, you can use the to_adt function.
Example:

sorted_list = book.defs.Sort(my_list).to_adt(book.adts.List)

This way you can convert the Term object into a ADT to use complex data structures in Python.