use std::rc::Rc; use crate::ast::*; //TODO maybe these functions should take closures that return a KeepRecursing | StopHere type, //or a tuple of (T, ) pub trait ASTVisitor: Sized { fn ast(&mut self, _ast: &AST) {} fn block(&mut self, _statements: &Vec) {} fn statement(&mut self, _statement: &Statement) {} fn declaration(&mut self, _declaration: &Declaration) {} fn signature(&mut self, _signature: &Signature) {} fn type_declaration(&mut self, _name: &TypeSingletonName, _body: &TypeBody, _mutable: bool) {} fn type_alias(&mut self, _alias: &Rc, _original: &Rc) {} fn binding(&mut self, _name: &Rc, _constant: bool, _type_anno: Option<&TypeIdentifier>, _expr: &Expression) {} fn implemention(&mut self, _type_name: &TypeIdentifier, _interface_name: Option<&TypeSingletonName>, _block: &Vec) {} fn interface(&mut self, _name: &Rc, _signatures: &Vec) {} fn expression(&mut self, _expression: &Expression) {} fn expression_kind(&mut self, _kind: &ExpressionKind) {} fn type_annotation(&mut self, _type_anno: Option<&TypeIdentifier>) {} fn named_struct(&mut self, _name: &QualifiedName, _fields: &Vec<(Rc, Expression)>) {} fn call(&mut self, _f: &Expression, _arguments: &Vec) {} fn index(&mut self, _indexee: &Expression, _indexers: &Vec) {} fn if_expression(&mut self, _discrim: Option<&Expression>, _body: &IfExpressionBody) {} fn condition_arm(&mut self, _arm: &ConditionArm) {} fn while_expression(&mut self, _condition: Option<&Expression>, _body: &Block) {} fn for_expression(&mut self, _enumerators: &Vec, _body: &ForBody) {} fn lambda(&mut self, _params: &Vec, _type_anno: Option<&TypeIdentifier>, _body: &Block) {} fn invocation_argument(&mut self, _arg: &InvocationArgument) {} fn formal_param(&mut self, _param: &FormalParam) {} fn import(&mut self, _import: &ImportSpecifier) {} fn module(&mut self, _module: &ModuleSpecifier) {} fn qualified_name(&mut self, _name: &QualifiedName) {} fn nat_literal(&mut self, _n: u64) {} fn float_literal(&mut self, _f: f64) {} fn string_literal(&mut self, _s: &Rc) {} fn bool_literal(&mut self, _b: bool) {} fn binexp(&mut self, _op: &BinOp, _lhs: &Expression, _rhs: &Expression) {} fn prefix_exp(&mut self, _op: &PrefixOp, _arg: &Expression) {} fn pattern(&mut self, _pat: &Pattern) {} } pub trait ExpressionVisitor {//TODO maybe this should be an associated type? type Output; fn type_anno(&mut self, _anno: &TypeIdentifier) -> Self::Output; fn nat_literal(&mut self, _value: &u64) -> Self::Output; fn string_literal(&mut self, _value: &Rc) -> Self::Output; fn binexp(&mut self, _op: &BinOp, _lhs_resul: Self::Output, _rhs_result: Self::Output) -> Self::Output; fn done(&mut self, kind: Self::Output, anno: Option) -> Self::Output; } pub fn dispatch_expression_visitor(input: &Expression, visitor: &mut dyn ExpressionVisitor) -> Result { let output = match input.kind { ExpressionKind::NatLiteral(ref n) => visitor.nat_literal(n), ExpressionKind::StringLiteral(ref s) => visitor.string_literal(s), ExpressionKind::BinExp(ref op, ref lhs, ref rhs) => { let lhs = dispatch_expression_visitor(lhs, visitor)?; let rhs = dispatch_expression_visitor(rhs, visitor)?; visitor.binexp(op, lhs, rhs) }, _ => return Err(format!("Lol not done yet!")), }; let type_output = input.type_anno.as_ref().map(|anno| visitor.type_anno(anno)); Ok(visitor.done(output, type_output)) }