Building Programs
This chapter will show you how to utilize the gen
module in order to compile your own lovm2
programs. It is also possible to persist compiled modules onto your disk and load them later.
use lovm2::prelude::*; fn main() { let mut builder = LV2ModuleBuilder::new(); // creates the entry point function and trigger a debug interrupt. builder .entry() .trigger(10); let module = builder.build().except("compile error"); println!("{}", module); }
The main generation functionality is exposed via LV2Block
and every structure that contains it like LV2Branch
, LV2Repeat
and functions. You can use these methods on all of them:
step(..)
append a new statement to the block.branch()
create a new branch at the current position. This returns aLV2BranchBuilder
.repeat()
andrepeat_until(..)
which return a mutable reference to a new block. The first variant is an endless loop, while the latter supports breaking once a condition is met.return_nil()
,return_value(<expr>)
return early from a block.assign(<var>, <expr>)
stores an evaluated expression in<var>
.global(<var>)
,local(<var>)
change scope of<var>
.
Functions
The whole LV2ModuleBuilder
is centered around the creation of LV2Function
s. The resulting bytecode is able to process a given amount of parameters and leave a return value in place.
As you can see in this example listing, you should not need to create such data manually as there is functionality for adding it to the builder directly.
use lovm2::prelude::*; fn main() { // creates a hir with no arguments let fn_no_args = builder.add("fn1"); // creates a hir that expects parameter n let fn_with_args = builder.add_with_args("fn2", &[lv2_var!(n)]); }
To return from function, call .return_value(expr)
on the block specifying the returned value or .return_nil()
if no value is produced.
Due to the convention that every function has to return a value, an implicit nil push is appended if the last instruction is not a return already.
Helper Macros
There are a bunch of macros inside the prelude that trivialize creating more complicated lovm2
constructs for developers.
lv2_var!(ident, ...)
turns all the identifiers given into the special typeLV2Variable
which is needed basically everywhere. If more than one ident is declared, this returns a tuple.lv2_dict!(ident => expr, ...)
creates anLV2Expr
that will dynamically initialize a dictionary with the key-values pairs specified.lv2_list!(item, ...)
creates anLV2Expr
that initializes a list dynamically.lv2_call!(ident, ... args)
syntactic sugar for theLV2Call
element.lv2_access!(ident, ... keys)
syntactic sugar for retrieving items of a dictionary or list.