Rejiggering how visitor works

This commit is contained in:
greg 2018-11-18 20:27:42 -08:00
parent 4ded241c82
commit 71dacc94d6
2 changed files with 83 additions and 72 deletions

View File

@ -70,6 +70,7 @@ https://rust-lang-nursery.github.io/rustc-guide/type-inference.html
### Parsing ### Parsing
http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/ http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/
https://soc.github.io/languages/unified-condition-syntax https://soc.github.io/languages/unified-condition-syntax
http://www.lihaoyi.com/post/ZeroOverheadTreeProcessingwiththeVisitorPattern.html?a=1
[Crafting Interpreters](http://www.craftinginterpreters.com/) [Crafting Interpreters](http://www.craftinginterpreters.com/)

View File

@ -1,59 +1,80 @@
use std::rc::Rc; use std::rc::Rc;
use builtin::{PrefixOp, BinOp};
use ast::*; use ast::*;
pub fn dispatch<T, V: ASTVisitor<T>>(visitor: &mut V, ast: &AST) -> T { pub fn dispatch<V: ASTVisitor>(visitor: &mut V, ast: &AST) {
visitor.ast(ast);
for statement in ast.0.iter() { for statement in ast.0.iter() {
let output = match statement { match statement {
Statement::ExpressionStatement(expr) => { Statement::ExpressionStatement(e) => {
let ref mut expression_visitor = visitor.expression(); match e {
ExpressionVisitor::dispatch(expression_visitor, expr) Expression(expr, maybe_anno) => {
match expr {
ExpressionType::NatLiteral(n) => visitor.nat_literal(n),
ExpressionType::FloatLiteral(f) => visitor.float_literal(f),
ExpressionType::StringLiteral(s) => visitor.string_literal(s),
ExpressionType::BoolLiteral(b) => visitor.bool_literal(b),
ExpressionType::BinExp(binop, lhs, rhs) => visitor.binop(binop, lhs, rhs),
ExpressionType::PrefixExp(prefix, expr) => visitor.prefixop(prefix, expr),
ExpressionType::TupleLiteral(v) => visitor.tuple_literal(v),
ExpressionType::Value(v) => visitor.value(v),
ExpressionType::NamedStruct { name, fields } => visitor.named_struct(name, fields),
ExpressionType::Call { f, arguments } => visitor.call(f, arguments),
ExpressionType::Index { indexee, indexers } => visitor.index(indexee, indexers),
ExpressionType::IfExpression { discriminator, body } => visitor.if_expression(discriminator, body),
ExpressionType::WhileExpression { condition, body } => visitor.while_expresssion(condition, body),
ExpressionType::ForExpression { enumerators, body } => visitor.for_expression(enumerators, body),
ExpressionType::Lambda { params, type_anno, body } => visitor.lambda_expression(params, type_anno, body),
ExpressionType::ListLiteral(items) => visitor.list_literal(items),
}
visitor.anno_expr(maybe_anno);
visitor.expr_kind(expr);
}
}
visitor.expression(e);
}, },
Statement::Declaration(decl) => { Statement::Declaration(decl) => {
let ref mut declaration_visitor = visitor.declaration(); match decl {
DeclarationVisitor::dispatch(declaration_visitor, decl) Declaration::FuncSig(sig) => visitor.func_signature(sig),
Declaration::FuncDecl(sig, block) => visitor.func_declaration(sig, block),
Declaration::TypeDecl { name, body, mutable } => visitor.type_declaration(name, body, mutable),
Declaration::TypeAlias(alias, name) => visitor.type_alias(alias, name),
Declaration::Binding { name, constant, expr} => visitor.binding(name, constant, expr),
Declaration::Impl { type_name, interface_name, block } => visitor.impl_block(type_name, interface_name, block),
Declaration::Interface { name, signatures } => visitor.interface(name, signatures),
}
visitor.declaration(decl);
}, },
}; };
visitor.statement(output); visitor.statement(statement);
} }
visitor.done() visitor.ast(ast)
} }
pub trait ASTVisitor<T> { pub trait ASTVisitor {
type EV : ExpressionVisitor<T>;
type DV : DeclarationVisitor<T>;
fn ast(&mut self, _ast: &AST) { } fn ast(&mut self, _ast: &AST) { }
fn statement(&mut self, T) { } fn statement(&mut self, _stmt: &Statement) { }
fn expression(&mut self) -> Self::EV; fn expression(&mut self, _expr: &Expression) { }
fn declaration(&mut self) -> Self::DV; fn anno_expr(&mut self, &Option<TypeIdentifier>) { }
fn done(&mut self) -> T; fn expr_kind(&mut self, _expr: &ExpressionType) { }
}
pub trait ExpressionVisitor<T> { fn nat_literal(&mut self, _n: &u64) { }
fn dispatch(visitor: &mut Self, expr: &Expression) -> T { fn float_literal(&mut self, _f: &f64) { }
visitor.expression(expr); fn string_literal(&mut self, _s: &Rc<String>) { }
visitor.done() fn bool_literal(&mut self, _bool: &bool) { }
} fn binop(&mut self, _binop: &BinOp, _lhs: &Expression, _rhs: &Expression) { }
fn expression(&mut self, _expression: &Expression) { } fn prefixop(&mut self, prefix: &PrefixOp, _expr: &Expression) { }
fn done(&mut self) -> T; fn tuple_literal(&mut self, _v: &Vec<Expression>) { }
} fn value(&mut self, _v: &Rc<String>) { }
fn named_struct(&mut self, _name: &Rc<String>, _values: &Vec<(Rc<String>, Expression)>) { }
fn call(&mut self, _f: &Box<Expression>, _arguments: &Vec<Expression>) { }
fn index(&mut self, _indexee: &Box<Expression>, _indexers: &Vec<Expression>) { }
fn if_expression(&mut self, _discriminator: &Discriminator, _body: &IfExpressionBody) { }
fn while_expresssion(&mut self, _condition: &Option<Box<Expression>>, body: &Block) { }
fn for_expression(&mut self, _enumerators: &Vec<Enumerator>, _body: &Box<ForBody>) { }
fn lambda_expression(&mut self, _params: &Vec<FormalParam>, type_anno: &Option<TypeIdentifier>, body: &Block) { }
fn list_literal(&mut self, _items: &Vec<Expression>) { }
pub trait DeclarationVisitor<T> {
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 { name, constant, expr} => visitor.binding(name, constant, expr),
Impl { type_name, interface_name, block } => visitor.impl_block(type_name, interface_name, block),
Interface { name, signatures } => visitor.interface(name, signatures),
};
visitor.done()
}
fn declaration(&mut self, _decl: &Declaration) { } fn declaration(&mut self, _decl: &Declaration) { }
fn func_signature(&mut self, _sig: &Signature) { } fn func_signature(&mut self, _sig: &Signature) { }
@ -63,49 +84,38 @@ pub trait DeclarationVisitor<T> {
fn binding(&mut self, _name: &Rc<String>, _constant: &bool, _expr: &Expression) { } fn binding(&mut self, _name: &Rc<String>, _constant: &bool, _expr: &Expression) { }
fn impl_block(&mut self, _type_name: &TypeIdentifier, _interface_name: &Option<InterfaceName>, _block: &Vec<Declaration>) { } fn impl_block(&mut self, _type_name: &TypeIdentifier, _interface_name: &Option<InterfaceName>, _block: &Vec<Declaration>) { }
fn interface(&mut self, name: &Rc<String>, signatures: &Vec<Signature>) { } fn interface(&mut self, name: &Rc<String>, signatures: &Vec<Signature>) { }
fn done(&mut self) -> T;
} }
#[derive(Default, Clone)] #[derive(Clone)]
struct SchalaPrinter { struct SchalaPrinter {
s: String s: String
} }
impl ASTVisitor<String> for SchalaPrinter { impl SchalaPrinter {
type EV = SchalaPrinter; fn new() -> SchalaPrinter {
type DV = SchalaPrinter; SchalaPrinter {
fn ast(&mut self, _: &AST) { s: format!("Schala source code:\n"),
self.s.push_str("Pretty-printed AST"); }
} }
fn statement(&mut self, s: String) { fn done(self) -> String {
self.s
}
}
impl ASTVisitor for SchalaPrinter {
fn statement(&mut self, _: &Statement) {
self.s.push_str("\n"); self.s.push_str("\n");
self.s.push_str(&s);
} }
fn expression(&mut self) -> Self::EV { fn expression(&mut self, _: &Expression) {
SchalaPrinter::default() self.s.push_str("some_expr");
} }
fn declaration(&mut self) -> Self::DV { fn declaration(&mut self, _: &Declaration) {
SchalaPrinter::default() self.s.push_str("some_decl");
}
fn done(&mut self) -> String {
self.s.clone()
} }
} }
impl ExpressionVisitor<String> for SchalaPrinter {
fn done(&mut self) -> String {
format!("some_expr")
}
}
impl DeclarationVisitor<String> for SchalaPrinter {
fn done(&mut self) -> String {
format!("some_decl")
}
}
#[cfg(test)] #[cfg(test)]
mod visitor_tests { mod visitor_tests {
@ -123,9 +133,9 @@ mod visitor_tests {
#[test] #[test]
fn test() { fn test() {
let ast = parse("let a = 1 + 2; let b = 2 + 44;foo()").unwrap(); let ast = parse("let a = 1 + 2; let b = 2 + 44;foo()").unwrap();
let mut pp = SchalaPrinter::default(); let mut pp = SchalaPrinter::new();
dispatch(&mut pp, &ast);
let result = dispatch(&mut pp, &ast); let result = pp.done();
assert_eq!(result, r#"Pretty-printed AST assert_eq!(result, r#"Pretty-printed AST
let a = 1 + 2 let a = 1 + 2
let b = 2 + 44 let b = 2 + 44