mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
fix an array literal assignment type error for word arrays
This commit is contained in:
parent
b9d8ec1463
commit
bb9d29b061
@ -1539,6 +1539,7 @@ internal class AstChecker(private val program: Program,
|
||||
when (it) {
|
||||
is NumericLiteral -> it.number.toInt()
|
||||
is AddressOf -> it.identifier.hashCode() and 0xffff
|
||||
is IdentifierReference -> it.hashCode() and 0xffff
|
||||
is TypecastExpression -> {
|
||||
val constVal = it.expression.constValue(program)
|
||||
val cast = constVal?.cast(it.type)
|
||||
|
@ -433,7 +433,12 @@ class IntermediateAstMaker(private val program: Program, private val options: Co
|
||||
|
||||
private fun transform(src: AddressOf): PtAddressOf {
|
||||
val addr = PtAddressOf(src.position)
|
||||
addr.add(transform(src.identifier))
|
||||
val (name, dt) = src.identifier.targetNameAndType(program)
|
||||
if(dt in SplitWordArrayTypes) {
|
||||
addr.add(PtIdentifier(name+"_lsb", dt, src.identifier.position))
|
||||
} else {
|
||||
addr.add(transform(src.identifier))
|
||||
}
|
||||
return addr
|
||||
}
|
||||
|
||||
|
@ -7,14 +7,12 @@ import prog8.ast.expressions.ArrayLiteral
|
||||
import prog8.ast.expressions.BinaryExpression
|
||||
import prog8.ast.expressions.IdentifierReference
|
||||
import prog8.ast.expressions.StringLiteral
|
||||
import prog8.ast.statements.Assignment
|
||||
import prog8.ast.statements.VarDecl
|
||||
import prog8.ast.statements.WhenChoice
|
||||
import prog8.ast.walk.AstWalker
|
||||
import prog8.ast.walk.IAstModification
|
||||
import prog8.code.core.DataType
|
||||
import prog8.code.core.Encoding
|
||||
import prog8.code.core.ICompilationTarget
|
||||
import prog8.code.core.IErrorReporter
|
||||
import prog8.code.core.*
|
||||
|
||||
|
||||
internal class LiteralsToAutoVars(private val program: Program,
|
||||
@ -60,10 +58,12 @@ internal class LiteralsToAutoVars(private val program: Program,
|
||||
} else {
|
||||
val arrayDt = array.guessDatatype(program)
|
||||
if(arrayDt.isKnown) {
|
||||
val parentAssign = parent as? Assignment
|
||||
val targetDt = parentAssign?.target?.inferType(program) ?: arrayDt
|
||||
// turn the array literal it into an identifier reference
|
||||
val litval2 = array.cast(arrayDt.getOr(DataType.UNDEFINED))
|
||||
val litval2 = array.cast(targetDt.getOr(DataType.UNDEFINED))
|
||||
if(litval2!=null) {
|
||||
val vardecl2 = VarDecl.createAuto(litval2)
|
||||
val vardecl2 = VarDecl.createAuto(litval2, targetDt.getOr(DataType.UNDEFINED) in SplitWordArrayTypes)
|
||||
val identifier = IdentifierReference(listOf(vardecl2.name), vardecl2.position)
|
||||
return listOf(
|
||||
IAstModification.ReplaceNode(array, identifier, parent),
|
||||
|
@ -291,8 +291,10 @@ internal class StatementReorderer(val program: Program,
|
||||
} else {
|
||||
if (sourceVar.arraysize!!.constIndex() != targetVar.arraysize!!.constIndex())
|
||||
errors.err("element count mismatch", assign.position)
|
||||
if (sourceVar.datatype != targetVar.datatype)
|
||||
errors.err("element type mismatch", assign.position)
|
||||
if (sourceVar.datatype != targetVar.datatype) {
|
||||
if(!targetVar.splitArray || (sourceVar.datatype!=DataType.ARRAY_W && sourceVar.datatype!=DataType.ARRAY_UW))
|
||||
errors.err("element type mismatch", assign.position)
|
||||
}
|
||||
}
|
||||
|
||||
if(!errors.noErrors())
|
||||
|
@ -26,7 +26,7 @@ class TestSubroutines: FunSpec({
|
||||
|
||||
sub start() {
|
||||
func("abc")
|
||||
uword[] commands = ["abc", func]
|
||||
uword[] commands = ["abc", 1.234]
|
||||
}
|
||||
}"""
|
||||
val errors = ErrorReporterForTests()
|
||||
|
@ -4,7 +4,6 @@ import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.kotest.matchers.shouldNotBe
|
||||
import io.kotest.matchers.string.shouldContain
|
||||
import prog8.code.ast.printAst
|
||||
import prog8.code.target.C64Target
|
||||
import prog8.code.target.VMTarget
|
||||
import prog8tests.helpers.ErrorReporterForTests
|
||||
@ -130,10 +129,23 @@ main {
|
||||
}}
|
||||
}
|
||||
}"""
|
||||
val result6502 = compileText(C64Target(), false, text, writeAssembly = true)!!.codegenAst!!
|
||||
val resultVm = compileText(VMTarget(), false, text, writeAssembly = true)!!.codegenAst!!
|
||||
printAst(result6502, true, ::println)
|
||||
printAst(resultVm, true, ::println)
|
||||
compileText(C64Target(), false, text, writeAssembly = true) shouldNotBe null
|
||||
compileText(VMTarget(), false, text, writeAssembly = true) shouldNotBe null
|
||||
}
|
||||
|
||||
test("split array assignments") {
|
||||
val text = """
|
||||
main {
|
||||
sub start() {
|
||||
str name1 = "name1"
|
||||
str name2 = "name2"
|
||||
uword[] @split names = [name1, name2, "name3"]
|
||||
cx16.r0++
|
||||
names = [1111,2222,3333]
|
||||
}
|
||||
}"""
|
||||
compileText(C64Target(), false, text, writeAssembly = true) shouldNotBe null
|
||||
compileText(VMTarget(), false, text, writeAssembly = true) shouldNotBe null
|
||||
}
|
||||
})
|
||||
|
@ -782,22 +782,42 @@ class ArrayLiteral(val type: InferredTypes.InferredType, // inferred because
|
||||
return this
|
||||
if(targettype in ArrayDatatypes) {
|
||||
val elementType = ArrayToElementTypes.getValue(targettype)
|
||||
val castArray = value.map{
|
||||
val num = it as? NumericLiteral
|
||||
if(num==null) {
|
||||
// an array of UWORDs could possibly also contain AddressOfs, other stuff can't be typecasted
|
||||
if (elementType != DataType.UWORD || it !is AddressOf)
|
||||
return null // can't cast a value of the array, abort
|
||||
it
|
||||
} else {
|
||||
val cast = num.cast(elementType)
|
||||
|
||||
// if all values are numeric literals, just do the cast.
|
||||
// if not:
|
||||
// if all values are numeric literals OR addressof OR identifiers, and the target type is WORD or UWORD,
|
||||
// do the cast for the numeric literals and leave the rest.
|
||||
// otherwise: return null (cast cannot be done)
|
||||
|
||||
if(value.all { it is NumericLiteral }) {
|
||||
val castArray = value.map {
|
||||
val cast = (it as NumericLiteral).cast(elementType)
|
||||
if(cast.isValid)
|
||||
cast.valueOrZero()
|
||||
cast.valueOrZero() as Expression
|
||||
else
|
||||
return null // can't cast a value of the array, abort
|
||||
}
|
||||
}.toTypedArray()
|
||||
return ArrayLiteral(InferredTypes.InferredType.known(targettype), castArray, position = position)
|
||||
return null // abort
|
||||
}.toTypedArray()
|
||||
return ArrayLiteral(InferredTypes.InferredType.known(targettype), castArray, position = position)
|
||||
}
|
||||
else if(elementType in WordDatatypes && value.all { it is NumericLiteral || it is AddressOf || it is IdentifierReference}) {
|
||||
val castArray = value.map {
|
||||
when(it) {
|
||||
is AddressOf -> it as Expression
|
||||
is IdentifierReference -> it as Expression
|
||||
is NumericLiteral -> {
|
||||
val numcast = it.cast(elementType)
|
||||
if(numcast.isValid)
|
||||
numcast.valueOrZero() as Expression
|
||||
else
|
||||
return null // abort
|
||||
}
|
||||
else -> return null // abort
|
||||
}
|
||||
}.toTypedArray()
|
||||
return ArrayLiteral(InferredTypes.InferredType.known(targettype), castArray, position = position)
|
||||
}
|
||||
else
|
||||
return null
|
||||
}
|
||||
return null // invalid type conversion from $this to $targettype
|
||||
}
|
||||
|
@ -216,13 +216,13 @@ class VarDecl(val type: VarDeclType,
|
||||
)
|
||||
}
|
||||
|
||||
fun createAuto(array: ArrayLiteral): VarDecl {
|
||||
fun createAuto(array: ArrayLiteral, splitArray: Boolean): VarDecl {
|
||||
val autoVarName = "auto_heap_value_${++autoHeapValueSequenceNumber}"
|
||||
val arrayDt = array.type.getOrElse { throw FatalAstException("unknown dt") }
|
||||
val declaredType = ArrayToElementTypes.getValue(arrayDt)
|
||||
val arraysize = ArrayIndex.forArray(array)
|
||||
return VarDecl(VarDeclType.VAR, VarDeclOrigin.ARRAYLITERAL, declaredType, ZeropageWish.NOT_IN_ZEROPAGE, arraysize, autoVarName, array,
|
||||
isArray = true, sharedWithAsm = false, splitArray = false, position = array.position)
|
||||
isArray = true, sharedWithAsm = false, splitArray = splitArray, position = array.position)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
%import floats
|
||||
%import textio
|
||||
%zeropage basicsafe
|
||||
%option no_sysinit
|
||||
@ -6,29 +5,11 @@
|
||||
main {
|
||||
|
||||
sub start() {
|
||||
uword[] split_uwords = [12345, 60000, 4096]
|
||||
word[] split_words = [12345, -6000, 4096]
|
||||
float[] floats = [1.1,2.2,3.3]
|
||||
reverse(split_uwords)
|
||||
reverse(split_words)
|
||||
reverse(floats)
|
||||
uword ww
|
||||
for ww in split_uwords {
|
||||
txt.print_uw(ww)
|
||||
txt.spc()
|
||||
}
|
||||
txt.nl()
|
||||
word sw
|
||||
for sw in split_words {
|
||||
txt.print_w(sw)
|
||||
txt.spc()
|
||||
}
|
||||
txt.nl()
|
||||
ubyte ix
|
||||
for ix in 0 to len(floats)-1 {
|
||||
floats.print_f(floats[ix])
|
||||
txt.spc()
|
||||
}
|
||||
str name1 = "name1"
|
||||
str name2 = "name2"
|
||||
uword[] @split names = [name1, name2, "name3"]
|
||||
cx16.r0++
|
||||
names = [1111,2222,3333]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -326,9 +326,16 @@ class VmProgramLoader {
|
||||
}
|
||||
in SplitWordArrayTypes -> {
|
||||
for(elt in it) {
|
||||
val number = elt.number!!.toInt().toUInt()
|
||||
val number = if(elt.addressOfSymbol!=null) {
|
||||
val name = elt.addressOfSymbol!!
|
||||
val symbolAddress = symbolAddresses[name]
|
||||
?: throw IRParseException("vm cannot yet load a label address as a value: $name") // TODO
|
||||
symbolAddress.toUInt()
|
||||
} else {
|
||||
elt.number!!.toInt().toUInt()
|
||||
}
|
||||
memory.setUB(addr, (number and 255u).toUByte())
|
||||
memory.setUB(addr+variable.length!!, (number shr 8).toUByte())
|
||||
memory.setUB(addr + variable.length!!, (number shr 8).toUByte())
|
||||
addr++
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user