Rewrite Visitor
And implement the scope resolver in terms of it
This commit is contained in:
parent
92a695e523
commit
e947569100
@ -1,16 +1,14 @@
|
|||||||
#![allow(clippy::upper_case_acronyms)]
|
#![allow(clippy::upper_case_acronyms)]
|
||||||
#![allow(clippy::enum_variant_names)]
|
#![allow(clippy::enum_variant_names)]
|
||||||
|
|
||||||
|
mod visitor;
|
||||||
|
mod operators;
|
||||||
|
|
||||||
|
pub use operators::{PrefixOp, BinOp};
|
||||||
|
pub use visitor::{walk_ast, ASTVisitor};
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use crate::derivative::Derivative;
|
use crate::derivative::Derivative;
|
||||||
|
|
||||||
mod walker;
|
|
||||||
mod visitor;
|
|
||||||
mod visitor_test;
|
|
||||||
mod operators;
|
|
||||||
pub use operators::{PrefixOp, BinOp};
|
|
||||||
pub use visitor::ASTVisitor;
|
|
||||||
pub use walker::walk_ast;
|
|
||||||
use crate::tokenizing::Location;
|
use crate::tokenizing::Location;
|
||||||
|
|
||||||
/// An abstract identifier for an AST node. Note that
|
/// An abstract identifier for an AST node. Note that
|
||||||
|
@ -1,43 +1,212 @@
|
|||||||
use std::rc::Rc;
|
|
||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
|
|
||||||
//TODO maybe these functions should take closures that return a KeepRecursing | StopHere type,
|
|
||||||
//or a tuple of (T, <that type>)
|
|
||||||
|
|
||||||
pub trait ASTVisitor: Sized {
|
pub trait ASTVisitor: Sized {
|
||||||
fn ast(&mut self, _ast: &AST) {}
|
fn expression(&mut self, _expression: &Expression) {}
|
||||||
fn block(&mut self, _statements: &[ Statement ]) {}
|
fn expression_post(&mut self, _expression: &Expression) {}
|
||||||
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 declaration_post(&mut self, _declaration: &Declaration) {}
|
||||||
fn type_declaration(&mut self, _name: &TypeSingletonName, _body: &TypeBody, _mutable: bool) {}
|
|
||||||
fn type_alias(&mut self, _alias: &Rc<String>, _original: &Rc<String>) {}
|
fn import(&mut self, _import: &ImportSpecifier) {}
|
||||||
fn binding(&mut self, _name: &Rc<String>, _constant: bool, _type_anno: Option<&TypeIdentifier>, _expr: &Expression) {}
|
fn module(&mut self, _module: &ModuleSpecifier) {}
|
||||||
fn implemention(&mut self, _type_name: &TypeIdentifier, _interface_name: Option<&TypeSingletonName>, _block: &[ Declaration ]) {}
|
fn module_post(&mut self, _module: &ModuleSpecifier) {}
|
||||||
fn interface(&mut self, _name: &Rc<String>, _signatures: &[ Signature ]) {}
|
|
||||||
fn expression(&mut self, _expression: &Expression) {}
|
fn pattern(&mut self, _pat: &Pattern) {}
|
||||||
fn expression_kind(&mut self, _kind: &ExpressionKind) {}
|
fn pattern_post(&mut self, _pat: &Pattern) {}
|
||||||
fn type_annotation(&mut self, _type_anno: Option<&TypeIdentifier>) {}
|
}
|
||||||
fn named_struct(&mut self, _name: &QualifiedName, _fields: &[ (Rc<String>, Expression) ]) {}
|
|
||||||
fn call(&mut self, _f: &Expression, _arguments: &[ InvocationArgument ]) {}
|
pub fn walk_ast<V: ASTVisitor>(v: &mut V, ast: &AST) {
|
||||||
fn index(&mut self, _indexee: &Expression, _indexers: &[ Expression ]) {}
|
walk_block(v, &ast.statements);
|
||||||
fn if_expression(&mut self, _discrim: Option<&Expression>, _body: &IfExpressionBody) {}
|
}
|
||||||
fn condition_arm(&mut self, _arm: &ConditionArm) {}
|
|
||||||
#[allow(clippy::ptr_arg)]
|
fn walk_block<V: ASTVisitor>(v: &mut V, block: &Block) {
|
||||||
fn while_expression(&mut self, _condition: Option<&Expression>, _body: &Block) {}
|
use StatementKind::*;
|
||||||
fn for_expression(&mut self, _enumerators: &[ Enumerator ], _body: &ForBody) {}
|
for statement in block.iter() {
|
||||||
#[allow(clippy::ptr_arg)]
|
match statement.kind {
|
||||||
fn lambda(&mut self, _params: &[ FormalParam ], _type_anno: Option<&TypeIdentifier>, _body: &Block) {}
|
StatementKind::Expression(ref expr) => {
|
||||||
fn invocation_argument(&mut self, _arg: &InvocationArgument) {}
|
walk_expression(v, expr);
|
||||||
fn formal_param(&mut self, _param: &FormalParam) {}
|
}
|
||||||
fn import(&mut self, _import: &ImportSpecifier) {}
|
Declaration(ref decl) => {
|
||||||
fn module(&mut self, _module: &ModuleSpecifier) {}
|
walk_declaration(v, decl);
|
||||||
fn qualified_name(&mut self, _name: &QualifiedName) {}
|
}
|
||||||
fn nat_literal(&mut self, _n: u64) {}
|
Import(ref import_spec) => v.import(import_spec),
|
||||||
fn float_literal(&mut self, _f: f64) {}
|
Module(ref module_spec) => {
|
||||||
fn string_literal(&mut self, _s: &Rc<String>) {}
|
v.module(module_spec);
|
||||||
fn bool_literal(&mut self, _b: bool) {}
|
walk_block(v, &module_spec.contents);
|
||||||
fn binexp(&mut self, _op: &BinOp, _lhs: &Expression, _rhs: &Expression) {}
|
v.module_post(module_spec);
|
||||||
fn prefix_exp(&mut self, _op: &PrefixOp, _arg: &Expression) {}
|
}
|
||||||
fn pattern(&mut self, _pat: &Pattern) {}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn walk_declaration<V: ASTVisitor>(v: &mut V, decl: &Declaration) {
|
||||||
|
use Declaration::*;
|
||||||
|
|
||||||
|
v.declaration(decl);
|
||||||
|
|
||||||
|
match decl {
|
||||||
|
FuncDecl(_sig, block) => {
|
||||||
|
walk_block(v, block);
|
||||||
|
}
|
||||||
|
Binding {
|
||||||
|
name: _,
|
||||||
|
constant: _,
|
||||||
|
type_anno: _,
|
||||||
|
expr,
|
||||||
|
} => {
|
||||||
|
walk_expression(v, expr);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
};
|
||||||
|
v.declaration_post(decl);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn walk_expression<V: ASTVisitor>(v: &mut V, expr: &Expression) {
|
||||||
|
use ExpressionKind::*;
|
||||||
|
|
||||||
|
v.expression(expr);
|
||||||
|
|
||||||
|
match &expr.kind {
|
||||||
|
NatLiteral(_) | FloatLiteral(_) | StringLiteral(_) | BoolLiteral(_) | Value(_) => (),
|
||||||
|
BinExp(_, lhs, rhs) => {
|
||||||
|
walk_expression(v, &lhs);
|
||||||
|
walk_expression(v, &rhs);
|
||||||
|
}
|
||||||
|
PrefixExp(_, arg) => {
|
||||||
|
walk_expression(v, &arg);
|
||||||
|
}
|
||||||
|
TupleLiteral(exprs) => {
|
||||||
|
for expr in exprs {
|
||||||
|
walk_expression(v, &expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NamedStruct { name: _, fields } => {
|
||||||
|
for (_, expr) in fields.iter() {
|
||||||
|
walk_expression(v, expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Call { f, arguments } => {
|
||||||
|
walk_expression(v, &f);
|
||||||
|
for arg in arguments.iter() {
|
||||||
|
match arg {
|
||||||
|
InvocationArgument::Positional(expr) => walk_expression(v, expr),
|
||||||
|
InvocationArgument::Keyword { expr, .. } => walk_expression(v, expr), //TODO maybe I can combine this pattern
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Index { indexee, indexers } => {
|
||||||
|
walk_expression(v, &indexee);
|
||||||
|
for indexer in indexers.iter() {
|
||||||
|
walk_expression(v, indexer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IfExpression {
|
||||||
|
discriminator,
|
||||||
|
body,
|
||||||
|
} => {
|
||||||
|
if let Some(d) = discriminator.as_ref() {
|
||||||
|
walk_expression(v, &d);
|
||||||
|
}
|
||||||
|
walk_if_expr_body(v, &body.as_ref());
|
||||||
|
}
|
||||||
|
WhileExpression { condition, body } => {
|
||||||
|
if let Some(d) = condition.as_ref() {
|
||||||
|
walk_expression(v, d);
|
||||||
|
}
|
||||||
|
walk_block(v, &body);
|
||||||
|
}
|
||||||
|
ForExpression { enumerators, body } => {
|
||||||
|
for enumerator in enumerators {
|
||||||
|
walk_expression(v, &enumerator.generator);
|
||||||
|
}
|
||||||
|
match body.as_ref() {
|
||||||
|
ForBody::MonadicReturn(expr) => walk_expression(v, expr),
|
||||||
|
ForBody::StatementBlock(block) => walk_block(v, block),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Lambda {
|
||||||
|
params: _,
|
||||||
|
type_anno: _,
|
||||||
|
body,
|
||||||
|
} => {
|
||||||
|
walk_block(v, &body);
|
||||||
|
}
|
||||||
|
ListLiteral(exprs) => {
|
||||||
|
for expr in exprs {
|
||||||
|
walk_expression(v, &expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
v.expression_post(expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn walk_if_expr_body<V: ASTVisitor>(v: &mut V, body: &IfExpressionBody) {
|
||||||
|
use IfExpressionBody::*;
|
||||||
|
|
||||||
|
match body {
|
||||||
|
SimpleConditional {
|
||||||
|
then_case,
|
||||||
|
else_case,
|
||||||
|
} => {
|
||||||
|
walk_block(v, then_case);
|
||||||
|
if let Some(block) = else_case.as_ref() {
|
||||||
|
walk_block(v, block)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SimplePatternMatch {
|
||||||
|
pattern,
|
||||||
|
then_case,
|
||||||
|
else_case,
|
||||||
|
} => {
|
||||||
|
walk_pattern(v, pattern);
|
||||||
|
walk_block(v, &then_case);
|
||||||
|
if let Some(ref block) = else_case.as_ref() {
|
||||||
|
walk_block(v, &block)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CondList(arms) => {
|
||||||
|
for arm in arms {
|
||||||
|
match arm.condition {
|
||||||
|
Condition::Pattern(ref pat) => {
|
||||||
|
walk_pattern(v, pat);
|
||||||
|
}
|
||||||
|
Condition::TruncatedOp(ref _binop, ref expr) => {
|
||||||
|
walk_expression(v, expr);
|
||||||
|
}
|
||||||
|
Condition::Expression(ref expr) => {
|
||||||
|
walk_expression(v, expr);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn walk_pattern<V: ASTVisitor>(v: &mut V, pat: &Pattern) {
|
||||||
|
use Pattern::*;
|
||||||
|
|
||||||
|
v.pattern(pat);
|
||||||
|
|
||||||
|
match pat {
|
||||||
|
TuplePattern(patterns) => {
|
||||||
|
for pat in patterns {
|
||||||
|
walk_pattern(v, pat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TupleStruct(_, patterns) => {
|
||||||
|
for pat in patterns {
|
||||||
|
walk_pattern(v, pat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Record(_, name_and_patterns) => {
|
||||||
|
for (_, pat) in name_and_patterns {
|
||||||
|
walk_pattern(v, pat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
};
|
||||||
|
|
||||||
|
v.pattern_post(pat);
|
||||||
}
|
}
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
#![cfg(test)]
|
|
||||||
|
|
||||||
use crate::ast::visitor::ASTVisitor;
|
|
||||||
use crate::ast::walker;
|
|
||||||
use crate::util::quick_ast;
|
|
||||||
|
|
||||||
struct Tester {
|
|
||||||
count: u64,
|
|
||||||
float_count: u64
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ASTVisitor for Tester {
|
|
||||||
fn nat_literal(&mut self, _n: u64) {
|
|
||||||
self.count += 1;
|
|
||||||
}
|
|
||||||
fn float_literal(&mut self, _f: f64) {
|
|
||||||
self.float_count += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn foo() {
|
|
||||||
let mut tester = Tester { count: 0, float_count: 0 };
|
|
||||||
let ast = quick_ast(r#"
|
|
||||||
import gragh
|
|
||||||
|
|
||||||
let a = 20 + 84
|
|
||||||
let b = 28 + 1 + 2 + 2.0
|
|
||||||
fn heh() {
|
|
||||||
let m = 9
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
"#);
|
|
||||||
|
|
||||||
walker::walk_ast(&mut tester, &ast);
|
|
||||||
|
|
||||||
assert_eq!(tester.count, 6);
|
|
||||||
assert_eq!(tester.float_count, 1);
|
|
||||||
}
|
|
@ -1,273 +0,0 @@
|
|||||||
#![allow(dead_code)]
|
|
||||||
use std::rc::Rc;
|
|
||||||
use crate::ast::*;
|
|
||||||
use crate::ast::visitor::ASTVisitor;
|
|
||||||
use crate::util::deref_optional_box;
|
|
||||||
|
|
||||||
pub fn walk_ast<V: ASTVisitor>(v: &mut V, ast: &AST) {
|
|
||||||
v.ast(ast);
|
|
||||||
walk_block(v, &ast.statements);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::ptr_arg)]
|
|
||||||
fn walk_block<V: ASTVisitor>(v: &mut V, block: &Vec<Statement>) {
|
|
||||||
for s in block {
|
|
||||||
v.statement(s);
|
|
||||||
statement(v, s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn statement<V: ASTVisitor>(v: &mut V, statement: &Statement) {
|
|
||||||
use StatementKind::*;
|
|
||||||
match statement.kind {
|
|
||||||
Expression(ref expr) => {
|
|
||||||
v.expression(expr);
|
|
||||||
expression(v, expr);
|
|
||||||
},
|
|
||||||
Declaration(ref decl) => {
|
|
||||||
v.declaration(decl);
|
|
||||||
declaration(v, decl);
|
|
||||||
},
|
|
||||||
Import(ref import_spec) => v.import(import_spec),
|
|
||||||
Module(ref module_spec) => {
|
|
||||||
v.module(module_spec);
|
|
||||||
walk_block(v, &module_spec.contents);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn declaration<V: ASTVisitor>(v: &mut V, decl: &Declaration) {
|
|
||||||
use Declaration::*;
|
|
||||||
match decl {
|
|
||||||
FuncSig(sig) => {
|
|
||||||
v.signature(sig);
|
|
||||||
signature(v, sig);
|
|
||||||
},
|
|
||||||
FuncDecl(sig, block) => {
|
|
||||||
v.signature(sig);
|
|
||||||
v.block(block);
|
|
||||||
walk_block(v, block);
|
|
||||||
},
|
|
||||||
TypeDecl { name, body, mutable } => v.type_declaration(name, body, *mutable),
|
|
||||||
TypeAlias { alias, original} => v.type_alias(alias, original),
|
|
||||||
Binding { name, constant, type_anno, expr } => {
|
|
||||||
v.binding(name, *constant, type_anno.as_ref(), expr);
|
|
||||||
v.type_annotation(type_anno.as_ref());
|
|
||||||
v.expression(expr);
|
|
||||||
expression(v, expr);
|
|
||||||
},
|
|
||||||
Impl { type_name, interface_name, block } => {
|
|
||||||
v.implemention(type_name, interface_name.as_ref(), block);
|
|
||||||
}
|
|
||||||
Interface { name, signatures } => v.interface(name, signatures),
|
|
||||||
//TODO fill this in
|
|
||||||
Annotation { .. } => ()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn signature<V: ASTVisitor>(v: &mut V, signature: &Signature) {
|
|
||||||
for p in signature.params.iter() {
|
|
||||||
v.formal_param(p);
|
|
||||||
}
|
|
||||||
v.type_annotation(signature.type_anno.as_ref());
|
|
||||||
for p in signature.params.iter() {
|
|
||||||
formal_param(v, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn expression<V: ASTVisitor>(v: &mut V, expression: &Expression) {
|
|
||||||
v.expression_kind(&expression.kind);
|
|
||||||
v.type_annotation(expression.type_anno.as_ref());
|
|
||||||
expression_kind(v, &expression.kind);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn call<V: ASTVisitor>(v: &mut V, f: &Expression, args: &[ InvocationArgument ]) {
|
|
||||||
v.expression(f);
|
|
||||||
expression(v, f);
|
|
||||||
for arg in args.iter() {
|
|
||||||
v.invocation_argument(arg);
|
|
||||||
invocation_argument(v, arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn invocation_argument<V: ASTVisitor>(v: &mut V, arg: &InvocationArgument) {
|
|
||||||
use InvocationArgument::*;
|
|
||||||
match arg {
|
|
||||||
Positional(expr) => {
|
|
||||||
v.expression(expr);
|
|
||||||
expression(v, expr);
|
|
||||||
},
|
|
||||||
Keyword { expr, .. } => {
|
|
||||||
v.expression(expr);
|
|
||||||
expression(v, expr);
|
|
||||||
},
|
|
||||||
Ignored => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn index<V: ASTVisitor>(v: &mut V, indexee: &Expression, indexers: &[ Expression ]) {
|
|
||||||
v.expression(indexee);
|
|
||||||
for i in indexers.iter() {
|
|
||||||
v.expression(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn named_struct<V: ASTVisitor>(v: &mut V, n: &QualifiedName, fields: &[ (Rc<String>, Expression) ]) {
|
|
||||||
v.qualified_name(n);
|
|
||||||
for (_, expr) in fields.iter() {
|
|
||||||
v.expression(expr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::ptr_arg)]
|
|
||||||
fn lambda<V: ASTVisitor>(v: &mut V, params: &Vec<FormalParam>, type_anno: Option<&TypeIdentifier>, body: &Block) {
|
|
||||||
for param in params {
|
|
||||||
v.formal_param(param);
|
|
||||||
formal_param(v, param);
|
|
||||||
}
|
|
||||||
v.type_annotation(type_anno);
|
|
||||||
v.block(body);
|
|
||||||
walk_block(v, body);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn formal_param<V: ASTVisitor>(v: &mut V, param: &FormalParam) {
|
|
||||||
if let Some(p) = param.default.as_ref() {
|
|
||||||
v.expression(p);
|
|
||||||
expression(v, p);
|
|
||||||
};
|
|
||||||
v.type_annotation(param.anno.as_ref());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn expression_kind<V: ASTVisitor>(v: &mut V, expression_kind: &ExpressionKind) {
|
|
||||||
use ExpressionKind::*;
|
|
||||||
match expression_kind {
|
|
||||||
NatLiteral(n) => v.nat_literal(*n),
|
|
||||||
FloatLiteral(f) => v.float_literal(*f),
|
|
||||||
StringLiteral(s) => v.string_literal(s),
|
|
||||||
BoolLiteral(b) => v.bool_literal(*b),
|
|
||||||
BinExp(op, lhs, rhs) => {
|
|
||||||
v.binexp(op, lhs, rhs);
|
|
||||||
expression(v, lhs);
|
|
||||||
expression(v, rhs);
|
|
||||||
},
|
|
||||||
PrefixExp(op, arg) => {
|
|
||||||
v.prefix_exp(op, arg);
|
|
||||||
expression(v, arg);
|
|
||||||
}
|
|
||||||
TupleLiteral(exprs) => {
|
|
||||||
for expr in exprs {
|
|
||||||
v.expression(expr);
|
|
||||||
expression(v, expr);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Value(name) => v.qualified_name(name),
|
|
||||||
NamedStruct { name, fields } => {
|
|
||||||
v.named_struct(name, fields);
|
|
||||||
named_struct(v, name, fields);
|
|
||||||
}
|
|
||||||
Call { f, arguments } => {
|
|
||||||
v.call(f, arguments);
|
|
||||||
call(v, f, arguments);
|
|
||||||
},
|
|
||||||
Index { indexee, indexers } => {
|
|
||||||
v.index(indexee, indexers);
|
|
||||||
index(v, indexee, indexers);
|
|
||||||
},
|
|
||||||
IfExpression { discriminator, body } => {
|
|
||||||
v.if_expression(deref_optional_box(discriminator), body);
|
|
||||||
if let Some(d) = discriminator.as_ref() { expression(v, d) }
|
|
||||||
if_expression_body(v, body);
|
|
||||||
},
|
|
||||||
WhileExpression { condition, body } => v.while_expression(deref_optional_box(condition), body),
|
|
||||||
ForExpression { enumerators, body } => v.for_expression(enumerators, body),
|
|
||||||
Lambda { params , type_anno, body } => {
|
|
||||||
v.lambda(params, type_anno.as_ref(), body);
|
|
||||||
lambda(v, params, type_anno.as_ref(), body);
|
|
||||||
},
|
|
||||||
ListLiteral(exprs) => {
|
|
||||||
for expr in exprs {
|
|
||||||
v.expression(expr);
|
|
||||||
expression(v, expr);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn if_expression_body<V: ASTVisitor>(v: &mut V, body: &IfExpressionBody) {
|
|
||||||
use IfExpressionBody::*;
|
|
||||||
match body {
|
|
||||||
SimpleConditional { then_case, else_case } => {
|
|
||||||
walk_block(v, then_case);
|
|
||||||
if let Some(block) = else_case.as_ref() { walk_block(v, block) }
|
|
||||||
},
|
|
||||||
SimplePatternMatch { pattern, then_case, else_case } => {
|
|
||||||
v.pattern(pattern);
|
|
||||||
walk_pattern(v, pattern);
|
|
||||||
walk_block(v, then_case);
|
|
||||||
if let Some(block) = else_case.as_ref() { walk_block(v, block) }
|
|
||||||
},
|
|
||||||
CondList(arms) => {
|
|
||||||
for arm in arms {
|
|
||||||
v.condition_arm(arm);
|
|
||||||
condition_arm(v, arm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn condition_arm<V: ASTVisitor>(v: &mut V, arm: &ConditionArm) {
|
|
||||||
use Condition::*;
|
|
||||||
v.condition_arm(arm);
|
|
||||||
match arm.condition {
|
|
||||||
Pattern(ref pat) => {
|
|
||||||
v.pattern(pat);
|
|
||||||
walk_pattern(v, pat);
|
|
||||||
},
|
|
||||||
TruncatedOp(ref _binop, ref expr) => {
|
|
||||||
v.expression(expr);
|
|
||||||
expression(v, expr);
|
|
||||||
},
|
|
||||||
Expression(ref expr) => {
|
|
||||||
v.expression(expr);
|
|
||||||
expression(v, expr);
|
|
||||||
},
|
|
||||||
_ => ()
|
|
||||||
}
|
|
||||||
if let Some(guard) = arm.guard.as_ref() {
|
|
||||||
v.expression(guard);
|
|
||||||
expression(v, guard);
|
|
||||||
};
|
|
||||||
v.block(&arm.body);
|
|
||||||
walk_block(v, &arm.body);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn walk_pattern<V: ASTVisitor>(v: &mut V, pat: &Pattern) {
|
|
||||||
use Pattern::*;
|
|
||||||
match pat {
|
|
||||||
TuplePattern(patterns) => {
|
|
||||||
for pat in patterns {
|
|
||||||
v.pattern(pat);
|
|
||||||
walk_pattern(v, pat);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
TupleStruct(qualified_name, patterns) => {
|
|
||||||
v.qualified_name(qualified_name);
|
|
||||||
for pat in patterns {
|
|
||||||
v.pattern(pat);
|
|
||||||
walk_pattern(v, pat);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Record(qualified_name, name_and_patterns) => {
|
|
||||||
v.qualified_name(qualified_name);
|
|
||||||
for (_, pat) in name_and_patterns {
|
|
||||||
v.pattern(pat);
|
|
||||||
walk_pattern(v, pat);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
VarOrName(qualified_name) => {
|
|
||||||
v.qualified_name(qualified_name);
|
|
||||||
},
|
|
||||||
_ => ()
|
|
||||||
}
|
|
||||||
}
|
|
@ -46,12 +46,11 @@ impl<'a> Resolver<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This might be a variable or a pattern, depending on whether this symbol
|
fn qualified_name(&mut self, name: &QualifiedName) {
|
||||||
// already exists in the table.
|
let fqsn = self.lookup_name_in_scope(name);
|
||||||
fn qualified_name_in_pattern(&mut self, qualified_name: &QualifiedName) {
|
let symbol = self.symbol_table.fqsn_to_symbol.get(&fqsn);
|
||||||
let maybe_sym = self.symbol_table.id_to_symbol.get(&qualified_name.id).cloned();
|
if let Some(symbol) = symbol {
|
||||||
if let Some(symbol) = maybe_sym {
|
self.symbol_table.id_to_symbol.insert(name.id.clone(), symbol.clone());
|
||||||
self.symbol_table.id_to_symbol.insert(qualified_name.id.clone(), symbol);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,35 +99,28 @@ impl<'a> ASTVisitor for Resolver<'a> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn qualified_name(&mut self, qualified_name: &QualifiedName) {
|
fn expression(&mut self, expression: &Expression) {
|
||||||
let fqsn = self.lookup_name_in_scope(qualified_name);
|
use ExpressionKind::*;
|
||||||
let symbol = self.symbol_table.fqsn_to_symbol.get(&fqsn);
|
match &expression.kind {
|
||||||
if let Some(symbol) = symbol {
|
Value(name) => {
|
||||||
self.symbol_table.id_to_symbol.insert(qualified_name.id.clone(), symbol.clone());
|
self.qualified_name(name);
|
||||||
}
|
},
|
||||||
}
|
NamedStruct { name, fields: _ } => {
|
||||||
|
self.qualified_name(name);
|
||||||
fn named_struct(
|
},
|
||||||
&mut self,
|
_ => (),
|
||||||
qualified_name: &QualifiedName,
|
|
||||||
_fields: &[(Rc<String>, Expression)],
|
|
||||||
) {
|
|
||||||
let fqsn = self.lookup_name_in_scope(qualified_name);
|
|
||||||
|
|
||||||
let symbol = self.symbol_table.fqsn_to_symbol.get(&fqsn);
|
|
||||||
if let Some(symbol) = symbol {
|
|
||||||
self.symbol_table.id_to_symbol.insert(qualified_name.id.clone(), symbol.clone());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pattern(&mut self, pat: &Pattern) {
|
fn pattern(&mut self, pat: &Pattern) {
|
||||||
use Pattern::*;
|
use Pattern::*;
|
||||||
|
|
||||||
match pat {
|
match pat {
|
||||||
//TODO I think not handling TuplePattern is an oversight
|
//TODO I think not handling TuplePattern is an oversight
|
||||||
TuplePattern(_) => (),
|
TuplePattern(_) => (),
|
||||||
Literal(_) | Ignored => (),
|
Literal(_) | Ignored => (),
|
||||||
TupleStruct(name, _) | Record(name, _) | VarOrName(name) => {
|
TupleStruct(name, _) | Record(name, _) | VarOrName(name) => {
|
||||||
self.qualified_name_in_pattern(name)
|
self.qualified_name(name);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user