fixing name lookup issue

This commit is contained in:
Irmen de Jong
2025-06-15 23:53:57 +02:00
parent 49a4d9ba37
commit 6f0a0981bd
6 changed files with 110 additions and 35 deletions

View File

@@ -106,14 +106,14 @@ internal fun Program.preprocessAst(errors: IErrorReporter, options: CompilationO
val mergeBlocks = BlockMerger(errors)
mergeBlocks.visit(this)
if(errors.noErrors()) {
val structPreprocessor = AstStructPreprocessor(this)
structPreprocessor.visit(this)
structPreprocessor.applyModifications()
val transforms = AstPreprocessor(this, errors, options)
transforms.visit(this)
while (errors.noErrors() && transforms.applyModifications() > 0)
transforms.visit(this)
val structPreprocessor = AstStructPreprocessor(this)
structPreprocessor.visit(this)
structPreprocessor.applyModifications()
}
}

View File

@@ -338,6 +338,18 @@ class AstPreprocessor(val program: Program,
return noModifications
}
override fun after(struct: StructDecl, parent: Node): Iterable<IAstModification> {
// convert all antlr names to structs
struct.fields.forEach {
if(it.first.subTypeFromAntlr!=null) {
val struct = struct.definingScope.lookup(it.first.subTypeFromAntlr!!) as? ISubType
if(struct!=null)
it.first.setActualSubType(struct)
}
}
return noModifications
}
private fun checkStringParam(call: IFunctionCall, stmt: Statement) {
val targetStatement = call.target.checkFunctionOrLabelExists(program, stmt, errors)

View File

@@ -7,22 +7,13 @@ import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification
import prog8.code.core.BaseDataType
import prog8.code.core.DataType
import prog8.code.core.ISubType
// TODO integrate back into AstPreprocessor?
class AstStructPreprocessor(val program: Program) : AstWalker() {
override fun after(struct: StructDecl, parent: Node): Iterable<IAstModification> {
// convert all antlr names to structs
struct.fields.forEach {
if(it.first.subTypeFromAntlr!=null) {
val struct = struct.definingScope.lookup(it.first.subTypeFromAntlr!!) as? ISubType
if(struct!=null)
it.first.setActualSubType(struct)
}
}
// convert str fields to ^^ubyte
val convertedFields = struct.fields.map {
if(it.first.isString)

View File

@@ -1139,4 +1139,59 @@ main {
compileText(VMTarget(), false, src, outputDir) shouldNotBe null
}
xtest("local and global struct pointer qualified name lookups") {
val src="""
main {
struct Node {
str question
str animal
^^Node negative
^^Node positive
}
^^Node @shared first
sub start() {
cx16.r0 = first
cx16.r1 = first.negative
cx16.r0 = first^^.negative
cx16.r1 = first.negative.animal
cx16.r0 = first^^.negative^^.animal
cx16.r2 = db.first
cx16.r3 = db.first.negative ; TODO fix symbol lookup errors
cx16.r2 = db.first^^.negative ; TODO fix symbol lookup errors
cx16.r3 = db.first.negative.animal
cx16.r2 = db.first^^.negative^^.animal
db.first.negative.animal = 0
db.first.negative = 0 ; TODO fix symbol lookup errors
db.first = 0
; TODO fix symbol lookup errors:
func(db.first)
func(db.first.negative)
func(db.first.negative.animal)
}
sub func(uword arg) {
cx16.r0 = arg
}
}
db {
struct Node {
str question
str animal
^^Node negative
^^Node positive
}
^^Node @shared first
}"""
compileText(VMTarget(), false, src, outputDir) shouldNotBe null
}
})

View File

@@ -176,13 +176,40 @@ interface INameScope: IStatementContainer, INamedStatement {
private fun lookupQualified(scopedName: List<String>): Statement? {
val localSymbol = this.searchSymbol(scopedName[0]) ?: this.lookupUnqualified(scopedName[0])
val fieldRef = searchStructFieldRef(localSymbol, scopedName)
if(fieldRef!=null)
return fieldRef
// a scoped name refers to a name in another namespace, and always starts from the root.
for(module in (this as Node).definingModule.program.modules) {
val block = module.searchSymbol(scopedName[0])
if(block!=null) {
var statement = block
for((idx, name) in scopedName.drop(1).withIndex()) {
val symbol = (statement as? IStatementContainer)?.searchSymbol(name)
if(symbol==null) {
val fieldRef = searchStructFieldRef(statement, scopedName.drop(idx+1))
if(fieldRef!=null)
return fieldRef
println("LOOKUP FAIL $statement ${scopedName.drop(idx+1)}") // TODO FIX
return null
} else {
statement = symbol
}
}
return statement
}
}
return null
}
fun searchStructFieldRef(localSymbol: Statement?, scopedName: List<String>): StructFieldRef? {
if(localSymbol is VarDecl && localSymbol.datatype.isPointer) {
var struct = localSymbol.datatype.subType as? StructDecl
if(struct!=null) {
for ((idx, field) in scopedName.drop(1).withIndex()) {
val fieldDt = struct!!.getFieldType(field)
if (fieldDt == null)
break
val fieldDt = struct!!.getFieldType(field) ?:
return null
if (idx == scopedName.size - 2) {
// was last path element
val pointer = IdentifierReference(scopedName, Position.DUMMY)
@@ -190,25 +217,13 @@ interface INameScope: IStatementContainer, INamedStatement {
ref.linkParents(this as Node)
return ref
}
struct = fieldDt.subType as? StructDecl
if(struct==null)
break
}
}
}
// a scoped name refers to a name in another namespace, and always starts from the root.
for(module in (this as Node).definingModule.program.modules) {
val block = module.searchSymbol(scopedName[0])
if(block!=null) {
var statement = block
for(name in scopedName.drop(1)) {
statement = (statement as? IStatementContainer)?.searchSymbol(name)
if(statement==null) {
struct = fieldDt.subType as? StructDecl ?:
return null
}
}
return statement
} else {
if(localSymbol.datatype.subTypeFromAntlr!=null)
TODO("antlr subtype must have been converted to a struct type by now $localSymbol : ${localSymbol.datatype.subTypeFromAntlr}")
return null
}
}
return null

View File

@@ -1,7 +1,9 @@
TODO
====
Fix symbol lookup bug
Fix symbol lookup bug "antlr subtype must have been converted to a struct type by now" , "LOOKUP FAIL"
Reintegrate AstStructPreprocessor into AstPreProcessor , if possible.
STRUCTS and TYPED POINTERS