pub fn def_syntax_keyword() -> impl BindingMonad<Binding=SyntaxCompiler> {
    get_expression_arguments().map_result(|ListWithTail((name, patterns), statements): ListWithTail<(AtomId, CellRef), CellRef>| {

        // Parse the arguments to the expression

        // Process the patterns (each is of the form <pattern> <macro>)
        let mut current_pattern = patterns;
        let mut macros          = vec![];
        while !current_pattern.is_nil() {
            // Each pattern is two cells, the pattern definition and the macro definition
            // Format is `(<symbol> . <pattern>) <macro>`
            let pattern_def: ListWithTail<(ListWithTail<(AtomId, ), CellRef>, CellRef), CellRef>    = ListWithTail::try_from(current_pattern)?;
            let ListWithTail((ListWithTail((symbol_name, ), pattern_def), macro_def), next_pattern) = pattern_def;

            // Compile the pattern
            let pattern_def = PatternMatch::from_pattern_as_cells(pattern_def)?;

            // Add to the macros
            macros.push((symbol_name, pattern_def, macro_def));

            // Move to the next pattern
            current_pattern = next_pattern;
        }

        // Group by symbol, so we a vec of each symbol we want to match and the corresponding macro definition
        let macros = macros.into_iter().group_by(|(AtomId(symbol_name), _pattern_def, _macro_def)| *symbol_name);
        let macros = macros.into_iter()
            .map(|(symbol, values)| {
                let values = values.into_iter().map(|(_symbol, pattern_def, macro_def)| (Arc::new(pattern_def), macro_def));
                (symbol, values.collect::<Vec<_>>())
            })
            .collect::<Vec<_>>();

        // Result of the first stage is the list of patterns
        Ok((name, Arc::new(macros), statements))

    }).and_then(|args| {

        // Bind each of the macros and generate the syntax item

        BindingFn::from_binding_fn(move |bindings| {

            // Fetch the values computed by the previous step
            let (name, macros, statements)  = &args;

            // Bind the syntax closure
            let (mut bindings, syntax_closure)  = syntax_closure_from_macro_definitions(bindings, macros, None);
            let syntax_closure                  = match syntax_closure { Ok(syntax_closure) => syntax_closure, Err(err) => return (bindings, Err(err)) };

            // Generate a btree with the 'syntax' entry in it
            let mut btree                       = btree_new();
            btree                               = btree_insert(btree, (SafasCell::atom("syntax"), syntax_closure.syntax_btree())).unwrap();

            // Bind to the name
            let AtomId(name_id) = name;

            let syntax          = SafasCell::Syntax(Box::new(syntax_closure.syntax()), btree);
            bindings.symbols.insert(*name_id, syntax.into());
            bindings.export(*name_id);

            (bindings, Ok(NIL.clone()))

        })
    }).map(|_| SyntaxCompiler::default())
}
///
/// The (def_syntax) keyword, expressed as a binding monad
/// 
/// Syntax is defined using:
/// 
/// ```(def_syntax <name> (<pattern> <macro> ...) [prelude_statements])```
/// 
/// <name> becomes a syntax item in the binding. We can use the new syntax like this:
/// 
/// ```(<name> <statements>)```
/// 
/// Every syntax we define contains a special `syntax` keyword that can be used to retrieve the
/// bindings it contains (so it's possible to extend it). This can be accessed like this: 
/// `(<name> syntax)`
///
The (def_syntax) keyword, expressed as a binding monad
Syntax is defined using.



 becomes a syntax item in the binding. We can use the new syntax like this.



