use std::collections::HashMap; use crate::ast::hir::{Binding, Decl, Expr, Pattern}; use crate::ast::{BinaryOperator, Ident, Literal, UnaryOperator}; pub(crate) mod monomorphize; pub(crate) mod strip_positive_units; pub(crate) trait Visitor<'a, 'ast, T: 'ast>: Sized + 'a { type Error; fn visit_type(&mut self, _type: &mut T) -> Result<(), Self::Error> { Ok(()) } fn visit_ident(&mut self, _ident: &mut Ident<'ast>) -> Result<(), Self::Error> { Ok(()) } fn visit_literal(&mut self, _literal: &mut Literal<'ast>) -> Result<(), Self::Error> { Ok(()) } fn visit_unary_operator(&mut self, _op: &mut UnaryOperator) -> Result<(), Self::Error> { Ok(()) } fn visit_binary_operator(&mut self, _op: &mut BinaryOperator) -> Result<(), Self::Error> { Ok(()) } fn visit_pattern(&mut self, _pat: &mut Pattern<'ast, T>) -> Result<(), Self::Error> { Ok(()) } fn visit_binding(&mut self, binding: &mut Binding<'ast, T>) -> Result<(), Self::Error> { self.visit_pattern(&mut binding.pat)?; self.visit_expr(&mut binding.body)?; Ok(()) } fn post_visit_call( &mut self, _fun: &mut Expr<'ast, T>, _type_args: &mut HashMap<Ident<'ast>, T>, _args: &mut Vec<Expr<'ast, T>>, ) -> Result<(), Self::Error> { Ok(()) } fn pre_visit_call( &mut self, _fun: &mut Expr<'ast, T>, _type_args: &mut HashMap<Ident<'ast>, T>, _args: &mut Vec<Expr<'ast, T>>, ) -> Result<(), Self::Error> { Ok(()) } fn visit_tuple(&mut self, members: &mut Vec<Expr<'ast, T>>) -> Result<(), Self::Error> { for expr in members { self.visit_expr(expr)?; } Ok(()) } fn pre_visit_expr(&mut self, _expr: &mut Expr<'ast, T>) -> Result<(), Self::Error> { Ok(()) } fn visit_expr(&mut self, expr: &mut Expr<'ast, T>) -> Result<(), Self::Error> { self.pre_visit_expr(expr)?; match expr { Expr::Ident(id, t) => { self.visit_ident(id)?; self.visit_type(t)?; } Expr::Literal(lit, t) => { self.visit_literal(lit)?; self.visit_type(t)?; } Expr::UnaryOp { op, rhs, type_ } => { self.visit_unary_operator(op)?; self.visit_expr(rhs)?; self.visit_type(type_)?; } Expr::BinaryOp { lhs, op, rhs, type_, } => { self.visit_expr(lhs)?; self.visit_binary_operator(op)?; self.visit_expr(rhs)?; self.visit_type(type_)?; } Expr::Let { bindings, body, type_, } => { for binding in bindings.iter_mut() { self.visit_binding(binding)?; } self.visit_expr(body)?; self.visit_type(type_)?; } Expr::If { condition, then, else_, type_, } => { self.visit_expr(condition)?; self.visit_expr(then)?; self.visit_expr(else_)?; self.visit_type(type_)?; } Expr::Fun { args, body, type_args, type_, } => { for (ident, t) in args { self.visit_ident(ident)?; self.visit_type(t)?; } for ta in type_args { self.visit_ident(ta)?; } self.visit_expr(body)?; self.visit_type(type_)?; } Expr::Call { fun, args, type_args, type_, } => { self.pre_visit_call(fun, type_args, args)?; self.visit_expr(fun)?; for arg in args.iter_mut() { self.visit_expr(arg)?; } self.visit_type(type_)?; self.post_visit_call(fun, type_args, args)?; } Expr::Tuple(tup, type_) => { self.visit_tuple(tup)?; self.visit_type(type_)?; } } Ok(()) } fn post_visit_decl(&mut self, _decl: &'a Decl<'ast, T>) -> Result<(), Self::Error> { Ok(()) } fn post_visit_fun_decl( &mut self, _name: &mut Ident<'ast>, _type_args: &mut Vec<Ident>, _args: &mut Vec<(Ident, T)>, _body: &mut Box<Expr<T>>, _type_: &mut T, ) -> Result<(), Self::Error> { Ok(()) } fn visit_decl(&mut self, decl: &'a mut Decl<'ast, T>) -> Result<(), Self::Error> { match decl { Decl::Fun { name, type_args, args, body, type_, } => { self.visit_ident(name)?; for type_arg in type_args.iter_mut() { self.visit_ident(type_arg)?; } for (arg, t) in args.iter_mut() { self.visit_ident(arg)?; self.visit_type(t)?; } self.visit_expr(body)?; self.visit_type(type_)?; self.post_visit_fun_decl(name, type_args, args, body, type_)?; } Decl::Extern { name, arg_types, ret_type, } => { self.visit_ident(name)?; for arg_t in arg_types { self.visit_type(arg_t)?; } self.visit_type(ret_type)?; } } self.post_visit_decl(decl)?; Ok(()) } }