pub fn bind_statement(source: CellRef, bindings: SymbolBindings) -> BindResult<CellRef> {
    use self::SafasCell::*;

    match &*source {
        // Lists are processed according to their first value
        List(car, cdr)  => { bind_list_statement(Arc::clone(car), Arc::clone(cdr), bindings) }

        // Atoms bind to their atom value
        Atom(atom_id)   => {
            // Look up the value for this symbol
            let symbol_value = bindings.look_up(*atom_id);

            if let Some((symbol_value, symbol_level)) = symbol_value {
                use self::SafasCell::*;

                match &*symbol_value {
                    Nil                                         |
                    Any(_)                                      |
                    Number(_)                                   |
                    Boolean(_)                                  |
                    Atom(_)                                     |
                    String(_)                                   |
                    BitCode(_)                                  |
                    Char(_)                                     |
                    BTree(_, _)                                 |
                    List(_, _)                                  |
                    Monad(_, _)                                 |
                    Error(_)                                    |
                    BoundSyntax(_)                              |
                    FrameMonad(_)                               => Ok((symbol_value, bindings)),

                    FrameReference(cell_num, frame, cell_type)  => {
                        let (cell_num, frame) = (*cell_num, *frame);
                        if frame == 0 {
                            // Local symbol
                            Ok((symbol_value, bindings))
                        } else {
                            // Import from a parent frame
                            let mut bindings    = bindings;
                            let local_cell_id   = bindings.alloc_cell();
                            bindings.import(SafasCell::FrameReference(cell_num, frame, *cell_type).into(), local_cell_id);

                            Ok((SafasCell::FrameReference(local_cell_id, 0, *cell_type).into(), bindings))
                        }
                    },

                    Syntax(binding_monad, parameter)     => {
                        // If we're on a different syntax level, try rebinding the monad (the syntax might need to import symbols from an outer frame, for example)
                        let mut bindings = bindings;

                        if symbol_level != 0 {
                            // Try to rebind the syntax from an outer frame
                            let (mut new_bindings, rebound_monad) = binding_monad.rebind_from_outer_frame(bindings, parameter.clone(), symbol_level);

                            // If the compiler rebinds itself...
                            if let Some((rebound_monad, parameter)) = rebound_monad {
                                // Add to the symbols in the current bindings so we don't need to rebind the syntax multiple times
                                let new_syntax = Syntax(rebound_monad, parameter).into();
                                new_bindings.symbols.insert(*atom_id, new_syntax);
                                new_bindings.export(*atom_id);

                                // Re-evaluate this binding (as we insert the binding at the current level we won't rebind the next time through)
                                return bind_statement(source, new_bindings);
                            }

                            // Update the bindings to apply the effects of the rebinding
                            bindings = new_bindings
                        }

                        let mut bindings            = bindings.push_interior_frame();
                        bindings.args               = None;
                        bindings.depth              = Some(symbol_level);
                        let (bindings, compiler)    = binding_monad.bind(bindings);
                        let (bindings, imports)     = bindings.pop();

                        if imports.len() > 0 { panic!("Should not need to import symbols into an interior frame"); }

                        match compiler {
                            Ok(compiler)       => Ok((SafasCell::BoundSyntax(compiler).into(), bindings)),
                            Err(error)      => Err((error, bindings))
                        }
                    }
                }
            } else {
                // Not a valid symbol
                Err((BindError::UnknownSymbol(name_for_atom_with_id(*atom_id)), bindings))
            }
        }

        // Normal values just get loaded into cell 0
        _other          => { Ok((source, bindings)) }
    }
}
///
/// Binds a statement to the value used for compiling
/// 
/// Binding is the process of swapping the symbolic values of the items in a statement with their 'actual'
/// values from a binding environment. A binding environment is represented by the `SymbolBindings` structure.
/// 
/// The binding environment is set up by the `pre_bind_statement` call for a given set of statements.
/// 
/// Most of the types of symbol are constants: ie, the number `1` is just bound to itself. Atoms are a bit more
/// interesting: they are looked up in the environment and bound to whatever value is found there, for example
/// to a cell in the current frame.
/// 
/// Lists are processed as function calls or can be processed in a custom way if their first value is bound to
/// a `Syntax` item.
/// 
/// Atoms that are bound to `Syntax` values can provide custom binding behaviour. They can either appear alone
/// or in a list, and can return any value for their binding. They bind to a new list starting with the syntax
/// item they're bound to (and followed by whatever their binding function returns). The compiler uses this to
/// invoke their `generate_actions` funciton.
/// 
/// Atoms that are bound to `Monad` values or functions that evaluate to `Monad` values (whose `reference_type` is
/// `ReturnsMonad`) are further treated specially. Rather than evaluating them as straight values, their wrapped
/// value is obtained by rewriting the statement so that their `flat_map` method is called. This allows them to
/// be treated as if they are normal values (this is equivalent to `do` syntax in other languages). 
/// 
/// For example: `(wrap 1)` creates a monad wrapping the value `1`. If we use this as a parameter to a function
/// call - for instance `(list (wrap 1) 2)` - the result is not a list containing the monad and the number 2
/// but instead is a monad containing a list `(1 2)`. This allows for a very natural code style when building
/// assembler programs as well as a way to build similar code structures.
/// 
/// SAFAS is typeless, so there is only one `wrap` function needed.
///
Binds a statement to the value used for compiling
Binding is the process of swapping the symbolic values of the items in a statement with their 'actual'
values from a binding environment. A binding environment is represented by the `SymbolBindings` structure.

