replace str or ubyte[] param and returnvalue type into ^^ubyte rather than uword

This commit is contained in:
Irmen de Jong
2025-07-21 22:59:14 +02:00
parent 33470c47fc
commit 893e16d814
8 changed files with 52 additions and 22 deletions

View File

@@ -467,7 +467,7 @@ private fun processAst(program: Program, errors: IErrorReporter, compilerOptions
errors.report()
program.constantFold(errors, compilerOptions)
errors.report()
program.reorderStatements(errors)
program.reorderStatements(compilerOptions.compTarget, errors)
errors.report()
program.desugaring(errors, compilerOptions)
errors.report()

View File

@@ -494,8 +494,9 @@ internal class AstChecker(private val program: Program,
errors.err("parameter '${param.first.name}' should be (u)byte or bool", param.first.position)
}
else if(param.second.registerOrPair in arrayOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)) {
if (!param.first.type.isWord && !param.first.type.isString && !param.first.type.isArray)
err("parameter '${param.first.name}' should be (u)word (an address) or str")
if (!param.first.type.isWord && !param.first.type.isString && !param.first.type.isArray && param.first.type!=DataType.pointer(BaseDataType.UBYTE)) {
err("parameter '${param.first.name}' should be (u)word, str or ^^ubyte")
}
}
else if(param.second.statusflag!=null) {
if (!param.first.type.isBool)
@@ -508,8 +509,8 @@ internal class AstChecker(private val program: Program,
err("return type #${index + 1} should be (u)byte")
}
else if(pair.second.registerOrPair in arrayOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)) {
if (!pair.first.isWord && !pair.first.isString && !pair.first.isArray)
err("return type #${index + 1} should be (u)word/address")
if (!pair.first.isWord && !pair.first.isString && !pair.first.isArray && pair.first!=DataType.pointer(BaseDataType.UBYTE))
err("return type #${index + 1} should be (u)word/address or ^^ubyte")
}
else if(pair.second.statusflag!=null) {
if (!pair.first.isBool)

View File

@@ -20,8 +20,8 @@ internal fun Program.checkValid(errors: IErrorReporter, compilerOptions: Compila
checker.visit(this)
}
internal fun Program.reorderStatements(errors: IErrorReporter) {
val reorder = StatementReorderer(this, errors)
internal fun Program.reorderStatements(target: ICompilationTarget, errors: IErrorReporter) {
val reorder = StatementReorderer(this, target, errors)
reorder.visit(this)
if(errors.noErrors()) {
reorder.applyModifications()

View File

@@ -5,13 +5,11 @@ import prog8.ast.expressions.*
import prog8.ast.statements.*
import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification
import prog8.code.core.AssociativeOperators
import prog8.code.core.BaseDataType
import prog8.code.core.DataType
import prog8.code.core.IErrorReporter
import prog8.code.core.*
internal class StatementReorderer(
val program: Program,
val target: ICompilationTarget,
val errors: IErrorReporter
) : AstWalker() {
// Reorders the statements in a way the compiler needs.
@@ -215,16 +213,16 @@ internal class StatementReorderer(
subs.map { IAstModification.InsertLast(it, subroutine) }
}
// change 'str' and 'ubyte[]' parameters into 'uword' (just treat it as an address)
// change 'str' and 'ubyte[]' parameters or return types into ^^ubyte (TODO also for 6502 target, that is still uword for now)
val stringParams = subroutine.parameters.filter { it.type.isString || it.type.isUnsignedByteArray }
val replacementForStrDt = if(target.cpu!=CpuType.VIRTUAL) DataType.UWORD else DataType.pointer(BaseDataType.UBYTE) // TODO fix this once 6502 has pointers too
val parameterChanges = stringParams.map {
val uwordParam = SubroutineParameter(it.name, DataType.UWORD, it.zp, it.registerOrPair, it.position)
val uwordParam = SubroutineParameter(it.name, replacementForStrDt, it.zp, it.registerOrPair, it.position)
IAstModification.ReplaceNode(it, uwordParam, subroutine)
}
// change 'str' and 'ubyte[]' return types into 'uword' (just treat it as an address)
subroutine.returntypes.withIndex().forEach { (index, type) ->
if(type.isString || type.isUnsignedByteArray)
subroutine.returntypes[index] = DataType.UWORD
subroutine.returntypes[index] = replacementForStrDt
}
val varsChanges = mutableListOf<IAstModification>()

View File

@@ -96,7 +96,8 @@ internal class VerifyFunctionArgTypes(val program: Program, val options: Compila
// if uword is passed, check if the parameter type is pointer to array element type
if(argDt.isArray && paramDt.isPointer) {
TODO("array vs element pointer check")
if(argDt.sub==paramDt.sub)
return true
}
// if expected is UWORD and actual is any pointer, we allow it (uword is untyped pointer, for backwards compatibility)

View File

@@ -458,6 +458,36 @@ thing {
// TODO compileText(C64Target(), false, src, outputDir) shouldNotBe null
}
test("str or ubyte array params or return type replaced by pointer to ubyte") {
val src="""
main {
sub start() {
test1("zzz")
test2("zzz")
}
sub test1(str arg) -> str {
cx16.r0++
return cx16.r0
}
sub test2(ubyte[] arg) {
cx16.r0++
}
}"""
// TODO check this for C64 target too
val result = compileText(VMTarget(), false, src, outputDir, writeAssembly = false)!!
val main = result.compilerAst.allBlocks.first {it.name=="main"}
val test1 = main.statements[1] as Subroutine
val test2 = main.statements[2] as Subroutine
test1.name shouldBe "test1"
test1.parameters.single().type shouldBe DataType.pointer(DataType.UBYTE)
test1.returntypes.single() shouldBe DataType.pointer(DataType.UBYTE)
test2.name shouldBe "test2"
test2.parameters.single().type shouldBe DataType.pointer(DataType.UBYTE)
}
test("creating instances") {
val src="""
main {

View File

@@ -752,7 +752,7 @@ main {
errors.errors[3] shouldContain (":9:28: value type uword doesn't match target")
}
test("str replaced with uword in subroutine params and return types") {
test("str replaced with uword in subroutine params and return types (6502 only until that has pointers too)") { // TODO remove this test once 6502 has pointers too
val src = """
main {
sub start() {
@@ -773,13 +773,12 @@ main {
}}
}
}"""
compileText(C64Target(), true, src, outputDir, writeAssembly = true) shouldNotBe null
val result = compileText(VMTarget(), true, src, outputDir, writeAssembly = true)!!
val result = compileText(C64Target(), true, src, outputDir, writeAssembly = true)!!
val main = result.codegenAst!!.allBlocks().first()
val derp = main.children.single { it is PtSub && it.name == "main.derp" } as PtSub
val derp = main.children.single { it is PtSub && it.name == "p8s_derp" } as PtSub
derp.signature.returns shouldBe listOf(DataType.UWORD)
(derp.signature.children.single() as PtSubroutineParameter).type shouldBe DataType.UWORD
val mult3 = main.children.single { it is PtAsmSub && it.name == "main.mult3" } as PtAsmSub
val mult3 = main.children.single { it is PtAsmSub && it.name == "p8s_mult3" } as PtAsmSub
mult3.parameters.single().second.type shouldBe DataType.UWORD
mult3.returns.single().second shouldBe DataType.UWORD
}

View File

@@ -60,7 +60,7 @@ STRUCTS and TYPED POINTERS
- DONE: added peekbool() and pokebool() and pokebowl() boolean peek and poke, the latter is equivalent to pokebool()
- DONE: fixed support for (expression) array index dereferencing "array[2]^^" where array contains pointers to primitives: replace with peek()
- DONE: fixed support for (assigntarget) array index dereferencing "array[2]^^" where array contains pointers to primitives: replace with poke()
- replace str param type into ^^ubyte rather than uword
- DONE: replace str or ubyte[] param and returnvalue type into ^^ubyte rather than uword
- write docs in structpointers.rst
- virtual/sorting.p8 module generates slightly less efficient code than the old version with untyped uword pointers
- add support for array index dereferencing as assign target "array[2]^^.value = 99" where array is struct pointers (currently a 'no support' error)
@@ -71,6 +71,7 @@ STRUCTS and TYPED POINTERS
- 6502 codegen: remove checks in checkForPointerTypesOn6502()
- 6502 codegen should warn about writing to initialized struct instances when using romable code, like with arrays "can only be used as read-only in ROMable code"
- 6502 asm symbol name prefixing should work for dereferences too.
- 6502 statementreorderer: fix todo for str -> ^^ubyte instead of uword
- update structpointers.rst docs with 6502 things?
- 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