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

View File

@ -14,4 +14,4 @@ export misc;
export comparisons; export comparisons;
var version* = 1; 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 { fn first(x: int): int {
var y = x; return x + 1;
y = y + 1;
return y;
} }
fn second(x: int): int { fn second(x: int): int {
var x = first(x); return first(x) + 1;
x = x + 1;
return x;
} }
print(first(0) == 1); # true
print(second(0) == 2); # true print(second(0) == 2); # true