Compare commits
8 Commits
antiquated
...
e0df4bda86
Author | SHA1 | Date | |
---|---|---|---|
|
e0df4bda86 | ||
|
5bbbcfa676 | ||
|
ad385d2f4f | ||
|
2d0f558415 | ||
|
a36be407ca | ||
|
a7cad3b88e | ||
|
4b8f1c35b6 | ||
|
1bc684fa15 |
@ -6,7 +6,8 @@ use crate::ast::*;
|
|||||||
|
|
||||||
pub trait ASTVisitor: Sized {
|
pub trait ASTVisitor: Sized {
|
||||||
fn ast(&mut self, _ast: &AST) {}
|
fn ast(&mut self, _ast: &AST) {}
|
||||||
fn block(&mut self, _statements: &Vec<Statement>) {}
|
fn enter_block(&mut self, _statements: &Vec<Statement>) {}
|
||||||
|
fn exit_block(&mut self, _statements: &Vec<Statement>) {}
|
||||||
fn statement(&mut self, _statement: &Statement) {}
|
fn statement(&mut self, _statement: &Statement) {}
|
||||||
fn declaration(&mut self, _declaration: &Declaration) {}
|
fn declaration(&mut self, _declaration: &Declaration) {}
|
||||||
fn signature(&mut self, _signature: &Signature) {}
|
fn signature(&mut self, _signature: &Signature) {}
|
||||||
@ -39,3 +40,53 @@ pub trait ASTVisitor: Sized {
|
|||||||
fn prefix_exp(&mut self, _op: &PrefixOp, _arg: &Expression) {}
|
fn prefix_exp(&mut self, _op: &PrefixOp, _arg: &Expression) {}
|
||||||
fn pattern(&mut self, _pat: &Pattern) {}
|
fn pattern(&mut self, _pat: &Pattern) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum VisitorOutput<T, E> {
|
||||||
|
NotImplemented,
|
||||||
|
Ok(T),
|
||||||
|
Err(E)
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO - cf. the example about "Tree Construction Visitors", every enum type needs its own Visitor
|
||||||
|
//trait
|
||||||
|
pub trait ExpressionVisitor {
|
||||||
|
type Output;
|
||||||
|
fn type_anno(&mut self, _anno: &TypeIdentifier) -> Self::Output;
|
||||||
|
fn nat_literal(&mut self, _value: &u64) -> Self::Output;
|
||||||
|
fn string_literal(&mut self, _value: &Rc<String>) -> Self::Output;
|
||||||
|
fn binexp(&mut self, _op: &BinOp, _lhs_resul: Self::Output, _rhs_result: Self::Output) -> Self::Output;
|
||||||
|
fn tuple_literal(&mut self, _items: Vec<Self::Output>) -> Self::Output;
|
||||||
|
fn visit_statement(&mut self) -> StatementVisitor<Output=Self::Output>;
|
||||||
|
fn done(&mut self, kind: Self::Output, anno: Option<Self::Output>) -> Self::Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait StatementVisitor {
|
||||||
|
type Output;
|
||||||
|
|
||||||
|
fn expression(&mut self) -> Self::Output;
|
||||||
|
fn declaration(&mut self, &Declaration) -> Self::Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dispatch_expression<T>(input: &Expression, visitor: &mut dyn ExpressionVisitor<Output=T>) -> Result<T, String> {
|
||||||
|
|
||||||
|
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(lhs, visitor)?;
|
||||||
|
let rhs = dispatch_expression(rhs, visitor)?;
|
||||||
|
visitor.binexp(op, lhs, rhs)
|
||||||
|
},
|
||||||
|
ExpressionKind::TupleLiteral(ref exprs) => {
|
||||||
|
let mut output = vec![];
|
||||||
|
for ex in exprs {
|
||||||
|
output.push(dispatch_expression(&ex, visitor)?);
|
||||||
|
}
|
||||||
|
visitor.tuple_literal(output)
|
||||||
|
},
|
||||||
|
_ => return Err(format!("Lol not done yet!")),
|
||||||
|
};
|
||||||
|
|
||||||
|
let type_output = input.type_anno.as_ref().map(|anno| visitor.type_anno(anno));
|
||||||
|
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::*;
|
||||||
use crate::ast::walker;
|
use crate::ast::walker;
|
||||||
use crate::util::quick_ast;
|
use crate::util::quick_ast;
|
||||||
|
|
||||||
@ -39,3 +40,61 @@ fn heh() {
|
|||||||
assert_eq!(tester.count, 6);
|
assert_eq!(tester.count, 6);
|
||||||
assert_eq!(tester.float_count, 1);
|
assert_eq!(tester.float_count, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct ExprPrinter {
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExpressionVisitor for ExprPrinter {
|
||||||
|
type Output = String;
|
||||||
|
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 tuple_literal(&mut self, items: Vec<String>) -> String {
|
||||||
|
let mut buf = String::new();
|
||||||
|
buf.push('(');
|
||||||
|
for item in items {
|
||||||
|
buf.push_str(item.as_str());
|
||||||
|
buf.push_str(", ");
|
||||||
|
}
|
||||||
|
buf.push(')');
|
||||||
|
buf
|
||||||
|
}
|
||||||
|
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]
|
||||||
|
fn new_visitor() {
|
||||||
|
let expr: Expression = make_expr("7+\"nueces\"*(33,32)");
|
||||||
|
|
||||||
|
let mut printer = ExprPrinter { };
|
||||||
|
let s = dispatch_expression(&expr, &mut printer).unwrap();
|
||||||
|
assert_eq!(s, r#"7 + "nueces" * (33, 32, )"#);
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
use crate::ast::visitor::ASTVisitor;
|
use crate::ast::visitor::{ASTVisitor, BlockEntry};
|
||||||
use crate::util::deref_optional_box;
|
use crate::util::deref_optional_box;
|
||||||
|
|
||||||
pub fn walk_ast<V: ASTVisitor>(v: &mut V, ast: &AST) {
|
pub fn walk_ast<V: ASTVisitor>(v: &mut V, ast: &AST) {
|
||||||
@ -10,10 +10,12 @@ pub fn walk_ast<V: ASTVisitor>(v: &mut V, ast: &AST) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn walk_block<V: ASTVisitor>(v: &mut V, block: &Vec<Statement>) {
|
fn walk_block<V: ASTVisitor>(v: &mut V, block: &Vec<Statement>) {
|
||||||
|
v.enter_block(&block);
|
||||||
for s in block {
|
for s in block {
|
||||||
v.statement(s);
|
v.statement(s);
|
||||||
statement(v, s);
|
statement(v, s);
|
||||||
}
|
}
|
||||||
|
v.exit_block(&block);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn statement<V: ASTVisitor>(v: &mut V, statement: &Statement) {
|
fn statement<V: ASTVisitor>(v: &mut V, statement: &Statement) {
|
||||||
@ -44,7 +46,6 @@ fn declaration<V: ASTVisitor>(v: &mut V, decl: &Declaration) {
|
|||||||
},
|
},
|
||||||
FuncDecl(sig, block) => {
|
FuncDecl(sig, block) => {
|
||||||
v.signature(&sig);
|
v.signature(&sig);
|
||||||
v.block(&block);
|
|
||||||
walk_block(v, block);
|
walk_block(v, block);
|
||||||
},
|
},
|
||||||
TypeDecl { name, body, mutable } => v.type_declaration(name, body, *mutable),
|
TypeDecl { name, body, mutable } => v.type_declaration(name, body, *mutable),
|
||||||
@ -123,7 +124,6 @@ fn lambda<V: ASTVisitor>(v: &mut V, params: &Vec<FormalParam>, type_anno: Option
|
|||||||
formal_param(v, param);
|
formal_param(v, param);
|
||||||
}
|
}
|
||||||
v.type_annotation(type_anno);
|
v.type_annotation(type_anno);
|
||||||
v.block(body);
|
|
||||||
walk_block(v, body);
|
walk_block(v, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,7 +234,6 @@ fn condition_arm<V: ASTVisitor>(v: &mut V, arm: &ConditionArm) {
|
|||||||
v.expression(guard);
|
v.expression(guard);
|
||||||
expression(v, guard);
|
expression(v, guard);
|
||||||
});
|
});
|
||||||
v.block(&arm.body);
|
|
||||||
walk_block(v, &arm.body);
|
walk_block(v, &arm.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user