Every syntax we define contains a special `syntax` keyword that can be used to retrieve the
bindings it contains (so it's possible to extend it). This can be accessed like this:
`( syntax)`
The ( def_syntax ) keyword expressed as a binding monad Syntax is defined using . becomes a syntax item in the binding . We can use the new syntax like this . Every syntax we define contains a special ` syntax ` keyword that can be used to retrieve the bindings it contains ( so it ' s possible to extend it ) . This can be accessed like this : ` ( syntax ) `
pub fn def_syntax_keyword() -> impl BindingMonad<Binding=SyntaxCompiler> {
    get_expression_arguments().map_result(|ListWithTail((name, patterns), statements): ListWithTail<(AtomId, CellRef), CellRef>| {
        // Parse the arguments to the expression
        // Process the patterns (each is of the form <pattern> <macro>)
        let mut current_pattern = patterns;
        let mut macros          = vec![];
        while !current_pattern.is_nil() {
            // Each pattern is two cells, the pattern definition and the macro definition
            // Format is `(<symbol> . <pattern>) <macro>`
            let pattern_def: ListWithTail<(ListWithTail<(AtomId, ), CellRef>, CellRef), CellRef>    = ListWithTail::try_from(current_pattern)?;
            let ListWithTail((ListWithTail((symbol_name, ), pattern_def), macro_def), next_pattern) = pattern_def;
            // Compile the pattern
            let pattern_def = PatternMatch::from_pattern_as_cells(pattern_def)?;
            // Add to the macros
            macros.push((symbol_name, pattern_def, macro_def));
            // Move to the next pattern
            current_pattern = next_pattern;
        }
        // Group by symbol, so we a vec of each symbol we want to match and the corresponding macro definition
        let macros = macros.into_iter().group_by(|(AtomId(symbol_name), _pattern_def, _macro_def)| *symbol_name);
        let macros = macros.into_iter()
            .map(|(symbol, values)| {
                let values = values.into_iter().map(|(_symbol, pattern_def, macro_def)| (Arc::new(pattern_def), macro_def));
                (symbol, values.collect::<Vec<_>>())
            })
            .collect::<Vec<_>>();
        // Result of the first stage is the list of patterns
        Ok((name, Arc::new(macros), statements))
    }).and_then(|args| {
        // Bind each of the macros and generate the syntax item
        BindingFn::from_binding_fn(move |bindings| {
            // Fetch the values computed by the previous step
            let (name, macros, statements)  = &args;
            // Bind the syntax closure
            let (mut bindings, syntax_closure)  = syntax_closure_from_macro_definitions(bindings, macros, None);
            let syntax_closure                  = match syntax_closure { Ok(syntax_closure) => syntax_closure, Err(err) => return (bindings, Err(err)) };
            // Generate a btree with the 'syntax' entry in it
            let mut btree                       = btree_new();
            btree                               = btree_insert(btree, (SafasCell::atom("syntax"), syntax_closure.syntax_btree())).unwrap();
            // Bind to the name
            let AtomId(name_id) = name;
            let syntax          = SafasCell::Syntax(Box::new(syntax_closure.syntax()), btree);
            bindings.symbols.insert(*name_id, syntax.into());
            bindings.export(*name_id);
            (bindings, Ok(NIL.clone()))
        })
    }).map(|_| SyntaxCompiler::default())
}
pub fn def_syntax_keyword ( ) -> impl BindingMonad < Binding = SyntaxCompiler > { get_expression_arguments ( ) . map_result ( | ListWithTail ( ( name , patterns ) , statements ) : ListWithTail < ( AtomId , CellRef ) , CellRef > | { // Parse the arguments to the expression // Process the patterns (each is of the form <pattern> <macro>) let mut current_pattern = patterns ; let mut macros = vec ! [ ] ; while ! current_pattern . is_nil ( ) { // Each pattern is two cells, the pattern definition and the macro definition // Format is `(<symbol> . <pattern>) <macro>` let pattern_def : ListWithTail < ( ListWithTail < ( AtomId , ) , CellRef > , CellRef ) , CellRef > = ListWithTail :: try_from ( current_pattern ) ? ; let ListWithTail ( ( ListWithTail ( ( symbol_name , ) , pattern_def ) , macro_def ) , next_pattern ) = pattern_def ; // Compile the pattern let pattern_def = PatternMatch :: from_pattern_as_cells ( pattern_def ) ? ; // Add to the macros macros . push ( ( symbol_name , pattern_def , macro_def ) ) ; // Move to the next pattern current_pattern = next_pattern ; } // Group by symbol, so we a vec of each symbol we want to match and the corresponding macro definition let macros = macros . into_iter ( ) . group_by ( | ( AtomId ( symbol_name ) , _pattern_def , _macro_def ) | * symbol_name ) ; let macros = macros . into_iter ( ) . map ( | ( symbol , values ) | { let values = values . into_iter ( ) . map ( | ( _symbol , pattern_def , macro_def ) | ( Arc :: new ( pattern_def ) , macro_def ) ) ; ( symbol , values . collect :: < Vec < _ > > ( ) ) } ) . collect :: < Vec < _ > > ( ) ; // Result of the first stage is the list of patterns Ok ( ( name , Arc :: new ( macros ) , statements ) ) } ) . and_then ( | args | { // Bind each of the macros and generate the syntax item BindingFn :: from_binding_fn ( move | bindings | { // Fetch the values computed by the previous step let ( name , macros , statements ) = & args ; // Bind the syntax closure let ( mut bindings , syntax_closure ) = syntax_closure_from_macro_definitions ( bindings , macros , None ) ; let syntax_closure = match syntax_closure { Ok ( syntax_closure ) => syntax_closure , Err ( err ) => return ( bindings , Err ( err ) ) } ; // Generate a btree with the 'syntax' entry in it let mut btree = btree_new ( ) ; btree = btree_insert ( btree , ( SafasCell :: atom ( " " ) , syntax_closure . syntax_btree ( ) ) ) . unwrap ( ) ; // Bind to the name let AtomId ( name_id ) = name ; let syntax = SafasCell :: Syntax ( Box :: new ( syntax_closure . syntax ( ) ) , btree ) ; bindings . symbols . insert ( * name_id , syntax . into ( ) ) ; bindings . export ( * name_id ) ; ( bindings , Ok ( NIL . clone ( ) ) ) } ) } ) . map ( | _ | SyntaxCompiler :: default ( ) ) }
The (def_syntax) keyword, expressed as a binding monad
Syntax is defined using:
The ( def_syntax ) keyword expressed as a binding monad Syntax is defined using :