Cell

If Scheme can be represented by an aggregate type called a sexpr, then we just need to create a type in Rust that represents an S-expression: a type that can be either an atom, or a pair. Fortunately Rust's enum type allows exactly this: the creation of a type that represents one of several possible variants.

Marwood's Cell is the enum type that represents Scheme data and code in Marwood. It is the main input to Marwood's compiler, macro transformers, and printer, and is the output of Marwood's VM as a result of evaluating scheme.

Most Cell's variants represent atom types in Scheme, such as booleans, numbers, symbols, characters, and strings:

pub enum Cell {
    Bool(bool),
    Char(char),
    Number(Number),
    Nil,
    String(String),
    Symbol(String),
    ...
}

As an example, parsing the scheme expression #f would result in Marwood's parser outputting the value Cell::Bool(false).

Pairs

Cell also contains an aggregate type called Pair, which represents a sexpr pair:

pub enum Cell {
    ...
    Pair(Box<Cell>, Box<Cell>),
    ...
}

Pair is a pair of Cells representing the car and cdr parts of a cons pair. This structure can be used to represent pairs in scheme, which in turn may be used to represent lists. This is the main building block for representing Scheme code's tree structure in Rust.

Vectors

Vector represents a literal scheme vector, such as #(10 20 30).

pub enum Cell {
    ...
    Vector(Vec<Cell>),
    ...
}

Special Variants

The Cell enum also contains a few variants that can only be produced as output of Marwood's evaluator. For example, the Cell::Void variant is produced by some Marwood procedures that evaluate to #<void> (e.g. define, set!). It is not possible to produce these variants via Marwood's parser.

#[derive(Debug, Eq, PartialEq, Hash, Clone)]
pub enum Cell {
    ...
    Continuation,
    Macro,
    Procedure(Option<String>),
    Undefined,
    Void,
}