pub fn desugar(exp: Exp) -> Result<Exp, ScmErr> {
    fn require_len(list: &Vec<Exp>, min_len: usize) -> Result<(), ScmErr> {
        let len = list.len();
        if len < min_len {
            Err(ScmErr::from(&format!(
                "desugar: too few arguments ({}/{})",
                len, min_len
            )))
        } else {
            Ok(())
        }
    }

    match exp.clone() {
        Exp::List(list) => {
            // println!("Sugar debug: {:?}", list);
            match list.get(0) {
                Some(Exp::Symbol(s)) => match s.as_ref() {
                    "define" => {
                        // (define (f . args) body+) => (define f (lambda args body+))
                        require_len(&list, 3)?;
                        let f: Exp; // Symbol
                        let args: Exp; // List
                        let body: Vec<Exp>;
                        match &list[1] {
                            Exp::List(f_args) => {
                                require_len(f_args, 1)?;
                                f = match f_args[0].clone() {
                                    Exp::Symbol(s) => Exp::Symbol(s),
                                    _ => {
                                        return Err(ScmErr::from(
                                            "desugar: can only define a Symbol",
                                        ))
                                    }
                                };
                                args = {
                                    let args_list: Vec<Exp> =
                                        f_args.iter().skip(1).cloned().collect();
                                    Exp::List(args_list)
                                };
                                body = list.iter().skip(2).cloned().collect();
                                desugar(Exp::List({
                                    let lambda_args_body: Vec<Exp> =
                                        [Exp::Symbol("lambda".into()), args]
                                            .iter()
                                            .cloned()
                                            .chain(body.into_iter())
                                            .collect();
                                    let res: Vec<Exp> = [
                                        Exp::Symbol("define".into()),
                                        f,
                                        Exp::List(lambda_args_body),
                                    ]
                                    .iter()
                                    .cloned()
                                    .collect();
                                    // println!("Sugar debug: {:?}", res);
                                    res
                                }))
                            }
                            _ => {
                                let res: Vec<Exp> =
                                    list.iter().map(|x| desugar(x.clone()).unwrap()).collect();
                                // println!("Sugar debug: {:?}", res);
                                Ok(Exp::List(res))
                            }
                        }
                    }

                    _ => Ok(exp),
                },

                _ => {
                    let res: Vec<Exp> = list.iter().map(|x| desugar(x.clone()).unwrap()).collect();
                    Ok(Exp::List(res))
                }
            }
        }
        _ => Ok(exp), // a non-list cannot be expanded.
    }
}
/// Handles syntax sugar forms.
// ! This is EXTREMELY DIRTY.
// TODO: refactor this function in a more elegant way.
Handles syntax sugar forms.
This is EXTREMELY DIRTY.
TODO: refactor this function in a more elegant way.
Handles syntax sugar forms . This is EXTREMELY DIRTY . TODO : refactor this function in a more elegant way .
pub fn desugar(exp: Exp) -> Result<Exp, ScmErr> {
    fn require_len(list: &Vec<Exp>, min_len: usize) -> Result<(), ScmErr> {
        let len = list.len();
        if len < min_len {
            Err(ScmErr::from(&format!(
                "desugar: too few arguments ({}/{})",
                len, min_len
            )))
        } else {
            Ok(())
        }
    }
    match exp.clone() {
        Exp::List(list) => {
            // println!("Sugar debug: {:?}", list);
            match list.get(0) {
                Some(Exp::Symbol(s)) => match s.as_ref() {
                    "define" => {
                        // (define (f . args) body+) => (define f (lambda args body+))
                        require_len(&list, 3)?;
                        let f: Exp; // Symbol
                        let args: Exp; // List
                        let body: Vec<Exp>;
                        match &list[1] {
                            Exp::List(f_args) => {
                                require_len(f_args, 1)?;
                                f = match f_args[0].clone() {
                                    Exp::Symbol(s) => Exp::Symbol(s),
                                    _ => {
                                        return Err(ScmErr::from(
                                            "desugar: can only define a Symbol",
                                        ))
                                    }
                                };
                                args = {
                                    let args_list: Vec<Exp> =
                                        f_args.iter().skip(1).cloned().collect();
                                    Exp::List(args_list)
                                };
                                body = list.iter().skip(2).cloned().collect();
                                desugar(Exp::List({
                                    let lambda_args_body: Vec<Exp> =
                                        [Exp::Symbol("lambda".into()), args]
                                            .iter()
                                            .cloned()
                                            .chain(body.into_iter())
                                            .collect();
                                    let res: Vec<Exp> = [
                                        Exp::Symbol("define".into()),
                                        f,
                                        Exp::List(lambda_args_body),
                                    ]
                                    .iter()
                                    .cloned()
                                    .collect();
                                    // println!("Sugar debug: {:?}", res);
                                    res
                                }))
                            }
                            _ => {
                                let res: Vec<Exp> =
                                    list.iter().map(|x| desugar(x.clone()).unwrap()).collect();
                                // println!("Sugar debug: {:?}", res);
                                Ok(Exp::List(res))
                            }
                        }
                    }
                    _ => Ok(exp),
                },
                _ => {
                    let res: Vec<Exp> = list.iter().map(|x| desugar(x.clone()).unwrap()).collect();
                    Ok(Exp::List(res))
                }
            }
        }
        _ => Ok(exp), // a non-list cannot be expanded.
    }
}
pub fn desugar ( exp : Exp ) -> Result < Exp , ScmErr > { fn require_len ( list : & Vec < Exp > , min_len : usize ) -> Result < ( ) , ScmErr > { let len = list . len ( ) ; if len < min_len { Err ( ScmErr :: from ( & format ! ( " " len min_len ) ) ) } else { Ok ( ( ) ) } } match exp . clone ( ) { Exp :: List ( list ) => { // println!("Sugar debug: {:?}", list); match list . get ( 0 ) { Some ( Exp :: Symbol ( s ) ) => match s . as_ref ( ) { " " => { // (define (f . args) body+) => (define f (lambda args body+)) require_len ( & list , 3 ) ? ; let f : Exp ; // Symbol let args : Exp ; // List let body : Vec < Exp > ; match & list [ 1 ] { Exp :: List ( f_args ) => { require_len ( f_args , 1 ) ? ; f = match f_args [ 0 ] . clone ( ) { Exp :: Symbol ( s ) => Exp :: Symbol ( s ) , _ => { return Err ( ScmErr :: from ( " " , ) ) } } ; args = { let args_list : Vec < Exp > = f_args . iter ( ) . skip ( 1 ) . cloned ( ) . collect ( ) ; Exp :: List ( args_list ) } ; body = list . iter ( ) . skip ( 2 ) . cloned ( ) . collect ( ) ; desugar ( Exp :: List ( { let lambda_args_body : Vec < Exp > = [ Exp :: Symbol ( " " . into ( ) ) , args ] . iter ( ) . cloned ( ) . chain ( body . into_iter ( ) ) . collect ( ) ; let res : Vec < Exp > = [ Exp :: Symbol ( " " . into ( ) ) , f , Exp :: List ( lambda_args_body ) , ] . iter ( ) . cloned ( ) . collect ( ) ; // println!("Sugar debug: {:?}", res); res } ) ) } _ => { let res : Vec < Exp > = list . iter ( ) . map ( | x | desugar ( x . clone ( ) ) . unwrap ( ) ) . collect ( ) ; // println!("Sugar debug: {:?}", res); Ok ( Exp :: List ( res ) ) } } } _ => Ok ( exp ) , } , _ => { let res : Vec < Exp > = list . iter ( ) . map ( | x | desugar ( x . clone ( ) ) . unwrap ( ) ) . collect ( ) ; Ok ( Exp :: List ( res ) ) } } } _ => Ok ( exp ) , // a non-list cannot be expanded. } }
Handles syntax sugar forms.
Handles syntax sugar forms .
exp
Exp
exp
Exp