mirror of
https://github.com/irmen/prog8.git
synced 2025-11-24 06:17:39 +00:00
support word size indexing on typed pointers
This commit is contained in:
@@ -719,6 +719,8 @@ class AsmGen6502Internal (
|
|||||||
val reg = register.toString().lowercase()
|
val reg = register.toString().lowercase()
|
||||||
val indexnum = expr.index.asConstInteger()
|
val indexnum = expr.index.asConstInteger()
|
||||||
if (indexnum != null) {
|
if (indexnum != null) {
|
||||||
|
if(indexnum > 255)
|
||||||
|
throw AssemblyError("array index $indexnum is larger than a byte ${expr.position}")
|
||||||
val indexValue = if(expr.splitWords)
|
val indexValue = if(expr.splitWords)
|
||||||
indexnum
|
indexnum
|
||||||
else
|
else
|
||||||
@@ -727,6 +729,9 @@ class AsmGen6502Internal (
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!expr.index.type.isByte)
|
||||||
|
throw AssemblyError("array index $indexnum is larger than a byte ${expr.position}")
|
||||||
|
|
||||||
if(expr.splitWords) {
|
if(expr.splitWords) {
|
||||||
assignExpressionToRegister(expr.index, RegisterOrPair.fromCpuRegister(register))
|
assignExpressionToRegister(expr.index, RegisterOrPair.fromCpuRegister(register))
|
||||||
return
|
return
|
||||||
@@ -806,15 +811,15 @@ class AsmGen6502Internal (
|
|||||||
when(target.kind) {
|
when(target.kind) {
|
||||||
TargetStorageKind.VARIABLE -> {
|
TargetStorageKind.VARIABLE -> {
|
||||||
if (isTargetCpu(CpuType.CPU6502))
|
if (isTargetCpu(CpuType.CPU6502))
|
||||||
out("lda #0 | sta ${target.asmVarname}")
|
out(" lda #0 | sta ${target.asmVarname}")
|
||||||
else
|
else
|
||||||
out("stz ${target.asmVarname}")
|
out(" stz ${target.asmVarname}")
|
||||||
}
|
}
|
||||||
TargetStorageKind.MEMORY -> {
|
TargetStorageKind.MEMORY -> {
|
||||||
val address = target.memory!!.address.asConstInteger()
|
val address = target.memory!!.address.asConstInteger()
|
||||||
if(address!=null) {
|
if(address!=null) {
|
||||||
if (isTargetCpu(CpuType.CPU6502))
|
if (isTargetCpu(CpuType.CPU6502))
|
||||||
out("lda #0 | sta ${address.toHex()}")
|
out(" lda #0 | sta ${address.toHex()}")
|
||||||
else
|
else
|
||||||
out(" stz ${address.toHex()}")
|
out(" stz ${address.toHex()}")
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -3606,7 +3606,9 @@ $endLabel""")
|
|||||||
if(indexVar!=null) {
|
if(indexVar!=null) {
|
||||||
asmgen.out(" ldy ${asmgen.asmVariableName(indexVar)} | sta ${target.asmVarname},y")
|
asmgen.out(" ldy ${asmgen.asmVariableName(indexVar)} | sta ${target.asmVarname},y")
|
||||||
} else {
|
} else {
|
||||||
require(target.array.index.type.isByteOrBool)
|
require(target.array.index.type.isByte) {
|
||||||
|
"wot"
|
||||||
|
}
|
||||||
asmgen.saveRegisterStack(register, false)
|
asmgen.saveRegisterStack(register, false)
|
||||||
asmgen.assignExpressionToRegister(target.array.index, RegisterOrPair.Y)
|
asmgen.assignExpressionToRegister(target.array.index, RegisterOrPair.Y)
|
||||||
asmgen.out(" pla | sta ${target.asmVarname},y")
|
asmgen.out(" pla | sta ${target.asmVarname},y")
|
||||||
|
|||||||
@@ -1594,8 +1594,15 @@ internal class AstChecker(private val program: Program,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (leftDt.isBool || rightDt.isBool) {
|
if (leftDt.isBool || rightDt.isBool) {
|
||||||
if(expr.operator!="==" && expr.operator!="!=")
|
if(expr.operator!="==" && expr.operator!="!=") {
|
||||||
errors.err("operator requires numeric operands", expr.right.position)
|
val msg = when(expr.operator) {
|
||||||
|
"^" -> "operator requires numeric operands, did you mean logical 'xor'?"
|
||||||
|
"&" -> "operator requires numeric operands, did you mean logical 'and'?"
|
||||||
|
"|" -> "operator requires numeric operands, did you mean logical 'or'?"
|
||||||
|
else -> "operator requires numeric operands"
|
||||||
|
}
|
||||||
|
errors.err(msg, expr.right.position)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -240,6 +240,7 @@ _after:
|
|||||||
override fun after(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> {
|
override fun after(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> {
|
||||||
// replace pointervar[word] by @(pointervar+word) to avoid the
|
// replace pointervar[word] by @(pointervar+word) to avoid the
|
||||||
// "array indexing is limited to byte size 0..255" error for pointervariables.
|
// "array indexing is limited to byte size 0..255" error for pointervariables.
|
||||||
|
// (uses pokew or pokef if the ointer is a word or float pointer).
|
||||||
|
|
||||||
if(arrayIndexedExpression.pointerderef!=null) {
|
if(arrayIndexedExpression.pointerderef!=null) {
|
||||||
return noModifications
|
return noModifications
|
||||||
@@ -247,7 +248,7 @@ _after:
|
|||||||
|
|
||||||
val indexExpr = arrayIndexedExpression.indexer.indexExpr
|
val indexExpr = arrayIndexedExpression.indexer.indexExpr
|
||||||
val arrayVar = arrayIndexedExpression.plainarrayvar!!.targetVarDecl()
|
val arrayVar = arrayIndexedExpression.plainarrayvar!!.targetVarDecl()
|
||||||
if(arrayVar!=null && (arrayVar.datatype.isUnsignedWord || (arrayVar.datatype.isPointer && arrayVar.datatype.sub==BaseDataType.UBYTE))) {
|
if(arrayVar!=null && (arrayVar.datatype.isUnsignedWord || arrayVar.datatype.isPointer)) {
|
||||||
val wordIndex = TypecastExpression(indexExpr, DataType.UWORD, true, indexExpr.position)
|
val wordIndex = TypecastExpression(indexExpr, DataType.UWORD, true, indexExpr.position)
|
||||||
val address = BinaryExpression(
|
val address = BinaryExpression(
|
||||||
arrayIndexedExpression.plainarrayvar!!.copy(),
|
arrayIndexedExpression.plainarrayvar!!.copy(),
|
||||||
@@ -255,22 +256,58 @@ _after:
|
|||||||
wordIndex,
|
wordIndex,
|
||||||
arrayIndexedExpression.position
|
arrayIndexedExpression.position
|
||||||
)
|
)
|
||||||
|
if(arrayVar.datatype.isUnsignedWord || arrayVar.datatype.sub?.isByte==true) {
|
||||||
return if (parent is AssignTarget) {
|
return if (parent is AssignTarget) {
|
||||||
// assignment to array
|
// assignment to array
|
||||||
val memwrite = DirectMemoryWrite(address, arrayIndexedExpression.position)
|
val memwrite = DirectMemoryWrite(address, arrayIndexedExpression.position)
|
||||||
val newtarget = AssignTarget(
|
val newtarget = AssignTarget(null, null, memwrite, null, false, position = arrayIndexedExpression.position)
|
||||||
null,
|
|
||||||
null,
|
|
||||||
memwrite,
|
|
||||||
null,
|
|
||||||
false,
|
|
||||||
position = arrayIndexedExpression.position
|
|
||||||
)
|
|
||||||
listOf(IAstModification.ReplaceNode(parent, newtarget, parent.parent))
|
listOf(IAstModification.ReplaceNode(parent, newtarget, parent.parent))
|
||||||
} else {
|
} else {
|
||||||
// read from array
|
// read from array
|
||||||
val memread = DirectMemoryRead(address, arrayIndexedExpression.position)
|
val memread = DirectMemoryRead(address, arrayIndexedExpression.position)
|
||||||
listOf(IAstModification.ReplaceNode(arrayIndexedExpression, memread, parent))
|
val replacement = if(arrayVar.datatype.sub?.isSigned==true)
|
||||||
|
TypecastExpression(memread, DataType.BYTE, true, memread.position)
|
||||||
|
else
|
||||||
|
memread
|
||||||
|
listOf(IAstModification.ReplaceNode(arrayIndexedExpression, replacement, parent))
|
||||||
|
}
|
||||||
|
} else if(arrayVar.datatype.sub?.isWord==true) {
|
||||||
|
// use peekw/pokew
|
||||||
|
if(parent is AssignTarget) {
|
||||||
|
val assignment = parent.parent as Assignment
|
||||||
|
val args = mutableListOf(address, assignment.value)
|
||||||
|
val poke = FunctionCallStatement(IdentifierReference(listOf("pokew"), arrayIndexedExpression.position), args, false, arrayIndexedExpression.position)
|
||||||
|
return listOf(IAstModification.ReplaceNode(assignment, poke, assignment.parent))
|
||||||
|
} else {
|
||||||
|
val peek = FunctionCallExpression(IdentifierReference(listOf("peekw"), arrayIndexedExpression.position), mutableListOf(address), arrayIndexedExpression.position)
|
||||||
|
val replacement = if(arrayVar.datatype.sub?.isSigned==true)
|
||||||
|
TypecastExpression(peek, DataType.WORD, true, peek.position)
|
||||||
|
else
|
||||||
|
peek
|
||||||
|
return listOf(IAstModification.ReplaceNode(arrayIndexedExpression, replacement, parent))
|
||||||
|
}
|
||||||
|
} else if(arrayVar.datatype.sub==BaseDataType.BOOL) {
|
||||||
|
// use peekbool/pokebool
|
||||||
|
if(parent is AssignTarget) {
|
||||||
|
val assignment = parent.parent as Assignment
|
||||||
|
val args = mutableListOf(address, assignment.value)
|
||||||
|
val poke = FunctionCallStatement(IdentifierReference(listOf("pokebool"), arrayIndexedExpression.position), args, false, arrayIndexedExpression.position)
|
||||||
|
return listOf(IAstModification.ReplaceNode(assignment, poke, assignment.parent))
|
||||||
|
} else {
|
||||||
|
val peek = FunctionCallExpression(IdentifierReference(listOf("peekbool"), arrayIndexedExpression.position), mutableListOf(address), arrayIndexedExpression.position)
|
||||||
|
return listOf(IAstModification.ReplaceNode(arrayIndexedExpression, peek, parent))
|
||||||
|
}
|
||||||
|
} else if(arrayVar.datatype.sub==BaseDataType.FLOAT) {
|
||||||
|
// use peekf/pokef
|
||||||
|
if(parent is AssignTarget) {
|
||||||
|
val assignment = parent.parent as Assignment
|
||||||
|
val args = mutableListOf(address, assignment.value)
|
||||||
|
val poke = FunctionCallStatement(IdentifierReference(listOf("pokef"), arrayIndexedExpression.position), args, false, arrayIndexedExpression.position)
|
||||||
|
return listOf(IAstModification.ReplaceNode(assignment, poke, assignment.parent))
|
||||||
|
} else {
|
||||||
|
val peek = FunctionCallExpression(IdentifierReference(listOf("peekf"), arrayIndexedExpression.position), mutableListOf(address), arrayIndexedExpression.position)
|
||||||
|
return listOf(IAstModification.ReplaceNode(arrayIndexedExpression, peek, parent))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if(arrayVar!=null && (arrayVar.type==VarDeclType.MEMORY || arrayVar.datatype.isString || arrayVar.datatype.isPointer || arrayVar.datatype.isArray)) {
|
} else if(arrayVar!=null && (arrayVar.type==VarDeclType.MEMORY || arrayVar.datatype.isString || arrayVar.datatype.isPointer || arrayVar.datatype.isArray)) {
|
||||||
return noModifications
|
return noModifications
|
||||||
|
|||||||
@@ -840,7 +840,7 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
|
|||||||
// don't multiply simply shift
|
// don't multiply simply shift
|
||||||
offset = PtBinaryExpression("<<", DataType.UWORD, expr.position)
|
offset = PtBinaryExpression("<<", DataType.UWORD, expr.position)
|
||||||
offset.add(transformExpression(expr.right))
|
offset.add(transformExpression(expr.right))
|
||||||
offset.add(PtNumber(BaseDataType.UWORD, log2(structSize.toDouble()), expr.position))
|
offset.add(PtNumber(BaseDataType.UBYTE, log2(structSize.toDouble()), expr.position))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
offset = PtBinaryExpression("*", DataType.UWORD, expr.position)
|
offset = PtBinaryExpression("*", DataType.UWORD, expr.position)
|
||||||
|
|||||||
@@ -332,11 +332,11 @@ main {
|
|||||||
st.size shouldBe 27
|
st.size shouldBe 27
|
||||||
|
|
||||||
val a_zz = (st[20] as Assignment).value
|
val a_zz = (st[20] as Assignment).value
|
||||||
a_zz shouldBe instanceOf<ArrayIndexedExpression>()
|
a_zz shouldBe instanceOf<FunctionCallExpression>()
|
||||||
val a_fl = (st[21] as Assignment).value
|
val a_fl = (st[21] as Assignment).value
|
||||||
a_fl shouldBe instanceOf<ArrayIndexedExpression>()
|
a_fl shouldBe instanceOf<FunctionCallExpression>()
|
||||||
val a_bb = (st[22] as Assignment).value
|
val a_bb = (st[22] as Assignment).value
|
||||||
a_bb shouldBe instanceOf<ArrayIndexedExpression>()
|
a_bb shouldBe instanceOf<DirectMemoryRead>()
|
||||||
val a_r0 = (st[23] as Assignment).value
|
val a_r0 = (st[23] as Assignment).value
|
||||||
a_r0 shouldBe instanceOf<DirectMemoryRead>()
|
a_r0 shouldBe instanceOf<DirectMemoryRead>()
|
||||||
val a_r1 = (st[24] as Assignment).value
|
val a_r1 = (st[24] as Assignment).value
|
||||||
@@ -885,28 +885,6 @@ main {
|
|||||||
compileText(Cx16Target(), false, src, outputDir) shouldNotBe null
|
compileText(Cx16Target(), false, src, outputDir) shouldNotBe null
|
||||||
}
|
}
|
||||||
|
|
||||||
test("uword as pointer versus pointer to uword difference") {
|
|
||||||
val src="""
|
|
||||||
main {
|
|
||||||
sub start() {
|
|
||||||
uword @shared ptr1
|
|
||||||
^^uword @shared ptr2
|
|
||||||
|
|
||||||
ptr1[2] = 1
|
|
||||||
ptr2[2] = 1
|
|
||||||
}
|
|
||||||
}"""
|
|
||||||
|
|
||||||
compileText(C64Target(), false, src, outputDir) shouldNotBe null
|
|
||||||
val result = compileText(VMTarget(), false, src, outputDir)!!
|
|
||||||
val st = result.codegenAst!!.entrypoint()!!.children
|
|
||||||
st.size shouldBe 8
|
|
||||||
val a1 = st[5] as PtAssignment
|
|
||||||
val a2 = st[6] as PtAssignment
|
|
||||||
a1.target.memory shouldNotBe null
|
|
||||||
a2.target.array shouldNotBe null
|
|
||||||
}
|
|
||||||
|
|
||||||
test("array indexing on non pointer fields give correct error messages") {
|
test("array indexing on non pointer fields give correct error messages") {
|
||||||
val src="""
|
val src="""
|
||||||
main {
|
main {
|
||||||
@@ -1021,15 +999,15 @@ main {
|
|||||||
val dr7 = (st[17] as Assignment).target.pointerDereference!!
|
val dr7 = (st[17] as Assignment).target.pointerDereference!!
|
||||||
val dr8 = (st[18] as Assignment).target.pointerDereference!!
|
val dr8 = (st[18] as Assignment).target.pointerDereference!!
|
||||||
|
|
||||||
val dr9 = (st[19] as Assignment).value as PtrDereference
|
val dr9 = (st[19] as Assignment).value as FunctionCallExpression
|
||||||
val dr10 = (st[20] as Assignment).value as PtrDereference
|
val dr10 = (st[20] as Assignment).value as PtrDereference
|
||||||
val dr11 = (st[21] as Assignment).target.pointerDereference!!
|
val dr11 = (st[21] as Assignment).target.pointerDereference!!
|
||||||
val dr12 = (st[22] as Assignment).target.pointerDereference!!
|
(st[22] as FunctionCallStatement).target.nameInSource shouldBe listOf("pokew")
|
||||||
|
|
||||||
val dr13 = (st[23] as Assignment).value as PtrDereference
|
val dr13 = (st[23] as Assignment).value as PtrDereference
|
||||||
val dr14 = (st[24] as Assignment).value as PtrDereference
|
((st[24] as Assignment).value as FunctionCallExpression).target.nameInSource shouldBe listOf("peekf")
|
||||||
val dr15 = (st[25] as Assignment).target.pointerDereference!!
|
val dr15 = (st[25] as Assignment).target.pointerDereference!!
|
||||||
val dr16 = (st[26] as Assignment).target.pointerDereference!!
|
(st[26] as FunctionCallStatement).target.nameInSource shouldBe listOf("pokef")
|
||||||
|
|
||||||
dr0.chain shouldBe listOf("l1", "s")
|
dr0.chain shouldBe listOf("l1", "s")
|
||||||
dr0.derefLast shouldBe true
|
dr0.derefLast shouldBe true
|
||||||
@@ -1051,23 +1029,16 @@ main {
|
|||||||
dr8.chain shouldBe listOf("l1", "s")
|
dr8.chain shouldBe listOf("l1", "s")
|
||||||
dr8.derefLast shouldBe true
|
dr8.derefLast shouldBe true
|
||||||
|
|
||||||
dr9.chain shouldBe listOf("wptr")
|
dr9.target.nameInSource shouldBe listOf("peekw")
|
||||||
dr9.derefLast shouldBe true
|
|
||||||
dr10.chain shouldBe listOf("wptr")
|
dr10.chain shouldBe listOf("wptr")
|
||||||
dr10.derefLast shouldBe true
|
dr10.derefLast shouldBe true
|
||||||
dr11.chain shouldBe listOf("wptr")
|
dr11.chain shouldBe listOf("wptr")
|
||||||
dr11.derefLast shouldBe true
|
dr11.derefLast shouldBe true
|
||||||
dr12.chain shouldBe listOf("wptr")
|
|
||||||
dr12.derefLast shouldBe true
|
|
||||||
|
|
||||||
dr13.chain shouldBe listOf("fptr")
|
dr13.chain shouldBe listOf("fptr")
|
||||||
dr13.derefLast shouldBe true
|
dr13.derefLast shouldBe true
|
||||||
dr14.chain shouldBe listOf("fptr")
|
|
||||||
dr14.derefLast shouldBe true
|
|
||||||
dr15.chain shouldBe listOf("fptr")
|
dr15.chain shouldBe listOf("fptr")
|
||||||
dr15.derefLast shouldBe true
|
dr15.derefLast shouldBe true
|
||||||
dr16.chain shouldBe listOf("fptr")
|
|
||||||
dr16.derefLast shouldBe true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test("global and local pointer vars") {
|
test("global and local pointer vars") {
|
||||||
@@ -1721,6 +1692,84 @@ main {
|
|||||||
compileText(Cx16Target(), false, src, outputDir) shouldNotBe null
|
compileText(Cx16Target(), false, src, outputDir) shouldNotBe null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test("array indexing on a pointer with a word size index works") {
|
||||||
|
val src="""
|
||||||
|
%import floats
|
||||||
|
|
||||||
|
main {
|
||||||
|
sub start() {
|
||||||
|
^^ubyte @shared ptr1 = $4000
|
||||||
|
^^uword @shared ptr2 = $4000
|
||||||
|
^^float @shared ptr3 = $4000
|
||||||
|
^^bool @shared ptr4 = $4000
|
||||||
|
uword @shared untyped = $4000
|
||||||
|
float @shared fl
|
||||||
|
bool @shared bb, bb2
|
||||||
|
|
||||||
|
untyped[$1000] = 0
|
||||||
|
ptr1[$1000] = 0
|
||||||
|
ptr2[$1000] = 0
|
||||||
|
ptr3[$1000] = 0
|
||||||
|
ptr4[$1000] = false
|
||||||
|
untyped[$1000] = 99
|
||||||
|
ptr1[$1000] = 99
|
||||||
|
ptr2[$1000] = 99
|
||||||
|
ptr3[$1000] = 99
|
||||||
|
ptr4[$1000] = true
|
||||||
|
untyped[$1000] = cx16.r0L
|
||||||
|
ptr1[$1000] = cx16.r0L
|
||||||
|
ptr2[$1000] = cx16.r0L
|
||||||
|
ptr3[$1000] = fl
|
||||||
|
ptr4[$1000] = bb
|
||||||
|
untyped[$1000] = cx16.r0L+1
|
||||||
|
ptr1[$1000] = cx16.r0L+1
|
||||||
|
ptr2[$1000] = cx16.r0L+1
|
||||||
|
ptr3[$1000] = fl+1.1
|
||||||
|
ptr4[$1000] = bb xor bb2
|
||||||
|
|
||||||
|
untyped[$1000 + cx16.r0] = 0
|
||||||
|
ptr1[$1000 + cx16.r0] = 0
|
||||||
|
ptr2[$1000 + cx16.r0] = 0
|
||||||
|
ptr3[$1000 + cx16.r0] = 0
|
||||||
|
ptr4[$1000 + cx16.r0] = false
|
||||||
|
untyped[$1000 + cx16.r0] = 99
|
||||||
|
ptr1[$1000 + cx16.r0] = 99
|
||||||
|
ptr2[$1000 + cx16.r0] = 99
|
||||||
|
ptr3[$1000 + cx16.r0] = 99
|
||||||
|
ptr4[$1000 + cx16.r0] = true
|
||||||
|
untyped[$1000 + cx16.r0] = cx16.r0L
|
||||||
|
ptr1[$1000 + cx16.r0] = cx16.r0L
|
||||||
|
ptr2[$1000 + cx16.r0] = cx16.r0L
|
||||||
|
ptr3[$1000 + cx16.r0] = fl
|
||||||
|
ptr4[$1000 + cx16.r0] = bb
|
||||||
|
untyped[$1000 + cx16.r0] = cx16.r0L+1
|
||||||
|
ptr1[$1000 + cx16.r0] = cx16.r0L+1
|
||||||
|
ptr2[$1000 + cx16.r0] = cx16.r0L+1
|
||||||
|
ptr3[$1000 + cx16.r0] = fl+1.1
|
||||||
|
ptr4[$1000 + cx16.r0] = bb xor bb2
|
||||||
|
|
||||||
|
cx16.r0L = untyped[$1000]
|
||||||
|
cx16.r1L = ptr1[$1000]
|
||||||
|
cx16.r2 = ptr2[$1000]
|
||||||
|
fl = ptr3[$1000]
|
||||||
|
bb = ptr4[$1000]
|
||||||
|
cx16.r0L = untyped[cx16.r0]
|
||||||
|
cx16.r1L = ptr1[cx16.r0]
|
||||||
|
cx16.r2 = ptr2[cx16.r0]
|
||||||
|
fl = ptr3[cx16.r0]
|
||||||
|
bb = ptr4[cx16.r0]
|
||||||
|
cx16.r0L = untyped[cx16.r0+1]
|
||||||
|
cx16.r1L = ptr1[cx16.r0+1]
|
||||||
|
cx16.r2 = ptr2[cx16.r0+1]
|
||||||
|
fl = ptr3[cx16.r0+1]
|
||||||
|
bb = ptr4[cx16.r0+1]
|
||||||
|
}
|
||||||
|
}"""
|
||||||
|
|
||||||
|
compileText(VMTarget(), false, src, outputDir) shouldNotBe null
|
||||||
|
compileText(C64Target(), false, src, outputDir) shouldNotBe null
|
||||||
|
}
|
||||||
|
|
||||||
test("correct type of address of split and nosplit arrays") {
|
test("correct type of address of split and nosplit arrays") {
|
||||||
val src="""
|
val src="""
|
||||||
main {
|
main {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ TODO
|
|||||||
====
|
====
|
||||||
|
|
||||||
c64 (and cx16 as well) fileselector has 2 issues when using ^^ubyte (code size and compiler error about return statement)
|
c64 (and cx16 as well) fileselector has 2 issues when using ^^ubyte (code size and compiler error about return statement)
|
||||||
cx16 life code size regression when using ^^ubyte
|
|
||||||
|
|
||||||
|
|
||||||
pointer arithmetic precedence issue?:
|
pointer arithmetic precedence issue?:
|
||||||
@@ -33,3 +32,5 @@ STRUCTS and TYPED POINTERS (6502 codegen specific)
|
|||||||
- optimize the float copying in assignIndexedPointer() (also word?)
|
- optimize the float copying in assignIndexedPointer() (also word?)
|
||||||
- implement some more struct instance assignments (via memcopy) in CodeDesugarer (see the TODO) (add to documentation as well, paragraph 'Structs')
|
- implement some more struct instance assignments (via memcopy) in CodeDesugarer (see the TODO) (add to documentation as well, paragraph 'Structs')
|
||||||
- try to optimize pointer arithmetic used in peek/poke a bit more so the routines in sorting module can use typed pointers without increasing code size
|
- try to optimize pointer arithmetic used in peek/poke a bit more so the routines in sorting module can use typed pointers without increasing code size
|
||||||
|
- should @(wordpointer) be equivalent to wordpointer^^ (that would require a LOT of code rewrite that now knows that @() is strictly byte based) ?
|
||||||
|
or do an implicit cast @(wpointer as ubyte^^) ? And/or add a warning about that?
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
; conway's game of life.
|
; Conway's game of life.
|
||||||
|
; the world is represented by a matrix of bytes (the cells) that can be 1 (alive) or 0 (dead)
|
||||||
|
; numeric byte is used because we need to count the number of neighbors and that would require casts if we used booleans.
|
||||||
|
; (but you totally could use booleans)
|
||||||
|
|
||||||
%import math
|
%import math
|
||||||
%import textio
|
%import textio
|
||||||
@@ -7,9 +10,9 @@ main {
|
|||||||
const ubyte WIDTH = 80
|
const ubyte WIDTH = 80
|
||||||
const ubyte HEIGHT = 60-4
|
const ubyte HEIGHT = 60-4
|
||||||
const uword STRIDE = $0002+WIDTH
|
const uword STRIDE = $0002+WIDTH
|
||||||
uword world1 = memory("world1", (WIDTH+2)*(HEIGHT+2), 0)
|
^^ubyte world1 = memory("world1", (WIDTH+2)*(HEIGHT+2), 0)
|
||||||
uword world2 = memory("world2", (WIDTH+2)*(HEIGHT+2), 0)
|
^^ubyte world2 = memory("world2", (WIDTH+2)*(HEIGHT+2), 0)
|
||||||
uword @requirezp active_world = world1
|
^^ubyte @requirezp active_world = world1
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
; cx16.set_screen_mode(3)
|
; cx16.set_screen_mode(3)
|
||||||
@@ -91,7 +94,7 @@ main {
|
|||||||
const ubyte DYOFFSET = 2
|
const ubyte DYOFFSET = 2
|
||||||
ubyte[2] cell_chars = [sc:' ', sc:'●']
|
ubyte[2] cell_chars = [sc:' ', sc:'●']
|
||||||
|
|
||||||
uword @requirezp new_world = world1
|
^^ubyte @requirezp new_world = world1
|
||||||
if active_world == world1
|
if active_world == world1
|
||||||
new_world = world2
|
new_world = world2
|
||||||
|
|
||||||
@@ -102,8 +105,8 @@ main {
|
|||||||
; It's more readable to use active_world[offset] etc, but offset is a word value, and this produces
|
; It's more readable to use active_world[offset] etc, but offset is a word value, and this produces
|
||||||
; inefficient assembly code because we can't use a register indexed mode in this case. Costly inside a loop.
|
; inefficient assembly code because we can't use a register indexed mode in this case. Costly inside a loop.
|
||||||
|
|
||||||
uword @requirezp new_world_ptr = new_world + STRIDE+1-DXOFFSET
|
^^ubyte @requirezp new_world_ptr = new_world + STRIDE+1-DXOFFSET
|
||||||
uword @requirezp active_world_ptr = active_world + STRIDE+1-DXOFFSET
|
^^ubyte @requirezp active_world_ptr = active_world + STRIDE+1-DXOFFSET
|
||||||
|
|
||||||
ubyte x
|
ubyte x
|
||||||
ubyte y
|
ubyte y
|
||||||
@@ -114,7 +117,7 @@ main {
|
|||||||
for x in DXOFFSET to WIDTH+DXOFFSET-1 {
|
for x in DXOFFSET to WIDTH+DXOFFSET-1 {
|
||||||
; count the living neighbors
|
; count the living neighbors
|
||||||
ubyte cell = @(active_world_ptr + x)
|
ubyte cell = @(active_world_ptr + x)
|
||||||
uword @requirezp ptr = active_world_ptr + x - STRIDE - 1
|
^^ubyte @requirezp ptr = active_world_ptr + x - STRIDE - 1
|
||||||
ubyte neighbors = @(ptr) + @(ptr+1) + @(ptr+2) +
|
ubyte neighbors = @(ptr) + @(ptr+1) + @(ptr+2) +
|
||||||
@(ptr+STRIDE) + cell + @(ptr+STRIDE+2) +
|
@(ptr+STRIDE) + cell + @(ptr+STRIDE+2) +
|
||||||
@(ptr+STRIDE*2) + @(ptr+STRIDE*2+1) + @(ptr+STRIDE*2+2)
|
@(ptr+STRIDE*2) + @(ptr+STRIDE*2+1) + @(ptr+STRIDE*2+2)
|
||||||
|
|||||||
246
examples/test.p8
246
examples/test.p8
@@ -1,228 +1,32 @@
|
|||||||
%option no_sysinit
|
%import floats
|
||||||
%zeropage kernalsafe
|
|
||||||
%import textio
|
|
||||||
%import compression
|
|
||||||
%import math
|
|
||||||
%import sorting
|
|
||||||
%import strings
|
|
||||||
%import diskio
|
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
|
struct List {
|
||||||
|
^^uword s
|
||||||
|
ubyte n
|
||||||
|
^^List next
|
||||||
|
}
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
; test_compression()
|
ubyte[10] array
|
||||||
; test_sorting1()
|
uword @shared wordptr
|
||||||
; test_sorting2()
|
^^bool @shared boolptr
|
||||||
; test_math()
|
^^float @shared floatptr
|
||||||
; test_syslib()
|
^^byte @shared byteptr
|
||||||
; test_strings()
|
^^ubyte @shared ubyteptr
|
||||||
; test_conv()
|
^^List @shared listptr
|
||||||
test_diskio()
|
^^List @shared listptr2
|
||||||
; test_textio()
|
|
||||||
|
|
||||||
repeat {}
|
bool @shared zz
|
||||||
}
|
float @shared fl
|
||||||
|
byte @shared bb
|
||||||
|
|
||||||
sub test_diskio() {
|
zz = boolptr[999]
|
||||||
txt.print("--diskio--\n")
|
fl = floatptr[999]
|
||||||
sys.memset(target, len(target), 0)
|
bb = byteptr[999]
|
||||||
diskio.delete("derp.bin")
|
cx16.r0L = ubyteptr[999]
|
||||||
void diskio.f_open_w("derp.bin")
|
cx16.r1L = wordptr[999]
|
||||||
repeat 12
|
cx16.r2L = array[9]
|
||||||
void diskio.f_write("derpderp123", 11)
|
|
||||||
diskio.f_close_w()
|
|
||||||
|
|
||||||
void diskio.f_open("derp.bin")
|
|
||||||
diskio.f_read(target, 60)
|
|
||||||
txt.print(target)
|
|
||||||
txt.nl()
|
|
||||||
}
|
|
||||||
|
|
||||||
ubyte[100] target
|
|
||||||
|
|
||||||
sub test_conv() {
|
|
||||||
txt.print("--conv--\n")
|
|
||||||
txt.print_b(-111)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_ub(222)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_uw(22222)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_w(-22222)
|
|
||||||
txt.nl()
|
|
||||||
txt.print_ubbin(222, true)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_ubhex(222, true)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_uwbin(2222, true)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_uwhex(2222, true)
|
|
||||||
txt.nl()
|
|
||||||
txt.print_ub0(1)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_uw0(123)
|
|
||||||
txt.nl()
|
|
||||||
}
|
|
||||||
|
|
||||||
sub test_strings() {
|
|
||||||
txt.print("--strings--\n")
|
|
||||||
ubyte idx
|
|
||||||
bool found
|
|
||||||
idx, found = strings.rfind(source, '1')
|
|
||||||
txt.print_ub(idx)
|
|
||||||
txt.nl()
|
|
||||||
}
|
|
||||||
|
|
||||||
sub test_textio() {
|
|
||||||
txt.print("--textio--\n")
|
|
||||||
txt.print("enter some input: ")
|
|
||||||
void txt.input_chars(&target)
|
|
||||||
txt.print(target)
|
|
||||||
txt.nl()
|
|
||||||
}
|
|
||||||
|
|
||||||
sub test_syslib() {
|
|
||||||
txt.print("--syslib--\n")
|
|
||||||
sys.internal_stringcopy(source, target)
|
|
||||||
txt.print(target)
|
|
||||||
txt.nl()
|
|
||||||
sys.memset(target, sizeof(target), 0)
|
|
||||||
txt.print(target)
|
|
||||||
txt.nl()
|
|
||||||
sys.memcopy(source, target, len(source))
|
|
||||||
txt.print(target)
|
|
||||||
txt.nl()
|
|
||||||
sys.memsetw(&target as ^^uword, 20, $5051)
|
|
||||||
txt.print(target)
|
|
||||||
txt.nl()
|
|
||||||
txt.print_b(sys.memcmp(source, target, len(source)))
|
|
||||||
txt.nl()
|
|
||||||
}
|
|
||||||
|
|
||||||
sub test_sorting1() {
|
|
||||||
txt.print("--sorting (shell)--\n")
|
|
||||||
ubyte[] bytes1 = [77,33,44,99,11,55]
|
|
||||||
ubyte[] bytes2 = [77,33,44,99,11,55]
|
|
||||||
uword[] @nosplit values1 = [1,2,3,4,5,6]
|
|
||||||
uword[] @nosplit words1 = [777,333,444,999,111,555]
|
|
||||||
uword[] @nosplit words2 = [777,333,444,999,111,555]
|
|
||||||
uword[] @nosplit values2 = [1,2,3,4,5,6]
|
|
||||||
sorting.shellsort_ub(&bytes1, len(bytes1))
|
|
||||||
sorting.shellsort_by_ub(&bytes2, &values1, len(bytes2))
|
|
||||||
sorting.shellsort_uw(&words1, len(words1))
|
|
||||||
sorting.shellsort_by_uw(&words2, &values2, len(words2))
|
|
||||||
|
|
||||||
for cx16.r0L in bytes1 {
|
|
||||||
txt.print_ub(cx16.r0L)
|
|
||||||
txt.spc()
|
|
||||||
}
|
|
||||||
txt.nl()
|
|
||||||
for cx16.r0L in bytes2 {
|
|
||||||
txt.print_ub(cx16.r0L)
|
|
||||||
txt.spc()
|
|
||||||
}
|
|
||||||
txt.nl()
|
|
||||||
for cx16.r0 in values1 {
|
|
||||||
txt.print_uw(cx16.r0)
|
|
||||||
txt.spc()
|
|
||||||
}
|
|
||||||
txt.nl()
|
|
||||||
for cx16.r0 in words1 {
|
|
||||||
txt.print_uw(cx16.r0)
|
|
||||||
txt.spc()
|
|
||||||
}
|
|
||||||
txt.nl()
|
|
||||||
for cx16.r0 in words2 {
|
|
||||||
txt.print_uw(cx16.r0)
|
|
||||||
txt.spc()
|
|
||||||
}
|
|
||||||
txt.nl()
|
|
||||||
for cx16.r0 in values2 {
|
|
||||||
txt.print_uw(cx16.r0)
|
|
||||||
txt.spc()
|
|
||||||
}
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
sub test_sorting2() {
|
|
||||||
txt.print("--sorting (gnome)--\n")
|
|
||||||
ubyte[] bytes1 = [77,33,44,99,11,55]
|
|
||||||
ubyte[] bytes2 = [77,33,44,99,11,55]
|
|
||||||
uword[] @nosplit values1 = [1,2,3,4,5,6]
|
|
||||||
uword[] @nosplit words1 = [777,333,444,999,111,555]
|
|
||||||
uword[] @nosplit words2 = [777,333,444,999,111,555]
|
|
||||||
uword[] @nosplit values2 = [1,2,3,4,5,6]
|
|
||||||
sorting.gnomesort_ub(&bytes1, len(bytes1))
|
|
||||||
sorting.gnomesort_by_ub(&bytes2, &values1, len(bytes2))
|
|
||||||
sorting.gnomesort_uw(&words1, len(words1))
|
|
||||||
sorting.gnomesort_by_uw(&words2, &values2, len(words2))
|
|
||||||
|
|
||||||
for cx16.r0L in bytes1 {
|
|
||||||
txt.print_ub(cx16.r0L)
|
|
||||||
txt.spc()
|
|
||||||
}
|
|
||||||
txt.nl()
|
|
||||||
for cx16.r0L in bytes2 {
|
|
||||||
txt.print_ub(cx16.r0L)
|
|
||||||
txt.spc()
|
|
||||||
}
|
|
||||||
txt.nl()
|
|
||||||
for cx16.r0 in values1 {
|
|
||||||
txt.print_uw(cx16.r0)
|
|
||||||
txt.spc()
|
|
||||||
}
|
|
||||||
txt.nl()
|
|
||||||
for cx16.r0 in words1 {
|
|
||||||
txt.print_uw(cx16.r0)
|
|
||||||
txt.spc()
|
|
||||||
}
|
|
||||||
txt.nl()
|
|
||||||
for cx16.r0 in words2 {
|
|
||||||
txt.print_uw(cx16.r0)
|
|
||||||
txt.spc()
|
|
||||||
}
|
|
||||||
txt.nl()
|
|
||||||
for cx16.r0 in values2 {
|
|
||||||
txt.print_uw(cx16.r0)
|
|
||||||
txt.spc()
|
|
||||||
}
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
sub test_math() {
|
|
||||||
txt.print("--math--\n")
|
|
||||||
txt.print("expected 15567: ")
|
|
||||||
txt.print_uw(math.crc16(source, len(source)))
|
|
||||||
txt.print("\nexpected 8747,54089: ")
|
|
||||||
math.crc32(source, len(source))
|
|
||||||
txt.print_uw(cx16.r14)
|
|
||||||
txt.chrout(',')
|
|
||||||
txt.print_uw(cx16.r15)
|
|
||||||
txt.nl()
|
|
||||||
}
|
|
||||||
|
|
||||||
str source = petscii:"Lorem ipsuuuuuuuuuuuum dollllllllllllllloooooooor sit ametttttttttttttttt, cccccccccccccccconsecteeeeetuuuuuur aaaaaaaaa111111222222333333444444"
|
|
||||||
|
|
||||||
sub test_compression() {
|
|
||||||
txt.print("--compression--\n")
|
|
||||||
|
|
||||||
ubyte[256] compressed
|
|
||||||
ubyte[256] decompressed
|
|
||||||
|
|
||||||
txt.print_uw(len(source))
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
uword size = compression.encode_rle(source, len(source), compressed, true)
|
|
||||||
txt.print_uw(size)
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
size = compression.decode_rle(compressed, decompressed, sizeof(decompressed))
|
|
||||||
txt.print_uw(size)
|
|
||||||
txt.nl()
|
|
||||||
txt.print(source)
|
|
||||||
txt.nl()
|
|
||||||
txt.print(decompressed)
|
|
||||||
txt.nl()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user