fn create_relation(rel: Relation) -> TokenStream {
    let left = rel.expression;
    let operator = rel.operator;
    let right = rel.range_list;

    // All relations that need to be represented in the rust code are folded here. They are unfolded into one token steam later.
    let mut relations = Vec::<TokenStream>::new();

    let l = match left.operand {
        Operand::N => "n",
        Operand::I => "i",
        Operand::V => "v",
        Operand::T => "t",
        Operand::W => "w",
        Operand::F => "f",
    };
    let l = Ident::new(l, Span::call_site());
    let o = get_operator_symbol(&operator);
    let r1 = convert_rangl(right);

    // If there is a modulus, convert to literal. If not, placehold literal
    let (mod_check, m) = if left.modulus != None {
        (true, convert_literal((left.modulus.unwrap().0).0))
    } else {
        (false, convert_literal(0))
    };

    // Here, we have to manage 4 varying types of expression that we may write.

    // First, we check for a within operator because it changes the number of expressions we need.
    // Then, within that check, we look for the operand 'n'. Because 'n' can be a float, we may need to
    // change the compared value to a float type, or use the operand 'i' in 'n's place and also check for f == 0
    // We also check for a modulus on the operand.
    // Lastly, we want to make sure we allow values and ranges to be indeterminately folded together.

    // If within type operator, use format x < po && po < y
    if operator == Operator::Within || operator == Operator::NotWithin {
        let rfront = &(r1.1)[0].0;
        let rback = &(r1.1)[0].1;

        // Variants handled here
        let (rfront, rback, whole_symbol) = if left.operand == Operand::N {
            if !mod_check {
                (quote!(#rfront.0), quote!(#rback.0), quote!(po.#l))
            } else {
                (quote!(#rfront), quote!(#rback), quote!(po.i % #m))
            }
        } else {
            (
                quote!(#rfront),
                quote!(#rback),
                if !mod_check {
                    quote!(po.#l)
                } else {
                    quote!(po.i % #m)
                },
            )
        };

        let rel_tokens = quote! { #rfront #o #whole_symbol && #whole_symbol #o #rback};
        relations.push(rel_tokens);
    // if not within type, use format po < x
    } else {
        // Recurisvely fold all values
        for r in r1.0 {
            // Variants handled here
            let (symbol, rval) = if left.operand == Operand::N {
                if !mod_check {
                    (quote!(po.#l), quote!(#r.0))
                } else {
                    (quote!(po.i % #m), quote!(#r))
                }
            } else {
                (
                    if !mod_check {
                        quote!(po.#l)
                    } else {
                        quote!(po.#l % #m)
                    },
                    quote!(#r),
                )
            };

            let rel_tokens = quote! { #symbol #o #rval };
            relations.push(rel_tokens);
        }
        // Recursively fold all ranges
        for r in r1.1 {
            let rfront = r.0;
            let rback = r.1;

            // Variants handled here
            let (symbol, perim) = if left.operand == Operand::N {
                if !mod_check {
                    (quote!(po.i), quote! { && po.f == 0})
                } else {
                    (quote!(po.i), quote! {})
                }
            } else {
                (
                    if !mod_check {
                        quote!(po.#l)
                    } else {
                        quote!(po.#l % #m)
                    },
                    quote! {},
                )
            };

            let rel_tokens = match operator {
                Operator::In | Operator::Is | Operator::EQ => {
                    quote! { (#rfront ..= #rback).contains(&(#symbol)) #perim }
                }
                Operator::NotIn | Operator::NotEQ | Operator::IsNot => {
                    quote! { !(#rfront ..= #rback).contains(&(#symbol)) #perim }
                }
                Operator::Within | Operator::NotWithin => {
                    panic!("There was a problem with the source file.")
                }
            };
            relations.push(rel_tokens);
        }
    }

    // Unfold all expressions from folded expressions
    match operator {
        Operator::In | Operator::Is | Operator::EQ => {
            if relations.len() > 1 {
                quote! { ( #(#relations)||* ) }
            } else {
                quote! { #(#relations)||* }
            }
        }
        Operator::NotIn | Operator::NotEQ | Operator::IsNot => quote! { #(#relations)&&* },
        Operator::Within | Operator::NotWithin => quote! { #(#relations)||* },
    }
}
/// Create a token stream representation from the AST Relation
Create a token stream representation from the AST Relation
Create a token stream representation from the AST Relation
fn create_relation(rel: Relation) -> TokenStream {
    let left = rel.expression;
    let operator = rel.operator;
    let right = rel.range_list;
    // All relations that need to be represented in the rust code are folded here. They are unfolded into one token steam later.
    let mut relations = Vec::<TokenStream>::new();
    let l = match left.operand {
        Operand::N => "n",
        Operand::I => "i",
        Operand::V => "v",
        Operand::T => "t",
        Operand::W => "w",
        Operand::F => "f",
    };
    let l = Ident::new(l, Span::call_site());
    let o = get_operator_symbol(&operator);
    let r1 = convert_rangl(right);
    // If there is a modulus, convert to literal. If not, placehold literal
    let (mod_check, m) = if left.modulus != None {
        (true, convert_literal((left.modulus.unwrap().0).0))
    } else {
        (false, convert_literal(0))
    };
    // Here, we have to manage 4 varying types of expression that we may write.
    // First, we check for a within operator because it changes the number of expressions we need.
    // Then, within that check, we look for the operand 'n'. Because 'n' can be a float, we may need to
    // change the compared value to a float type, or use the operand 'i' in 'n's place and also check for f == 0
    // We also check for a modulus on the operand.
    // Lastly, we want to make sure we allow values and ranges to be indeterminately folded together.
    // If within type operator, use format x < po && po < y
    if operator == Operator::Within || operator == Operator::NotWithin {
        let rfront = &(r1.1)[0].0;
        let rback = &(r1.1)[0].1;
        // Variants handled here
        let (rfront, rback, whole_symbol) = if left.operand == Operand::N {
            if !mod_check {
                (quote!(#rfront.0), quote!(#rback.0), quote!(po.#l))
            } else {
                (quote!(#rfront), quote!(#rback), quote!(po.i % #m))
            }
        } else {
            (
                quote!(#rfront),
                quote!(#rback),
                if !mod_check {
                    quote!(po.#l)
                } else {
                    quote!(po.i % #m)
                },
            )
        };
        let rel_tokens = quote! { #rfront #o #whole_symbol && #whole_symbol #o #rback};
        relations.push(rel_tokens);
    // if not within type, use format po < x
    } else {
        // Recurisvely fold all values
        for r in r1.0 {
            // Variants handled here
            let (symbol, rval) = if left.operand == Operand::N {
                if !mod_check {
                    (quote!(po.#l), quote!(#r.0))
                } else {
                    (quote!(po.i % #m), quote!(#r))
                }
            } else {
                (
                    if !mod_check {
                        quote!(po.#l)
                    } else {
                        quote!(po.#l % #m)
                    },
                    quote!(#r),
                )
            };
            let rel_tokens = quote! { #symbol #o #rval };
            relations.push(rel_tokens);
        }
        // Recursively fold all ranges
        for r in r1.1 {
            let rfront = r.0;
            let rback = r.1;
            // Variants handled here
            let (symbol, perim) = if left.operand == Operand::N {
                if !mod_check {
                    (quote!(po.i), quote! { && po.f == 0})
                } else {
                    (quote!(po.i), quote! {})
                }
            } else {
                (
                    if !mod_check {
                        quote!(po.#l)
                    } else {
                        quote!(po.#l % #m)
                    },
                    quote! {},
                )
            };
            let rel_tokens = match operator {
                Operator::In | Operator::Is | Operator::EQ => {
                    quote! { (#rfront ..= #rback).contains(&(#symbol)) #perim }
                }
                Operator::NotIn | Operator::NotEQ | Operator::IsNot => {
                    quote! { !(#rfront ..= #rback).contains(&(#symbol)) #perim }
                }
                Operator::Within | Operator::NotWithin => {
                    panic!("There was a problem with the source file.")
                }
            };
            relations.push(rel_tokens);
        }
    }
    // Unfold all expressions from folded expressions
    match operator {
        Operator::In | Operator::Is | Operator::EQ => {
            if relations.len() > 1 {
                quote! { ( #(#relations)||* ) }
            } else {
                quote! { #(#relations)||* }
            }
        }
        Operator::NotIn | Operator::NotEQ | Operator::IsNot => quote! { #(#relations)&&* },
        Operator::Within | Operator::NotWithin => quote! { #(#relations)||* },
    }
}
fn create_relation ( rel : Relation ) -> TokenStream { let left = rel . expression ; let operator = rel . operator ; let right = rel . range_list ; // All relations that need to be represented in the rust code are folded here. They are unfolded into one token steam later. let mut relations = Vec :: < TokenStream > :: new ( ) ; let l = match left . operand { Operand :: N => " " , Operand :: I => " " , Operand :: V => " " , Operand :: T => " " , Operand :: W => " " , Operand :: F => " " , } ; let l = Ident :: new ( l , Span :: call_site ( ) ) ; let o = get_operator_symbol ( & operator ) ; let r1 = convert_rangl ( right ) ; // If there is a modulus, convert to literal. If not, placehold literal let ( mod_check , m ) = if left . modulus != None { ( true , convert_literal ( ( left . modulus . unwrap ( ) . 0 ) . 0 ) ) } else { ( false , convert_literal ( 0 ) ) } ; // Here, we have to manage 4 varying types of expression that we may write. // First, we check for a within operator because it changes the number of expressions we need. // Then, within that check, we look for the operand 'n'. Because 'n' can be a float, we may need to // change the compared value to a float type, or use the operand 'i' in 'n's place and also check for f == 0 // We also check for a modulus on the operand. // Lastly, we want to make sure we allow values and ranges to be indeterminately folded together. // If within type operator, use format x < po && po < y if operator == Operator :: Within || operator == Operator :: NotWithin { let rfront = & ( r1 . 1 ) [ 0 ] . 0 ; let rback = & ( r1 . 1 ) [ 0 ] . 1 ; // Variants handled here let ( rfront , rback , whole_symbol ) = if left . operand == Operand :: N { if ! mod_check { ( quote ! ( rfront 0 ) , quote ! ( rback 0 ) , quote ! ( po l ) ) } else { ( quote ! ( rfront ) , quote ! ( rback ) , quote ! ( po i m ) ) } } else { ( quote ! ( rfront ) , quote ! ( rback ) , if ! mod_check { quote ! ( po l ) } else { quote ! ( po i m ) } , ) } ; let rel_tokens = quote ! { rfront o whole_symbol whole_symbol o rback } ; relations . push ( rel_tokens ) ; // if not within type, use format po < x } else { // Recurisvely fold all values for r in r1 . 0 { // Variants handled here let ( symbol , rval ) = if left . operand == Operand :: N { if ! mod_check { ( quote ! ( po l ) , quote ! ( r 0 ) ) } else { ( quote ! ( po i m ) , quote ! ( r ) ) } } else { ( if ! mod_check { quote ! ( po l ) } else { quote ! ( po l m ) } , quote ! ( r ) , ) } ; let rel_tokens = quote ! { symbol o rval } ; relations . push ( rel_tokens ) ; } // Recursively fold all ranges for r in r1 . 1 { let rfront = r . 0 ; let rback = r . 1 ; // Variants handled here let ( symbol , perim ) = if left . operand == Operand :: N { if ! mod_check { ( quote ! ( po i ) , quote ! { po f 0 } ) } else { ( quote ! ( po i ) , quote ! { } ) } } else { ( if ! mod_check { quote ! ( po l ) } else { quote ! ( po l m ) } , quote ! { } , ) } ; let rel_tokens = match operator { Operator :: In | Operator :: Is | Operator :: EQ => { quote ! { ( rfront rback ) contains ( ( symbol ) ) perim } } Operator :: NotIn | Operator :: NotEQ | Operator :: IsNot => { quote ! { ( rfront rback ) contains ( ( symbol ) ) perim } } Operator :: Within | Operator :: NotWithin => { panic ! ( " " ) } } ; relations . push ( rel_tokens ) ; } } // Unfold all expressions from folded expressions match operator { Operator :: In | Operator :: Is | Operator :: EQ => { if relations . len ( ) > 1 { quote ! { ( ( relations ) ) } } else { quote ! { ( relations ) } } } Operator :: NotIn | Operator :: NotEQ | Operator :: IsNot => quote ! { ( relations ) } , Operator :: Within | Operator :: NotWithin => quote ! { ( relations ) } , } }
Create a token stream representation from the AST Relation
Create a token stream representation from the AST Relation
rel
Relation
rel
Relation