pub fn eval_statements(statement_list: CellRef, monad: CellRef, bindings: SymbolBindings, frame: Frame) -> (CellRef, SymbolBindings, Frame) {
    // These three values represent the state of the evaluation
    let mut result      = monad;
    let mut frame       = frame;
    let mut bindings    = bindings;

    // Pre-bind the statements
    let mut current_statement = &statement_list;

    while let SafasCell::List(statement, cdr) = &**current_statement {
        // Perform pre-binding
        let (new_bindings, _) = pre_bind_statement(statement.clone(), bindings);
        bindings = new_bindings;

        // Move to the next statement
        current_statement = cdr;
    }

    // Create the bound statements (and determine if we're going to use monad behaviour or not)
    let mut monadic_result      = result.reference_type() == ReferenceType::Monad;
    let mut current_statement   = &statement_list;
    let mut compiled_actions    = vec![];

    while let SafasCell::List(statement, cdr) = &**current_statement {
        // Perform binding
        let bound_statement = bind_statement(statement.clone(), bindings);

        match bound_statement {
            Err((err, new_bindings)) => {
                // Give up with an error
                return (SafasCell::Error(err.into()).into(), new_bindings, frame);
            }

            Ok((bound, new_bindings)) => {
                // Update the bindings and store this statement
                let expression_type = bound.reference_type();
                bindings            = new_bindings;

                if expression_type == ReferenceType::Monad { monadic_result = true; }

                // Compile the bound statement
                let actions         = compile_statement(bound);
                let actions         = match actions { Ok(actions) => actions, Err(err) => return (SafasCell::Error(err.into()).into(), bindings, frame) };

                compiled_actions.push(actions);
            }
        }

        // Move to the next statement
        current_statement = cdr;
    }

    // Prepare the frame for execution
    frame.allocate_for_bindings(&bindings);

    let (nil_monad_value, nil_monad_type) = (NIL.clone(), wrap_nil());

    // Run the setup actions
    for actions in compiled_actions.iter() {
        let (new_frame, setup_result) = actions.frame_setup.execute(frame);
        frame = new_frame;
        if let Err(err) = setup_result { return (SafasCell::Error(err.into()).into(), bindings, frame); }
    }

    // Evaluate the actions
    for actions in compiled_actions {
        // Collect the actions into a list we can run
        let actions = actions.actions;

        let expr_result = actions.execute(frame);
        let expr_result = match expr_result {
            (new_frame, Ok(expr_result))    => { frame = new_frame; expr_result }
            (new_frame, Err(err))           => { return (SafasCell::Error(err.into()).into(), bindings, new_frame); }
        };

        // Combine the expression result into the final result
        if monadic_result {
            // Wrap the result if we're generating a monad return value
            let expr_result = if expr_result.reference_type() != ReferenceType::Monad {
                wrap_value(expr_result)
            } else {
                expr_result
            };

            // Fetch the current monad value/type from the reuslt
            let (monad_value, monad_type) = match &*result {
                SafasCell::Monad(monad_value, monad_type)   => (monad_value, monad_type),
                _                                           => (&nil_monad_value, &nil_monad_type)
            };

            // Map to the next result
            let (next_frame, next_result)   = monad_type.next(monad_value.clone(), expr_result, frame);
            frame                           = next_frame;

            match next_result {
                Ok(next_result)     => { result = next_result; },
                Err(err)            => { return (SafasCell::Error(err.into()).into(), bindings, frame); }
            }
        } else {
            // The result is the result of the last expression
            result = expr_result;
        }
    }

    (result, bindings, frame)
}
///
/// Evaluates a set of parsed statements
/// 
/// The input values are a statement list, an input monad (if the statements are 'monadic', this is the initial value passed into the monad)
/// and the initial frame and bindings (an updated version of these is returned). `monad` can be set to nil to indicate that a non-monad
/// result can be returned.
///
Evaluates a set of parsed statements
The input values are a statement list, an input monad (if the statements are 'monadic', this is the initial value passed into the monad)
and the initial frame and bindings (an updated version of these is returned). `monad` can be set to nil to indicate that a non-monad
result can be returned.
Evaluates a set of parsed statements The input values are a statement list an input monad ( if the statements are ' monadic ' this is the initial value passed into the monad ) and the initial frame and bindings ( an updated version of these is returned ) . ` monad ` can be set to nil to indicate that a non - monad result can be returned .
pub fn eval_statements(statement_list: CellRef, monad: CellRef, bindings: SymbolBindings, frame: Frame) -> (CellRef, SymbolBindings, Frame) {
    // These three values represent the state of the evaluation
    let mut result      = monad;
    let mut frame       = frame;
    let mut bindings    = bindings;
    // Pre-bind the statements
    let mut current_statement = &statement_list;
    while let SafasCell::List(statement, cdr) = &**current_statement {
        // Perform pre-binding
        let (new_bindings, _) = pre_bind_statement(statement.clone(), bindings);
        bindings = new_bindings;
        // Move to the next statement
        current_statement = cdr;
    }
    // Create the bound statements (and determine if we're going to use monad behaviour or not)
    let mut monadic_result      = result.reference_type() == ReferenceType::Monad;
    let mut current_statement   = &statement_list;
    let mut compiled_actions    = vec![];
    while let SafasCell::List(statement, cdr) = &**current_statement {
        // Perform binding
        let bound_statement = bind_statement(statement.clone(), bindings);
        match bound_statement {
            Err((err, new_bindings)) => {
                // Give up with an error
                return (SafasCell::Error(err.into()).into(), new_bindings, frame);
            }
            Ok((bound, new_bindings)) => {
                // Update the bindings and store this statement
                let expression_type = bound.reference_type();
                bindings            = new_bindings;
                if expression_type == ReferenceType::Monad { monadic_result = true; }
                // Compile the bound statement
                let actions         = compile_statement(bound);
                let actions         = match actions { Ok(actions) => actions, Err(err) => return (SafasCell::Error(err.into()).into(), bindings, frame) };
                compiled_actions.push(actions);
            }
        }
        // Move to the next statement
        current_statement = cdr;
    }
    // Prepare the frame for execution
    frame.allocate_for_bindings(&bindings);
    let (nil_monad_value, nil_monad_type) = (NIL.clone(), wrap_nil());
    // Run the setup actions
    for actions in compiled_actions.iter() {
        let (new_frame, setup_result) = actions.frame_setup.execute(frame);
        frame = new_frame;
        if let Err(err) = setup_result { return (SafasCell::Error(err.into()).into(), bindings, frame); }
    }
    // Evaluate the actions
    for actions in compiled_actions {
        // Collect the actions into a list we can run
        let actions = actions.actions;
        let expr_result = actions.execute(frame);
        let expr_result = match expr_result {
            (new_frame, Ok(expr_result))    => { frame = new_frame; expr_result }
            (new_frame, Err(err))           => { return (SafasCell::Error(err.into()).into(), bindings, new_frame); }
        };
        // Combine the expression result into the final result
        if monadic_result {
            // Wrap the result if we're generating a monad return value
            let expr_result = if expr_result.reference_type() != ReferenceType::Monad {
                wrap_value(expr_result)
            } else {
                expr_result
            };
            // Fetch the current monad value/type from the reuslt
            let (monad_value, monad_type) = match &*result {
                SafasCell::Monad(monad_value, monad_type)   => (monad_value, monad_type),
                _                                           => (&nil_monad_value, &nil_monad_type)
            };
            // Map to the next result
            let (next_frame, next_result)   = monad_type.next(monad_value.clone(), expr_result, frame);
            frame                           = next_frame;
            match next_result {
                Ok(next_result)     => { result = next_result; },
                Err(err)            => { return (SafasCell::Error(err.into()).into(), bindings, frame); }
            }
        } else {
            // The result is the result of the last expression
            result = expr_result;
        }
    }
    (result, bindings, frame)
}
pub fn eval_statements ( statement_list : CellRef , monad : CellRef , bindings : SymbolBindings , frame : Frame ) -> ( CellRef , SymbolBindings , Frame ) { // These three values represent the state of the evaluation let mut result = monad ; let mut frame = frame ; let mut bindings = bindings ; // Pre-bind the statements let mut current_statement = & statement_list ; while let SafasCell :: List ( statement , cdr ) = & * * current_statement { // Perform pre-binding let ( new_bindings , _ ) = pre_bind_statement ( statement . clone ( ) , bindings ) ; bindings = new_bindings ; // Move to the next statement current_statement = cdr ; } // Create the bound statements (and determine if we're going to use monad behaviour or not) let mut monadic_result = result . reference_type ( ) == ReferenceType :: Monad ; let mut current_statement = & statement_list ; let mut compiled_actions = vec ! [ ] ; while let SafasCell :: List ( statement , cdr ) = & * * current_statement { // Perform binding let bound_statement = bind_statement ( statement . clone ( ) , bindings ) ; match bound_statement { Err ( ( err , new_bindings ) ) => { // Give up with an error return ( SafasCell :: Error ( err . into ( ) ) . into ( ) , new_bindings , frame ) ; } Ok ( ( bound , new_bindings ) ) => { // Update the bindings and store this statement let expression_type = bound . reference_type ( ) ; bindings = new_bindings ; if expression_type == ReferenceType :: Monad { monadic_result = true ; } // Compile the bound statement let actions = compile_statement ( bound ) ; let actions = match actions { Ok ( actions ) => actions , Err ( err ) => return ( SafasCell :: Error ( err . into ( ) ) . into ( ) , bindings , frame ) } ; compiled_actions . push ( actions ) ; } } // Move to the next statement current_statement = cdr ; } // Prepare the frame for execution frame . allocate_for_bindings ( & bindings ) ; let ( nil_monad_value , nil_monad_type ) = ( NIL . clone ( ) , wrap_nil ( ) ) ; // Run the setup actions for actions in compiled_actions . iter ( ) { let ( new_frame , setup_result ) = actions . frame_setup . execute ( frame ) ; frame = new_frame ; if let Err ( err ) = setup_result { return ( SafasCell :: Error ( err . into ( ) ) . into ( ) , bindings , frame ) ; } } // Evaluate the actions for actions in compiled_actions { // Collect the actions into a list we can run let actions = actions . actions ; let expr_result = actions . execute ( frame ) ; let expr_result = match expr_result { ( new_frame , Ok ( expr_result ) ) => { frame = new_frame ; expr_result } ( new_frame , Err ( err ) ) => { return ( SafasCell :: Error ( err . into ( ) ) . into ( ) , bindings , new_frame ) ; } } ; // Combine the expression result into the final result if monadic_result { // Wrap the result if we're generating a monad return value let expr_result = if expr_result . reference_type ( ) != ReferenceType :: Monad { wrap_value ( expr_result ) } else { expr_result } ; // Fetch the current monad value/type from the reuslt let ( monad_value , monad_type ) = match & * result { SafasCell :: Monad ( monad_value , monad_type ) => ( monad_value , monad_type ) , _ => ( & nil_monad_value , & nil_monad_type ) } ; // Map to the next result let ( next_frame , next_result ) = monad_type . next ( monad_value . clone ( ) , expr_result , frame ) ; frame = next_frame ; match next_result { Ok ( next_result ) => { result = next_result ; } , Err ( err ) => { return ( SafasCell :: Error ( err . into ( ) ) . into ( ) , bindings , frame ) ; } } } else { // The result is the result of the last expression result = expr_result ; } } ( result , bindings , frame ) }
Evaluates a set of parsed statements
The input values are a statement list, an input monad (if the statements are 'monadic', this is the initial value passed into the monad)
and the initial frame and bindings (an updated version of these is returned).
Evaluates a set of parsed statements The input values are a statement list an input monad ( if the statements are ' monadic ' this is the initial value passed into the monad ) and the initial frame and bindings ( an updated version of these is returned ) .
statement_list
CellRef
monad
CellRef
bindings
SymbolBindings
frame
Frame
statement_list
CellRef
monad
CellRef
bindings
SymbolBindings
frame
Frame