Struct Builder

Source
pub struct Builder<'a, 'f, T: BuildTarget<'a, 'f>> { /* private fields */ }
Expand description

Easy way to build an Avid instance.

Instantiate it with new, change its settings with the various methods, and then “compile” the source into an Avid instance by calling build.

§Examples

use avid::Builder;

let src = "5 print";

// Prints `5`
Builder::new(src)
    .build()
    .unwrap()
    .run(None)
    .unwrap();

Implementations§

Source§

impl<'a, 'f: 'a> Builder<'a, 'f, Avid<'a, 'f>>

Source

pub fn new(src: &'a str) -> Self

Creates a new instance of a Builder with the default configuration.

For now, that means that it has the small Avid standard library, which can be found in the documentation. To change this configuration, use the Builder::remove() and Builder::register_fn() methods.

§Examples
use avid::Builder;

let src = "- + print";

let res = Builder::new(src).build();

// All of those functions are available.
assert!(res.is_ok());
Source§

impl<'a> Builder<'a, 'a, Ast<'a>>

Source

pub fn new_ast(src: &'a str) -> Builder<'a, 'a, Ast<'a>>

Start building an Ast with the default configuration.

If you want to just build the Ast with the default configuration, use Ast::new().

§Examples
use avid::{Ast, Builder};

let src = "hi";

let ast: Ast = Builder::new_ast(src)
    .promise("hi")
    .build()
    .unwrap();

// now do stuff with ast
Source§

impl<'a, 'f, T: BuildTarget<'a, 'f>> Builder<'a, 'f, T>

Source

pub fn build(self) -> Result<T>

Consumes the builder and creates the Avid instance

When this method is called, the source code is parsed and checked for syntax errors, then (if there were no errors) an Avid instance is returned.

§Examples
use avid::Builder;

let builder = Builder::new("/* some source code */");

match builder.build() {
    Err(e) => eprintln!("There was a syntax error: {e:?}"),
    Ok(avid) => todo!("Do something with the interpreter!")
}
Source

pub fn src_name<N: ToString>(self, name: N) -> Self

Set the name of the source file for error reporting.

If this method is not entered, errors will default to using “” as the name of the source file.

§Examples

Without changing the name of the source file:

use avid::Builder;

let src = "unknown-variable";

let should_be_error = Builder::new(src)
    .build()
    .unwrap_err();

assert!(should_be_error.to_string().starts_with("<provided>:1:1: Error"))

After changing the name of the source file:

use avid::Builder;

let src = "unknown-variable";

let should_be_error = Builder::new(src)
    .src_name("file")
    .build()
    .unwrap_err();

assert!(should_be_error.to_string().starts_with("file:1:1: Error"))
Source

pub fn promise<N: ToString>(self, name: N) -> Self

Promise that a function will be available at runtime.

This helps get around lifetime requirements or cases when a variable is unknown until call time, such as in hooks or callbacks.

§Examples
use avid::*;

let src = "get-msg print";

let avid = Builder::new(src)
    .promise("get-msg")
    .build().unwrap();

// Msg is not known until after the instance is compiled
let msg = "Hello!";

let get_msg = |s: &mut Stack| {
    s.push(Object::String(msg.to_string()));
    Ok(())
};

let mut promises = PromiseBuilder::new()
    .add_promise("get-msg", get_msg)
    .build();

// Prints "Hello!"
avid.run(Some(&mut promises)).unwrap();

This can be used to provide runtime-only information.

use avid::*;

let src = "inc-x";

let mut avid = Builder::new(src)
    .promise("inc-x")
    .build().unwrap();

let mut x = 0;

{
    let mut promises = PromiseBuilder::new()
        .add_promise("inc-x", |_| {
            x += 1;
            Ok(())
        })
        .build();

    // Increments x
    avid.run_mut(Some(&mut promises)).unwrap();
}

// Both of these can be reused in this way as soon as `promises` goes out of scope
dbg!(&x);
dbg!(&avid);

This also can be used to not consume variables until the Avid instance goes out of scope.

Source

pub fn register_fn<N: ToString, F: Into<T::Function> + 'f>( self, name: N, func: F, ) -> Self

Registers a new function in the interpreter-to-be under the specified name.

The function gets registered under name and must be called as such in the program.

§NOTE

If you get strange errors about lifetimes and/or closure typing while using this method, make sure that you have annotated the argument’s type (|arg: &mut Stack|).

Avid is still in it’s beta stage, so there are still some kinks to be worked out in the library. This is one of them. Hopefully it’ll be fixed soon!

§Examples
use avid::{Builder, Stack, Object};

let src = "msg eprint";

let avid = Builder::new(src)
    // Add a function that pushes a string onto the stack.
    .register_fn("msg", |stack: &mut Stack| {
        stack.push(Object::String("Hi!".to_string()));
        Ok(())
    })
    // Add a function that pops one thing from the stack and prints it
    // to stderr.
    .register_fn("eprint", |stack: &mut Stack| {
        let [to_print] = stack.pop()?;
        eprint!("{}", to_print.to_string());
        Ok(())
    }).build().unwrap();

// Will print "Hi!" to stderr
avid.run(None).unwrap();
Source

pub fn remove<N: ToString>(self, name: N) -> Self

Removes a function or object from the scope of the interpreter-to-be.

When this function is called, any function registered under name gets unregistered from the scope of the interpreter-to-be and, if a user tries to call it, an error is thrown.

§Examples
use avid::{Builder, Stack};

let src = "func";

let res = Builder::new(src)
    .register_fn("func", |_: &mut Stack| {
        println!("func was called");
        Ok(())
    })
    .remove("func")
    .build();

// Syntax error: Unknown variable "func"
assert!(res.is_err());
Source

pub fn allow_stack_debug(self, allowed: bool) -> Self

Enable or disable the stack debugger.

Often while writing code in stack-oriented languages, it can be difficult to keep track of what is on the stack at any particular point in the code. Avid has a “stack debugging” function, ???, which prints the types of the stack and then exits.

§Warning

The stack debugger makes the thread panic! This is okay in some kinds of programs, such as a basic interpreter or single-user application, but seemingly random crashes are not good in a multi-user program! Allow with caution!

§Examples
use avid::Builder;

let src = "1 false \"Hi!\" ???";

let avid = Builder::new(src)
    .allow_stack_debug(true)
    .build().unwrap();

// Panics with "[Num Bool String]"
avid.run(None).unwrap();
Source

pub fn no_io(self) -> Self

Removes all standard library IO functions from the interpreter.

Often, an author of a program wants to sandbox potentially malicious code written by users. This function helps with that by removing any ability to use IO functions in the Avid interpreter.

§Examples
use avid::Builder;

let src = "\"IO D:\" print";

let res = Builder::new(src)
    .no_io()
    .build();

// Syntax error: Unknown value "print"
assert!(res.is_err());

When this function is called, the following functions are removed from the standard library and will not be recognised if a user tries to use them: print.

Trait Implementations§

Source§

impl<'a, 'f, T: BuildTarget<'a, 'f>> Debug for Builder<'a, 'f, T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'a> TryFrom<Builder<'a, 'a, Ast<'a>>> for Ast<'a>

Source§

type Error = Error

The type returned in the event of a conversion error.
Source§

fn try_from(value: Builder<'a, 'a, Ast<'a>>) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl<'a, 'f: 'a> TryFrom<Builder<'a, 'f, Avid<'a, 'f>>> for Avid<'a, 'f>

Source§

type Error = Error

The type returned in the event of a conversion error.
Source§

fn try_from(value: Builder<'a, 'f, Self>) -> Result<Self, Self::Error>

Performs the conversion.

Auto Trait Implementations§

§

impl<'a, 'f, T> Freeze for Builder<'a, 'f, T>

§

impl<'a, 'f, T> RefUnwindSafe for Builder<'a, 'f, T>
where <T as BuildTarget<'a, 'f>>::Function: RefUnwindSafe,

§

impl<'a, 'f, T> Send for Builder<'a, 'f, T>
where <T as BuildTarget<'a, 'f>>::Function: Send,

§

impl<'a, 'f, T> Sync for Builder<'a, 'f, T>
where <T as BuildTarget<'a, 'f>>::Function: Sync,

§

impl<'a, 'f, T> Unpin for Builder<'a, 'f, T>
where <T as BuildTarget<'a, 'f>>::Function: Unpin,

§

impl<'a, 'f, T> UnwindSafe for Builder<'a, 'f, T>
where <T as BuildTarget<'a, 'f>>::Function: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.