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
/// A lightweight interpreter interface.
pub trait Interpreter: 'static {
    /// The value type the interpreter uses and returns.
    ///
    /// It is usually a trait object that allows supporting different kinds
    /// of actual values.
    ///
    /// Refer to the `value` module for example implementations.
    type Value: Clone;

    /// The error type that the interpreter raises.
    ///
    /// Could be a string, or the same as the `Value` type, or a dedicated
    /// error type.
    type Error: From<String> + From<&'static String>;

    /// The environment type that is used to evaluate code.
    ///
    /// Environments are complementary (mutable) structures that helps
    /// resolving static expressions.
    ///
    /// For example, environments might include these kinds of information:
    /// - The state (registers, heap and the stack). Tracking local and outer
    ///   variables.
    /// - What to do next (the program counter). Making it possible to suspend
    ///   and resume execution. This would require explicit support from the
    ///   stdlib so execution can be suspended and resumed.
    ///
    /// Refer to the `env` module for example implementations.
    type Env;

    /// The expression type.
    ///
    /// The type that can represent parsed code of this language.
    /// If the language wants to operate code as data, then there
    /// needs a way to convert `Expr` to `Value`.
    /// For interpreters that use bytecode, this might also include
    /// the bytecode.
    ///
    /// Refer to the `expr` module for example implementations.
    type Expr;

    /// Evaluate code in string. This is a shortcut for calling `parse`, and
    /// `evaluate` with `global_env()`.
    fn interpret(code: &str) -> Result<Self::Value, Self::Error> {
        let env = Self::global_env();
        let expr = Self::parse(code)?;
        Self::evaluate(&env, &expr)
    }

    /// Parse code into an `Expr`.
    ///
    /// For interpreters that use bytecode, consider compiling the code into
    /// bytecode in this function.
    fn parse(code: &str) -> Result<Self::Expr, Self::Error>;

    /// Define the default global environment.
    ///
    /// Usually this defines the standard library.
    fn global_env() -> Self::Env;

    /// Evaluate an expression in a given environment.
    fn evaluate(env: &Self::Env, expr: &Self::Expr) -> Result<Self::Value, Self::Error>;
}