proper warning for struct instance assignment (not yet supported)

This commit is contained in:
Irmen de Jong
2025-08-20 20:35:29 +02:00
parent 8db0344cee
commit f93d957999
5 changed files with 183 additions and 147 deletions
@@ -694,7 +694,8 @@ internal class AstChecker(private val program: Program,
return super.visit(assignment)
// unfortunately the AST regarding pointer dereferencing is a bit of a mess, and we cannot do precise type checking on elements inside such expressions yet.
if(assignment.value.inferType(program).isUnknown) {
val valueDt = assignment.value.inferType(program)
if(valueDt.isUnknown) {
val binexpr = assignment.value as? BinaryExpression
if(assignment.target.multi==null) {
if (binexpr != null && binexpr.operator != ".")
@@ -702,6 +703,8 @@ internal class AstChecker(private val program: Program,
else
errors.err("invalid assignment value", assignment.value.position)
}
} else if(valueDt.isStructInstance) {
errors.err("no support yet for assigning a struct instance by value", assignment.value.position)
}
super.visit(assignment)
@@ -744,18 +744,21 @@ _after:
// special case simple struct instance assignment via memory copy
val deref = assignment.value as? PtrDereference
if(deref!=null) {
// ptr1^^ = ptr2^^ --> memcopy(ptr2, ptr1, sizeof(struct))
val sourcePtr = IdentifierReference(deref.chain, assignment.position)
val targetPtr = IdentifierReference(assignment.target.pointerDereference!!.chain, assignment.position)
val size = program.memsizer.memorySize(sourceDt.getOrUndef(), null)
require(program.memsizer.memorySize(targetDt.getOrUndef(), null)==size)
val numBytes = NumericLiteral.optimalInteger(size, assignment.position)
val memcopy = FunctionCallStatement(IdentifierReference(listOf("sys", "memcopy"), assignment.position),
mutableListOf(sourcePtr, targetPtr, numBytes),
false, assignment.position)
return listOf(IAstModification.ReplaceNode(assignment, memcopy, parent))
val targetDeref = assignment.target.pointerDereference
if(targetDeref!=null) {
// ptr1^^ = ptr2^^ --> memcopy(ptr2, ptr1, sizeof(struct))
val targetPtr = IdentifierReference(targetDeref.chain, assignment.position)
val size = program.memsizer.memorySize(sourceDt.getOrUndef(), null)
require(program.memsizer.memorySize(targetDt.getOrUndef(), null)==size)
val numBytes = NumericLiteral.optimalInteger(size, assignment.position)
val memcopy = FunctionCallStatement(IdentifierReference(listOf("sys", "memcopy"), assignment.position),
mutableListOf(sourcePtr, targetPtr, numBytes),
false, assignment.position)
return listOf(IAstModification.ReplaceNode(assignment, memcopy, parent))
}
}
// TODO support other forms of struct instance assignments? such as ptr^^ = array[2]^^
// TODO support other forms of struct instance assignments, such as ptr^^ = array[2]^^ , array[3] = array[2], array[3] = ptr^^
}
}
+10 -8
View File
@@ -325,12 +325,11 @@ main {
cx16.r0L = ubyteptr[999]
cx16.r1L = wordptr[999]
cx16.r2L = array[9]
listptr2 = listptr[999]
}
}"""
val result = compileText(VMTarget(), false, src, outputDir, writeAssembly = false)!!
val st = result.compilerAst.entrypoint.statements
st.size shouldBe 28
st.size shouldBe 27
val a_zz = (st[20] as Assignment).value
a_zz shouldBe instanceOf<ArrayIndexedExpression>()
@@ -1197,10 +1196,11 @@ main {
val errors=ErrorReporterForTests()
compileText(VMTarget(), false, src, outputDir, errors=errors)
errors.errors.size shouldBe 3
errors.errors[0] shouldContain "doesn't match"
errors.errors[1] shouldContain "assigning this value to struct instance not supported"
errors.errors.size shouldBe 4
errors.errors[0] shouldContain "struct instance by value"
errors.errors[1] shouldContain "doesn't match"
errors.errors[2] shouldContain "assigning this value to struct instance not supported"
errors.errors[3] shouldContain "assigning this value to struct instance not supported"
}
test("a.b.c[i]^^.value as expression where pointer is struct") {
@@ -1876,9 +1876,11 @@ main {
}"""
val errors=ErrorReporterForTests(keepMessagesAfterReporting = true)
compileText(VMTarget(), false, src, outputDir, errors=errors) shouldBe null
errors.errors.size shouldBe 2
errors.errors[0] shouldContain "no support for getting the target value of pointer array indexing"
errors.errors[1] shouldContain "assigning this value to struct instance not supported"
errors.errors.size shouldBe 4
errors.errors[0] shouldContain "struct instance by value"
errors.errors[1] shouldContain "no support for getting the target value of pointer array indexing"
errors.errors[2] shouldContain "struct instance by value"
errors.errors[3] shouldContain "assigning this value to struct instance not supported"
}
test("pointer variable usage detection in other block 1") {
+2 -6
View File
@@ -1,15 +1,11 @@
TODO
====
fix compiler crash (virtual) for ^^List @shared lp ; ^^List @shared temp = lp[2]
fix invalid pointer arithmetic in 6502 code for &&lp[2] (it adds 2 to the pointer itself rather than the value of the pointer, and 2 is wrong as well)
STRUCTS and TYPED POINTERS (6502 codegen specific)
--------------------------------------------------
- implement the TODO's in PointerAssignmentsGen. (mostly related to an array indexed pointer assignment target)
- implement the TODO's in PointerAssignmentsGen.
- implement some more struct instance assignments (via memcopy) in CodeDesugarer (see the TODO)
- scan through 6502 library modules to change untyped uword pointers to typed pointers
- scan through 6502 examples to change untyped uword pointers to typed pointers
- fix code size regressions (if any left)
+154 -122
View File
@@ -4,137 +4,169 @@
%option no_sysinit
%zeropage basicsafe
main {
struct List {
^^uword s
ubyte n
^^List next
}
sub start() {
floatprob()
basicpointers()
ubyte[10] array
uword @shared wordptr
^^bool @shared boolptr
^^float @shared floatptr
^^byte @shared byteptr
^^ubyte @shared ubyteptr
^^List @shared listptr
^^List @shared listptr2
; TODO test address-of with array indexed as well
}
bool @shared zz
float @shared fl
byte @shared bb
sub floatprob() {
uword @shared dummy
^^float[10] floatptrs
^^float fptr1 = 20000 + 3*sizeof(float)
^^float fptr2 = 20000
txt.print_uw(&floatptrs)
txt.spc()
txt.print_uw(&floatptrs[3]) ; NOTE: will be 3 because the pointer array is split-words . This codegen is OK!
txt.nl()
txt.print_uw(fptr1)
txt.spc()
txt.print_uw(fptr2)
txt.spc()
txt.print_uw(& fptr2[3])
txt.spc()
txt.print_uw(&& fptr2[3])
txt.spc()
cx16.r0L = 3
txt.print_uw(& fptr2[cx16.r0L])
txt.spc()
txt.print_uw(&& fptr2[cx16.r0L])
txt.nl()
cx16.r0L = 2
txt.print_uw(& fptr2[cx16.r0L+1])
txt.spc()
txt.print_uw(&& fptr2[cx16.r0L+1])
txt.nl()
pokef(20000+3*sizeof(float), 3.1415927)
txt.print_f(fptr1^^)
txt.spc()
txt.print_f(fptr2[3])
txt.nl()
}
sub basicpointers() {
^^bool bptr = 20000
^^float fptr = 20100
^^word wptr = 20200
^^ubyte ubptr = 20300
txt.print("direct deref:\n")
txt.print_bool(bptr^^)
txt.spc()
txt.print_f(fptr^^)
txt.spc()
txt.print_w(wptr^^)
txt.spc()
txt.print_ub(ubptr^^)
txt.nl()
@(20000) = 1
pokef(20100, 3.1415927)
pokew(20200, -22222 as uword)
@(20300) = 123
txt.print_bool(bptr^^)
txt.spc()
txt.print_f(fptr^^)
txt.spc()
txt.print_w(wptr^^)
txt.spc()
txt.print_ub(ubptr^^)
txt.nl()
txt.print("indexed deref (const):\n")
@(20003) = 1
pokef(20100+3*sizeof(float), 9.876543)
pokew(20200+3*2, -11111 as uword)
@(20300+3) = 42
txt.print_bool(bptr[3])
txt.spc()
txt.print_f(fptr[3])
txt.spc()
txt.print_w(wptr[3])
txt.spc()
txt.print_ub(ubptr[3])
txt.nl()
txt.print("indexed deref (var):\n")
cx16.r0L = 3
txt.print_bool(bptr[cx16.r0L])
txt.spc()
txt.print_f(fptr[cx16.r0L])
txt.spc()
txt.print_w(wptr[cx16.r0L])
txt.spc()
txt.print_ub(ubptr[cx16.r0L])
txt.nl()
txt.print("indexed deref (expr):\n")
cx16.r0L = 2
txt.print_bool(bptr[cx16.r0L+1])
txt.spc()
txt.print_f(fptr[cx16.r0L+1])
txt.spc()
txt.print_w(wptr[cx16.r0L+1])
txt.spc()
txt.print_ub(ubptr[cx16.r0L+1])
txt.nl()
zz = boolptr[999]
fl = floatptr[999]
bb = byteptr[999]
cx16.r0L = ubyteptr[999]
cx16.r1L = wordptr[999]
cx16.r2L = array[9]
}
}
; ^^Node[5] nodesarray
;
; cx16.r0L = nodesarray[2].weight
; cx16.r0L = nodes[2].weight
;main {
; sub start() {
; struct List {
; bool b
; uword value
; }
; floatprob()
; basicpointers()
;
; ^^List[10] listarray
; cx16.r0 = listarray[2].value
; cx16.r1 = listarray[3]^^.value
; ; TODO test address-of with array indexed as well
; }
;
; sub floatprob() {
; uword @shared dummy
; ^^float[10] floatptrs
; ^^float fptr1 = 20000 + 3*sizeof(float)
; ^^float fptr2 = 20000
; txt.print_uw(&floatptrs)
; txt.spc()
; txt.print_uw(&floatptrs[3]) ; NOTE: will be 3 because the pointer array is split-words . This codegen is OK!
; txt.nl()
;
; txt.print_uw(fptr1)
; txt.spc()
; txt.print_uw(fptr2)
; txt.spc()
; txt.print_uw(& fptr2[3])
; txt.spc()
; txt.print_uw(&& fptr2[3])
; txt.spc()
; cx16.r0L = 3
; txt.print_uw(& fptr2[cx16.r0L])
; txt.spc()
; txt.print_uw(&& fptr2[cx16.r0L])
; txt.nl()
; cx16.r0L = 2
; txt.print_uw(& fptr2[cx16.r0L+1])
; txt.spc()
; txt.print_uw(&& fptr2[cx16.r0L+1])
; txt.nl()
;
; pokef(20000+3*sizeof(float), 3.1415927)
; txt.print_f(fptr1^^)
; txt.spc()
; txt.print_f(fptr2[3])
; txt.nl()
; }
;
; sub basicpointers() {
; ^^bool bptr = 20000
; ^^float fptr = 20100
; ^^word wptr = 20200
; ^^ubyte ubptr = 20300
;
; txt.print("direct deref:\n")
; txt.print_bool(bptr^^)
; txt.spc()
; txt.print_f(fptr^^)
; txt.spc()
; txt.print_w(wptr^^)
; txt.spc()
; txt.print_ub(ubptr^^)
; txt.nl()
;
; @(20000) = 1
; pokef(20100, 3.1415927)
; pokew(20200, -22222 as uword)
; @(20300) = 123
;
; txt.print_bool(bptr^^)
; txt.spc()
; txt.print_f(fptr^^)
; txt.spc()
; txt.print_w(wptr^^)
; txt.spc()
; txt.print_ub(ubptr^^)
; txt.nl()
;
;
; txt.print("indexed deref (const):\n")
; @(20003) = 1
; pokef(20100+3*sizeof(float), 9.876543)
; pokew(20200+3*2, -11111 as uword)
; @(20300+3) = 42
;
; txt.print_bool(bptr[3])
; txt.spc()
; txt.print_f(fptr[3])
; txt.spc()
; txt.print_w(wptr[3])
; txt.spc()
; txt.print_ub(ubptr[3])
; txt.nl()
;
;
; txt.print("indexed deref (var):\n")
; cx16.r0L = 3
; txt.print_bool(bptr[cx16.r0L])
; txt.spc()
; txt.print_f(fptr[cx16.r0L])
; txt.spc()
; txt.print_w(wptr[cx16.r0L])
; txt.spc()
; txt.print_ub(ubptr[cx16.r0L])
; txt.nl()
;
; txt.print("indexed deref (expr):\n")
; cx16.r0L = 2
; txt.print_bool(bptr[cx16.r0L+1])
; txt.spc()
; txt.print_f(fptr[cx16.r0L+1])
; txt.spc()
; txt.print_w(wptr[cx16.r0L+1])
; txt.spc()
; txt.print_ub(ubptr[cx16.r0L+1])
; txt.nl()
; }
;}
;
;
;; ^^Node[5] nodesarray
;;
;; cx16.r0L = nodesarray[2].weight
;; cx16.r0L = nodes[2].weight
;
;
;;main {
;; sub start() {
;; struct List {
;; bool b
;; uword value
;; }
;;
;; ^^List[10] listarray
;; cx16.r0 = listarray[2].value
;; cx16.r1 = listarray[3]^^.value
;; }
;;}