Some more visitor infrastructure

This commit is contained in:
greg 2019-07-13 08:16:24 -07:00
parent 975951e582
commit 9752e73d2e

View File

@ -1,5 +1,6 @@
use std::error::Error; use std::error::Error;
use crate::ast::*; use crate::ast::*;
use crate::builtin::{PrefixOp, BinOp};
pub type VResult = Result<(), Box<dyn Error>>; pub type VResult = Result<(), Box<dyn Error>>;
@ -7,6 +8,9 @@ pub trait ASTVisitor {
fn post_ast(&mut self, _: &mut AST) -> VResult { fn post_ast(&mut self, _: &mut AST) -> VResult {
Ok(()) Ok(())
} }
fn post_statement(&mut self, _: &mut Statement) -> VResult {
Ok(())
}
fn post_expression(&mut self, _: &mut Expression) -> VResult { fn post_expression(&mut self, _: &mut Expression) -> VResult {
Ok(()) Ok(())
} }
@ -16,6 +20,12 @@ pub trait Visitable {
fn visit(&mut self, v: &mut dyn ASTVisitor) -> VResult; fn visit(&mut self, v: &mut dyn ASTVisitor) -> VResult;
} }
impl <T: Visitable> Visitable for &mut T {
fn visit(&mut self, v: &mut dyn ASTVisitor) -> VResult {
self.visit(v)
}
}
impl<T: Visitable> Visitable for Option<T> { impl<T: Visitable> Visitable for Option<T> {
fn visit(&mut self, v: &mut dyn ASTVisitor) -> VResult { fn visit(&mut self, v: &mut dyn ASTVisitor) -> VResult {
match self { match self {
@ -25,10 +35,31 @@ impl<T: Visitable> Visitable for Option<T> {
} }
} }
impl<T: Visitable> Visitable for Vec<T> {
fn visit(&mut self, v: &mut dyn ASTVisitor) -> VResult {
for item in self {
item.visit(v)?;
}
Ok(())
}
}
impl <T: Visitable> Visitable for Box<T> {
fn visit(&mut self, v: &mut dyn ASTVisitor) -> VResult {
self.visit(v)
}
}
impl <T: Visitable> Visitable for Meta<T> {
fn visit(&mut self, v: &mut dyn ASTVisitor) -> VResult {
self.node_mut().visit(v)
}
}
impl Visitable for AST { impl Visitable for AST {
fn visit(&mut self, v: &mut dyn ASTVisitor) -> VResult { fn visit(&mut self, v: &mut dyn ASTVisitor) -> VResult {
for s in self.0.iter_mut() { for s in self.0.iter_mut() {
s.node_mut().visit(v)? s.visit(v)?
} }
v.post_ast(self) v.post_ast(self)
} }
@ -37,20 +68,12 @@ impl Visitable for AST {
impl Visitable for Statement { impl Visitable for Statement {
fn visit(&mut self, v: &mut dyn ASTVisitor) -> VResult { fn visit(&mut self, v: &mut dyn ASTVisitor) -> VResult {
match self { match self {
Statement::ExpressionStatement(meta) => meta.node_mut().visit(v), Statement::ExpressionStatement(meta) => meta.visit(v),
Statement::Declaration(decl) => decl.visit(v), Statement::Declaration(decl) => decl.visit(v),
} }
} }
} }
impl Visitable for Expression {
fn visit(&mut self, v: &mut dyn ASTVisitor) -> VResult {
let _ = self.kind.visit(v)?;
let _ = self.type_anno.visit(v)?;
v.post_expression(self)
}
}
impl Visitable for Declaration { impl Visitable for Declaration {
fn visit(&mut self, _v: &mut dyn ASTVisitor) -> VResult { fn visit(&mut self, _v: &mut dyn ASTVisitor) -> VResult {
use Declaration::*; use Declaration::*;
@ -66,8 +89,93 @@ impl Visitable for Declaration {
} }
} }
impl Visitable for Expression {
fn visit(&mut self, v: &mut dyn ASTVisitor) -> VResult {
let _ = self.kind.visit(v)?;
let _ = self.type_anno.visit(v)?;
v.post_expression(self)
}
}
impl Visitable for ExpressionKind { impl Visitable for ExpressionKind {
fn visit(&mut self, _v: &mut dyn ASTVisitor) -> VResult { fn visit(&mut self, v: &mut dyn ASTVisitor) -> VResult {
use ExpressionKind::*;
Ok(match self {
NatLiteral(_) | FloatLiteral(_) | StringLiteral(_)
| BoolLiteral(_) => (),
BinExp(op, lhs, rhs) => {
let _ = op.visit(v)?;
let _ = lhs.visit(v)?;
let _ = rhs.visit(v)?;
()
},
PrefixExp(op, expr) => {
let _ = op.visit(v)?;
let _ = expr.visit(v)?;
()
},
TupleLiteral(exprs) => exprs.visit(v)?,
Value(_) => (),
NamedStruct { fields, .. } => {
let mut x: Vec<_> = fields.iter_mut().map(|(_, expr)| expr).collect();
x.visit(v)?
},
Call { f, arguments } => {
let _ = f.visit(v)?;
arguments.visit(v)?
},
Index { indexee, indexers } => {
let _ = indexee.visit(v)?;
indexers.visit(v)?
},
IfExpression { discriminator, body } => {
let _ = discriminator.visit(v)?;
body.visit(v)?
},
WhileExpression { condition, body } => {
let _ = condition.visit(v)?;
body.visit(v)?
},
ForExpression { enumerators, body } => {
let _ = enumerators.visit(v)?;
body.visit(v)?
},
ListLiteral(expressions) => expressions.visit(v)?,
Lambda { params, type_anno, body } => {
let _ = params.visit(v)?;
let _ = type_anno.visit(v)?;
body.visit(v)?
},
})
}
}
impl Visitable for IfExpressionBody {
fn visit(&mut self, v: &mut dyn ASTVisitor) -> VResult {
Ok(())
}
}
impl Visitable for Discriminator {
fn visit(&mut self, v: &mut dyn ASTVisitor) -> VResult {
Ok(())
}
}
impl Visitable for InvocationArgument {
fn visit(&mut self, v: &mut dyn ASTVisitor) -> VResult {
Ok(())
}
}
impl Visitable for BinOp {
fn visit(&mut self, v: &mut dyn ASTVisitor) -> VResult {
Ok(())
}
}
impl Visitable for PrefixOp {
fn visit(&mut self, v: &mut dyn ASTVisitor) -> VResult {
Ok(()) Ok(())
} }
} }
@ -77,3 +185,21 @@ impl Visitable for TypeIdentifier {
Ok(()) Ok(())
} }
} }
impl Visitable for Enumerator {
fn visit(&mut self, _v: &mut dyn ASTVisitor) -> VResult {
Ok(())
}
}
impl Visitable for ForBody {
fn visit(&mut self, _v: &mut dyn ASTVisitor) -> VResult {
Ok(())
}
}
impl Visitable for FormalParam {
fn visit(&mut self, _v: &mut dyn ASTVisitor) -> VResult {
Ok(())
}
}