diff --git a/README.md b/README.md index 7029bc0..31328c1 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ https://rust-lang-nursery.github.io/rustc-guide/type-inference.html ### Parsing http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/ https://soc.github.io/languages/unified-condition-syntax +http://www.lihaoyi.com/post/ZeroOverheadTreeProcessingwiththeVisitorPattern.html?a=1 [Crafting Interpreters](http://www.craftinginterpreters.com/) diff --git a/schala-lang/language/src/ast_visitor.rs b/schala-lang/language/src/ast_visitor.rs index fad2489..654efd7 100644 --- a/schala-lang/language/src/ast_visitor.rs +++ b/schala-lang/language/src/ast_visitor.rs @@ -1,59 +1,80 @@ use std::rc::Rc; +use builtin::{PrefixOp, BinOp}; use ast::*; -pub fn dispatch>(visitor: &mut V, ast: &AST) -> T { - visitor.ast(ast); +pub fn dispatch(visitor: &mut V, ast: &AST) { for statement in ast.0.iter() { - let output = match statement { - Statement::ExpressionStatement(expr) => { - let ref mut expression_visitor = visitor.expression(); - ExpressionVisitor::dispatch(expression_visitor, expr) + match statement { + Statement::ExpressionStatement(e) => { + match e { + 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) => { - let ref mut declaration_visitor = visitor.declaration(); - DeclarationVisitor::dispatch(declaration_visitor, decl) + match 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 { - type EV : ExpressionVisitor; - type DV : DeclarationVisitor; - +pub trait ASTVisitor { fn ast(&mut self, _ast: &AST) { } - fn statement(&mut self, T) { } - fn expression(&mut self) -> Self::EV; - fn declaration(&mut self) -> Self::DV; - fn done(&mut self) -> T; -} + fn statement(&mut self, _stmt: &Statement) { } + fn expression(&mut self, _expr: &Expression) { } + fn anno_expr(&mut self, &Option) { } + fn expr_kind(&mut self, _expr: &ExpressionType) { } -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; -} + 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, _bool: &bool) { } + fn binop(&mut self, _binop: &BinOp, _lhs: &Expression, _rhs: &Expression) { } + fn prefixop(&mut self, prefix: &PrefixOp, _expr: &Expression) { } + fn tuple_literal(&mut self, _v: &Vec) { } + fn value(&mut self, _v: &Rc) { } + fn named_struct(&mut self, _name: &Rc, _values: &Vec<(Rc, Expression)>) { } + fn call(&mut self, _f: &Box, _arguments: &Vec) { } + fn index(&mut self, _indexee: &Box, _indexers: &Vec) { } + fn if_expression(&mut self, _discriminator: &Discriminator, _body: &IfExpressionBody) { } + fn while_expresssion(&mut self, _condition: &Option>, body: &Block) { } + fn for_expression(&mut self, _enumerators: &Vec, _body: &Box) { } + fn lambda_expression(&mut self, _params: &Vec, type_anno: &Option, body: &Block) { } + fn list_literal(&mut self, _items: &Vec) { } -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 { 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 func_signature(&mut self, _sig: &Signature) { } @@ -63,49 +84,38 @@ pub trait DeclarationVisitor { fn binding(&mut self, _name: &Rc, _constant: &bool, _expr: &Expression) { } fn impl_block(&mut self, _type_name: &TypeIdentifier, _interface_name: &Option, _block: &Vec) { } fn interface(&mut self, name: &Rc, signatures: &Vec) { } - fn done(&mut self) -> T; } -#[derive(Default, Clone)] +#[derive(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"); +impl SchalaPrinter { + fn new() -> SchalaPrinter { + SchalaPrinter { + s: format!("Schala source code:\n"), + } } - 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(&s); } - fn expression(&mut self) -> Self::EV { - SchalaPrinter::default() + fn expression(&mut self, _: &Expression) { + self.s.push_str("some_expr"); } - fn declaration(&mut self) -> Self::DV { - SchalaPrinter::default() - } - - fn done(&mut self) -> String { - self.s.clone() + fn declaration(&mut self, _: &Declaration) { + self.s.push_str("some_decl"); } } -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 { @@ -123,9 +133,9 @@ mod visitor_tests { #[test] fn test() { let ast = parse("let a = 1 + 2; let b = 2 + 44;foo()").unwrap(); - let mut pp = SchalaPrinter::default(); - - let result = dispatch(&mut pp, &ast); + let mut pp = SchalaPrinter::new(); + dispatch(&mut pp, &ast); + let result = pp.done(); assert_eq!(result, r#"Pretty-printed AST let a = 1 + 2 let b = 2 + 44