mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +00:00
add a split-array version for word containment check
This commit is contained in:
parent
8f799567cf
commit
28c721fa7d
@ -1941,12 +1941,15 @@ $endLabel""")
|
||||
}
|
||||
dt.isWordArray -> {
|
||||
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)
|
||||
asmgen.out(" ldy #$numElements")
|
||||
if(dt.isSplitWordArray)
|
||||
if(dt.isSplitWordArray) {
|
||||
assignAddressOf(AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.forDt(BaseDataType.UWORD), containment.definingISub(), containment.position, "P8ZP_SCRATCH_W2"), symbolName+"_lsb", null, null)
|
||||
asmgen.out(" ldy #$numElements")
|
||||
asmgen.out(" jsr prog8_lib.containment_splitwordarray")
|
||||
else
|
||||
asmgen.out(" jsr prog8_lib.containment_wordarray")
|
||||
} else {
|
||||
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")
|
||||
}
|
||||
|
@ -317,7 +317,7 @@ containment_bytearray .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
containment_wordarray .proc
|
||||
containment_linearwordarray .proc
|
||||
; -- 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).
|
||||
; 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).
|
||||
; returns boolean 0/1 in A.
|
||||
|
||||
; TODO FIX THIS!
|
||||
dey
|
||||
tya
|
||||
asl a
|
||||
tay
|
||||
- lda P8ZP_SCRATCH_W1
|
||||
cmp (P8ZP_SCRATCH_W2),y
|
||||
bne +
|
||||
; store the needle value in SCRATCH_B1(lsb) and SCRATCH_REG(msb)
|
||||
lda P8ZP_SCRATCH_W1
|
||||
sta P8ZP_SCRATCH_B1
|
||||
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
|
||||
beq _found
|
||||
dey
|
||||
+ dey
|
||||
dey
|
||||
cpy #254
|
||||
+ dey
|
||||
cpy #255
|
||||
bne -
|
||||
lda #0
|
||||
rts
|
||||
_found lda #1
|
||||
_found lda #1
|
||||
rts
|
||||
.pend
|
||||
.pend
|
||||
|
||||
|
||||
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)
|
||||
if(decl!=null && decl.datatype.isSplitWordArray) {
|
||||
// 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.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))
|
||||
errors.err("cannot take address of split word array", decl.position)
|
||||
}
|
||||
}
|
||||
return mods
|
||||
@ -160,22 +157,9 @@ internal class LiteralsToAutoVars(private val program: Program, private val erro
|
||||
if (variable!=null) {
|
||||
if (variable.datatype.isSplitWordArray) {
|
||||
// you can't take the adress of a split-word array.
|
||||
// instead of giving a fatal error, we remove the
|
||||
// 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))
|
||||
errors.err("cannot take address of split word array", addressOf.position)
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
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") {
|
||||
val text = """
|
||||
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: 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.
|
||||
- fix containment_splitwordarray
|
||||
- fix sprites.pos_batch
|
||||
- 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.)
|
||||
|
@ -2,14 +2,13 @@
|
||||
%zeropage basicsafe
|
||||
|
||||
main {
|
||||
uword[] array = [1000, 2000, 9000, 8000, 5000]
|
||||
sub start() {
|
||||
txt.print_bool(1000 in array)
|
||||
txt.spc()
|
||||
txt.print_bool(9000 in array)
|
||||
txt.spc()
|
||||
txt.print_bool(5000 in array)
|
||||
txt.spc()
|
||||
txt.print_bool(9001 in array)
|
||||
uword[] addresses = [scores2, start]
|
||||
uword[] scores1 = [10, 25, 50, 100]
|
||||
uword[] scores2 = [100, 250, 500, 1000]
|
||||
|
||||
cx16.r0 = &scores1
|
||||
cx16.r1 = &scores2
|
||||
cx16.r2 = &addresses
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user