# Oters Oters (**O**xidized **Te**mporal **R**eactive **S**treams) is a functional reactive programming language designed for intuitively building GUIs based on [Patrick Bahr's type system](https://www.cambridge.org/core/journals/journal-of-functional-programming/article/modal-frp-for-all-functional-reactive-programming-without-space-leaks-in-haskell/9BE20E8D61E9B74811CF3CF97B5D10C7). Documentation for the language can be found [here](https://planza.github.io/Oters). --- ### Features * Type Inference - Types are fully inferred such that you never have to explicitly write a type. * Interpreted - While the language is interpreted, static type checking ensures that your program is safe before running. * Imports Rust Code - Can import Rust functions into your Oters code with a single macro. * No space or time leakages - The size and computation of the program stays constant after initiation. --- ### Dependencies Oters relies on the [macroquad](https://github.com/not-fl3/macroquad) crate for its GUI functionality. This crate requires certain system dependencies. Specifically on Linux: ``` # ubuntu system dependencies apt install pkg-config libx11-dev libxi-dev libgl1-mesa-dev libasound2-dev # fedora system dependencies dnf install libX11-devel libXi-devel mesa-libGL-devel alsa-lib-devel # arch linux system dependencies pacman -S pkg-config libx11 libxi mesa-libgl alsa-lib ``` --- ### Usage Oters works as a Rust library and so must be included into your Rust project like any other dependency: ```toml [dependencies] oters = "0.1.2" ``` Running an Oters file requires a single macro call in your main function: ```rust fn main() { let config = oters::WindowConfig { title: "My Oters App".to_string(), dimensions: (800, 600), resizable: true, fullscreen: false, icon: None, }; oters::run!(vec!["./examples/demo/demo.otrs".to_string()], config,); } ``` Note that files passed to the `run!` macro must be in order of dependency. So if you have two files `main.otrs` and `logic.otrs`, and the former relies on the latter, then `logic.otrs` must come before `main.otrs` in the `Vec`. And importing a Rust function into Oters, is also done through a single macro call: ```rust #[export_oters] fn print_message(s: String) { println!("This message is being printed from a Rust function: \n{s}"); } // Can now call the function print_message from your Oters file ``` --- ### Examples A token example taken from `examples/demo/demo.otrs`: ``` use std::stream::const use std::stream::head use gui::widget::* use gui::color::* use gui::shape::* let ui = gui::frame ((100,50), (250, 100)) let (btn_id, btn_stream) = button ui (100, 50) (const "Click me!") let counter = { let aux = fn n -> { let delta = if head btn_stream then 1 else 0; (n + delta) << @(aux (n + delta)) }; aux 0 } let counter_string = std::int_to_string (head counter) << @counter_string let (lab_id, lab_stream) = label ui (100, 50) counter_string let (grp_id, grp_stream) = hgroup ui (250,100) (const [btn_id, lab_id]) (Alignment::Top) let _ = gui::attach_root (ui, grp_id) let circle_color = (if head counter % 3 == 0 then red else if head counter %3 == 1 then green else blue) << @circle_color let circle = (draw_shape (Shape::Circle((200,200), 30, head circle_color))) << @circle ```