Skip to content

Commit

Permalink
sema: check access to symbols in PathExpr
Browse files Browse the repository at this point in the history
  • Loading branch information
StunxFS committed Jul 4, 2024
1 parent 633d8b7 commit 1e00c2b
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 2 deletions.
9 changes: 7 additions & 2 deletions bsc/sema.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,11 @@ def check_path_expr(self, expr: PathExpr):

if path_sym := expr.left_sym.scope.find(expr.name):
expr.sym = path_sym
if not self.cur_sym.has_access_to(path_sym):
report.error(
f"cannot access private {path_sym.kind_of()} `{path_sym.name}`",
expr.pos
)
else:
report.error(
f"{expr.left_sym.kind_of()} `{expr.left_sym}` does not contain a symbol named `{expr.name}`",
Expand All @@ -337,9 +342,9 @@ def check_symbol(self, name, pos):
ret_sym = None
if local_sym := self.cur_scope.lookup(name):
ret_sym = local_sym
elif symbol_sym := self.cur_sym.scope.lookup(name):
elif symbol_sym := self.cur_sym.scope.find(name):
ret_sym = symbol_sym
elif module_sym := self.cur_mod.scope.lookup(name):
elif module_sym := self.cur_mod.scope.find(name):
ret_sym = module_sym
else:
report.error(f"cannot find symbol `{name}` in this scope", pos)
Expand Down
30 changes: 30 additions & 0 deletions bsc/sym.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,36 @@ def __init__(self, access_modifier, name, pos = None):
self.name = name
self.pos = pos

def get_pkg(self):
s = self
while True:
if isinstance(s, Module) and s.is_pkg:
return s
if s.parent == None:
break
s = s.parent
return None

def get_mod(self):
s = self
while True:
if isinstance(s, Module):
return s
if s.parent == None:
break
s = s.parent
return None

def has_access_to(self, other):
match other.access_modifier:
case AccessModifier.public:
return True # other is public
case AccessModifier.internal:
return self.get_pkg() == other.get_pkg()
case AccessModifier.private:
return self.get_mod() == other.get_mod()
return False

def kind_of(self):
if isinstance(self, Module):
return "package" if self.is_pkg else "module"
Expand Down
9 changes: 9 additions & 0 deletions tests/invalid_code/access_modifer.bs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
mod my_mod {
const x = 1;
pub const v = 4;
}

fn main() {
const my_x = my_mod::x; // error
const my_v = my_mod::v; // ok
}
1 change: 1 addition & 0 deletions tests/invalid_code/access_modifer.out
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tests/invalid_code/access_modifer.bs:7:26: error: cannot access private constant `x`

0 comments on commit 1e00c2b

Please sign in to comment.