ExpressionVisitor correctly normalizing code
This commit is contained in:
parent
1bc684fa15
commit
4b8f1c35b6
@ -40,32 +40,27 @@ pub trait ASTVisitor: Sized {
|
|||||||
fn pattern(&mut self, _pat: &Pattern) {}
|
fn pattern(&mut self, _pat: &Pattern) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ExpressionVisitor<T> {
|
pub trait ExpressionVisitor<T> {//TODO maybe this should be an associated type?
|
||||||
fn type_anno(&mut self, _anno: &TypeIdentifier) -> T;
|
fn type_anno(&mut self, _anno: &TypeIdentifier) -> T;
|
||||||
fn nat_literal(&mut self, _value: &u64) -> T;
|
fn nat_literal(&mut self, _value: &u64) -> T;
|
||||||
fn string_literal(&mut self, _value: &Rc<String>) -> T;
|
fn string_literal(&mut self, _value: &Rc<String>) -> 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>) -> T;
|
fn done(&mut self, kind: T, anno: Option<T>) -> T;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dispatch_expression_kind_visitor<T>(input: &AST, visitor: &mut dyn ExpressionVisitor<T>) -> Result<T, String> {
|
pub fn dispatch_expression_visitor<T>(input: &Expression, visitor: &mut dyn ExpressionVisitor<T>) -> Result<T, String> {
|
||||||
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!")),
|
|
||||||
};
|
|
||||||
|
|
||||||
let output = match expr.kind {
|
let output = match input.kind {
|
||||||
ExpressionKind::NatLiteral(ref n) => visitor.nat_literal(n),
|
ExpressionKind::NatLiteral(ref n) => visitor.nat_literal(n),
|
||||||
ExpressionKind::StringLiteral(ref s) => visitor.string_literal(s),
|
ExpressionKind::StringLiteral(ref s) => visitor.string_literal(s),
|
||||||
ExpressionKind::BinExp(ref op, ref lhs, ref rhs) => {
|
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)
|
visitor.binexp(op, lhs, rhs)
|
||||||
},
|
},
|
||||||
_ => return Err(format!("Lol not done yet!")),
|
_ => 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))
|
Ok(visitor.done(output, type_output))
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#![cfg(test)]
|
#![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::ast::walker;
|
||||||
use crate::util::quick_ast;
|
use crate::util::quick_ast;
|
||||||
|
|
||||||
@ -41,13 +42,48 @@ fn heh() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct NewTester {
|
struct ExprPrinter {
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExpressionVisitor<String> 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>) -> 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>) -> 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]
|
#[test]
|
||||||
fn new_visitor() {
|
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");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user