purescript-corefn 0.3.0

A parser for PureScript's corefn JSON representation.
Documentation
use {Alternative, Bind, Decl, Expression};

pub fn expression(
    expr: &Expression,
    pre: &mut impl FnMut(&Expression),
    post: &mut impl FnMut(&Expression),
) {
    macro_rules! f {
        ($a:expr) => {
            expression($a, pre, post);
        };
    }
    use Expression::*;
    pre(expr);
    match expr {
        Abs { body, .. } => f!(body),
        Accessor { expression, .. } => f!(expression),
        App {
            abstraction,
            argument,
            ..
        } => {
            f!(abstraction);
            f!(argument);
        }
        Case {
            alternatives,
            expressions,
            ..
        } => {
            for alternative in alternatives {
                match alternative {
                    Alternative::Guarded { expressions, .. } => {
                        for expression in expressions {
                            f!(&expression.guard);
                            f!(&expression.expression);
                        }
                    }
                    Alternative::Unguarded { expression, .. } => {
                        f!(expression);
                    }
                }
            }
            for expression in expressions {
                f!(expression);
            }
        }
        Constructor { .. } => {}
        Let {
            expression, binds, ..
        } => {
            f!(expression);
            for decl in binds {
                walk_decl(decl, pre, post);
            }
        }
        Literal { value, .. } => match value {
            ::Literal::Array { value } => {
                for v in value {
                    f!(v)
                }
            }
            ::Literal::Object { value } => {
                for (_, v) in value {
                    f!(v)
                }
            }
            _ => {}
        },
        ObjectUpdate {
            expression,
            updates,
            ..
        } => {
            f!(expression);
            for (_, update) in updates {
                f!(update);
            }
        }
        Var { .. } => {}
    }
    post(expr);

    fn walk_decl(
        decl: &Decl,
        pre: &mut impl FnMut(&Expression),
        post: &mut impl FnMut(&Expression),
    ) {
        let mut f = |bind: &Bind| expression(&bind.expression, pre, post);
        match decl {
            Decl::NonRec(bind) => f(bind),
            Decl::Rec { binds } => {
                for bind in binds {
                    f(bind)
                }
            }
        }
    }
}

pub fn expression_mut(
    expr: &mut Expression,
    pre: &mut impl FnMut(&mut Expression),
    post: &mut impl FnMut(&mut Expression),
) {
    macro_rules! f {
        ($a:expr) => {
            expression_mut($a, pre, post);
        };
    }
    use Expression::*;
    pre(expr);
    match expr {
        Abs { body, .. } => f!(body),
        Accessor { expression, .. } => f!(expression),
        App {
            abstraction,
            argument,
            ..
        } => {
            f!(abstraction);
            f!(argument);
        }
        Case {
            alternatives,
            expressions,
            ..
        } => {
            for alternative in alternatives {
                match alternative {
                    Alternative::Guarded { expressions, .. } => {
                        for expression in expressions {
                            f!(&mut expression.guard);
                            f!(&mut expression.expression);
                        }
                    }
                    Alternative::Unguarded { expression, .. } => {
                        f!(expression);
                    }
                }
            }
            for expression in expressions {
                f!(expression);
            }
        }
        Constructor { .. } => {}
        Let {
            expression, binds, ..
        } => {
            f!(expression);
            for decl in binds {
                walk_decl(decl, pre, post);
            }
        }
        Literal { value, .. } => match value {
            ::Literal::Array { value } => {
                for v in value {
                    f!(v)
                }
            }
            ::Literal::Object { value } => {
                for (_, v) in value {
                    f!(v)
                }
            }
            _ => {}
        },
        ObjectUpdate {
            expression,
            updates,
            ..
        } => {
            f!(expression);
            for (_, update) in updates {
                f!(update);
            }
        }
        Var { .. } => {}
    }
    post(expr);

    fn walk_decl(
        decl: &mut Decl,
        pre: &mut impl FnMut(&mut Expression),
        post: &mut impl FnMut(&mut Expression),
    ) {
        let mut f = |bind: &mut Bind| expression_mut(&mut bind.expression, pre, post);
        match decl {
            Decl::NonRec(bind) => f(bind),
            Decl::Rec { binds } => {
                for bind in binds {
                    f(bind)
                }
            }
        }
    }
}