[][src]Crate scriptful

Scriptful is a minimalistic no_std stack machine for executing domain specific interpreted languages.

This library is heavily inspired by FORTH and Script, the scripting language in Bitcoin.

General design

The whole library is built around four main concepts:

  • Stack: an ordered sequence of values that can be operated in a LIFO-alike way.
  • Item: either a Value (a piece of data to be pushed into the stack) or an Operator (the descriptor for an action that operates on the topmost items in the stack).
  • Operator system: a function that decides how each operator will mutate a given stack.
  • Script: an ordered sequence of items (values and operators) that can be passed to an operator system for operating on a given stack.
  • Machine: a convenient wrapper around a stack that enables multiple modes of operation.

Using this library is as easy as:

  1. Defining your own set of operators, or using any of the ones that come bundled in the op_systems module.
  2. Defining your own operator system function, or using any of the ones that come bundled in the op_systems module.
  3. Instantiating a machine with a reference to your operator system.
  4. Composing a script and running it in the machine.

Quick example

use scriptful::prelude::*;
use scriptful::prelude::Value::*;

#[derive(Debug, PartialEq, Eq)]
/// You can define your own operators.
enum MyOperator {
    Add,
    Equal,
    Sub,
}

/// An operator system decides what to do with the stack when each operator is
/// applied on it.
fn my_operator_system(stack: &mut Stack, operator: &MyOperator) {
    match operator {
        MyOperator::Add => {
            let a = stack.pop();
            let b = stack.pop();
            stack.push(a + b);
        }
        MyOperator::Equal => {
            let a = stack.pop();
            let b = stack.pop();
            stack.push(Value::Boolean(a == b));
        }
        MyOperator::Sub => {
            let a = stack.pop();
            let b = stack.pop();
            stack.push(a - b);
        }
    }
}

// Instantiate the machine with a reference to your operator system.
let mut machine = Machine::new(&my_operator_system);

// Run a script that simply adds `1` and `2`
let result = machine.run_script(&[
    Item::Value(Integer(1)),
    Item::Value(Integer(2)),
    Item::Operator(MyOperator::Add),
]);

// The result should unsurprisingly be `3`
assert_eq!(*result, Integer(3));Run

License

Scriptful is distributed under the terms of both the MIT license and the Apache License (Version 2.0).

See LICENSE-APACHE and LICENSE-MIT, and COPYRIGHT for details.

Modules

core

The core of this library.

op_systems

Some ready-to-use operator systems that may be useful for someone, somewhere, somewhen.

prelude

Re-exports the most frequently used parts of this library so that they can be used more conveniently.