#![allow(dead_code)] use std::rc::Rc; use crate::ast::*; use crate::ast::visitor::ASTVisitor; use crate::util::deref_optional_box; pub fn walk_ast(v: &mut V, ast: &AST) { v.ast(ast); walk_block(v, &ast.statements); } fn walk_block(v: &mut V, block: &Vec) { for s in block { v.statement(s); statement(v, s); } } fn statement(v: &mut V, statement: &Statement) { use StatementKind::*; match statement.kind { Expression(ref expr) => { v.expression(expr); expression(v, expr); }, Declaration(ref decl) => { v.declaration(decl); declaration(v, decl); }, Import(ref import_spec) => v.import(import_spec), Module(ref module_spec) => { v.module(module_spec); walk_block(v, &module_spec.contents); } } } fn declaration(v: &mut V, decl: &Declaration) { use Declaration::*; match decl { FuncSig(sig) => { v.signature(&sig); signature(v, &sig); }, FuncDecl(sig, block) => { v.signature(&sig); v.block(&block); walk_block(v, block); }, TypeDecl { name, body, mutable } => v.type_declaration(name, body, *mutable), TypeAlias { alias, original} => v.type_alias(alias, original), Binding { name, constant, type_anno, expr } => { v.binding(name, *constant, type_anno.as_ref(), expr); v.type_annotation(type_anno.as_ref()); v.expression(&expr); expression(v, &expr); }, Impl { type_name, interface_name, block } => { v.implemention(type_name, interface_name.as_ref(), block); } Interface { name, signatures } => v.interface(name, signatures), } } fn signature(v: &mut V, signature: &Signature) { for p in signature.params.iter() { v.formal_param(p); } v.type_annotation(signature.type_anno.as_ref()); for p in signature.params.iter() { formal_param(v, p); } } fn expression(v: &mut V, expression: &Expression) { v.expression_kind(&expression.kind); v.type_annotation(expression.type_anno.as_ref()); expression_kind(v, &expression.kind); } fn call(v: &mut V, f: &Expression, args: &Vec) { v.expression(f); expression(v, f); for arg in args.iter() { v.invocation_argument(arg); invocation_argument(v, arg); } } fn invocation_argument(v: &mut V, arg: &InvocationArgument) { use InvocationArgument::*; match arg { Positional(expr) => { v.expression(expr); expression(v, expr); }, Keyword { expr, .. } => { v.expression(expr); expression(v, expr); }, Ignored => (), } } fn index(v: &mut V, indexee: &Expression, indexers: &Vec) { v.expression(indexee); for i in indexers.iter() { v.expression(i); } } fn named_struct(v: &mut V, n: &QualifiedName, fields: &Vec<(Rc, Expression)>) { v.qualified_name(n); for (_, expr) in fields.iter() { v.expression(expr); } } fn lambda(v: &mut V, params: &Vec, type_anno: Option<&TypeIdentifier>, body: &Block) { for param in params { v.formal_param(param); formal_param(v, param); } v.type_annotation(type_anno); v.block(body); walk_block(v, body); } fn formal_param(v: &mut V, param: &FormalParam) { param.default.as_ref().map(|p| { v.expression(p); expression(v, p); }); v.type_annotation(param.anno.as_ref()); } fn expression_kind(v: &mut V, expression_kind: &ExpressionKind) { use ExpressionKind::*; match expression_kind { NatLiteral(n) => v.nat_literal(*n), FloatLiteral(f) => v.float_literal(*f), StringLiteral(s) => v.string_literal(s), BoolLiteral(b) => v.bool_literal(*b), BinExp(op, lhs, rhs) => { v.binexp(op, lhs, rhs); expression(v, lhs); expression(v, rhs); }, PrefixExp(op, arg) => { v.prefix_exp(op, arg); expression(v, arg); } TupleLiteral(exprs) => { for expr in exprs { v.expression(expr); expression(v, expr); } }, Value(name) => v.qualified_name(name), NamedStruct { name, fields } => { v.named_struct(name, fields); named_struct(v, name, fields); } Call { f, arguments } => { v.call(f, arguments); call(v, f, arguments); }, Index { indexee, indexers } => { v.index(indexee, indexers); index(v, indexee, indexers); }, IfExpression { discriminator, body } => { v.if_expression(deref_optional_box(discriminator), body); discriminator.as_ref().map(|d| expression(v, d)); if_expression_body(v, body); }, WhileExpression { condition, body } => v.while_expression(deref_optional_box(condition), body), ForExpression { enumerators, body } => v.for_expression(enumerators, body), Lambda { params , type_anno, body } => { v.lambda(params, type_anno.as_ref(), body); lambda(v, params, type_anno.as_ref(), body); }, ListLiteral(exprs) => { for expr in exprs { v.expression(expr); expression(v, expr); } }, } } fn if_expression_body(v: &mut V, body: &IfExpressionBody) { use IfExpressionBody::*; match body { SimpleConditional { then_case, else_case } => { walk_block(v, then_case); else_case.as_ref().map(|block| walk_block(v, block)); }, 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)); }, CondList(arms) => { for arm in arms { v.condition_arm(arm); condition_arm(v, arm); } } } } fn condition_arm(v: &mut V, arm: &ConditionArm) { use Condition::*; v.condition_arm(arm); match arm.condition { Pattern(ref pat) => { v.pattern(pat); walk_pattern(v, pat); }, TruncatedOp(ref _binop, ref expr) => { v.expression(expr); expression(v, expr); }, Expression(ref expr) => { v.expression(expr); expression(v, expr); }, _ => () } arm.guard.as_ref().map(|guard| { v.expression(guard); expression(v, guard); }); v.block(&arm.body); walk_block(v, &arm.body); } fn walk_pattern(v: &mut V, pat: &Pattern) { use Pattern::*; match pat { TuplePattern(patterns) => { for pat in patterns { v.pattern(pat); walk_pattern(v, pat); } }, TupleStruct(qualified_name, patterns) => { v.qualified_name(qualified_name); for pat in patterns { v.pattern(pat); walk_pattern(v, pat); } }, Record(qualified_name, name_and_patterns) => { v.qualified_name(qualified_name); for (_, pat) in name_and_patterns { v.pattern(pat); walk_pattern(v, pat); } }, VarOrName(qualified_name) => { v.qualified_name(qualified_name); }, _ => () } }