mirror of
https://github.com/irmen/prog8.git
synced 2025-11-01 22:16:16 +00:00
replace str or ubyte[] param and returnvalue type into ^^ubyte rather than uword
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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>()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user