The binding environment is set up by the `pre_bind_statement` call for a given set of statements.

Most of the types of symbol are constants: ie, the number `1` is just bound to itself. Atoms are a bit more
interesting: they are looked up in the environment and bound to whatever value is found there, for example
to a cell in the current frame.

Lists are processed as function calls or can be processed in a custom way if their first value is bound to
a `Syntax` item.

Atoms that are bound to `Syntax` values can provide custom binding behaviour. They can either appear alone
or in a list, and can return any value for their binding. They bind to a new list starting with the syntax
item they're bound to (and followed by whatever their binding function returns). The compiler uses this to
invoke their `generate_actions` funciton.



For example: `(wrap 1)` creates a monad wrapping the value `1`. If we use this as a parameter to a function
call - for instance `(list (wrap 1) 2)` - the result is not a list containing the monad and the number 2
but instead is a monad containing a list `(1 2)`. This allows for a very natural code style when building
assembler programs as well as a way to build similar code structures.

SAFAS is typeless, so there is only one `wrap` function needed.
Binds a statement to the value used for compiling Binding is the process of swapping the symbolic values of the items in a statement with their ' actual ' values from a binding environment . A binding environment is represented by the ` SymbolBindings ` structure . The binding environment is set up by the ` pre_bind_statement ` call for a given set of statements . Most of the types of symbol are constants : ie the number ` 1 ` is just bound to itself . Atoms are a bit more interesting : they are looked up in the environment and bound to whatever value is found there for example to a cell in the current frame . Lists are processed as function calls or can be processed in a custom way if their first value is bound to a ` Syntax ` item . Atoms that are bound to ` Syntax ` values can provide custom binding behaviour . They can either appear alone or in a list and can return any value for their binding . They bind to a new list starting with the syntax item they ' re bound to ( and followed by whatever their binding function returns ) . The compiler uses this to invoke their ` generate_actions ` funciton . For example : ` ( wrap 1 ) ` creates a monad wrapping the value ` 1 ` . If we use this as a parameter to a function call - for instance ` ( list ( wrap 1 ) 2 ) ` - the result is not a list containing the monad and the number 2 but instead is a monad containing a list ` ( 1 2 ) ` . This allows for a very natural code style when building assembler programs as well as a way to build similar code structures . SAFAS is typeless so there is only one ` wrap ` function needed .
pub fn bind_statement(source: CellRef, bindings: SymbolBindings) -> BindResult<CellRef> {
    use self::SafasCell::*;
    match &*source {
        // Lists are processed according to their first value
        List(car, cdr)  => { bind_list_statement(Arc::clone(car), Arc::clone(cdr), bindings) }
        // Atoms bind to their atom value
        Atom(atom_id)   => {
            // Look up the value for this symbol
            let symbol_value = bindings.look_up(*atom_id);
            if let Some((symbol_value, symbol_level)) = symbol_value {
                use self::SafasCell::*;
                match &*symbol_value {
                    Nil                                         |
                    Any(_)                                      |
                    Number(_)                                   |
                    Boolean(_)                                  |
                    Atom(_)                                     |
                    String(_)                                   |
                    BitCode(_)                                  |
                    Char(_)                                     |
                    BTree(_, _)                                 |
                    List(_, _)                                  |
                    Monad(_, _)                                 |
                    Error(_)                                    |
                    BoundSyntax(_)                              |
                    FrameMonad(_)                               => Ok((symbol_value, bindings)),
                    FrameReference(cell_num, frame, cell_type)  => {
                        let (cell_num, frame) = (*cell_num, *frame);
                        if frame == 0 {
                            // Local symbol
                            Ok((symbol_value, bindings))
                        } else {
                            // Import from a parent frame
                            let mut bindings    = bindings;
                            let local_cell_id   = bindings.alloc_cell();
                            bindings.import(SafasCell::FrameReference(cell_num, frame, *cell_type).into(), local_cell_id);
                            Ok((SafasCell::FrameReference(local_cell_id, 0, *cell_type).into(), bindings))
                        }
                    },
                    Syntax(binding_monad, parameter)     => {
                        // If we're on a different syntax level, try rebinding the monad (the syntax might need to import symbols from an outer frame, for example)
                        let mut bindings = bindings;
                        if symbol_level != 0 {
                            // Try to rebind the syntax from an outer frame
                            let (mut new_bindings, rebound_monad) = binding_monad.rebind_from_outer_frame(bindings, parameter.clone(), symbol_level);
                            // If the compiler rebinds itself...
                            if let Some((rebound_monad, parameter)) = rebound_monad {
                                // Add to the symbols in the current bindings so we don't need to rebind the syntax multiple times
                                let new_syntax = Syntax(rebound_monad, parameter).into();
                                new_bindings.symbols.insert(*atom_id, new_syntax);
                                new_bindings.export(*atom_id);
                                // Re-evaluate this binding (as we insert the binding at the current level we won't rebind the next time through)
                                return bind_statement(source, new_bindings);
                            }
                            // Update the bindings to apply the effects of the rebinding
                            bindings = new_bindings
                        }
                        let mut bindings            = bindings.push_interior_frame();
                        bindings.args               = None;
                        bindings.depth              = Some(symbol_level);
                        let (bindings, compiler)    = binding_monad.bind(bindings);
                        let (bindings, imports)     = bindings.pop();
                        if imports.len() > 0 { panic!("Should not need to import symbols into an interior frame"); }
                        match compiler {
                            Ok(compiler)       => Ok((SafasCell::BoundSyntax(compiler).into(), bindings)),
                            Err(error)      => Err((error, bindings))
                        }
                    }
                }
            } else {
                // Not a valid symbol
                Err((BindError::UnknownSymbol(name_for_atom_with_id(*atom_id)), bindings))
            }
        }
        // Normal values just get loaded into cell 0
        _other          => { Ok((source, bindings)) }
    }
}
pub fn bind_statement ( source : CellRef , bindings : SymbolBindings ) -> BindResult < CellRef > { use self :: SafasCell :: * ; match & * source { // Lists are processed according to their first value List ( car , cdr ) => { bind_list_statement ( Arc :: clone ( car ) , Arc :: clone ( cdr ) , bindings ) } // Atoms bind to their atom value Atom ( atom_id ) => { // Look up the value for this symbol let symbol_value = bindings . look_up ( * atom_id ) ; if let Some ( ( symbol_value , symbol_level ) ) = symbol_value { use self :: SafasCell :: * ; match & * symbol_value { Nil | Any ( _ ) | Number ( _ ) | Boolean ( _ ) | Atom ( _ ) | String ( _ ) | BitCode ( _ ) | Char ( _ ) | BTree ( _ , _ ) | List ( _ , _ ) | Monad ( _ , _ ) | Error ( _ ) | BoundSyntax ( _ ) | FrameMonad ( _ ) => Ok ( ( symbol_value , bindings ) ) , FrameReference ( cell_num , frame , cell_type ) => { let ( cell_num , frame ) = ( * cell_num , * frame ) ; if frame == 0 { // Local symbol Ok ( ( symbol_value , bindings ) ) } else { // Import from a parent frame let mut bindings = bindings ; let local_cell_id = bindings . alloc_cell ( ) ; bindings . import ( SafasCell :: FrameReference ( cell_num , frame , * cell_type ) . into ( ) , local_cell_id ) ; Ok ( ( SafasCell :: FrameReference ( local_cell_id , 0 , * cell_type ) . into ( ) , bindings ) ) } } , Syntax ( binding_monad , parameter ) => { // If we're on a different syntax level, try rebinding the monad (the syntax might need to import symbols from an outer frame, for example) let mut bindings = bindings ; if symbol_level != 0 { // Try to rebind the syntax from an outer frame let ( mut new_bindings , rebound_monad ) = binding_monad . rebind_from_outer_frame ( bindings , parameter . clone ( ) , symbol_level ) ; // If the compiler rebinds itself... if let Some ( ( rebound_monad , parameter ) ) = rebound_monad { // Add to the symbols in the current bindings so we don't need to rebind the syntax multiple times let new_syntax = Syntax ( rebound_monad , parameter ) . into ( ) ; new_bindings . symbols . insert ( * atom_id , new_syntax ) ; new_bindings . export ( * atom_id ) ; // Re-evaluate this binding (as we insert the binding at the current level we won't rebind the next time through) return bind_statement ( source , new_bindings ) ; } // Update the bindings to apply the effects of the rebinding bindings = new_bindings } let mut bindings = bindings . push_interior_frame ( ) ; bindings . args = None ; bindings . depth = Some ( symbol_level ) ; let ( bindings , compiler ) = binding_monad . bind ( bindings ) ; let ( bindings , imports ) = bindings . pop ( ) ; if imports . len ( ) > 0 { panic ! ( " " ) ; } match compiler { Ok ( compiler ) => Ok ( ( SafasCell :: BoundSyntax ( compiler ) . into ( ) , bindings ) ) , Err ( error ) => Err ( ( error , bindings ) ) } } } } else { // Not a valid symbol Err ( ( BindError :: UnknownSymbol ( name_for_atom_with_id ( * atom_id ) ) , bindings ) ) } } // Normal values just get loaded into cell 0 _other => { Ok ( ( source , bindings ) ) } } }
Binds a statement to the value used for compiling
Binding is the process of swapping the symbolic values of the items in a statement with their 'actual'
values from a binding environment.
Binds a statement to the value used for compiling Binding is the process of swapping the symbolic values of the items in a statement with their ' actual ' values from a binding environment .
source
CellRef
bindings
SymbolBindings
source
CellRef
bindings
SymbolBindings