fixing alias bugs

This commit is contained in:
Irmen de Jong
2025-09-07 21:53:47 +02:00
parent 6ababbf8f4
commit a1ab8ed208
6 changed files with 131 additions and 51 deletions

View File

@@ -210,6 +210,12 @@ class AstPreprocessor(val program: Program,
decl.datatype.setActualSubType(node)
} else if(antlrTypeName.size==1 && antlrTypeName[0] in program.builtinFunctions.names) {
errors.err("builtin function can only be called, not used as a type name", decl.position)
} else if(node is Alias) {
val actual = decl.definingScope.lookup(node.target.nameInSource)
if(actual is StructDecl)
decl.datatype.setActualSubType(actual)
else if(actual==null)
errors.err("cannot find struct type ${node.target.nameInSource.joinToString(".")}", decl.position)
}
}

View File

@@ -530,7 +530,7 @@ _after:
var struct = firstDt.subType
for(name in identifier.nameInSource.drop(1)) {
if(struct==null) {
errors.err("unknown field '${name}", position = identifier.position)
errors.err("unknown field '${name}'", position = identifier.position)
return noModifications
}
val fieldDt = struct.getFieldType(name)

View File

@@ -148,6 +148,15 @@ internal class LiteralsToAutoVarsAndRecombineIdentifiers(private val program: Pr
}
}
if(target==null && identifier.nameInSource.size>1) {
// maybe the first component of the scoped name is an alias?
val tgt2 = identifier.definingScope.lookup(identifier.nameInSource.take(1)) as? Alias
if(tgt2!=null && parent !is Alias) {
if(tgt2.target.targetStatement() !is Alias)
return listOf(IAstModification.ReplaceNode(identifier, tgt2.target.copy(position = identifier.position), parent))
}
}
// don't replace an identifier in an Alias or when the alias points to another alias (that will be resolved first elsewhere)
if(target is Alias && parent !is Alias) {
if(target.target.targetStatement() !is Alias)

View File

@@ -2349,4 +2349,40 @@ main {
compileText(C64Target(), false, src, outputDir) shouldNotBe null
}
test("struct and pointer aliasing") {
val src="""
main {
sub start() {
alias1()
alias2()
alias3()
}
sub alias1() {
alias TheNode = structdefs.Node
^^TheNode node = 20000
node.value = 100 ; TODO fix unknown field 'value'
}
sub alias2() {
^^structdefs.Node node = 20000
alias thing = node
thing.value=200 ; TODO fix undefined symbol: thing.value
}
sub alias3() {
alias TheNode = structdefs.Node
^^TheNode node = 20000
node++ ;; TODO fix compiler crash Key POINTER is missing in the map
}
}
structdefs {
struct Node {
ubyte value
}
}"""
compileText(VMTarget(), false, src, outputDir) shouldNotBe null
}
})

View File

@@ -56,6 +56,15 @@ main {
STRUCTS and TYPED POINTERS (6502 codegen specific)
--------------------------------------------------
- Bugs:
;node2.type = 10 ;; TODO: fix undefined symbol error
;^^StructAlias node3 = 30000
; node3.type = 10 ;; TODO: fix "unknown field 'type" error
^^OtherNodeAlias other = 20000
other++ ;; TODO fix compiler crash Key POINTER is missing in the map
- in CodeDesugarer there is support for ptr1[idx]^^ = ptr2^^ into memcopy() but it doesn't seem to trigger?
- allow struct initialization syntax in an array such as [ Node(), Node(), Node() ], update sorting example to use list of countries like that

View File

@@ -1,61 +1,81 @@
%import textio
%zeropage basicsafe
main {
struct Ptr {
word value
byte bvalue
}
sub start() {
^^Ptr pp = Ptr()
uword @nozp plainptr = &pp.bvalue
pp.value = -999
pp.bvalue = -99
txt.print_w(clamp(pp.value, 10, 2000))
txt.spc()
txt.print_b(clamp(pp.bvalue, 10, 100))
txt.spc()
pp.bvalue = 5
txt.print_ub(clamp(plainptr[0], 10, 100))
txt.nl()
pp.value = 5000
pp.bvalue = 120
txt.print_w(clamp(pp.value, 10, 2000))
txt.spc()
txt.print_b(clamp(pp.bvalue, 10, 100))
txt.spc()
pp.bvalue = 120
txt.print_ub(clamp(plainptr[0], 10, 100))
txt.nl()
pp.value = 1234
pp.bvalue = 66
txt.print_w(clamp(pp.value, 10, 2000))
txt.spc()
txt.print_b(clamp(pp.bvalue, 10, 100))
txt.spc()
pp.bvalue = 66
txt.print_ub(clamp(plainptr[0], 10, 100))
txt.nl()
alias derp = structdefs.normal
derp ++
alias1()
alias2()
alias3()
}
sub alias1() {
alias TheNode = structdefs.Node
^^TheNode node = 20000
node.value = 100
}
sub alias2() {
^^structdefs.Node node = 20000
alias thing = node
thing.value=200
}
sub alias3() {
alias TheNode = structdefs.Node
^^TheNode node = 20000
node++
}
}
;%import floats
structdefs {
struct Node {
ubyte value
}
ubyte @shared normal
}
;
;%import textio
;%zeropage kernalsafe
;
;
;main {
; struct Node {
; ubyte type, frame, framecounter
; }
;
;
; sub start() {
; struct List {
; uword s
; float fl
; uword n
; }
; ^^List l = List()
; l.n[cx16.r0L] = 99
;; l.s[cx16.r0L+2] = 42
;; l.n[cx16.r0L+2] = 99
; ^^Node storageElementBuffer = 20000
; ^^Node t_element = 30000
;
; alias node2 = t_element
; alias StructAlias = Node
; alias OtherNodeAlias = structdefs.OtherNode
;
; ;node2.type = 10 ;; TODO: fix undefined symbol error
; ;^^StructAlias node3 = 30000
; ; node3.type = 10 ;; TODO: fix "unknown field 'type" error
;
; ^^OtherNodeAlias other = 20000
; other++ ;; TODO fix compiler crash Key POINTER is missing in the map
;
;
; ubyte @shared i = 0
; storageElementBuffer[0] = t_element^^
; storageElementBuffer[0] = t_element^^
; storageElementBuffer[1] = t_element^^
; storageElementBuffer[2] = t_element^^
; storageElementBuffer[i] = t_element^^
; ;storageElementBuffer[10]^^ = t_element^^ ; TODO support this with memcopy it's the same as the one above
; ;storageElementBuffer[i]^^ = t_element^^
; }
;}
;
;structdefs {
; struct OtherNode {
; ubyte type, frame, framecounter
; }
;}