Crate avid

source ·
Expand description

Plug and play configuration language.

Provides a simple API to insert this configuration language into your project. The language is easy to learn and checks for many common errors, including unknown variables and malformed statements, at (Avid’s) compile time.

The available APIs and other settings can be tweaked or modified easily by using the different methods on the Builder struct.

Examples

use avid::{Builder, Stack};

let src = "1 2 + print \"Hello, World!\" print-to-log";
let mut log = String::new();

let avid = Builder::new(src)
    // Add a new function that pops one item from the top of the stack
    // and prints it to the log
    .register_fn("print-to-log", |stack: &mut Stack| {
        let [to_print] = stack.pop()?;
        log.push_str(&to_print.to_string());
        Ok(())
    })
    .build().unwrap();

// Prints `3` to standard output
avid.run(None).unwrap();

assert_eq!(&log, "Hello, World!");

You can use any function with the correct signature, including closures.

Avid Syntax

Avid’s syntax is heavily inspired by forth and uses reverse polish notation. This means that all functions operate on an implicit “stack,” pushing and popping elements as needed. Let’s take a look at an example:

/* stack is now empty */

/* Pushes `1` to the stack */
1

/* stack: 1 */
/* Pushes `2` to the stack */
2

/* stack: 1 2 */
/* Pops the top two elements from the stack, sums them up, and pushes the result onto the stack */
+

/* stack: 3 */
/* Pops an element from the top of the stack and prints it. */
print

/* stack is now empty */

Avid also allows strings:

/* Stack is now empty */
/* Pushes itself onto the stack */
"Hello, "

/* Stack: "Hello, " */
"World!"

/* Stack: "Hello, " "World!" */
/* Swaps the top two items on the stack */
swap

/* Stack: "World!" "Hello, " */
/* Prints "Hello, World!" */
print print 


/* This prints: */
/*
all of these escape codes are allowed!: "Quotes", preventing new lines, adding
 new lines, 'Single quotes,'
urns,age ret
         tabs, and \\ slashes! \\
*\
"all of these escape codes are allowed!: \"Quotes\", preventing \
new lines, adding \n new lines, \'Single quotes,\' 
carriage ret\rurns,
\t tabs, and \\ slashes! \\" print


/* Stack is now empty */

And lists:

/* Stack is now empty */
/* Pushes a new list to the stack */
list

/* Stack: [] */
/* Pushes several new items to the stack and appends each to the list */
1 append
2 append
3 append

/* Stack: [1, 2, 3] */
/* Copies the top item on the stack */
dup

/* Stack: [1, 2, 3] [1, 2, 3] */
/* Prints: [1, 2, 3] */

/* Stack: [1, 2, 3] */
/* The list can be used again */

Control Flow

Control flow is very simple in Avid: an if statement just pops from the top of the stack, sees if that value is truthy, and continues into the if statement if it is. while loops are similar: on each iteration of the loop, the code between the while and the do parts is executed, and if what is left on top of the stack is truthy, the code inside the block is executed and execution returns to the while for reevaluation.

Both of these types of blocks are terminated by end statements.

Now, some examples!

0
while
    1 +
    dup 11 != dup

    /* You can do if statements anywhere, even inside the conditions of while loops! */
    if
        "The value is not eleven! " print
    end
do
    "The value is: " print
    dup print
    "! " print
end

Functions

Currently, you cannot define your own functions in Avid, but you can in rust! Check out the rust documentation for more details, and the list of pre-defined functions too!

The Avid Standard Library

Avid’s standard library is relatively small and simple. So, without further ado, let’s get into it!

Basic functions

FunctionDescription
+Pops the top two items off of the stack, sums them up, and pushes the result onto the stack. Throws an error if the types at the top are not Num, Num.
-Pops the top two items off of the stack, finds their difference, and pushes the result onto the stack. Throws an error if the types at the top are not Num, Num.
dupMakes a copy of the top element of the stack and pushes it onto the stack.
swapSwaps the top two elements on the stack.
dropRemoves the top element on the stack.
listCreates a new list and pushes it onto the stack.
appendPops the value from the top of the stack and appends it to the second element on the stack. Throws an error if the second element on the stack is not a List.
notPops the top element on the stack, performs a logical not, and pushes the result onto the stack.
==Pops the top two elements on the stack, checks their equality, and pushes the result onto the stack.
!=Pops the top two elements on the stack, checks their inequality, and pushes the result onto the stack.
getPops the top two elements from the stack, then pushes onto the stack a copy of the nth item from the second element, where n is the first item. Throws an error if the first element is not a num and the second element is not a List.
rotPops the top three elements from the top of the stack (arg3, arg2, arg1), then pushes the first element, then the third, then the second onto the stack (arg1, arg3, arg2).

I/O functions

These are all of the I/O (input-output) functions that Avid supports. Note that these functions may be disabled for various reasons, so check with the program that you are using! | Function | Description | |:–|:–| | print | Pops the top element from the stack and prints it to standard output |

Structs

A compiled version of Avid source code, that can be sent between threads.
The actual state of the interpreter.
Easy way to build an Avid instance.
An error in an Avid program, along with the location it occurred.
A location in a file.
The way to construct Promises.
All of the functions promised by Builder::promise(), built by PromiseBuilder::build().
Stack that holds data while an Avid program is running.

Enums

Errors that can happen when running an Avid program.
The possible types in an Avid program.
The possible types of Object

Type Definitions

A shorthand for a Result type with Avid programs.