pub fn syntax(symbol: Arc<SyntaxSymbol>) -> impl BindingMonad<Binding=SyntaxCompiler> {
        let is_monad    = symbol.reference_type == ReferenceType::Monad;
        symbol.map(move |args| {
            let args        = args.clone();
            let compile     = move |args: CellRef| {
                // Arguments are an encoded syntax binding result
                let args        = SyntaxBindingResult::try_from(args)?;

                let mut actions = CompiledActions::empty();
                match args {
                    SyntaxBindingResult::Statements(args) => {
                        // We compile each of the statements generated by the binding
                        let mut first   = true;

                        for statement in args.to_vec().unwrap_or_else(|| vec![]) {
                            // Compile the statement
                            actions.extend(compile_statement(statement.clone())?);

                            // Map between values if the value is a monad
                            if is_monad {
                                if statement.reference_type() != ReferenceType::Monad {
                                    // Wrap the statement if it doesn't return a monad
                                    actions.push(Action::Wrap);
                                }

                                if first {
                                    // First monad is just pushed onto the stack
                                    actions.push(Action::Push);
                                } else {
                                    // Others are mapped using the next function
                                    actions.push(Action::Next);
                                }
                            }

                            first = false;
                        }

                        if is_monad && !first {
                            // Pop the monad value, if there's one on the stack
                            actions.push(Action::Pop);
                        }
                    },

                    SyntaxBindingResult::FlatMap(monad, closure) => {
                        let flat_map_actions = compile_flat_map(monad, closure)?;
                        actions.extend(flat_map_actions);
                    },

                    SyntaxBindingResult::Fallback(fallback) => {

                        match &*fallback {
                            SafasCell::BoundSyntax(fallback)    => return fallback.generate_actions(),
                            _                                   => return Err(BindError::NotImplemented)
                        }

                    }
                }

                Ok(actions)
            };

            // Arguments are changed to a CellRef representation to take advantage of the default rebinding behaviour
            let reference_type = if is_monad { ReferenceType::Monad } else { ReferenceType::Value };
            SyntaxCompiler::with_compiler_and_reftype(compile, args.into(), reference_type)
        })
    }
///
/// Creates the syntax compiler for this symbol
///
Creates the syntax compiler for this symbol
Creates the syntax compiler for this symbol
pub fn syntax(symbol: Arc<SyntaxSymbol>) -> impl BindingMonad<Binding=SyntaxCompiler> {
        let is_monad    = symbol.reference_type == ReferenceType::Monad;
        symbol.map(move |args| {
            let args        = args.clone();
            let compile     = move |args: CellRef| {
                // Arguments are an encoded syntax binding result
                let args        = SyntaxBindingResult::try_from(args)?;
                let mut actions = CompiledActions::empty();
                match args {
                    SyntaxBindingResult::Statements(args) => {
                        // We compile each of the statements generated by the binding
                        let mut first   = true;
                        for statement in args.to_vec().unwrap_or_else(|| vec![]) {
                            // Compile the statement
                            actions.extend(compile_statement(statement.clone())?);
                            // Map between values if the value is a monad
                            if is_monad {
                                if statement.reference_type() != ReferenceType::Monad {
                                    // Wrap the statement if it doesn't return a monad
                                    actions.push(Action::Wrap);
                                }
                                if first {
                                    // First monad is just pushed onto the stack
                                    actions.push(Action::Push);
                                } else {
                                    // Others are mapped using the next function
                                    actions.push(Action::Next);
                                }
                            }
                            first = false;
                        }
                        if is_monad && !first {
                            // Pop the monad value, if there's one on the stack
                            actions.push(Action::Pop);
                        }
                    },
                    SyntaxBindingResult::FlatMap(monad, closure) => {
                        let flat_map_actions = compile_flat_map(monad, closure)?;
                        actions.extend(flat_map_actions);
                    },
                    SyntaxBindingResult::Fallback(fallback) => {
                        match &*fallback {
                            SafasCell::BoundSyntax(fallback)    => return fallback.generate_actions(),
                            _                                   => return Err(BindError::NotImplemented)
                        }
                    }
                }
                Ok(actions)
            };
            // Arguments are changed to a CellRef representation to take advantage of the default rebinding behaviour
            let reference_type = if is_monad { ReferenceType::Monad } else { ReferenceType::Value };
            SyntaxCompiler::with_compiler_and_reftype(compile, args.into(), reference_type)
        })
    }
pub fn syntax ( symbol : Arc < SyntaxSymbol > ) -> impl BindingMonad < Binding = SyntaxCompiler > { let is_monad = symbol . reference_type == ReferenceType :: Monad ; symbol . map ( move | args | { let args = args . clone ( ) ; let compile = move | args : CellRef | { // Arguments are an encoded syntax binding result let args = SyntaxBindingResult :: try_from ( args ) ? ; let mut actions = CompiledActions :: empty ( ) ; match args { SyntaxBindingResult :: Statements ( args ) => { // We compile each of the statements generated by the binding let mut first = true ; for statement in args . to_vec ( ) . unwrap_or_else ( | | vec ! [ ] ) { // Compile the statement actions . extend ( compile_statement ( statement . clone ( ) ) ? ) ; // Map between values if the value is a monad if is_monad { if statement . reference_type ( ) != ReferenceType :: Monad { // Wrap the statement if it doesn't return a monad actions . push ( Action :: Wrap ) ; } if first { // First monad is just pushed onto the stack actions . push ( Action :: Push ) ; } else { // Others are mapped using the next function actions . push ( Action :: Next ) ; } } first = false ; } if is_monad && ! first { // Pop the monad value, if there's one on the stack actions . push ( Action :: Pop ) ; } } , SyntaxBindingResult :: FlatMap ( monad , closure ) => { let flat_map_actions = compile_flat_map ( monad , closure ) ? ; actions . extend ( flat_map_actions ) ; } , SyntaxBindingResult :: Fallback ( fallback ) => { match & * fallback { SafasCell :: BoundSyntax ( fallback ) => return fallback . generate_actions ( ) , _ => return Err ( BindError :: NotImplemented ) } } } Ok ( actions ) } ; // Arguments are changed to a CellRef representation to take advantage of the default rebinding behaviour let reference_type = if is_monad { ReferenceType :: Monad } else { ReferenceType :: Value } ; SyntaxCompiler :: with_compiler_and_reftype ( compile , args . into ( ) , reference_type ) } ) }
Creates the syntax compiler for this symbol
Creates the syntax compiler for this symbol
symbol
Arc<SyntaxSymbol>
symbol
Arc<SyntaxSymbol>