use std::rc::Rc; use ast::*; pub fn dispatch>(visitor: &mut V, ast: &AST) -> T { visitor.ast(ast); for statement in ast.0.iter() { visitor.statement(statement); match statement { Statement::ExpressionStatement(expr) => { let ref mut expression_visitor = visitor.expression(); ExpressionVisitor::dispatch(expression_visitor, expr); }, Statement::Declaration(decl) => { let ref mut declaration_visitor = visitor.declaration(); DeclarationVisitor::dispatch(declaration_visitor, decl); }, } } visitor.done() } pub trait ASTVisitor { type EV : ExpressionVisitor; type DV : DeclarationVisitor; fn ast(&mut self, _ast: &AST) { } fn statement(&mut self, _statement: &Statement) { } fn expression(&mut self) -> Self::EV; fn declaration(&mut self) -> Self::DV; fn done(&mut self) -> T; } pub trait ExpressionVisitor { fn dispatch(visitor: &mut Self, expr: &Expression) -> T { visitor.expression(expr); visitor.done() } fn expression(&mut self, _expression: &Expression) { } fn done(&mut self) -> T; } pub trait DeclarationVisitor { fn dispatch(visitor: &mut Self, decl: &Declaration) -> T { use self::Declaration::*; match decl { FuncSig(sig) => visitor.func_signature(sig), FuncDecl(sig, block) => visitor.func_declaration(sig, block), TypeDecl { name, body, mutable } => visitor.type_declaration(name, body, mutable), TypeAlias(alias, name) => visitor.type_alias(alias, name), Binding { .. } => unimplemented!(), Impl { .. } => unimplemented!(), Interface { .. } => unimplemented!(), }; visitor.done() } fn declaration(&mut self, _decl: &Declaration) { } fn func_signature(&mut self, _sig: &Signature) { } fn func_declaration(&mut self, _sig: &Signature, _block: &Vec) { } fn type_declaration(&mut self, _name: &TypeSingletonName, _body: &TypeBody, _mutable: &bool) { } fn type_alias(&mut self, _alias: &Rc, _name: &Rc) { } fn done(&mut self) -> T; } /*----*/ struct NullVisitor { } impl ASTVisitor<()> for NullVisitor { type EV = NullVisitor; type DV = NullVisitor; fn done(&mut self) -> () { () } fn expression(&mut self) -> Self::EV { NullVisitor { } } fn declaration(&mut self) -> Self::DV { NullVisitor { } } } impl ExpressionVisitor<()> for NullVisitor { fn done(&mut self) -> () { () } } impl DeclarationVisitor<()> for NullVisitor { fn done(&mut self) -> () { () } } #[derive(Default, Clone)] struct SchalaPrinter { s: String } impl ASTVisitor for SchalaPrinter { type EV = SchalaPrinter; type DV = SchalaPrinter; fn ast(&mut self, _: &AST) { self.s.push_str("Pretty-printed AST"); } fn expression(&mut self) -> Self::EV { SchalaPrinter::default() } fn declaration(&mut self) -> Self::DV { SchalaPrinter::default() } fn done(&mut self) -> String { self.s.clone() } } impl ExpressionVisitor for SchalaPrinter { fn done(&mut self) -> String { format!("some_expr") } } impl DeclarationVisitor for SchalaPrinter { fn done(&mut self) -> String { format!("some_decl") } } #[cfg(test)] mod visitor_tests { use ::tokenizing::{Token, tokenize}; use ::parsing::ParseResult; use ::ast::AST; fn parse(input: &str) -> ParseResult { let tokens = tokenize(input); let mut parser = ::parsing::Parser::new(tokens); parser.parse() } #[test] fn test() { let q = parse("foo"); } }