mirror of
https://github.com/irmen/prog8.git
synced 2025-08-15 14:27:37 +00:00
add a split-array version for word containment check
This commit is contained in:
@@ -1941,12 +1941,15 @@ $endLabel""")
|
|||||||
}
|
}
|
||||||
dt.isWordArray -> {
|
dt.isWordArray -> {
|
||||||
assignExpressionToVariable(containment.needle, "P8ZP_SCRATCH_W1", elementDt)
|
assignExpressionToVariable(containment.needle, "P8ZP_SCRATCH_W1", elementDt)
|
||||||
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.forDt(BaseDataType.UWORD), containment.definingISub(), containment.position, "P8ZP_SCRATCH_W2"), symbolName, null, null)
|
if(dt.isSplitWordArray) {
|
||||||
asmgen.out(" ldy #$numElements")
|
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.forDt(BaseDataType.UWORD), containment.definingISub(), containment.position, "P8ZP_SCRATCH_W2"), symbolName+"_lsb", null, null)
|
||||||
if(dt.isSplitWordArray)
|
asmgen.out(" ldy #$numElements")
|
||||||
asmgen.out(" jsr prog8_lib.containment_splitwordarray")
|
asmgen.out(" jsr prog8_lib.containment_splitwordarray")
|
||||||
else
|
} else {
|
||||||
asmgen.out(" jsr prog8_lib.containment_wordarray")
|
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.forDt(BaseDataType.UWORD), containment.definingISub(), containment.position, "P8ZP_SCRATCH_W2"), symbolName, null, null)
|
||||||
|
asmgen.out(" ldy #$numElements")
|
||||||
|
asmgen.out(" jsr prog8_lib.containment_linearwordarray")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else -> throw AssemblyError("invalid dt")
|
else -> throw AssemblyError("invalid dt")
|
||||||
}
|
}
|
||||||
|
@@ -317,7 +317,7 @@ containment_bytearray .proc
|
|||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
containment_wordarray .proc
|
containment_linearwordarray .proc
|
||||||
; -- check if a value exists in a linear word array.
|
; -- check if a value exists in a linear word array.
|
||||||
; parameters: P8ZP_SCRATCH_W1: value to check, P8ZP_SCRATCH_W2: address of the word array, Y = number of elements in the array (>=1).
|
; parameters: P8ZP_SCRATCH_W1: value to check, P8ZP_SCRATCH_W2: address of the word array, Y = number of elements in the array (>=1).
|
||||||
; returns boolean 0/1 in A.
|
; returns boolean 0/1 in A.
|
||||||
@@ -348,28 +348,37 @@ containment_splitwordarray .proc
|
|||||||
; parameters: P8ZP_SCRATCH_W1: value to check, P8ZP_SCRATCH_W2: start address of the lsb word array, Y = number of elements in the array (>=1).
|
; parameters: P8ZP_SCRATCH_W1: value to check, P8ZP_SCRATCH_W2: start address of the lsb word array, Y = number of elements in the array (>=1).
|
||||||
; returns boolean 0/1 in A.
|
; returns boolean 0/1 in A.
|
||||||
|
|
||||||
; TODO FIX THIS!
|
; store the needle value in SCRATCH_B1(lsb) and SCRATCH_REG(msb)
|
||||||
dey
|
lda P8ZP_SCRATCH_W1
|
||||||
tya
|
sta P8ZP_SCRATCH_B1
|
||||||
asl a
|
|
||||||
tay
|
|
||||||
- lda P8ZP_SCRATCH_W1
|
|
||||||
cmp (P8ZP_SCRATCH_W2),y
|
|
||||||
bne +
|
|
||||||
lda P8ZP_SCRATCH_W1+1
|
lda P8ZP_SCRATCH_W1+1
|
||||||
iny
|
sta P8ZP_SCRATCH_REG
|
||||||
|
|
||||||
|
; calculate where the msb array starts and put this in P8ZP_SCRATCH_W1 (_W2 is the start of the lsb array)
|
||||||
|
tya
|
||||||
|
clc
|
||||||
|
adc P8ZP_SCRATCH_W2
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
lda P8ZP_SCRATCH_W2+1
|
||||||
|
adc #0
|
||||||
|
sta P8ZP_SCRATCH_W1+1
|
||||||
|
|
||||||
|
; search needle
|
||||||
|
dey
|
||||||
|
- lda P8ZP_SCRATCH_REG
|
||||||
|
cmp (P8ZP_SCRATCH_W1),y
|
||||||
|
bne +
|
||||||
|
lda P8ZP_SCRATCH_B1
|
||||||
cmp (P8ZP_SCRATCH_W2),y
|
cmp (P8ZP_SCRATCH_W2),y
|
||||||
beq _found
|
beq _found
|
||||||
dey
|
+ dey
|
||||||
+ dey
|
cpy #255
|
||||||
dey
|
|
||||||
cpy #254
|
|
||||||
bne -
|
bne -
|
||||||
lda #0
|
lda #0
|
||||||
rts
|
rts
|
||||||
_found lda #1
|
_found lda #1
|
||||||
rts
|
rts
|
||||||
.pend
|
.pend
|
||||||
|
|
||||||
|
|
||||||
arraycopy_split_to_normal_words .proc
|
arraycopy_split_to_normal_words .proc
|
||||||
|
@@ -83,10 +83,7 @@ internal class LiteralsToAutoVars(private val program: Program, private val erro
|
|||||||
val decl = elt.targetVarDecl(program)
|
val decl = elt.targetVarDecl(program)
|
||||||
if(decl!=null && decl.datatype.isSplitWordArray) {
|
if(decl!=null && decl.datatype.isSplitWordArray) {
|
||||||
// you can't take the adress of a split-word array.
|
// you can't take the adress of a split-word array.
|
||||||
// instead of a fatal error, we give a warning and turn it back into a regular array.
|
errors.err("cannot take address of split word array", decl.position)
|
||||||
errors.warn("cannot take address of split word array - the array is turned back into a regular word array", decl.position)
|
|
||||||
val normalArray = makeNormalArrayFromSplit(decl)
|
|
||||||
mods.add(IAstModification.ReplaceNode(decl, normalArray, decl.parent))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mods
|
return mods
|
||||||
@@ -160,22 +157,9 @@ internal class LiteralsToAutoVars(private val program: Program, private val erro
|
|||||||
if (variable!=null) {
|
if (variable!=null) {
|
||||||
if (variable.datatype.isSplitWordArray) {
|
if (variable.datatype.isSplitWordArray) {
|
||||||
// you can't take the adress of a split-word array.
|
// you can't take the adress of a split-word array.
|
||||||
// instead of giving a fatal error, we remove the
|
errors.err("cannot take address of split word array", addressOf.position)
|
||||||
// instead of a fatal error, we give a warning and turn it back into a regular array.
|
|
||||||
errors.warn("cannot take address of split word array - the array is turned back into a regular word array", addressOf.position)
|
|
||||||
val normalArray = makeNormalArrayFromSplit(variable)
|
|
||||||
return listOf(IAstModification.ReplaceNode(variable, normalArray, variable.parent))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun makeNormalArrayFromSplit(variable: VarDecl): VarDecl {
|
|
||||||
val normalDt = DataType.arrayFor(variable.datatype.sub!!.dt, false)
|
|
||||||
return VarDecl(
|
|
||||||
variable.type, variable.origin, normalDt, variable.zeropage, variable.arraysize, variable.name, emptyList(),
|
|
||||||
variable.value?.copy(), variable.sharedWithAsm, variable.alignment, variable.dirty, variable.position
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -95,43 +95,6 @@ main {
|
|||||||
compileText(VMTarget(), false, text, writeAssembly = true) shouldNotBe null
|
compileText(VMTarget(), false, text, writeAssembly = true) shouldNotBe null
|
||||||
}
|
}
|
||||||
|
|
||||||
test("split only for word arrays") {
|
|
||||||
val srcGood = """
|
|
||||||
main {
|
|
||||||
uword[10] @nosplit sw
|
|
||||||
word[10] @nosplit sw2
|
|
||||||
|
|
||||||
sub start() {
|
|
||||||
}
|
|
||||||
}"""
|
|
||||||
compileText(C64Target(), false, srcGood, writeAssembly = false) shouldNotBe null
|
|
||||||
|
|
||||||
val srcWrong1 = """
|
|
||||||
main {
|
|
||||||
ubyte[10] @nosplit sb
|
|
||||||
|
|
||||||
sub start() {
|
|
||||||
}
|
|
||||||
}"""
|
|
||||||
val errors = ErrorReporterForTests()
|
|
||||||
compileText(C64Target(), false, srcWrong1, writeAssembly = false, errors=errors) shouldBe null
|
|
||||||
errors.errors.size shouldBe 1
|
|
||||||
errors.errors[0] shouldContain "nosplit can only be used on word arrays"
|
|
||||||
|
|
||||||
val srcWrong2 = """
|
|
||||||
%option enable_floats
|
|
||||||
main {
|
|
||||||
float[10] @nosplit sf
|
|
||||||
|
|
||||||
sub start() {
|
|
||||||
}
|
|
||||||
}"""
|
|
||||||
errors.clear()
|
|
||||||
compileText(C64Target(), false, srcWrong2, writeAssembly = false, errors=errors) shouldBe null
|
|
||||||
errors.errors.size shouldBe 1
|
|
||||||
errors.errors[0] shouldContain "nosplit can only be used on word arrays"
|
|
||||||
}
|
|
||||||
|
|
||||||
test("split word arrays in asm as lsb/msb, nosplit as single linear") {
|
test("split word arrays in asm as lsb/msb, nosplit as single linear") {
|
||||||
val text = """
|
val text = """
|
||||||
main {
|
main {
|
||||||
|
@@ -3,9 +3,8 @@ TODO
|
|||||||
|
|
||||||
- DONE: make word arrays split by default (remove @split tag) and use new @nosplit tag to make an array use the old storage format? Also invert -splitarrays command line option.
|
- DONE: make word arrays split by default (remove @split tag) and use new @nosplit tag to make an array use the old storage format? Also invert -splitarrays command line option.
|
||||||
- DONE: remove "splitarrays" %option switch
|
- DONE: remove "splitarrays" %option switch
|
||||||
- Regular & will just return the start of the split array in memory whatever byte comes first.
|
- Regular & will just return the start of the split array in memory whatever byte comes first. Search "cannot take address of split word array"
|
||||||
- add &< and &> operators to get the address of the lsb-array and msb-array, respectively.
|
- add &< and &> operators to get the address of the lsb-array and msb-array, respectively.
|
||||||
- fix containment_splitwordarray
|
|
||||||
- fix sprites.pos_batch
|
- fix sprites.pos_batch
|
||||||
- fix anyall.anyw/allw
|
- fix anyall.anyw/allw
|
||||||
- update Syntax files + Document all of this (also that word arrays can then have length 256 by default as well, and that @linear will reduce it to half.)
|
- update Syntax files + Document all of this (also that word arrays can then have length 256 by default as well, and that @linear will reduce it to half.)
|
||||||
|
@@ -2,14 +2,13 @@
|
|||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
main {
|
main {
|
||||||
uword[] array = [1000, 2000, 9000, 8000, 5000]
|
|
||||||
sub start() {
|
sub start() {
|
||||||
txt.print_bool(1000 in array)
|
uword[] addresses = [scores2, start]
|
||||||
txt.spc()
|
uword[] scores1 = [10, 25, 50, 100]
|
||||||
txt.print_bool(9000 in array)
|
uword[] scores2 = [100, 250, 500, 1000]
|
||||||
txt.spc()
|
|
||||||
txt.print_bool(5000 in array)
|
cx16.r0 = &scores1
|
||||||
txt.spc()
|
cx16.r1 = &scores2
|
||||||
txt.print_bool(9001 in array)
|
cx16.r2 = &addresses
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user