fix countries[2]^^ = 0 compiler crash

This commit is contained in:
Irmen de Jong
2025-07-31 02:03:18 +02:00
parent 3d10882f57
commit eb8b408b82
5 changed files with 88 additions and 39 deletions

View File

@@ -688,31 +688,37 @@ _after:
// get rid of ArrayIndexedPtrDereference in the assignment target // get rid of ArrayIndexedPtrDereference in the assignment target
// z[i]^^ = value --> pokeX(z[i], value) // z[i]^^ = value --> pokeX(z[i], value)
val dt = deref.inferType(program).getOrUndef() val dt = deref.inferType(program).getOrUndef()
require(dt.isNumericOrBool) if(dt.isNumericOrBool) {
// if it's something else beside number (like, a struct instance) we don't support rewriting that...
val (pokeFunc, cast) = val (pokeFunc, cast) =
if(dt.isBool) "pokebool" to null if (dt.isBool) "pokebool" to null
else if (dt.isUnsignedByte) "poke" to null else if (dt.isUnsignedByte) "poke" to null
else if (dt.isSignedByte) "poke" to DataType.UBYTE else if (dt.isSignedByte) "poke" to DataType.UBYTE
else if (dt.isUnsignedWord) "pokew" to null else if (dt.isUnsignedWord) "pokew" to null
else if (dt.isSignedWord) "pokew" to DataType.UWORD else if (dt.isSignedWord) "pokew" to DataType.UWORD
else if (dt.isLong) "pokel" to null else if (dt.isLong) "pokel" to null
else if (dt.isFloat) "pokef" to null else if (dt.isFloat) "pokef" to null
else throw FatalAstException("can only deref a numeric or boolean pointer here") else throw FatalAstException("can only deref a numeric or boolean pointer here")
val indexer = deref.chain.last().second!! val indexer = deref.chain.last().second!!
val identifier = IdentifierReference(deref.chain.map { it.first }, deref.position) val identifier = IdentifierReference(deref.chain.map { it.first }, deref.position)
val indexed = ArrayIndexedExpression(identifier, null, indexer, deref.position) val indexed = ArrayIndexedExpression(identifier, null, indexer, deref.position)
val pokeIdent = IdentifierReference(listOf(pokeFunc), deref.position) val pokeIdent = IdentifierReference(listOf(pokeFunc), deref.position)
val assignment = parent.parent as Assignment val assignment = parent.parent as Assignment
val pokeCall: FunctionCallStatement val pokeCall: FunctionCallStatement
if(cast==null) { if (cast == null) {
pokeCall = FunctionCallStatement(pokeIdent, mutableListOf(indexed, assignment.value), false, deref.position) pokeCall = FunctionCallStatement(
pokeIdent,
mutableListOf(indexed, assignment.value),
false,
deref.position
)
} else {
val casted = TypecastExpression(assignment.value, cast, true, deref.position)
pokeCall =
FunctionCallStatement(pokeIdent, mutableListOf(indexed, casted), false, deref.position)
}
return listOf(IAstModification.ReplaceNode(assignment, pokeCall, assignment.parent))
} }
else {
val casted = TypecastExpression(assignment.value, cast, true, deref.position)
pokeCall = FunctionCallStatement(pokeIdent, mutableListOf(indexed, casted), false, deref.position)
}
return listOf(IAstModification.ReplaceNode(assignment, pokeCall, assignment.parent))
} }
else { else {
TODO("cannot translate $deref here ${deref.position}") TODO("cannot translate $deref here ${deref.position}")

View File

@@ -3,6 +3,7 @@ package prog8tests.compiler
import io.kotest.assertions.withClue import io.kotest.assertions.withClue
import io.kotest.core.spec.style.FunSpec import io.kotest.core.spec.style.FunSpec
import io.kotest.engine.spec.tempdir import io.kotest.engine.spec.tempdir
import io.kotest.matchers.comparables.shouldBeGreaterThanOrEqualTo
import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe import io.kotest.matchers.shouldNotBe
import io.kotest.matchers.string.shouldContain import io.kotest.matchers.string.shouldContain
@@ -1159,13 +1160,15 @@ other {
^^List[10] listarray ^^List[10] listarray
listarray[3]^^.value = cx16.r0 listarray[3]^^.value = cx16.r0
listarray[3]^^ = 999 ; cannot assign word value to struct instance
} }
}""" }"""
val errors = ErrorReporterForTests() val errors = ErrorReporterForTests()
compileText(VMTarget(), false, src, outputDir, errors=errors) shouldBe null compileText(VMTarget(), false, src, outputDir, errors=errors) shouldBe null
errors.errors.size shouldBe 2 errors.errors.size shouldBeGreaterThanOrEqualTo 3
errors.errors[0] shouldContain "no support for" errors.errors[0] shouldContain "no support for"
errors.errors[1] shouldContain "no support for" errors.errors[1] shouldContain "no support for"
errors.errors[2] shouldContain "assigning this value to struct instance not supported"
} }
xtest("array indexed assignment parses with and without explicit dereference after struct pointer [IGNORED because it's a parser error right now]") { xtest("array indexed assignment parses with and without explicit dereference after struct pointer [IGNORED because it's a parser error right now]") {

View File

@@ -1728,8 +1728,16 @@ class ArrayIndexedPtrDereference(
val arrayIdentifier = chain.map { it.first } val arrayIdentifier = chain.map { it.first }
val symbol = definingScope.lookup(arrayIdentifier) as? VarDecl val symbol = definingScope.lookup(arrayIdentifier) as? VarDecl
if(symbol!=null) { if(symbol!=null) {
if(symbol.datatype.isArray) if(symbol.datatype.isArray) {
return InferredTypes.knownFor(symbol.datatype.sub!!) if(symbol.datatype.sub!=null)
return InferredTypes.knownFor(symbol.datatype.sub!!)
else if(symbol.datatype.subType!=null) {
val structType = DataType.structInstance(symbol.datatype.subType!!)
return InferredTypes.knownFor(structType)
}
else
return InferredTypes.unknown()
}
else if(symbol.datatype.isPointer) else if(symbol.datatype.isPointer)
return InferredTypes.knownFor(symbol.datatype.dereference()) return InferredTypes.knownFor(symbol.datatype.dereference())
} }

View File

@@ -3,7 +3,6 @@ TODO
fix ^^Node nodes / cx16.r0L = nodes[2].weight (TODO("IR datatype for struct instances") fix ^^Node nodes / cx16.r0L = nodes[2].weight (TODO("IR datatype for struct instances")
fix bool bb2 = bptr[2]^^ ... peekbool(bptr[2]) gives a arg 1 type error... just omit peekbool() here? fix bool bb2 = bptr[2]^^ ... peekbool(bptr[2]) gives a arg 1 type error... just omit peekbool() here?
fix countries[2]^^ = 0 compiler crash
fix passing array of structptrs to subroutine , arg type mismatches fix passing array of structptrs to subroutine , arg type mismatches
disallow ^^str disallow ^^str

View File

@@ -1,19 +1,52 @@
main { main {
struct Node {
bool flag
}
^^Node[10] ptrs
sub start() { sub start() {
struct Node { ptrs[2]^^ = 999 ; should be normal compiler error
ubyte weight
}
^^Node nodes
^^Node[10] array
^^bool bptr
bool bb1 = bptr[2]
bool bb2 = bptr[2]^^ ; TODO fix this ... peekbool(bptr[2]) gives a arg 1 type error... just omit peekbool() here?
cx16.r0L = array[2].weight
cx16.r1L = nodes[2].weight ; TODO implement support for this one
} }
} }
;%import textio
;
;main {
; bool bb1, bb2
;
; sub start() {
;; struct Node {
;; ubyte weight
;; }
;; ^^Node nodes
;; ^^Node[10] array
; ^^bool bptr = 2000
; bb1 = bptr[2]
; bb2 = bptr[2]^^ ; TODO fix this ... peekbool(bptr[2]) gives a arg 1 type error... just omit peekbool() here?
;
; bb1 = thing.routine.bptrx[2]
; bb2 = thing.routine.bptrx[2]^^ ; TODO fix this ... peekbool(bptr[2]) gives a arg 1 type error... just omit peekbool() here?
;
; bptr[2] = false
; bptr[3]^^ = false
; thing.routine.bptrx[2] = false
; thing.routine.bptrx[3]^^ = false
;
;
;; cx16.r0L = array[2].weight
;; cx16.r1L = nodes[2].weight ; TODO implement support for this one
; }
;}
;
;thing {
; sub routine() {
; ^^bool @shared bptrx = 3000
; }
;}
;%import floats ;%import floats
;%import textio ;%import textio
; ;