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