Fixed issues with shadowing and cross-shadowing
This commit is contained in:
parent
7ab757074f
commit
582d29d149
|
@ -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
|
||||
|
|
|
@ -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)
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue