use std::rc::Rc; use crate::ast::*; use crate::util::deref_optional_box; //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 ASTVisitorNew: Sized { fn expression(&mut self, _expression: &Expression) -> VisitResult { VisitResult::default() } fn expression_kind(&mut self, _kind: &ExpressionKind) -> VisitResult { VisitResult::default() } fn type_annotation(&mut self, _id: ItemId, _type_anno: Option<&TypeIdentifier>) -> VisitResult { VisitResult::default() } fn named_struct(&mut self, _name: &QualifiedName, _fields: &Vec<(Rc, Expression)>) -> VisitResult { VisitResult::default() } fn nat_literal(&mut self, _id: ItemId, _n: u64)-> VisitResult { VisitResult::default() } fn float_literal(&mut self, _id: ItemId, _f: f64) -> VisitResult { VisitResult::default() } fn string_literal(&mut self, _id: ItemId, _s: &Rc) -> VisitResult { VisitResult::default() } fn bool_literal(&mut self, _id: ItemId, _b: bool) -> VisitResult { VisitResult::default() } fn qualified_name(&mut self, _id: ItemId, _name: &QualifiedName) {} } enum VisitResult { KeepRecursing, Stop } impl std::default::Default for VisitResult { fn default() -> VisitResult { VisitResult::KeepRecursing } } pub fn traverse(visitor: &mut V, expression: &Expression) { expresion(visitor, expresion) } fn expression(visitor: &mut V, expression: &Expression) { use ExpressionKind::*; let Expression { id, kind, type_anno } = expression; let output = match kind { NatLiteral(n) => v.nat_literal(id, *n), FloatLiteral(f) => v.float_literal(id, *f), StringLiteral(s) => v.string_literal(id, s), BoolLiteral(b) => v.bool_literal(d, *b), BinExp(op, lhs, rhs) => { expression(v, lhs); expression(v, rhs); }, PrefixExp(op, arg) => { expression(v, arg); } TupleLiteral(exprs) => { for expr in exprs { expression(v, expr); } }, Value(name) => v.qualified_name(id, name), NamedStruct { name, fields } => { for (_, expr) in fields.iter() { v.expression(expr); } } Call { f, arguments } => { expression(v, f); for arg in args.iter() { match arg { InvocationArgument::Positional(expr) => { expression(v, expr); }, InvocationArgument::Keyword { expr, .. } => { expression(v, expr); }, Ignored => (), } } }, Index { indexee, indexers } => { expression(v, indexee); for i in indexers.iter() { expression(v, i); } }, IfExpression { discriminator, body } => { discriminator.as_ref().map(|d| expression(v, d)); match body { IfExpressionBody::SimpleConditional { then_case, else_case } => { walk_block(v, then_case); else_case.as_ref().map(|block| walk_block(v, block)); }, IfExpressionBody::SimplePatternMatch { pattern, then_case, else_case } => { v.pattern(pattern); walk_pattern(v, pattern); walk_block(v, then_case); else_case.as_ref().map(|block| walk_block(v, block)); }, IfExpressionBody::CondList(arms) => { for arm in arms { v.condition_arm(arm); condition_arm(v, arm); } } } }, WhileExpression { condition, body } => (), ForExpression { enumerators, body } => (), Lambda { params , type_anno, body } => { for param in params { formal_param(v, param); } v.type_annotation(type_anno); }, ListLiteral(exprs) => { for expr in exprs { expression(v, expr); } }, }; output } fn formal_param(v: &mut V, param: &FormalParam) { param.default.as_ref().map(|p| { expression(v, p); }); v.type_annotation(param.anno.as_ref()); }