Skip to content

Commit

Permalink
support block scoping
Browse files Browse the repository at this point in the history
  • Loading branch information
chioni16 committed Oct 9, 2023
1 parent 13c3a42 commit beef124
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 37 deletions.
69 changes: 52 additions & 17 deletions src/bin/languageserver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ struct Builder<'a> {
hovers: Vec<(usize, HoverEntry)>,
references: Vec<(usize, ReferenceEntry)>,
scopes: Vec<(usize, ScopeEntry)>,
top_code_objects: Vec<(usize, (String, Option<DefinitionIndex>))>,
top_level_code_objects: Vec<(usize, (String, Option<DefinitionIndex>))>,

definitions: Definitions,
types: Types,
Expand All @@ -385,7 +385,7 @@ impl<'a> Builder<'a> {
hovers: Vec::new(),
references: Vec::new(),
scopes: Vec::new(),
top_code_objects: Vec::new(),
top_level_code_objects: Vec::new(),

definitions: HashMap::new(),
types: HashMap::new(),
Expand Down Expand Up @@ -1325,7 +1325,7 @@ impl<'a> Builder<'a> {
}

if contract_no.is_none() {
self.top_code_objects.push((
self.top_level_code_objects.push((
file_no,
(
variable.name.clone(),
Expand Down Expand Up @@ -1435,7 +1435,7 @@ impl<'a> Builder<'a> {
);

if enum_decl.contract.is_none() {
self.top_code_objects
self.top_level_code_objects
.push((file_no, (enum_decl.name.clone(), Some(di))));
}
}
Expand Down Expand Up @@ -1479,7 +1479,7 @@ impl<'a> Builder<'a> {
);

if struct_decl.contract.is_none() {
self.top_code_objects
self.top_level_code_objects
.push((file_no, (struct_decl.name.clone(), Some(di))));
}
}
Expand Down Expand Up @@ -1617,26 +1617,61 @@ impl<'a> Builder<'a> {
.map(|stmt| stmt.loc())
.unwrap_or(func.loc)
.exclusive_end(),
// val: func
// .symtable
// .vars
// .values()
// .map(|val| {
// (
// val.id.name.clone(),
// get_type_definition(&val.ty).map(|dt| dt.into()),
// )
// })
// .collect(),
val: func
.symtable
.vars
.values()
.map(|val| {
(
val.id.name.clone(),
get_type_definition(&val.ty).map(|dt| dt.into()),
)
.names
.first()
.map(|curr_scope| {
curr_scope
.0
.values()
.filter_map(|pos| {
func.symtable.vars.get(pos).map(|var| {
(
var.id.name.clone(),
get_type_definition(&var.ty).map(|dt| dt.into()),
)
})
})
.collect_vec()
})
.collect(),
.unwrap(),
},
));

if func.contract_no.is_none() {
self.top_code_objects
self.top_level_code_objects
.push((file_no, (func.name.clone(), None)))
}
}

self.scopes.extend(self.ns.scopes.iter().map(|(loc, vars)| {
let file_no = loc.file_no();
let scope_entry = ScopeEntry {
start: loc.start(),
stop: loc.exclusive_end(),
val: vars
.iter()
.map(|(name, ty)| {
let ty = get_type_definition(ty).map(|dt| dt.into());
(name.clone(), ty)
})
.collect_vec(),
};
(file_no, scope_entry)
}));

for (i, constant) in self.ns.constants.iter().enumerate() {
let samptb = symtable::Symtable::new();
self.contract_variable(constant, &samptb, None, i);
Expand Down Expand Up @@ -1829,7 +1864,7 @@ impl<'a> Builder<'a> {

// Contracts can't be defined within other contracts.
// So all the contracts are top level objects in a file.
self.top_code_objects
self.top_level_code_objects
.push((file_no, (contract.name.clone(), Some(cdi))));
}

Expand Down Expand Up @@ -1857,7 +1892,7 @@ impl<'a> Builder<'a> {
.insert(di.clone(), loc_to_range(&event.loc, file));

if event.contract.is_none() {
self.top_code_objects
self.top_level_code_objects
.push((file_no, (event.name.clone(), Some(di))));
}
}
Expand Down Expand Up @@ -1954,7 +1989,7 @@ impl<'a> Builder<'a> {
.collect(),
),
top_level_code_objects: self
.top_code_objects
.top_level_code_objects
.iter_mut()
.filter(|co| co.0 == i)
.map(|co| {
Expand Down
2 changes: 2 additions & 0 deletions src/sema/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,8 @@ pub struct Namespace {
pub var_constants: HashMap<pt::Loc, codegen::Expression>,
/// Overrides for hover in the language server
pub hover_overrides: HashMap<pt::Loc, String>,

pub scopes: HashMap<pt::Loc, Vec<(String, Type)>>,
}

#[derive(Debug)]
Expand Down
2 changes: 2 additions & 0 deletions src/sema/namespace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ impl Namespace {
next_id: 0,
var_constants: HashMap::new(),
hover_overrides: HashMap::new(),

scopes: HashMap::new(),
};

match target {
Expand Down
39 changes: 26 additions & 13 deletions src/sema/statements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,9 +417,9 @@ fn statement(
Ok(true)
}
pt::Statement::Block {
loc,
statements,
unchecked,
..
} => {
symtable.new_scope();
let mut reachable = true;
Expand All @@ -438,7 +438,20 @@ fn statement(
reachable = statement(stmt, res, &mut context, symtable, loops, ns, diagnostics)?;
}

symtable.leave_scope();
// symtable.leave_scope().map(|curr_scope| {
// let curr_scope = curr_scope
// .0
// .values()
// .filter_map(|pos| {
// symtable
// .vars
// .get(pos)
// .map(|var| (var.id.name.clone(), var.ty.clone()))
// })
// .collect();
// ns.scopes.insert(*loc, curr_scope);
// });
symtable.leave_scope(ns, *loc);

Ok(reachable)
}
Expand Down Expand Up @@ -491,7 +504,7 @@ fn statement(
ns,
diagnostics,
)?;
symtable.leave_scope();
symtable.leave_scope(ns, *loc);
loops.leave_scope();

res.push(Statement::While(*loc, true, cond, body_stmts));
Expand Down Expand Up @@ -523,7 +536,7 @@ fn statement(
ns,
diagnostics,
)?;
symtable.leave_scope();
symtable.leave_scope(ns, *loc);
loops.leave_scope();

res.push(Statement::DoWhile(*loc, true, body_stmts, cond));
Expand Down Expand Up @@ -554,7 +567,7 @@ fn statement(
ns,
diagnostics,
)?;
symtable.leave_scope();
symtable.leave_scope(ns, *loc);

let mut else_stmts = Vec::new();
if let Some(stmts) = else_ {
Expand All @@ -569,7 +582,7 @@ fn statement(
diagnostics,
)?;

symtable.leave_scope();
symtable.leave_scope(ns, *loc);
} else {
reachable = true;
}
Expand Down Expand Up @@ -634,7 +647,7 @@ fn statement(
)?);
}

symtable.leave_scope();
symtable.leave_scope(ns, *loc);

res.push(Statement::For {
loc: *loc,
Expand Down Expand Up @@ -713,7 +726,7 @@ fn statement(
}
}

symtable.leave_scope();
symtable.leave_scope(ns, *loc);

res.push(Statement::For {
loc: *loc,
Expand Down Expand Up @@ -2445,7 +2458,7 @@ fn try_catch(
diagnostics,
)?;

symtable.leave_scope();
symtable.leave_scope(ns, *loc);

let mut clauses_unique = HashSet::new();
let mut errors_resolved = Vec::new();
Expand All @@ -2470,7 +2483,7 @@ fn try_catch(
}

match clause_stmt {
CatchClause::Simple(_, param, stmt) => {
CatchClause::Simple(catch_loc, param, stmt) => {
symtable.new_scope();

let mut catch_param = None;
Expand Down Expand Up @@ -2536,7 +2549,7 @@ fn try_catch(

finally_reachable |= reachable;

symtable.leave_scope();
symtable.leave_scope(ns, *catch_loc);

catch_all = Some(super::ast::CatchClause {
param: catch_param,
Expand All @@ -2546,7 +2559,7 @@ fn try_catch(

Ok(())
}
CatchClause::Named(_, id, param, stmt) => {
CatchClause::Named(catch_loc, id, param, stmt) => {
if id.name != "Error" && id.name != "Panic" {
let message = format!(
"only catch 'Error' and 'Panic' are supported, not '{}'",
Expand Down Expand Up @@ -2626,7 +2639,7 @@ fn try_catch(

finally_reachable |= reachable;

symtable.leave_scope();
symtable.leave_scope(ns, *catch_loc);

errors_resolved.push((error_pos, error_param, error_stmt_resolved));

Expand Down
37 changes: 33 additions & 4 deletions src/sema/symtable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,12 @@ pub enum VariableUsage {
}

#[derive(Debug, Clone)]
struct VarScope(HashMap<String, usize>, Option<HashSet<usize>>);
pub struct VarScope(pub HashMap<String, usize>, Option<HashSet<usize>>);

#[derive(Default, Debug, Clone)]
pub struct Symtable {
pub vars: IndexMap<usize, Variable>,
names: Vec<VarScope>,
pub names: Vec<VarScope>,
pub arguments: Vec<Option<usize>>,
pub returns: Vec<usize>,
}
Expand Down Expand Up @@ -187,8 +187,19 @@ impl Symtable {
self.names.push(VarScope(HashMap::new(), None));
}

pub fn leave_scope(&mut self) {
self.names.pop();
pub fn leave_scope(&mut self, ns: &mut Namespace, loc: pt::Loc) {
if let Some(curr_scope) = self.names.pop() {
let curr_scope = curr_scope
.0
.values()
.filter_map(|pos| {
self.vars
.get(pos)
.map(|var| (var.id.name.clone(), var.ty.clone()))
})
.collect();
ns.scopes.insert(loc, curr_scope);
}
}

pub fn get_name(&self, pos: usize) -> &str {
Expand Down Expand Up @@ -245,3 +256,21 @@ impl LoopScopes {
}
}
}

// impl Namespace {
// pub fn add_scope(&mut self, loc: pt::Loc, scope: Option<VarScope>) {
// symtable.leave_scope().map(|curr_scope| {
// let curr_scope = curr_scope
// .0
// .values()
// .filter_map(|pos| {
// symtable
// .vars
// .get(pos)
// .map(|var| (var.id.name.clone(), var.ty.clone()))
// })
// .collect();
// self.scopes.insert(loc, curr_scope);
// });
// }
// }
2 changes: 1 addition & 1 deletion src/sema/yul/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub fn resolve_yul_block(
);

next_reachable &= reachable;
symtable.leave_scope();
symtable.leave_scope(ns, *loc);
function_table.leave_scope(ns);

(
Expand Down
2 changes: 1 addition & 1 deletion src/sema/yul/for_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ pub(crate) fn resolve_for_loop(
ns,
);

symtable.leave_scope();
symtable.leave_scope(ns, yul_for.loc);
function_table.leave_scope(ns);

Ok((
Expand Down
2 changes: 1 addition & 1 deletion src/sema/yul/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub fn resolve_inline_assembly(
ns,
);

symtable.leave_scope();
symtable.leave_scope(ns, *loc);
functions_table.leave_scope(ns);
let end = start + functions_table.resolved_functions.len();
ns.yul_functions
Expand Down

0 comments on commit beef124

Please sign in to comment.