mirror of
				https://github.com/irmen/prog8.git
				synced 2025-11-03 19:16:13 +00:00 
			
		
		
		
	fixing name lookup issue
This commit is contained in:
		@@ -106,14 +106,14 @@ internal fun Program.preprocessAst(errors: IErrorReporter, options: CompilationO
 | 
				
			|||||||
    val mergeBlocks = BlockMerger(errors)
 | 
					    val mergeBlocks = BlockMerger(errors)
 | 
				
			||||||
    mergeBlocks.visit(this)
 | 
					    mergeBlocks.visit(this)
 | 
				
			||||||
    if(errors.noErrors()) {
 | 
					    if(errors.noErrors()) {
 | 
				
			||||||
        val structPreprocessor = AstStructPreprocessor(this)
 | 
					 | 
				
			||||||
        structPreprocessor.visit(this)
 | 
					 | 
				
			||||||
        structPreprocessor.applyModifications()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        val transforms = AstPreprocessor(this, errors, options)
 | 
					        val transforms = AstPreprocessor(this, errors, options)
 | 
				
			||||||
        transforms.visit(this)
 | 
					        transforms.visit(this)
 | 
				
			||||||
        while (errors.noErrors() && transforms.applyModifications() > 0)
 | 
					        while (errors.noErrors() && transforms.applyModifications() > 0)
 | 
				
			||||||
            transforms.visit(this)
 | 
					            transforms.visit(this)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val structPreprocessor = AstStructPreprocessor(this)
 | 
				
			||||||
 | 
					        structPreprocessor.visit(this)
 | 
				
			||||||
 | 
					        structPreprocessor.applyModifications()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -338,6 +338,18 @@ class AstPreprocessor(val program: Program,
 | 
				
			|||||||
        return noModifications
 | 
					        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) {
 | 
					    private fun checkStringParam(call: IFunctionCall, stmt: Statement) {
 | 
				
			||||||
        val targetStatement = call.target.checkFunctionOrLabelExists(program, stmt, errors)
 | 
					        val targetStatement = call.target.checkFunctionOrLabelExists(program, stmt, errors)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,22 +7,13 @@ import prog8.ast.walk.AstWalker
 | 
				
			|||||||
import prog8.ast.walk.IAstModification
 | 
					import prog8.ast.walk.IAstModification
 | 
				
			||||||
import prog8.code.core.BaseDataType
 | 
					import prog8.code.core.BaseDataType
 | 
				
			||||||
import prog8.code.core.DataType
 | 
					import prog8.code.core.DataType
 | 
				
			||||||
import prog8.code.core.ISubType
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO integrate back into AstPreprocessor?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AstStructPreprocessor(val program: Program) : AstWalker() {
 | 
					class AstStructPreprocessor(val program: Program) : AstWalker() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun after(struct: StructDecl, parent: Node): Iterable<IAstModification> {
 | 
					    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
 | 
					        // convert str fields to ^^ubyte
 | 
				
			||||||
        val convertedFields = struct.fields.map {
 | 
					        val convertedFields = struct.fields.map {
 | 
				
			||||||
            if(it.first.isString)
 | 
					            if(it.first.isString)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1139,4 +1139,59 @@ main {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        compileText(VMTarget(), false, src, outputDir) shouldNotBe null
 | 
					        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
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
@@ -176,13 +176,40 @@ interface INameScope: IStatementContainer, INamedStatement {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private fun lookupQualified(scopedName: List<String>): Statement? {
 | 
					    private fun lookupQualified(scopedName: List<String>): Statement? {
 | 
				
			||||||
        val localSymbol = this.searchSymbol(scopedName[0]) ?: this.lookupUnqualified(scopedName[0])
 | 
					        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) {
 | 
					        if(localSymbol is VarDecl && localSymbol.datatype.isPointer) {
 | 
				
			||||||
            var struct = localSymbol.datatype.subType as? StructDecl
 | 
					            var struct = localSymbol.datatype.subType as? StructDecl
 | 
				
			||||||
            if(struct!=null) {
 | 
					            if(struct!=null) {
 | 
				
			||||||
                for ((idx, field) in scopedName.drop(1).withIndex()) {
 | 
					                for ((idx, field) in scopedName.drop(1).withIndex()) {
 | 
				
			||||||
                    val fieldDt = struct!!.getFieldType(field)
 | 
					                    val fieldDt = struct!!.getFieldType(field)  ?:
 | 
				
			||||||
                    if (fieldDt == null)
 | 
					                        return null
 | 
				
			||||||
                        break
 | 
					 | 
				
			||||||
                    if (idx == scopedName.size - 2) {
 | 
					                    if (idx == scopedName.size - 2) {
 | 
				
			||||||
                        // was last path element
 | 
					                        // was last path element
 | 
				
			||||||
                        val pointer = IdentifierReference(scopedName, Position.DUMMY)
 | 
					                        val pointer = IdentifierReference(scopedName, Position.DUMMY)
 | 
				
			||||||
@@ -190,25 +217,13 @@ interface INameScope: IStatementContainer, INamedStatement {
 | 
				
			|||||||
                        ref.linkParents(this as Node)
 | 
					                        ref.linkParents(this as Node)
 | 
				
			||||||
                        return ref
 | 
					                        return ref
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    struct = fieldDt.subType as? StructDecl
 | 
					                    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) {
 | 
					 | 
				
			||||||
                        return null
 | 
					                        return null
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                }
 | 
					            } else {
 | 
				
			||||||
                return statement
 | 
					                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
 | 
					        return null
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,9 @@
 | 
				
			|||||||
TODO
 | 
					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
 | 
					STRUCTS and TYPED POINTERS
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user