Link Search Menu Expand Document

Oters - Exporting Rust Code


While Oters is already a pretty powerful language, it is missing all the libraries and community content that a mature language has. To remedy this, Oters provides a mechanism to export certain Rust code so that you can use it from your Oters programs.

Exportable Types

All Rust code exported into Oters must be translated to be compatible with Oters’ type system. This means that we are a bit restricted with the types that we can include in our exported code. The following is a series of mappings of Rust types to Oters types:

Rust Type Oters Type
i64 int
f64 float
bool bool
String string
Vec<T> [T]
(T1, ..., Tn) (T1, ... , Tn)

Aside from these, exported functions without arguments or a return type take a unit type as input or return unit respectively.

Attempting to export a type not in the list above will result in a compilation error.

Exporting Structs and Enums

Aside from the aforementioned types, you can also export composite types so that you can use them from both Rust and Oters. Note however, tath the structs and enums that you do export must have fields with exportable types. To export a struct or enum you simply add the macro [oters::export_oters] above its definition.

use oters::export_oters;

#[export_oters]
pub struct Color {
    pub r: i64,
    pub g: i64,
    pub b: i64,
    pub a: i64,
}

#[export_oters]
pub enum Shape {
    Circle((i64, i64), i64, Color),    
    Rect((i64, i64), (i64, i64), Color),
    Line((i64, i64), (i64, i64), i64, Color),
    Triangle((i64, i64), (i64, i64), (i64, i64), Color),
}

Exporting Functions

Exporting a Rust function to Oters is done in the same way as for structs or enums. You just attach the macro [oters::export_oters] above the function definition.

#[export_oters]
fn shape_area(s: Shape) -> f64 {
    match s {
        Shape::Circle(_, r, _) => r as f64 * r as f64 * 3.14159265358979,
        Shape::Rect(_, dims, _) => (dims.0 * dims.1) as f64,
        Shape::Line(..) => 0.0,
      	Shape::Triangle(a, b, c, _) => (a.0 * (b.1 - c.1) + 
                                        b.0 * (c.1 - a.1) + 
                                        c.0 * (a.1 - b.1)
                                       ) as f64 / 2.0,
    }
}

#[export_oters]
fn int_sum(i1: i64, i2: i64) -> i64 {
    i1 + i2
}

Functions with multiple arguments will get imported into Oters as taking a tuple of said arguments as input. So the rather contrived function int_sum will have type (int, int) -> int in Oters.

Also, unfortunately you can’t pass imported functions as first-order values yet. So, int_sum above could not be used as an argument to a function in Oters. This can be worked around fairly easily by simply wrapping it in another function like so:

fn i1 i2 -> int_sum (i1, i2)

Importing into Oters

All your exported functions, structs and enums are automatically imported into Oters. It is important to note that they are specifically imported into the first file in the Vec passed as input to the run! macro. To use them in your other files you will need to add use statements. So for example, if I have two Oters files data.rs and main.rs in that order, using the exports above in main.rs may look like the following:

use data::Color
use data::Shape
use data::shape_area

let my_circ = Shape::Circ((100, 100), 20, Color { r: 255, g: 0, b: 0, a: 255 })
let circ_area = shape_area my_circ