Fixed issues with shadowing and cross-shadowing

This commit is contained in:
Mattia Giambirtone 2022-11-27 14:31:53 +01:00
parent 7ab757074f
commit 582d29d149
3 changed files with 19 additions and 24 deletions

View File

@ -700,14 +700,14 @@ proc getStackPos(self: Compiler, name: Name): int =
## of a given name, relative to the current
## stack frame
var found = false
result = 2
for variable in reversed(self.names):
result = 2 # Locals start at frame offset 2
for variable in self.names:
# Only variables and arguments are actually located on
# the stack, so we skip everything else
if variable.kind notin [NameKind.Var, NameKind.Argument]:
continue
# Variable is in a scope above us, so not in frame. Skip it!
elif variable.depth < self.depth:
elif variable.depth < name.depth:
continue
# Arguments to builtin functions are optimized away to stack
# temporaries. There is no stack frame for builtins, so we skip
@ -716,19 +716,20 @@ proc getStackPos(self: Compiler, name: Name): int =
continue
# This variable isn't in declared in our module,
# but we may still have access to it
elif variable.owner != self.currentModule:
elif variable.owner != name.owner:
# Variable is private in its owner module
# or it wasn't exported to us explcitly, so
# we increase our index to make sure we don't
# overwrite it and move on
if variable.isPrivate or self.currentModule notin variable.exportedTo:
#inc(result)
# or it wasn't exported to us explicitly,
# so we just move on
if variable.isPrivate or name.owner notin variable.exportedTo:
inc(result)
continue
# Note: this is not an elif by design (lets us match public exported names
# in other modules!) Also, since getStackPos() takes a specific name object, we
# match the identifier as well as the name's scope depth
if name.ident == variable.ident and variable.depth == name.depth:
if name.ident == variable.ident and variable.depth == name.depth and name.owner == variable.owner:
if not name.belongsTo.isNil() and not variable.belongsTo.isNil():
if name.belongsTo != variable.belongsTo and variable.belongsTo.depth > name.belongsTo.depth:
dec(result)
continue
found = true
variable.resolved = true
break
inc(result)
if not found:
@ -1845,11 +1846,8 @@ proc identifier(self: Compiler, node: IdentExpr, name: Name = nil) =
var s = name
if s.isNil():
s = self.resolveOrError(node)
# If there's more than one variable with this name,
# we cannot tell which one to use, so we error out
var t = self.findByType(s.ident.token.lexeme, Type(kind: All))
if len(t) > 1:
self.error(&"ambiguous name reference to '{s.ident.token.lexeme}', please use fully qualified names instead", node)
s = t[0] # Shadowing!
if s.isConst:
# Constants are always emitted as Load* instructions
# no matter the scope depth

View File

@ -14,4 +14,4 @@ export misc;
export comparisons;
var version* = 1;
var private = 2; # Invisible outside the module
var _private = 5; # Invisible outside the module (underscore is to silence warning)

View File

@ -4,17 +4,14 @@ import std;
fn first(x: int): int {
var y = x;
y = y + 1;
return y;
return x + 1;
}
fn second(x: int): int {
var x = first(x);
x = x + 1;
return x;
return first(x) + 1;
}
print(first(0) == 1); # true
print(second(0) == 2); # true