1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
//! ___Scriptful_ is a minimalist `no_std`, zero dependency stack machine for interpreting scripts written with domain
//! specific interpreted languages.__
//!
//! This library is heavily inspired by the [Forth] programming language and [Script][BitcoinScript]
//! (the scripting language in Bitcoin).
//!
//! # General design
//!
//! The whole library is built around these 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).
//! - __Type system__: an [`enum`][enum] whose variants are all the possible data types allowed in a [`Stack`][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.
//! - __[Codec]__: a set of methods for encoding and decoding scripts and items, normally into and from binary formats.
//!
//! 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`][Operator system] module.
//! 2. Defining your own type system, or using the [`Value`][Value] type system that comes bundled in the [`core::value`][Value] module.
//! 3. Defining your own [operator system][Operator system] function, or using any of the ones that come bundled in the [`op_systems`][Operator system] module.
//! 4. Instantiating a [machine][Machine] with a reference to your operator system.
//! 5. Composing a [script][Script] and running it in the machine.
//!
//! # Quick example
//!
//! ```rust
//! use scriptful::prelude::*;
//! use scriptful::core::value::Value::*;
//!
//! // You can define your own operators.
//! #[derive(Debug, PartialEq, Eq)]
//! 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(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(&Vec::from([
//! Item::Value(Integer(1)),
//! Item::Value(Integer(2)),
//! Item::Operator(MyOperator::Add),
//! ]));
//!
//! // The result should unsurprisingly be 3.
//! assert_eq!(result, Some(&Integer(3)));
//! ```
//!
//! # Known limitations
//!
//! - _Beware of unwraps!_ This is a proof-of-concept and it is modelled to panic upon errors.
//! Making the library safe for production usage is in the near horizon though.
//!
//! # 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.
//!
//! [Forth]: https://en.wikipedia.org/wiki/Forth_(programming_language)
//! [BitcoinScript]: https://en.bitcoin.it/wiki/Script
//! [LIFO]: https://en.wikipedia.org/wiki/Stack_(abstract_data_type)
//! [Stack]: core/stack/struct.Stack.html
//! [Item]: core/item/enum.Item.html
//! [Operator system]: op_systems/
//! [Script]: core/type.Script.html
//! [Machine]: core/machine/struct.Machine.html
//! [Value]: core/value/enum.Value.html
//! [Codec]: codecs/index.html
//! [enum]: https://doc.rust-lang.org/std/keyword.enum.html
//! [LICENSE-APACHE]: https://github.com/aesedepece/scriptful/blob/master/LICENSE-APACHE
//! [LICENSE-MIT]: https://github.com/aesedepece/scriptful/blob/master/LICENSE-MIT
//! [COPYRIGHT]: https://github.com/aesedepece/scriptful/blob/master/COPYRIGHT
#![no_std]
#![doc(html_playground_url = "https://play.rust-lang.org/")]
extern crate alloc;
#[cfg(feature = "codecs")]
pub mod codecs;
/// The core of this library.
///
/// Provides all the [`Item`][Item], [`Stack`][Stack], [`Machine`][Machine] and [`Value`][Value] goodness.
///
/// [Item]: item/
/// [Stack]: stack/
/// [Machine]: machine/
/// [Value]: value/
pub mod core;
/// Some ready-to-use operator systems that may be useful for _someone_, _somewhere_, _somewhen_.
pub mod op_systems;
/// Re-exports the most frequently used parts of this library so that they can be used more conveniently.
pub mod prelude {
pub use crate::core::{
condition_stack::ConditionStack, item::Item, machine::Machine, stack::Stack, Error, Script,
};
}