visitor-less scopes

This commit is contained in:
Aleksey Kladov 2018-08-27 10:12:28 +03:00
parent 8b0298ce09
commit c16530c988
3 changed files with 49 additions and 17 deletions

View file

@ -5,7 +5,6 @@ use libsyntax2::{
ast::{self, NameOwner}, ast::{self, NameOwner},
algo::{ algo::{
ancestors, ancestors,
visit::{visitor_ctx, VisitorCtx},
walk::preorder, walk::preorder,
generate, generate,
}, },
@ -52,24 +51,24 @@ fn compute_scopes(fn_def: ast::FnDef) -> FnScopes {
let mut scope = root; let mut scope = root;
if let Some(body) = fn_def.body() { if let Some(body) = fn_def.body() {
for child in body.syntax().children() { for stmt in body.statements() {
let _ = visitor_ctx((&mut scopes, &mut scope)) match stmt {
.visit::<ast::LetStmt, _>(|stmt, (scopes, scope)| { ast::Stmt::LetStmt(stmt) => {
*scope = scopes.new_scope(*scope); scope = scopes.new_scope(scope);
if let Some(pat) = stmt.pat() { if let Some(pat) = stmt.pat() {
scopes.add_bindings(*scope, pat); scopes.add_bindings(scope, pat);
} }
if let Some(expr) = stmt.initializer() { if let Some(expr) = stmt.initializer() {
scopes.set_scope(expr.syntax(), *scope) scopes.set_scope(expr.syntax(), scope)
} }
}) }
.visit::<ast::ExprStmt, _>(|expr, (scopes, scope)| { ast::Stmt::ExprStmt(expr) => {
scopes.set_scope(expr.syntax(), *scope) scopes.set_scope(expr.syntax(), scope)
}) }
.visit::<ast::Expr, _>(|expr, (scopes, scope)| { }
scopes.set_scope(expr.syntax(), *scope) }
}) if let Some(expr) = body.expr() {
.accept(child); scopes.set_scope(expr.syntax(), scope)
} }
} }
scopes scopes

View file

@ -116,9 +116,13 @@ impl<'a> AstNode<'a> for Block<'a> {
} }
impl<'a> Block<'a> { impl<'a> Block<'a> {
pub fn let_stmts(self) -> impl Iterator<Item = LetStmt<'a>> + 'a { pub fn statements(self) -> impl Iterator<Item = Stmt<'a>> + 'a {
super::children(self) super::children(self)
} }
pub fn expr(self) -> Option<Expr<'a>> {
super::child_opt(self)
}
} }
// BlockExpr // BlockExpr
@ -1370,6 +1374,31 @@ impl<'a> ast::TypeParamsOwner<'a> for StaticDef<'a> {}
impl<'a> ast::AttrsOwner<'a> for StaticDef<'a> {} impl<'a> ast::AttrsOwner<'a> for StaticDef<'a> {}
impl<'a> StaticDef<'a> {} impl<'a> StaticDef<'a> {}
// Stmt
#[derive(Debug, Clone, Copy)]
pub enum Stmt<'a> {
ExprStmt(ExprStmt<'a>),
LetStmt(LetStmt<'a>),
}
impl<'a> AstNode<'a> for Stmt<'a> {
fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
match syntax.kind() {
EXPR_STMT => Some(Stmt::ExprStmt(ExprStmt { syntax })),
LET_STMT => Some(Stmt::LetStmt(LetStmt { syntax })),
_ => None,
}
}
fn syntax(self) -> SyntaxNodeRef<'a> {
match self {
Stmt::ExprStmt(inner) => inner.syntax(),
Stmt::LetStmt(inner) => inner.syntax(),
}
}
}
impl<'a> Stmt<'a> {}
// StructDef // StructDef
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct StructDef<'a> { pub struct StructDef<'a> {

View file

@ -437,9 +437,13 @@ Grammar(
["pat", "Pat"], ["pat", "Pat"],
["initializer", "Expr"], ["initializer", "Expr"],
]), ]),
"Stmt": (
enum: ["ExprStmt", "LetStmt"],
),
"Block": ( "Block": (
options: [["expr", "Expr"]],
collections: [ collections: [
["let_stmts", "LetStmt"], ["statements", "Stmt"],
] ]
), ),
"ParamList": ( "ParamList": (