mirror of
https://github.com/irmen/prog8.git
synced 2024-11-16 22:09:56 +00:00
improved parameter name shadowing check
This commit is contained in:
parent
a56956797a
commit
ff1294207e
@ -429,7 +429,7 @@ interface INameScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getLabelOrVariable(name: String): IStatement? {
|
fun getLabelOrVariable(name: String): IStatement? {
|
||||||
// this is called A LOT and could perhaps be optimized a bit more, but adding a cache didn't make much of a practical runtime difference
|
// TODO this is called A LOT and could perhaps be optimized a bit more, but adding a cache didn't make much of a practical runtime difference
|
||||||
for (stmt in statements) {
|
for (stmt in statements) {
|
||||||
if (stmt is VarDecl && stmt.name==name) return stmt
|
if (stmt is VarDecl && stmt.name==name) return stmt
|
||||||
if (stmt is Label && stmt.name==name) return stmt
|
if (stmt is Label && stmt.name==name) return stmt
|
||||||
@ -437,8 +437,17 @@ interface INameScope {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun allDefinedNames(): Set<String> =
|
fun allDefinedSymbols(): List<Pair<String, IStatement>> {
|
||||||
statements.filterIsInstance<Label>().map { it.name }.toSet() + statements.filterIsInstance<VarDecl>().map { it.name }.toSet()
|
return statements.mapNotNull {
|
||||||
|
when (it) {
|
||||||
|
is Label -> it.name to it
|
||||||
|
is VarDecl -> it.name to it
|
||||||
|
is Subroutine -> it.name to it
|
||||||
|
is Block -> it.name to it
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun lookup(scopedName: List<String>, localContext: Node) : IStatement? {
|
fun lookup(scopedName: List<String>, localContext: Node) : IStatement? {
|
||||||
if(scopedName.size>1) {
|
if(scopedName.size>1) {
|
||||||
|
@ -114,14 +114,18 @@ private class AstIdentifiersChecker(private val namespace: INameScope) : IAstPro
|
|||||||
if (existing != null && existing !== subroutine)
|
if (existing != null && existing !== subroutine)
|
||||||
nameError(subroutine.name, subroutine.position, existing)
|
nameError(subroutine.name, subroutine.position, existing)
|
||||||
|
|
||||||
// check that there are no local variables that redefine the subroutine's parameters
|
// check that there are no local variables, labels, or other subs that redefine the subroutine's parameters
|
||||||
val allDefinedNames = subroutine.allDefinedNames()
|
val symbolsInSub = subroutine.allDefinedSymbols()
|
||||||
|
val namesInSub = symbolsInSub.map{ it.first }.toSet()
|
||||||
val paramNames = subroutine.parameters.map { it.name }.toSet()
|
val paramNames = subroutine.parameters.map { it.name }.toSet()
|
||||||
val paramsToCheck = paramNames.intersect(allDefinedNames)
|
val paramsToCheck = paramNames.intersect(namesInSub)
|
||||||
for(name in paramsToCheck) {
|
for(name in paramsToCheck) {
|
||||||
val thing = subroutine.getLabelOrVariable(name)!!
|
val labelOrVar = subroutine.getLabelOrVariable(name)
|
||||||
if(thing.position != subroutine.position)
|
if(labelOrVar!=null && labelOrVar.position != subroutine.position)
|
||||||
nameError(name, thing.position, subroutine)
|
nameError(name, labelOrVar.position, subroutine)
|
||||||
|
val sub = subroutine.statements.singleOrNull { it is Subroutine && it.name==name}
|
||||||
|
if(sub!=null)
|
||||||
|
nameError(name, sub.position, subroutine)
|
||||||
}
|
}
|
||||||
|
|
||||||
// inject subroutine params as local variables (if they're not there yet) (for non-kernel subroutines and non-asm parameters)
|
// inject subroutine params as local variables (if they're not there yet) (for non-kernel subroutines and non-asm parameters)
|
||||||
@ -132,7 +136,7 @@ private class AstIdentifiersChecker(private val namespace: INameScope) : IAstPro
|
|||||||
if(subroutine.asmAddress==null && !subroutine.canBeAsmSubroutine) {
|
if(subroutine.asmAddress==null && !subroutine.canBeAsmSubroutine) {
|
||||||
if(subroutine.asmParameterRegisters.isEmpty()) {
|
if(subroutine.asmParameterRegisters.isEmpty()) {
|
||||||
subroutine.parameters
|
subroutine.parameters
|
||||||
.filter { it.name !in allDefinedNames }
|
.filter { it.name !in namesInSub }
|
||||||
.forEach {
|
.forEach {
|
||||||
val vardecl = VarDecl(VarDeclType.VAR, it.type, false, null, it.name, null, false, subroutine.position)
|
val vardecl = VarDecl(VarDeclType.VAR, it.type, false, null, it.name, null, false, subroutine.position)
|
||||||
vardecl.linkParents(subroutine)
|
vardecl.linkParents(subroutine)
|
||||||
|
@ -315,7 +315,9 @@ private class StatementReorderer(private val program: Program): IAstProcessor {
|
|||||||
|
|
||||||
|
|
||||||
private class VarInitValueAndAddressOfCreator(private val namespace: INameScope): IAstProcessor {
|
private class VarInitValueAndAddressOfCreator(private val namespace: INameScope): IAstProcessor {
|
||||||
// Replace the var decl with an assignment and add a new vardecl with the default constant value.
|
// For VarDecls that declare an initialization value:
|
||||||
|
// Replace the vardecl with an assignment (to set the initial value),
|
||||||
|
// and add a new vardecl with the default constant value of that type (usually zero) to the scope.
|
||||||
// This makes sure the variables get reset to the intended value on a next run of the program.
|
// This makes sure the variables get reset to the intended value on a next run of the program.
|
||||||
// Variable decls without a value don't get this treatment, which means they retain the last
|
// Variable decls without a value don't get this treatment, which means they retain the last
|
||||||
// value they had when restarting the program.
|
// value they had when restarting the program.
|
||||||
|
@ -5,59 +5,21 @@
|
|||||||
~ main {
|
~ main {
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
c64scr.setcc(0,0,160,0)
|
|
||||||
c64scr.setcc(0,1,160,1)
|
|
||||||
c64scr.setcc(0,2,160,2)
|
|
||||||
c64scr.setcc(0,3,160,3)
|
|
||||||
c64scr.setcc(0,4,160,4)
|
|
||||||
c64scr.setcc(0,5,160,5)
|
|
||||||
c64scr.setcc(0,6,160,6)
|
|
||||||
c64scr.setcc(0,7,160,7)
|
|
||||||
c64scr.setcc(0,8,160,8)
|
|
||||||
c64scr.setcc(0,9,160,9)
|
|
||||||
c64scr.setcc(0,10,160,10)
|
|
||||||
c64scr.setcc(0,11,160,11)
|
|
||||||
c64scr.setcc(0,12,160,12)
|
|
||||||
c64scr.setcc(0,13,160,13)
|
|
||||||
c64scr.setcc(0,14,160,14)
|
|
||||||
c64scr.setcc(0,15,160,15)
|
|
||||||
|
|
||||||
c64scr.setcc(1,0,160,0)
|
foo(1)
|
||||||
c64scr.setcc(1,1,160,1)
|
}
|
||||||
c64scr.setcc(1,2,160,2)
|
|
||||||
c64scr.setcc(1,3,160,3)
|
sub foo(ubyte param1) {
|
||||||
c64scr.setcc(1,4,160,4)
|
|
||||||
c64scr.setcc(1,5,160,5)
|
sub subsub() {
|
||||||
c64scr.setcc(1,6,160,6)
|
|
||||||
c64scr.setcc(1,7,160,7)
|
}
|
||||||
c64scr.setcc(1,8,160,8)
|
|
||||||
c64scr.setcc(1,9,160,9)
|
sub param1() {
|
||||||
c64scr.setcc(1,10,160,10)
|
}
|
||||||
c64scr.setcc(1,11,160,11)
|
}
|
||||||
c64scr.setcc(1,12,160,12)
|
|
||||||
c64scr.setcc(1,13,160,13)
|
|
||||||
c64scr.setcc(1,14,160,14)
|
|
||||||
c64scr.setcc(1,15,160,15)
|
|
||||||
|
|
||||||
c64scr.setcc(2,0,160,0)
|
|
||||||
c64scr.setcc(2,1,160,1)
|
|
||||||
c64scr.setcc(2,2,160,2)
|
|
||||||
c64scr.setcc(2,3,160,3)
|
|
||||||
c64scr.setcc(2,4,160,4)
|
|
||||||
c64scr.setcc(2,5,160,5)
|
|
||||||
c64scr.setcc(2,6,160,6)
|
|
||||||
c64scr.setcc(2,7,160,7)
|
|
||||||
c64scr.setcc(2,8,160,8)
|
|
||||||
c64scr.setcc(2,9,160,9)
|
|
||||||
c64scr.setcc(2,10,160,10)
|
|
||||||
c64scr.setcc(2,11,160,11)
|
|
||||||
c64scr.setcc(2,12,160,12)
|
|
||||||
c64scr.setcc(2,13,160,13)
|
|
||||||
c64scr.setcc(2,14,160,14)
|
|
||||||
c64scr.setcc(2,15,160,15)
|
|
||||||
|
|
||||||
_x:
|
|
||||||
goto _x
|
|
||||||
|
|
||||||
; for ubyte y in 0 to 3 {
|
; for ubyte y in 0 to 3 {
|
||||||
; for ubyte x in 0 to 10 {
|
; for ubyte x in 0 to 10 {
|
||||||
@ -94,6 +56,4 @@
|
|||||||
; c64flt.print_f(xcoor[2])
|
; c64flt.print_f(xcoor[2])
|
||||||
; c64.CHROUT('\n')
|
; c64.CHROUT('\n')
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user