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
use std::collections::HashMap;
use std::fmt::Debug;

use gc::{Finalize, Gc, Trace};

use ast::Expr;
use collections::GcLinkedList;
use modules::ExportedModule;
use symbol::Symbol;
use util::GcVoid;
use value::Value;

/// A trait for the things a [`Value`](enum.Value.html) is parameterized
/// over.
///
/// Yeah, it's vague. Basically, think of it as a collection of associated
/// types that is used to define `Value`.
pub trait Context: Sized {
    /// The type of a function implemented by the runtime.
    type BuiltinFunction: Clone + Debug + Finalize + Trace;

    /// The type of an expression in the AST.
    type Expr: Clone + Debug + Finalize + Trace;

    /// The type of the vtable of an object.
    type ObjectVtable: Clone + Debug + Finalize + Trace;

    /// The type of a user function. This probably should just be the
    /// arguments (as an `Args<C>`), the body (as `C::Expr`), and the variables
    /// closed over and their values (as a `GcLinkedList<(Symbol, Value<C>)>`).
    type UserFunction: Clone + Debug + Finalize + Trace;

    /// The metadata attached to the value.
    type ValueMeta: Clone + Debug + Default + Finalize + Trace;

    /// Converts a standard `ast::Expr` to the expression type of the context.
    fn from_expr(expr: Gc<Expr<Self>>) -> Gc<Self::Expr>;
}

/// A [`Context`](trait.Context.html) that allows for the running of OftLisp
/// code.
pub trait InterpreterContext: Context + Sized {
    /// An error encountered at runtime.
    type RuntimeError: Debug;

    /// Evaluates an expression.
    fn eval(
        expr: Gc<Self::Expr>,
        env: &mut GcLinkedList<(Symbol, Gc<Value<Self>>)>,
    ) -> Result<Gc<Value<Self>>, Self::RuntimeError>;

    /// Returns the values in the `std/internal/primitives` module.
    fn primitives() -> HashMap<Symbol, Gc<Value<Self>>>;
}

/// A [`Context`](trait.Context.html) that allows for the compilation of OftLisp
/// code.
pub trait CompilerContext: Context + Sized {
    /// An error encountered during compilation.
    type CompileError: Debug;

    /// Compiles a module.
    ///
    /// This function gets passed the name of the main module, as well as the
    /// module and its dependencies.
    ///
    /// It should return the contents of the object file.
    fn compile(
        main_mod: Symbol,
        modules: HashMap<Symbol, ExportedModule<Self>>,
    ) -> Result<Vec<u8>, Self::CompileError>;
}

/// A [`Context`](trait.Context.html) for plain data.
pub enum NullContext {}

impl Context for NullContext {
    type BuiltinFunction = GcVoid;
    type Expr = Expr<Self>;
    type ObjectVtable = GcVoid;
    type UserFunction = GcVoid;
    type ValueMeta = ();

    fn from_expr(expr: Gc<Expr<Self>>) -> Gc<Self::Expr> {
        expr
    }
}