diff --git a/schala-lang/language/src/ast/visitor.rs b/schala-lang/language/src/ast/visitor.rs index 05fc157..392fd4c 100644 --- a/schala-lang/language/src/ast/visitor.rs +++ b/schala-lang/language/src/ast/visitor.rs @@ -1,5 +1,6 @@ use std::rc::Rc; use crate::ast::*; +use crate::util::deref_optional_box; //TODO maybe these functions should take closures that return a KeepRecursing | StopHere type, //or a tuple of (T, ) @@ -39,3 +40,126 @@ pub trait ASTVisitor: Sized { fn prefix_exp(&mut self, _op: &PrefixOp, _arg: &Expression) {} fn pattern(&mut self, _pat: &Pattern) {} } + +pub trait ASTVisitorNew: Sized { + fn expression(&mut self, _expression: &Expression) -> VisitResult { VisitResult::default() } + fn expression_kind(&mut self, _kind: &ExpressionKind) -> VisitResult { VisitResult::default() } + + fn type_annotation(&mut self, _id: ItemId, _type_anno: Option<&TypeIdentifier>) -> VisitResult { VisitResult::default() } + + fn named_struct(&mut self, _name: &QualifiedName, _fields: &Vec<(Rc, Expression)>) -> VisitResult { VisitResult::default() } + + fn nat_literal(&mut self, _id: ItemId, _n: u64)-> VisitResult { VisitResult::default() } + fn float_literal(&mut self, _id: ItemId, _f: f64) -> VisitResult { VisitResult::default() } + fn string_literal(&mut self, _id: ItemId, _s: &Rc) -> VisitResult { VisitResult::default() } + fn bool_literal(&mut self, _id: ItemId, _b: bool) -> VisitResult { VisitResult::default() } + + fn qualified_name(&mut self, _id: ItemId, _name: &QualifiedName) {} +} + +enum VisitResult { + KeepRecursing, + Stop +} + +impl std::default::Default for VisitResult { + fn default() -> VisitResult { VisitResult::KeepRecursing } +} + +pub fn traverse(visitor: &mut V, expression: &Expression) { + expresion(visitor, expresion) +} + +fn expression(visitor: &mut V, expression: &Expression) { + use ExpressionKind::*; + + let Expression { id, kind, type_anno } = expression; + + let output = match kind { + NatLiteral(n) => v.nat_literal(id, *n), + FloatLiteral(f) => v.float_literal(id, *f), + StringLiteral(s) => v.string_literal(id, s), + BoolLiteral(b) => v.bool_literal(d, *b), + BinExp(op, lhs, rhs) => { + expression(v, lhs); + expression(v, rhs); + }, + PrefixExp(op, arg) => { + expression(v, arg); + } + TupleLiteral(exprs) => { + for expr in exprs { + expression(v, expr); + } + }, + Value(name) => v.qualified_name(id, name), + NamedStruct { name, fields } => { + for (_, expr) in fields.iter() { + v.expression(expr); + } + } + Call { f, arguments } => { + expression(v, f); + for arg in args.iter() { + match arg { + InvocationArgument::Positional(expr) => { + expression(v, expr); + }, + InvocationArgument::Keyword { expr, .. } => { + expression(v, expr); + }, + Ignored => (), + } + } + }, + Index { indexee, indexers } => { + expression(v, indexee); + for i in indexers.iter() { + expression(v, i); + } + }, + IfExpression { discriminator, body } => { + discriminator.as_ref().map(|d| expression(v, d)); + match body { + IfExpressionBody::SimpleConditional { then_case, else_case } => { + walk_block(v, then_case); + else_case.as_ref().map(|block| walk_block(v, block)); + }, + IfExpressionBody::SimplePatternMatch { pattern, then_case, else_case } => { + v.pattern(pattern); + walk_pattern(v, pattern); + walk_block(v, then_case); + else_case.as_ref().map(|block| walk_block(v, block)); + }, + IfExpressionBody::CondList(arms) => { + for arm in arms { + v.condition_arm(arm); + condition_arm(v, arm); + } + } + } + }, + WhileExpression { condition, body } => (), + ForExpression { enumerators, body } => (), + Lambda { params , type_anno, body } => { + for param in params { + formal_param(v, param); + } + v.type_annotation(type_anno); + }, + ListLiteral(exprs) => { + for expr in exprs { + expression(v, expr); + } + }, + }; + output +} + +fn formal_param(v: &mut V, param: &FormalParam) { + param.default.as_ref().map(|p| { + expression(v, p); + }); + v.type_annotation(param.anno.as_ref()); +} +