From 4b8f1c35b6bdca77c980620217b5789b6901e224 Mon Sep 17 00:00:00 2001 From: greg Date: Mon, 11 Nov 2019 02:44:17 -0800 Subject: [PATCH] ExpressionVisitor correctly normalizing code --- schala-lang/language/src/ast/visitor.rs | 19 ++++----- schala-lang/language/src/ast/visitor_test.rs | 44 ++++++++++++++++++-- 2 files changed, 47 insertions(+), 16 deletions(-) diff --git a/schala-lang/language/src/ast/visitor.rs b/schala-lang/language/src/ast/visitor.rs index 7291313..dfd9ee2 100644 --- a/schala-lang/language/src/ast/visitor.rs +++ b/schala-lang/language/src/ast/visitor.rs @@ -40,32 +40,27 @@ pub trait ASTVisitor: Sized { fn pattern(&mut self, _pat: &Pattern) {} } -pub trait ExpressionVisitor { +pub trait ExpressionVisitor {//TODO maybe this should be an associated type? fn type_anno(&mut self, _anno: &TypeIdentifier) -> T; fn nat_literal(&mut self, _value: &u64) -> T; fn string_literal(&mut self, _value: &Rc) -> T; - fn binexp(&mut self, _op: &BinOp, _lhs: &Expression, _rhs: &Expression) -> T; + fn binexp(&mut self, _op: &BinOp, _lhs_resul: T, _rhs_result: T) -> T; fn done(&mut self, kind: T, anno: Option) -> T; } -pub fn dispatch_expression_kind_visitor(input: &AST, visitor: &mut dyn ExpressionVisitor) -> Result { - if input.statements.len() != 1 { - return Err(format!("One statement only!")); - } - let expr = match input.statements[0].kind { - StatementKind::Expression(ref expr) => expr, - _ => return Err(format!("Single statement needs to be an expr!")), - }; +pub fn dispatch_expression_visitor(input: &Expression, visitor: &mut dyn ExpressionVisitor) -> Result { - let output = match expr.kind { + let output = match input.kind { ExpressionKind::NatLiteral(ref n) => visitor.nat_literal(n), ExpressionKind::StringLiteral(ref s) => visitor.string_literal(s), ExpressionKind::BinExp(ref op, ref lhs, ref rhs) => { + let lhs = dispatch_expression_visitor(lhs, visitor)?; + let rhs = dispatch_expression_visitor(rhs, visitor)?; visitor.binexp(op, lhs, rhs) }, _ => return Err(format!("Lol not done yet!")), }; - let type_output = expr.type_anno.as_ref().map(|anno| visitor.type_anno(anno)); + let type_output = input.type_anno.as_ref().map(|anno| visitor.type_anno(anno)); Ok(visitor.done(output, type_output)) } diff --git a/schala-lang/language/src/ast/visitor_test.rs b/schala-lang/language/src/ast/visitor_test.rs index feaa2ef..d180d30 100644 --- a/schala-lang/language/src/ast/visitor_test.rs +++ b/schala-lang/language/src/ast/visitor_test.rs @@ -1,6 +1,7 @@ #![cfg(test)] -use crate::ast::visitor::ASTVisitor; +use crate::ast::*; +use crate::ast::visitor::{ASTVisitor, ExpressionVisitor, dispatch_expression_visitor}; use crate::ast::walker; use crate::util::quick_ast; @@ -41,13 +42,48 @@ fn heh() { } -struct NewTester { +struct ExprPrinter { +} + +impl ExpressionVisitor for ExprPrinter { + fn type_anno(&mut self, _anno: &TypeIdentifier) -> String { + "Any".to_string() + } + fn nat_literal(&mut self, n: &u64) -> String { + format!("{}", n) + } + fn string_literal(&mut self, s: &Rc) -> String { + format!("\"{}\"", s) + } + fn binexp(&mut self, op: &BinOp, lhs_result: String, rhs_result: String) -> String { + format!("{} {} {}", lhs_result, op.sigil().to_string(), rhs_result) + } + fn done(&mut self, kind: String, anno: Option) -> String { + match anno { + Some(anno) => format!("{}: {}", kind, anno), + None => format!("{}", kind), + } + } +} + +fn make_expr(input: &str) -> Expression { + let (ast, _) = quick_ast(input); + if ast.statements.len() != 1 { + panic!("One statement only!"); + } + let expr = match ast.statements[0].kind { + StatementKind::Expression(ref expr) => expr, + _ => panic!("Single statement needs to be an expr!"), + }; + expr.clone() } #[test] fn new_visitor() { + let expr: Expression = make_expr("7+20"); - - + let mut printer = ExprPrinter { }; + let s = dispatch_expression_visitor(&expr, &mut printer).unwrap(); + assert_eq!(s, "7 + 20"); }