diff --git a/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt b/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt index f1c7e5f34..2660d020e 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt @@ -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) } } diff --git a/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt b/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt index 307fc7559..1225441a9 100644 --- a/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt +++ b/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt @@ -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) diff --git a/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVarsAndRecombineIdentifiers.kt b/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVarsAndRecombineIdentifiers.kt index 174255001..dad13ef0f 100644 --- a/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVarsAndRecombineIdentifiers.kt +++ b/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVarsAndRecombineIdentifiers.kt @@ -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) diff --git a/compiler/test/TestPointers.kt b/compiler/test/TestPointers.kt index 750d8d670..a0c7f35d1 100644 --- a/compiler/test/TestPointers.kt +++ b/compiler/test/TestPointers.kt @@ -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 + } }) \ No newline at end of file diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 4373ce6c4..f042d74ea 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -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 diff --git a/examples/test.p8 b/examples/test.p8 index 8d6a0e5af..3794819ba 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -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 ; } ;}