mirror of
https://github.com/irmen/prog8.git
synced 2025-02-20 03:29:01 +00:00
make word arrays split by default (w.i.p.)
This commit is contained in:
parent
9e8cc8b54d
commit
8f799567cf
@ -127,7 +127,7 @@ fun printAst(root: PtNode, skipLibraries: Boolean, output: (text: String) -> Uni
|
||||
str
|
||||
}
|
||||
is PtVariable -> {
|
||||
val split = if(node.type.isSplitWordArray) "@split" else ""
|
||||
val split = if(node.type.isSplitWordArray) "" else "@nosplit"
|
||||
val align = when(node.align) {
|
||||
0u -> ""
|
||||
2u -> "@alignword"
|
||||
|
@ -27,7 +27,7 @@ class CompilationOptions(val output: OutputType,
|
||||
var varsGolden: Boolean = false,
|
||||
var slabsHighBank: Int? = null,
|
||||
var slabsGolden: Boolean = false,
|
||||
var splitWordArrays: Boolean = false,
|
||||
var dontSplitWordArrays: Boolean = false,
|
||||
var breakpointCpuInstruction: String? = null,
|
||||
var ignoreFootguns: Boolean = false,
|
||||
var outputDir: Path = Path(""),
|
||||
|
@ -117,19 +117,18 @@ class DataType private constructor(val base: BaseDataType, val sub: SubType?) {
|
||||
|
||||
fun forDt(dt: BaseDataType) = simpletypes.getValue(dt)
|
||||
|
||||
fun arrayFor(elementDt: BaseDataType, split: Boolean=false): DataType {
|
||||
fun arrayFor(elementDt: BaseDataType, splitwordarray: Boolean=true): DataType {
|
||||
val actualElementDt = if(elementDt==BaseDataType.STR) BaseDataType.UWORD else elementDt // array of strings is actually just an array of UWORD pointers
|
||||
if(split) return DataType(BaseDataType.ARRAY_SPLITW, SubType.forDt(actualElementDt))
|
||||
else return DataType(BaseDataType.ARRAY, SubType.forDt(actualElementDt))
|
||||
return if(splitwordarray && elementDt.isWord)
|
||||
DataType(BaseDataType.ARRAY_SPLITW, SubType.forDt(actualElementDt))
|
||||
else
|
||||
DataType(BaseDataType.ARRAY, SubType.forDt(actualElementDt))
|
||||
}
|
||||
}
|
||||
|
||||
fun elementToArray(split: Boolean = false): DataType {
|
||||
if(split) {
|
||||
return if (base == BaseDataType.UWORD || base == BaseDataType.WORD || base == BaseDataType.STR) arrayFor(base, true)
|
||||
else throw IllegalArgumentException("invalid split array elt dt")
|
||||
}
|
||||
return arrayFor(base)
|
||||
fun elementToArray(splitwords: Boolean = true): DataType {
|
||||
return if (base == BaseDataType.UWORD || base == BaseDataType.WORD || base == BaseDataType.STR) arrayFor(base, splitwords)
|
||||
else arrayFor(base, false)
|
||||
}
|
||||
|
||||
fun elementType(): DataType =
|
||||
@ -152,8 +151,8 @@ class DataType private constructor(val base: BaseDataType, val sub: SubType?) {
|
||||
}
|
||||
BaseDataType.ARRAY_SPLITW -> {
|
||||
when(sub) {
|
||||
SubSignedWord -> "@split word[]"
|
||||
SubUnsignedWord -> "@split uword[]"
|
||||
SubSignedWord -> "word[] (split)"
|
||||
SubUnsignedWord -> "uword[] (split)"
|
||||
else -> throw IllegalArgumentException("invalid sub type")
|
||||
}
|
||||
}
|
||||
@ -172,18 +171,18 @@ class DataType private constructor(val base: BaseDataType, val sub: SubType?) {
|
||||
BaseDataType.ARRAY -> {
|
||||
when(sub) {
|
||||
SubUnsignedByte -> "ubyte["
|
||||
SubUnsignedWord -> "uword["
|
||||
SubUnsignedWord -> "@nosplit uword["
|
||||
SubBool -> "bool["
|
||||
SubSignedByte -> "byte["
|
||||
SubSignedWord -> "word["
|
||||
SubSignedWord -> "@nosplit word["
|
||||
SubFloat -> "float["
|
||||
null -> throw IllegalArgumentException("invalid sub type")
|
||||
}
|
||||
}
|
||||
BaseDataType.ARRAY_SPLITW -> {
|
||||
when(sub) {
|
||||
SubUnsignedWord -> "@split uword["
|
||||
SubSignedWord -> "@split word["
|
||||
SubUnsignedWord -> "uword["
|
||||
SubSignedWord -> "word["
|
||||
else -> throw IllegalArgumentException("invalid sub type")
|
||||
}
|
||||
}
|
||||
|
@ -670,7 +670,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
val msbAdd: Int
|
||||
if(indexer.splitWords) {
|
||||
val arrayVariable = indexer.variable
|
||||
indexer.children[0] = PtIdentifier(arrayVariable.name + if(msb) "_msb" else "_lsb", DataType.arrayFor(BaseDataType.UBYTE), arrayVariable.position)
|
||||
indexer.children[0] = PtIdentifier(arrayVariable.name + if(msb) "_msb" else "_lsb", DataType.arrayFor(BaseDataType.UBYTE, false), arrayVariable.position)
|
||||
indexer.children[0].parent = indexer
|
||||
elementSize = 1
|
||||
msbAdd = 0
|
||||
|
@ -1939,11 +1939,14 @@ $endLabel""")
|
||||
asmgen.out(" ldy #$numElements")
|
||||
asmgen.out(" jsr prog8_lib.containment_bytearray")
|
||||
}
|
||||
dt.isWordArray && !dt.isSplitWordArray -> {
|
||||
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")
|
||||
asmgen.out(" jsr prog8_lib.containment_wordarray")
|
||||
if(dt.isSplitWordArray)
|
||||
asmgen.out(" jsr prog8_lib.containment_splitwordarray")
|
||||
else
|
||||
asmgen.out(" jsr prog8_lib.containment_wordarray")
|
||||
}
|
||||
else -> throw AssemblyError("invalid dt")
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ class VarConstantValueTypeAdjuster(
|
||||
if (declValue != null) {
|
||||
// variable is never written to, so it can be replaced with a constant, IF the value is a constant
|
||||
errors.info("variable '${decl.name}' is never written to and was replaced by a constant", decl.position)
|
||||
val const = VarDecl(VarDeclType.CONST, decl.origin, decl.datatype, decl.zeropage, decl.arraysize, decl.name, decl.names, declValue, decl.sharedWithAsm, decl.splitArray, decl.alignment, decl.dirty, decl.position)
|
||||
val const = VarDecl(VarDeclType.CONST, decl.origin, decl.datatype, decl.zeropage, decl.arraysize, decl.name, decl.names, declValue, decl.sharedWithAsm, decl.alignment, decl.dirty, decl.position)
|
||||
decl.value = null
|
||||
return listOf(
|
||||
IAstModification.ReplaceNode(decl, const, parent)
|
||||
@ -90,7 +90,7 @@ class VarConstantValueTypeAdjuster(
|
||||
}
|
||||
// variable only has a single write, and it is the initialization value, so it can be replaced with a constant, IF the value is a constant
|
||||
errors.info("variable '${decl.name}' is never written to and was replaced by a constant", decl.position)
|
||||
val const = VarDecl(VarDeclType.CONST, decl.origin, decl.datatype, decl.zeropage, decl.arraysize, decl.name, decl.names, singleAssignment.value, decl.sharedWithAsm, decl.splitArray, decl.alignment, decl.dirty, decl.position)
|
||||
val const = VarDecl(VarDeclType.CONST, decl.origin, decl.datatype, decl.zeropage, decl.arraysize, decl.name, decl.names, singleAssignment.value, decl.sharedWithAsm, decl.alignment, decl.dirty, decl.position)
|
||||
return listOf(
|
||||
IAstModification.ReplaceNode(decl, const, parent),
|
||||
IAstModification.Remove(singleAssignment, singleAssignment.parent as IStatementContainer)
|
||||
@ -392,7 +392,7 @@ internal class ConstantIdentifierReplacer(
|
||||
if(targetDatatype.isArray) {
|
||||
val decl = VarDecl(VarDeclType.VAR, VarDeclOrigin.ARRAYLITERAL, targetDatatype.getOrUndef(),
|
||||
ZeropageWish.DONTCARE, null, "dummy", emptyList(),
|
||||
assignment.value, false, false, 0u, false, Position.DUMMY)
|
||||
assignment.value, false, 0u, false, Position.DUMMY)
|
||||
val replaceValue = createConstArrayInitializerValue(decl)
|
||||
if(replaceValue!=null) {
|
||||
return listOf(IAstModification.ReplaceNode(assignment.value, replaceValue, assignment))
|
||||
@ -447,7 +447,7 @@ internal class ConstantIdentifierReplacer(
|
||||
if(declArraySize!=null && declArraySize!=rangeExpr.size())
|
||||
errors.err("range expression size (${rangeExpr.size()}) doesn't match declared array size ($declArraySize)", decl.value?.position!!)
|
||||
if(constRange!=null) {
|
||||
return ArrayLiteral(InferredTypes.InferredType.known(DataType.arrayFor(BaseDataType.FLOAT)),
|
||||
return ArrayLiteral(InferredTypes.InferredType.known(DataType.arrayFor(BaseDataType.FLOAT, false)),
|
||||
constRange.map { NumericLiteral(BaseDataType.FLOAT, it.toDouble(), decl.value!!.position) }.toTypedArray(),
|
||||
position = decl.value!!.position)
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ anyall {
|
||||
|
||||
sub anyw(uword arrayptr, uword num_elements) -> bool {
|
||||
; -- returns true if any word in the array is not zero.
|
||||
; doesn't work on @split arrays.
|
||||
; TODO FIX: doesn't work on @split arrays.
|
||||
cx16.r1 = arrayptr
|
||||
if msb(num_elements)==0 {
|
||||
repeat lsb(num_elements) {
|
||||
@ -62,7 +62,7 @@ anyall {
|
||||
|
||||
sub allw(uword arrayptr, uword num_elements) -> bool {
|
||||
; -- returns true if all words in the array are not zero.
|
||||
; doesn't work on @split arrays.
|
||||
; TODO FIX: doesn't work on @split arrays.
|
||||
cx16.r1 = arrayptr
|
||||
if msb(num_elements)==0 {
|
||||
repeat lsb(num_elements) {
|
||||
|
@ -188,7 +188,7 @@ c64 {
|
||||
&ubyte SP7X = $d00e
|
||||
&ubyte SP7Y = $d00f
|
||||
&ubyte[16] SPXY = $d000 ; the 8 sprite X and Y registers as an array.
|
||||
&uword[8] SPXYW = $d000 ; the 8 sprite X and Y registers as a combined xy word array.
|
||||
&uword[8] @nosplit SPXYW = $d000 ; the 8 sprite X and Y registers as a combined xy word array.
|
||||
|
||||
&ubyte MSIGX = $d010
|
||||
&ubyte SCROLY = $d011
|
||||
|
@ -189,7 +189,7 @@ c64 {
|
||||
&ubyte SP7X = $d00e
|
||||
&ubyte SP7Y = $d00f
|
||||
&ubyte[16] SPXY = $d000 ; the 8 sprite X and Y registers as an array.
|
||||
&uword[8] SPXYW = $d000 ; the 8 sprite X and Y registers as a combined xy word array.
|
||||
&uword[8] @nosplit SPXYW = $d000 ; the 8 sprite X and Y registers as a combined xy word array.
|
||||
|
||||
&ubyte MSIGX = $d010
|
||||
&ubyte SCROLY = $d011
|
||||
|
@ -174,7 +174,7 @@ psg {
|
||||
}
|
||||
|
||||
ubyte[16] envelope_states
|
||||
uword[16] @split envelope_volumes ; scaled by 256
|
||||
uword[16] envelope_volumes ; scaled by 256
|
||||
ubyte[16] envelope_attacks
|
||||
ubyte[16] envelope_sustains
|
||||
ubyte[16] envelope_releases
|
||||
|
@ -318,8 +318,8 @@ containment_bytearray .proc
|
||||
.pend
|
||||
|
||||
containment_wordarray .proc
|
||||
; -- check if a value exists in a word array.
|
||||
; parameters: P8ZP_SCRATCH_W1: value to check, P8ZP_SCRATCH_W2: address of the word array, Y = length of array (>=1).
|
||||
; -- 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.
|
||||
dey
|
||||
tya
|
||||
@ -343,6 +343,34 @@ _found lda #1
|
||||
rts
|
||||
.pend
|
||||
|
||||
containment_splitwordarray .proc
|
||||
; -- check if a value exists in a split lsb/msb word array. (Assuming lsb array comes first, immediately followed by msb array)
|
||||
; 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 +
|
||||
lda P8ZP_SCRATCH_W1+1
|
||||
iny
|
||||
cmp (P8ZP_SCRATCH_W2),y
|
||||
beq _found
|
||||
dey
|
||||
+ dey
|
||||
dey
|
||||
cpy #254
|
||||
bne -
|
||||
lda #0
|
||||
rts
|
||||
_found lda #1
|
||||
rts
|
||||
.pend
|
||||
|
||||
|
||||
arraycopy_split_to_normal_words .proc
|
||||
; P8ZP_SCRATCH_W1 = start of lsb array
|
||||
|
@ -66,7 +66,7 @@ private fun compileMain(args: Array<String>): Boolean {
|
||||
val slabsGolden by cli.option(ArgType.Boolean, fullName = "slabsgolden", description = "put memory() slabs in 'golden ram' memory area instead of at the end of the program. On the cx16 target this is $0400-07ff. This is unavailable on other systems.")
|
||||
val slabsHighBank by cli.option(ArgType.Int, fullName = "slabshigh", description = "put memory() slabs in high memory area instead of at the end of the program. On the cx16 target the value specifies the HiRAM bank to use, on other systems this value is ignored.")
|
||||
val includeSourcelines by cli.option(ArgType.Boolean, fullName = "sourcelines", description = "include original Prog8 source lines in generated asm code")
|
||||
val splitWordArrays by cli.option(ArgType.Boolean, fullName = "splitarrays", description = "treat all word arrays as tagged with @split to make them lsb/msb split in memory")
|
||||
val dontSplitWordArrays by cli.option(ArgType.Boolean, fullName = "dontsplitarrays", description = "don't store any word array as split lsb/msb in memory, as if all of those have @nosplit")
|
||||
val sourceDirs by cli.option(ArgType.String, fullName="srcdirs", description = "list of extra paths, separated with ${File.pathSeparator}, to search in for imported modules").multiple().delimiter(File.pathSeparator)
|
||||
val compilationTarget by cli.option(ArgType.String, fullName = "target", description = "target output of the compiler (one of ${CompilationTargets.joinToString(",")}) (required)")
|
||||
val varsGolden by cli.option(ArgType.Boolean, fullName = "varsgolden", description = "put uninitialized variables in 'golden ram' memory area instead of at the end of the program. On the cx16 target this is $0400-07ff. This is unavailable on other systems.")
|
||||
@ -184,7 +184,7 @@ private fun compileMain(args: Array<String>): Boolean {
|
||||
slabsHighBank,
|
||||
slabsGolden == true,
|
||||
compilationTarget!!,
|
||||
splitWordArrays == true,
|
||||
dontSplitWordArrays == true,
|
||||
breakpointCpuInstruction,
|
||||
printAst1 == true,
|
||||
printAst2 == true,
|
||||
@ -267,7 +267,7 @@ private fun compileMain(args: Array<String>): Boolean {
|
||||
slabsHighBank,
|
||||
slabsGolden == true,
|
||||
compilationTarget!!,
|
||||
splitWordArrays == true,
|
||||
dontSplitWordArrays == true,
|
||||
breakpointCpuInstruction,
|
||||
printAst1 == true,
|
||||
printAst2 == true,
|
||||
|
@ -48,7 +48,7 @@ class CompilerArguments(val filepath: Path,
|
||||
val slabsHighBank: Int?,
|
||||
val slabsGolden: Boolean,
|
||||
val compilationTarget: String,
|
||||
val splitWordArrays: Boolean,
|
||||
val dontSplitWordArrays: Boolean,
|
||||
val breakpointCpuInstruction: String?,
|
||||
val printAst1: Boolean,
|
||||
val printAst2: Boolean,
|
||||
@ -87,7 +87,7 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
|
||||
varsGolden = args.varsGolden
|
||||
slabsHighBank = args.slabsHighBank
|
||||
slabsGolden = args.slabsGolden
|
||||
splitWordArrays = args.splitWordArrays
|
||||
dontSplitWordArrays = args.dontSplitWordArrays
|
||||
outputDir = args.outputDir.normalize()
|
||||
symbolDefs = args.symbolDefs
|
||||
}
|
||||
|
@ -703,7 +703,7 @@ internal class AstChecker(private val program: Program,
|
||||
if (variable!=null) {
|
||||
if (variable.type == VarDeclType.CONST && addressOf.arrayIndex == null)
|
||||
errors.err("invalid pointer-of operand type",addressOf.position)
|
||||
if (variable.splitArray)
|
||||
if (variable.datatype.isSplitWordArray)
|
||||
errors.err("cannot take address of split word array",addressOf.position)
|
||||
}
|
||||
super.visit(addressOf)
|
||||
@ -888,8 +888,8 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
}
|
||||
|
||||
if(decl.splitArray && decl.type==VarDeclType.MEMORY)
|
||||
err("@split can't be used on memory mapped arrays")
|
||||
if(decl.datatype.isSplitWordArray && decl.type==VarDeclType.MEMORY)
|
||||
err("memory mapped word arrays cannot be split, should have @nosplit")
|
||||
}
|
||||
|
||||
if(decl.datatype.isString) {
|
||||
@ -911,7 +911,7 @@ internal class AstChecker(private val program: Program,
|
||||
if(compilerOptions.zeropage==ZeropageType.DONTUSE && decl.zeropage == ZeropageWish.REQUIRE_ZEROPAGE)
|
||||
err("zeropage usage has been disabled by options")
|
||||
|
||||
if(decl.splitArray) {
|
||||
if(decl.datatype.isSplitWordArray) {
|
||||
if (!decl.datatype.isWordArray) {
|
||||
errors.err("split can only be used on word arrays", decl.position)
|
||||
}
|
||||
@ -1044,14 +1044,14 @@ internal class AstChecker(private val program: Program,
|
||||
err("this directive may only occur in a block or at module level")
|
||||
if(directive.args.isEmpty())
|
||||
err("missing option directive argument(s)")
|
||||
else if(directive.args.map{it.name in arrayOf("enable_floats", "force_output", "no_sysinit", "merge", "verafxmuls", "splitarrays", "no_symbol_prefixing", "ignore_unused")}.any { !it })
|
||||
else if(directive.args.map{it.name in arrayOf("enable_floats", "force_output", "no_sysinit", "merge", "verafxmuls", "no_symbol_prefixing", "ignore_unused")}.any { !it })
|
||||
err("invalid option directive argument(s)")
|
||||
if(directive.parent is Block) {
|
||||
if(directive.args.any {it.name !in arrayOf("force_output", "merge", "verafxmuls", "splitarrays", "no_symbol_prefixing", "ignore_unused")})
|
||||
if(directive.args.any {it.name !in arrayOf("force_output", "merge", "verafxmuls", "no_symbol_prefixing", "ignore_unused")})
|
||||
err("using an option that is not valid for blocks")
|
||||
}
|
||||
if(directive.parent is Module) {
|
||||
if(directive.args.any {it.name !in arrayOf("enable_floats", "no_sysinit", "splitarrays", "no_symbol_prefixing", "ignore_unused")})
|
||||
if(directive.args.any {it.name !in arrayOf("enable_floats", "no_sysinit", "no_symbol_prefixing", "ignore_unused")})
|
||||
err("using an option that is not valid for modules")
|
||||
}
|
||||
if(directive.args.any { it.name=="verafxmuls" } && compilerOptions.compTarget.name != Cx16Target.NAME)
|
||||
|
@ -112,8 +112,8 @@ class AstPreprocessor(val program: Program,
|
||||
val replacements = mutableListOf<IAstModification>()
|
||||
|
||||
for(decl in vars) {
|
||||
if(shouldSplitArray(decl))
|
||||
continue // splitting must be done first
|
||||
if(shouldUnSplitArray(decl))
|
||||
continue // unsplitting must be done first
|
||||
if(decl.type != VarDeclType.VAR) {
|
||||
movements.add(IAstModification.InsertFirst(decl, parentscope))
|
||||
replacements.add(IAstModification.Remove(decl, scope))
|
||||
@ -181,28 +181,21 @@ class AstPreprocessor(val program: Program,
|
||||
}
|
||||
}
|
||||
|
||||
if(shouldSplitArray(decl)) {
|
||||
return makeSplitArray(decl)
|
||||
}
|
||||
|
||||
if(decl.datatype.isWordArray) {
|
||||
if ("splitarrays" in decl.definingBlock.options())
|
||||
return makeSplitArray(decl)
|
||||
if ("splitarrays" in decl.definingModule.options())
|
||||
return makeSplitArray(decl)
|
||||
if(shouldUnSplitArray(decl)) {
|
||||
return makeUnSplitArray(decl)
|
||||
}
|
||||
|
||||
return noModifications
|
||||
}
|
||||
|
||||
private fun shouldSplitArray(decl: VarDecl): Boolean =
|
||||
options.splitWordArrays && (decl.datatype.isWordArray && !decl.datatype.isSplitWordArray) && !decl.definingBlock.isInLibrary
|
||||
private fun shouldUnSplitArray(decl: VarDecl): Boolean =
|
||||
options.dontSplitWordArrays && decl.datatype.isSplitWordArray
|
||||
|
||||
private fun makeSplitArray(decl: VarDecl): Iterable<IAstModification> {
|
||||
val splitDt = DataType.arrayFor(decl.datatype.sub!!.dt, true)
|
||||
private fun makeUnSplitArray(decl: VarDecl): Iterable<IAstModification> {
|
||||
val splitDt = DataType.arrayFor(decl.datatype.sub!!.dt, false)
|
||||
val newDecl = VarDecl(
|
||||
decl.type, decl.origin, splitDt, decl.zeropage, decl.arraysize, decl.name, emptyList(),
|
||||
decl.value?.copy(), decl.sharedWithAsm, true, decl.alignment, false, decl.position
|
||||
decl.value?.copy(), decl.sharedWithAsm, decl.alignment, false, decl.position
|
||||
)
|
||||
return listOf(IAstModification.ReplaceNode(decl, newDecl, decl.parent))
|
||||
}
|
||||
|
@ -202,7 +202,7 @@ class IntermediateAstMaker(private val program: Program, private val errors: IEr
|
||||
"no_symbol_prefixing" -> noSymbolPrefixing = true
|
||||
"ignore_unused" -> ignoreUnused = true
|
||||
"force_output" -> forceOutput = true
|
||||
"merge", "splitarrays" -> { /* ignore this one */ }
|
||||
"merge" -> { /* ignore this one */ }
|
||||
"verafxmuls" -> veraFxMuls = true
|
||||
else -> throw FatalAstException("weird directive option: ${arg.name}")
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ internal class LiteralsToAutoVars(private val program: Program, private val erro
|
||||
// turn the array literal it into an identifier reference
|
||||
val litval2 = array.cast(targetDt.getOrUndef())
|
||||
if (litval2 != null) {
|
||||
val vardecl2 = VarDecl.createAuto(litval2, targetDt.getOrUndef().isSplitWordArray)
|
||||
val vardecl2 = VarDecl.createAuto(litval2)
|
||||
val identifier = IdentifierReference(listOf(vardecl2.name), vardecl2.position)
|
||||
return listOf(
|
||||
IAstModification.ReplaceNode(array, identifier, parent),
|
||||
@ -81,7 +81,7 @@ internal class LiteralsToAutoVars(private val program: Program, private val erro
|
||||
val mods = mutableListOf<IAstModification>()
|
||||
for(elt in array.value.filterIsInstance<IdentifierReference>()) {
|
||||
val decl = elt.targetVarDecl(program)
|
||||
if(decl!=null && decl.splitArray) {
|
||||
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)
|
||||
@ -158,7 +158,7 @@ internal class LiteralsToAutoVars(private val program: Program, private val erro
|
||||
override fun after(addressOf: AddressOf, parent: Node): Iterable<IAstModification> {
|
||||
val variable=addressOf.identifier.targetVarDecl(program)
|
||||
if (variable!=null) {
|
||||
if (variable.splitArray) {
|
||||
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.
|
||||
@ -174,7 +174,7 @@ internal class LiteralsToAutoVars(private val program: Program, private val erro
|
||||
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, false, variable.alignment, variable.dirty, variable.position
|
||||
variable.value?.copy(), variable.sharedWithAsm, variable.alignment, variable.dirty, variable.position
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -222,7 +222,6 @@ internal class StatementReorderer(
|
||||
emptyList(),
|
||||
null,
|
||||
it.sharedWithAsm,
|
||||
it.splitArray,
|
||||
it.alignment,
|
||||
it.dirty,
|
||||
it.position
|
||||
|
@ -15,7 +15,7 @@ import prog8.code.core.*
|
||||
internal class VariousCleanups(val program: Program, val errors: IErrorReporter, val options: CompilationOptions): AstWalker() {
|
||||
|
||||
override fun after(block: Block, parent: Node): Iterable<IAstModification> {
|
||||
val inheritOptions = block.definingModule.options() intersect setOf("splitarrays", "no_symbol_prefixing", "ignore_unused") subtract block.options()
|
||||
val inheritOptions = block.definingModule.options() intersect setOf("no_symbol_prefixing", "ignore_unused") subtract block.options()
|
||||
if(inheritOptions.isNotEmpty()) {
|
||||
val directive = Directive("%option", inheritOptions.map{ DirectiveArg(null, it, null, block.position) }, block.position)
|
||||
return listOf(IAstModification.InsertFirst(directive, block))
|
||||
@ -223,7 +223,7 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
|
||||
|
||||
// replace x==1 or x==2 or x==3 with a containment check x in [1,2,3]
|
||||
val valueCopies = values.sortedBy { it.number }.map { it.copy() }
|
||||
val arrayType = DataType.arrayFor(elementType.base)
|
||||
val arrayType = DataType.arrayFor(elementType.base, true)
|
||||
val valuesArray = ArrayLiteral(InferredTypes.InferredType.known(arrayType), valueCopies.toTypedArray(), expr.position)
|
||||
val containment = ContainmentCheck(needle, valuesArray, expr.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, containment, parent))
|
||||
|
@ -39,7 +39,7 @@ private fun compileTheThing(filepath: Path, optimize: Boolean, target: ICompilat
|
||||
slabsHighBank = null,
|
||||
slabsGolden = false,
|
||||
compilationTarget = target.name,
|
||||
splitWordArrays = false,
|
||||
dontSplitWordArrays = false,
|
||||
breakpointCpuInstruction = null,
|
||||
printAst1 = false,
|
||||
printAst2 = false,
|
||||
|
@ -339,6 +339,7 @@ class TestCompilerOnRanges: FunSpec({
|
||||
str name = "irmen"
|
||||
ubyte[] values = [1,2,3,4,5,6,7]
|
||||
uword[] wvalues = [1000,2000,3000]
|
||||
uword[] @nosplit wnsvalues = [1000,2000,3000]
|
||||
|
||||
if 'm' in name {
|
||||
xx++
|
||||
@ -376,6 +377,10 @@ class TestCompilerOnRanges: FunSpec({
|
||||
xx++
|
||||
}
|
||||
|
||||
if ww in wnsvalues {
|
||||
xx++
|
||||
}
|
||||
|
||||
if xx in 10 to 20 {
|
||||
xx++
|
||||
}
|
||||
@ -387,7 +392,7 @@ class TestCompilerOnRanges: FunSpec({
|
||||
}""", writeAssembly = true) shouldNotBe null
|
||||
}
|
||||
|
||||
test("containment check in expressions") {
|
||||
test("containment check expressions") {
|
||||
compileText(
|
||||
C64Target(), false, """
|
||||
main {
|
||||
@ -397,6 +402,7 @@ class TestCompilerOnRanges: FunSpec({
|
||||
str name = "irmen"
|
||||
ubyte[] values = [1,2,3,4,5,6,7]
|
||||
uword[] wvalues = [1000,2000,3000]
|
||||
uword[] @nosplit wnsvalues = [1000,2000,3000]
|
||||
|
||||
xx = 'm' in name
|
||||
xx = 5 in values
|
||||
@ -408,6 +414,7 @@ class TestCompilerOnRanges: FunSpec({
|
||||
xx = xx in [2,4,6,8]
|
||||
xx = ww in [9000,8000,7000]
|
||||
xx = ww in wvalues
|
||||
xx = ww in wnsvalues
|
||||
}
|
||||
}""", writeAssembly = true) shouldNotBe null
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ class TestCompilerOptionSourcedirs: FunSpec({
|
||||
slabsHighBank = null,
|
||||
slabsGolden = false,
|
||||
compilationTarget = Cx16Target.NAME,
|
||||
splitWordArrays = false,
|
||||
dontSplitWordArrays = false,
|
||||
breakpointCpuInstruction = null,
|
||||
printAst1 = false,
|
||||
printAst2 = false,
|
||||
|
@ -111,7 +111,7 @@ class TestMemory: FunSpec({
|
||||
}
|
||||
|
||||
fun createTestProgramForMemoryRefViaVar(address: UInt, vartype: VarDeclType): AssignTarget {
|
||||
val decl = VarDecl(vartype, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.BYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, false, 0u, false, Position.DUMMY)
|
||||
val decl = VarDecl(vartype, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.BYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, 0u, false, Position.DUMMY)
|
||||
val memexpr = IdentifierReference(listOf("address"), Position.DUMMY)
|
||||
val target = AssignTarget(null, null, DirectMemoryWrite(memexpr, Position.DUMMY), null, false, Position.DUMMY)
|
||||
val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
|
||||
@ -149,7 +149,7 @@ class TestMemory: FunSpec({
|
||||
}
|
||||
|
||||
test("regular variable not in mapped IO ram on C64") {
|
||||
val decl = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.BYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), null, false, false, 0u, false, Position.DUMMY)
|
||||
val decl = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.BYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), null, false, 0u, false, Position.DUMMY)
|
||||
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, null, false, Position.DUMMY)
|
||||
val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
|
||||
val subroutine = Subroutine("test", mutableListOf(), mutableListOf(), emptyList(), emptyList(), emptySet(), null, false, false, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||
@ -161,7 +161,7 @@ class TestMemory: FunSpec({
|
||||
|
||||
test("memory mapped variable not in mapped IO ram on C64") {
|
||||
val address = 0x1000u
|
||||
val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, false, 0u, false, Position.DUMMY)
|
||||
val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, 0u, false, Position.DUMMY)
|
||||
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, null, false, Position.DUMMY)
|
||||
val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
|
||||
val subroutine = Subroutine("test", mutableListOf(), mutableListOf(), emptyList(), emptyList(), emptySet(), null, false, false, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||
@ -173,7 +173,7 @@ class TestMemory: FunSpec({
|
||||
|
||||
test("memory mapped variable in mapped IO ram on C64") {
|
||||
val address = 0xd020u
|
||||
val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, false, 0u, false, Position.DUMMY)
|
||||
val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, 0u, false, Position.DUMMY)
|
||||
val target = AssignTarget(IdentifierReference(listOf("address"), Position.DUMMY), null, null, null, false, Position.DUMMY)
|
||||
val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
|
||||
val subroutine = Subroutine("test", mutableListOf(), mutableListOf(), emptyList(), emptyList(), emptySet(), null, false, false, false, mutableListOf(decl, assignment), Position.DUMMY)
|
||||
@ -184,7 +184,7 @@ class TestMemory: FunSpec({
|
||||
}
|
||||
|
||||
test("array not in mapped IO ram") {
|
||||
val decl = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.arrayFor(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), null, false, false, 0u, false, Position.DUMMY)
|
||||
val decl = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.arrayFor(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), null, false, 0u, false, Position.DUMMY)
|
||||
val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteral.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY)
|
||||
val target = AssignTarget(null, arrayindexed, null, null, false, Position.DUMMY)
|
||||
val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
|
||||
@ -197,7 +197,7 @@ class TestMemory: FunSpec({
|
||||
|
||||
test("memory mapped array not in mapped IO ram") {
|
||||
val address = 0x1000u
|
||||
val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.arrayFor(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, false, 0u, false, Position.DUMMY)
|
||||
val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.arrayFor(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, 0u, false, Position.DUMMY)
|
||||
val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteral.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY)
|
||||
val target = AssignTarget(null, arrayindexed, null, null, false, Position.DUMMY)
|
||||
val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
|
||||
@ -210,7 +210,7 @@ class TestMemory: FunSpec({
|
||||
|
||||
test("memory mapped array in mapped IO ram") {
|
||||
val address = 0xd800u
|
||||
val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.arrayFor(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, false, 0u, false, Position.DUMMY)
|
||||
val decl = VarDecl(VarDeclType.MEMORY, VarDeclOrigin.USERCODE, DataType.arrayFor(BaseDataType.UBYTE), ZeropageWish.DONTCARE, null, "address", emptyList(), NumericLiteral.optimalInteger(address, Position.DUMMY), false, 0u, false, Position.DUMMY)
|
||||
val arrayindexed = ArrayIndexedExpression(IdentifierReference(listOf("address"), Position.DUMMY), ArrayIndex(NumericLiteral.optimalInteger(1, Position.DUMMY), Position.DUMMY), Position.DUMMY)
|
||||
val target = AssignTarget(null, arrayindexed, null, null, false, Position.DUMMY)
|
||||
val assignment = Assignment(target, NumericLiteral.optimalInteger(0, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
|
||||
|
@ -261,9 +261,9 @@ main {
|
||||
val src="""
|
||||
main {
|
||||
sub start() {
|
||||
&uword[30] wb = ${'$'}2000
|
||||
&uword[100] array1 = ${'$'}9e00
|
||||
&uword[30] array2 = &array1[len(wb)]
|
||||
&uword[30] @nosplit wb = ${'$'}2000
|
||||
&uword[100] @nosplit array1 = ${'$'}9e00
|
||||
&uword[30] @nosplit array2 = &array1[len(wb)]
|
||||
|
||||
cx16.r0 = &array1 ; ${'$'}9e00
|
||||
cx16.r1 = &array1[len(wb)] ; ${'$'}9e3c
|
||||
@ -291,7 +291,7 @@ main {
|
||||
cx16.r0 = &array
|
||||
|
||||
const uword HIGH_MEMORY_START = 40960
|
||||
&uword[20] @shared wa = HIGH_MEMORY_START
|
||||
&uword[20] @shared @nosplit wa = HIGH_MEMORY_START
|
||||
}
|
||||
}"""
|
||||
val result = compileText(Cx16Target(), optimize=false, src, writeAssembly=true)!!
|
||||
|
@ -87,32 +87,6 @@ main {
|
||||
}"""
|
||||
compileText(VMTarget(), optimize=false, src, writeAssembly=false) shouldNotBe null
|
||||
}
|
||||
|
||||
test("split arrays back to normal when address is taken") {
|
||||
val src="""
|
||||
main {
|
||||
sub start() {
|
||||
cx16.r0L=0
|
||||
if cx16.r0L==0 {
|
||||
uword[] addresses = [scores2, start]
|
||||
uword[] @split scores1 = [10, 25, 50, 100]
|
||||
uword[] @split scores2 = [100, 250, 500, 1000]
|
||||
|
||||
cx16.r0 = &scores1
|
||||
cx16.r1 = &scores2
|
||||
cx16.r2 = &addresses
|
||||
}
|
||||
}
|
||||
}"""
|
||||
val errors = ErrorReporterForTests(keepMessagesAfterReporting = true)
|
||||
compileText(C64Target(), optimize=false, src, writeAssembly=true, errors=errors) shouldNotBe null
|
||||
errors.errors.size shouldBe 0
|
||||
errors.warnings.size shouldBe 2
|
||||
errors.warnings[0] shouldContain("address")
|
||||
errors.warnings[1] shouldContain("address")
|
||||
errors.warnings[0] shouldContain("split")
|
||||
errors.warnings[1] shouldContain("split")
|
||||
}
|
||||
}
|
||||
|
||||
context("alias") {
|
||||
@ -911,16 +885,12 @@ main {
|
||||
shouldThrow<NoSuchElementException> {
|
||||
DataType.arrayFor(BaseDataType.UNDEFINED)
|
||||
}
|
||||
shouldThrow<IllegalArgumentException> {
|
||||
DataType.arrayFor(BaseDataType.UBYTE, true)
|
||||
}
|
||||
|
||||
DataType.arrayFor(BaseDataType.UBYTE, true).isUnsignedByteArray shouldBe true
|
||||
DataType.arrayFor(BaseDataType.FLOAT).isFloatArray shouldBe true
|
||||
DataType.arrayFor(BaseDataType.UWORD).isUnsignedWordArray shouldBe true
|
||||
DataType.arrayFor(BaseDataType.UWORD).isArray shouldBe true
|
||||
DataType.arrayFor(BaseDataType.UWORD).isSplitWordArray shouldBe false
|
||||
DataType.arrayFor(BaseDataType.UWORD, true).isArray shouldBe true
|
||||
DataType.arrayFor(BaseDataType.UWORD, true).isSplitWordArray shouldBe true
|
||||
DataType.arrayFor(BaseDataType.UWORD).isSplitWordArray shouldBe true
|
||||
DataType.arrayFor(BaseDataType.UWORD, false).isSplitWordArray shouldBe false
|
||||
}
|
||||
|
||||
test("array of strings becomes array of uword pointers") {
|
||||
|
@ -98,8 +98,8 @@ main {
|
||||
test("split only for word arrays") {
|
||||
val srcGood = """
|
||||
main {
|
||||
uword[10] @split sw
|
||||
word[10] @split sw2
|
||||
uword[10] @nosplit sw
|
||||
word[10] @nosplit sw2
|
||||
|
||||
sub start() {
|
||||
}
|
||||
@ -108,7 +108,7 @@ main {
|
||||
|
||||
val srcWrong1 = """
|
||||
main {
|
||||
ubyte[10] @split sb
|
||||
ubyte[10] @nosplit sb
|
||||
|
||||
sub start() {
|
||||
}
|
||||
@ -116,12 +116,12 @@ main {
|
||||
val errors = ErrorReporterForTests()
|
||||
compileText(C64Target(), false, srcWrong1, writeAssembly = false, errors=errors) shouldBe null
|
||||
errors.errors.size shouldBe 1
|
||||
errors.errors[0] shouldContain "split can only be used on word arrays"
|
||||
errors.errors[0] shouldContain "nosplit can only be used on word arrays"
|
||||
|
||||
val srcWrong2 = """
|
||||
%option enable_floats
|
||||
main {
|
||||
float[10] @split sf
|
||||
float[10] @nosplit sf
|
||||
|
||||
sub start() {
|
||||
}
|
||||
@ -129,15 +129,15 @@ main {
|
||||
errors.clear()
|
||||
compileText(C64Target(), false, srcWrong2, writeAssembly = false, errors=errors) shouldBe null
|
||||
errors.errors.size shouldBe 1
|
||||
errors.errors[0] shouldContain "split can only be used on word arrays"
|
||||
errors.errors[0] shouldContain "nosplit can only be used on word arrays"
|
||||
}
|
||||
|
||||
test("split word arrays in asm as lsb/msb") {
|
||||
test("split word arrays in asm as lsb/msb, nosplit as single linear") {
|
||||
val text = """
|
||||
main {
|
||||
uword[10] @split @shared uw
|
||||
word[10] @split @shared sw
|
||||
uword[10] @shared normal
|
||||
uword[10] @shared uw
|
||||
word[10] @shared sw
|
||||
uword[10] @shared @nosplit normal
|
||||
|
||||
sub start() {
|
||||
%asm {{
|
||||
@ -170,7 +170,8 @@ main {
|
||||
val text = """
|
||||
main {
|
||||
sub start() {
|
||||
uword[3] @zp @split @shared thearray
|
||||
uword[3] @zp @shared thearray
|
||||
uword[3] @zp @nosplit @shared thearray2
|
||||
}
|
||||
}"""
|
||||
val result = compileText(C64Target(), false, text, writeAssembly = true)!!
|
||||
@ -178,6 +179,7 @@ main {
|
||||
val assembly = assemblyFile.readText()
|
||||
assembly shouldContain "thearray_lsb"
|
||||
assembly shouldContain "thearray_msb"
|
||||
assembly shouldContain "thearray2"
|
||||
}
|
||||
|
||||
test("indexing str or pointervar with expression") {
|
||||
@ -419,5 +421,31 @@ main {
|
||||
compileText(VMTarget(), false, src, writeAssembly = true) shouldNotBe null
|
||||
compileText(C64Target(), false, src, writeAssembly = true) shouldNotBe null
|
||||
}
|
||||
|
||||
test("taking address of split arrays") {
|
||||
val src="""
|
||||
main {
|
||||
sub start() {
|
||||
cx16.r0L=0
|
||||
if cx16.r0L==0 {
|
||||
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
|
||||
}
|
||||
}
|
||||
}"""
|
||||
val errors = ErrorReporterForTests(keepMessagesAfterReporting = true)
|
||||
compileText(C64Target(), optimize=false, src, writeAssembly=true, errors=errors) shouldNotBe null
|
||||
errors.errors.size shouldBe 0
|
||||
errors.warnings.size shouldBe 2
|
||||
errors.warnings[0] shouldContain("address")
|
||||
errors.warnings[1] shouldContain("address")
|
||||
errors.warnings[0] shouldContain("split")
|
||||
errors.warnings[1] shouldContain("split")
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -46,8 +46,8 @@ class TestAsmGenSymbols: StringSpec({
|
||||
}
|
||||
|
||||
*/
|
||||
val varInSub = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UWORD), ZeropageWish.DONTCARE, null, "localvar", emptyList(), NumericLiteral.optimalInteger(1234, Position.DUMMY), false, false, 0u, false, Position.DUMMY)
|
||||
val var2InSub = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UWORD), ZeropageWish.DONTCARE, null, "tgt", emptyList(), null, false, false, 0u, false, Position.DUMMY)
|
||||
val varInSub = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UWORD), ZeropageWish.DONTCARE, null, "localvar", emptyList(), NumericLiteral.optimalInteger(1234, Position.DUMMY), false, 0u, false, Position.DUMMY)
|
||||
val var2InSub = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UWORD), ZeropageWish.DONTCARE, null, "tgt", emptyList(), null, false, 0u, false, Position.DUMMY)
|
||||
val labelInSub = Label("locallabel", Position.DUMMY)
|
||||
|
||||
val tgt = AssignTarget(IdentifierReference(listOf("tgt"), Position.DUMMY), null, null, null, false, Position.DUMMY)
|
||||
@ -63,7 +63,7 @@ class TestAsmGenSymbols: StringSpec({
|
||||
val statements = mutableListOf(varInSub, var2InSub, labelInSub, assign1, assign2, assign3, assign4, assign5, assign6, assign7, assign8)
|
||||
val subroutine = Subroutine("start", mutableListOf(), mutableListOf(), emptyList(), emptyList(), emptySet(), null, false, false, false, statements, Position.DUMMY)
|
||||
val labelInBlock = Label("label_outside", Position.DUMMY)
|
||||
val varInBlock = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UWORD), ZeropageWish.DONTCARE, null, "var_outside", emptyList(),null, false, false, 0u, false, Position.DUMMY)
|
||||
val varInBlock = VarDecl(VarDeclType.VAR, VarDeclOrigin.USERCODE, DataType.forDt(BaseDataType.UWORD), ZeropageWish.DONTCARE, null, "var_outside", emptyList(),null, false, 0u, false, Position.DUMMY)
|
||||
val block = Block("main", null, mutableListOf(labelInBlock, varInBlock, subroutine), false, Position.DUMMY)
|
||||
|
||||
val module = Module(mutableListOf(block), Position.DUMMY, SourceCode.Generated("test"))
|
||||
|
@ -39,7 +39,7 @@ internal fun compileFile(
|
||||
symbolDefs = emptyMap(),
|
||||
outputDir = outputDir,
|
||||
errors = errors ?: ErrorReporterForTests(),
|
||||
splitWordArrays = false,
|
||||
dontSplitWordArrays = false,
|
||||
breakpointCpuInstruction = null,
|
||||
printAst1 = false,
|
||||
printAst2 = false,
|
||||
|
@ -88,7 +88,7 @@ class Program(val name: String,
|
||||
val varName = "string_${internedStringsBlock.statements.size}"
|
||||
val decl = VarDecl(
|
||||
VarDeclType.VAR, VarDeclOrigin.STRINGLITERAL, DataType.forDt(BaseDataType.STR), ZeropageWish.NOT_IN_ZEROPAGE, null, varName, emptyList(), string,
|
||||
sharedWithAsm = false, splitArray = false, alignment = 0u, dirty = false, position = string.position
|
||||
sharedWithAsm = false, alignment = 0u, dirty = false, position = string.position
|
||||
)
|
||||
internedStringsBlock.statements.add(decl)
|
||||
decl.linkParents(internedStringsBlock)
|
||||
|
@ -758,20 +758,14 @@ private fun VardeclContext.toAst(type: VarDeclType, value: Expression?): VarDecl
|
||||
val identifiername = identifiers[0].NAME() ?: identifiers[0].UNDERSCORENAME()
|
||||
val name = if(identifiers.size==1) identifiername.text else "<multiple>"
|
||||
val isArray = ARRAYSIG() != null || arrayindex() != null
|
||||
val split = options.SPLIT().isNotEmpty()
|
||||
val nosplit = options.NOSPLIT().isNotEmpty()
|
||||
val alignword = options.ALIGNWORD().isNotEmpty()
|
||||
val align64 = options.ALIGN64().isNotEmpty()
|
||||
val alignpage = options.ALIGNPAGE().isNotEmpty()
|
||||
if(alignpage && alignword)
|
||||
throw SyntaxError("choose a single alignment option", toPosition())
|
||||
val baseDt = datatype()?.toAst() ?: BaseDataType.UNDEFINED
|
||||
val origDt = DataType.forDt(baseDt)
|
||||
val dt = if(isArray) {
|
||||
if(split && origDt.isWord)
|
||||
origDt.elementToArray(split)
|
||||
else
|
||||
origDt.elementToArray(false) // type error will be generated later in the ast check
|
||||
} else origDt
|
||||
val dt = if(isArray) DataType.arrayFor(baseDt, nosplit!=true) else DataType.forDt(baseDt)
|
||||
|
||||
return VarDecl(
|
||||
type, VarDeclOrigin.USERCODE,
|
||||
@ -785,7 +779,6 @@ private fun VardeclContext.toAst(type: VarDeclType, value: Expression?): VarDecl
|
||||
},
|
||||
value,
|
||||
options.SHARED().isNotEmpty(),
|
||||
split,
|
||||
if(alignword) 2u else if(align64) 64u else if(alignpage) 256u else 0u,
|
||||
options.DIRTY().isNotEmpty(),
|
||||
toPosition()
|
||||
|
@ -91,7 +91,7 @@ object InferredTypes {
|
||||
}
|
||||
}
|
||||
type.isArray -> {
|
||||
InferredType.known(DataType.arrayFor(type.sub!!.dt))
|
||||
InferredType.known(DataType.arrayFor(type.sub!!.dt, false))
|
||||
}
|
||||
else -> throw IllegalArgumentException("invalid type")
|
||||
}
|
||||
|
@ -247,7 +247,6 @@ class VarDecl(val type: VarDeclType,
|
||||
val names: List<String>,
|
||||
var value: Expression?,
|
||||
val sharedWithAsm: Boolean,
|
||||
val splitArray: Boolean,
|
||||
val alignment: UInt,
|
||||
val dirty: Boolean,
|
||||
override val position: Position) : Statement(), INamedStatement {
|
||||
@ -273,27 +272,21 @@ class VarDecl(val type: VarDeclType,
|
||||
val dt = if(param.type.isArray) DataType.forDt(BaseDataType.UWORD) else param.type
|
||||
return VarDecl(decltype, VarDeclOrigin.SUBROUTINEPARAM, dt, param.zp, null, param.name, emptyList(), value,
|
||||
sharedWithAsm = false,
|
||||
splitArray = false,
|
||||
alignment = 0u,
|
||||
dirty = false,
|
||||
position = param.position
|
||||
)
|
||||
}
|
||||
|
||||
fun createAuto(array: ArrayLiteral, splitArray: Boolean): VarDecl {
|
||||
fun createAuto(array: ArrayLiteral): VarDecl {
|
||||
val autoVarName = "auto_heap_value_${++autoHeapValueSequenceNumber}"
|
||||
val arrayDt = array.type.getOrElse { throw FatalAstException("unknown dt") }
|
||||
val arraysize = ArrayIndex.forArray(array)
|
||||
return VarDecl(VarDeclType.VAR, VarDeclOrigin.ARRAYLITERAL, arrayDt, ZeropageWish.NOT_IN_ZEROPAGE, arraysize, autoVarName, emptyList(), array,
|
||||
sharedWithAsm = false, splitArray = splitArray, alignment = 0u, dirty = false, position = array.position)
|
||||
sharedWithAsm = false, alignment = 0u, dirty = false, position = array.position)
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
if(datatype.isSplitWordArray)
|
||||
require(splitArray)
|
||||
}
|
||||
|
||||
val isArray: Boolean
|
||||
get() = datatype.isArray
|
||||
|
||||
@ -329,7 +322,7 @@ class VarDecl(val type: VarDeclType,
|
||||
if(names.size>1)
|
||||
throw FatalAstException("should not copy a vardecl that still has multiple names")
|
||||
val copy = VarDecl(type, origin, newDatatype, zeropage, arraysize?.copy(), name, names, value?.copy(),
|
||||
sharedWithAsm, splitArray, alignment, dirty, position)
|
||||
sharedWithAsm, alignment, dirty, position)
|
||||
copy.allowInitializeWithZero = this.allowInitializeWithZero
|
||||
return copy
|
||||
}
|
||||
@ -344,19 +337,19 @@ class VarDecl(val type: VarDeclType,
|
||||
// just copy the initialization value to a separate vardecl for each component
|
||||
return names.map {
|
||||
val copy = VarDecl(type, origin, datatype, zeropage, arraysize?.copy(), it, emptyList(), value?.copy(),
|
||||
sharedWithAsm, splitArray, alignment, dirty, position)
|
||||
sharedWithAsm, alignment, dirty, position)
|
||||
copy.allowInitializeWithZero = this.allowInitializeWithZero
|
||||
copy
|
||||
}
|
||||
} else {
|
||||
// evaluate the value once in the vardecl for the first component, and set the other components to the first
|
||||
val first = VarDecl(type, origin, datatype, zeropage, arraysize?.copy(), names[0], emptyList(), value?.copy(),
|
||||
sharedWithAsm, splitArray, alignment, dirty, position)
|
||||
sharedWithAsm, alignment, dirty, position)
|
||||
first.allowInitializeWithZero = this.allowInitializeWithZero
|
||||
val firstVar = firstVarAsValue(first)
|
||||
return listOf(first) + names.drop(1 ).map {
|
||||
val copy = VarDecl(type, origin, datatype, zeropage, arraysize?.copy(), it, emptyList(), firstVar.copy(),
|
||||
sharedWithAsm, splitArray, alignment, dirty, position)
|
||||
sharedWithAsm, alignment, dirty, position)
|
||||
copy.allowInitializeWithZero = this.allowInitializeWithZero
|
||||
copy
|
||||
}
|
||||
|
@ -156,6 +156,10 @@ One or more .p8 module files
|
||||
Add this user-defined symbol directly to the beginning of the generated assembly file.
|
||||
Can be repeated to define multiple symbols.
|
||||
|
||||
``-dontsplitarrays``
|
||||
Treat all word arrays as tagged with @nosplit so they are all stored linearly in memory,
|
||||
instead of splitting them in separate lsb and msb arrays.
|
||||
|
||||
``-dumpsymbols``
|
||||
print a dump of the variable declarations and subroutine signatures
|
||||
|
||||
@ -219,11 +223,6 @@ One or more .p8 module files
|
||||
mixed in between the actual generated assembly code.
|
||||
This can be useful for debugging purposes to see what assembly was generated for what prog8 source code.
|
||||
|
||||
``-splitarrays``
|
||||
Treat all word arrays as tagged with @split so they are all lsb/msb split into memory.
|
||||
This removes the need to add @split yourself but some programs may fail to compile with
|
||||
this option as not all array operations are implemented yet on split arrays.
|
||||
|
||||
``-srcdirs <pathlist>``
|
||||
Specify a list of extra paths (separated with ':'), to search in for imported modules.
|
||||
Useful if you have library modules somewhere that you want to re-use,
|
||||
|
@ -403,7 +403,6 @@ Directives
|
||||
Overriding (monkeypatching) happens only if the signature of the subroutine exactly matches the original subroutine, including the exact names and types of the parameters.
|
||||
Where blocks with this option are merged into is intricate: it looks for the first other block with the same name that does not have %option merge,
|
||||
if that can't be found, select the first occurrence regardless. If no other blocks are found, no merge is done. Blocks in libraries are considered first to merge into.
|
||||
- ``splitarrays`` (block or module) makes all word-arrays in this scope lsb/msb split arrays (as if they all have the @split tag). See Arrays.
|
||||
- ``no_symbol_prefixing`` (block or module) makes the compiler *not* use symbol-prefixing when translating prog8 code into assembly.
|
||||
Only use this if you know what you're doing because it could result in invalid assembly code being generated.
|
||||
This option can be useful when writing library modules that you don't want to be exposing prefixed assembly symbols.
|
||||
|
@ -1,9 +1,15 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
- 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.
|
||||
- add &< and &> operators to get the address of the lsb-array and msb-array, respectively. Regular & will just return the start of the split array in memory whatever byte comes first.
|
||||
- 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.
|
||||
- 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.)
|
||||
- test all examples
|
||||
|
||||
...
|
||||
|
||||
|
@ -61,7 +61,7 @@ Tag Effect
|
||||
@requirezp force the variable into Zero page. If ZP is full, compilation will fail.
|
||||
@nozp force the variable to normal system ram, never place it into zeropage.
|
||||
@shared means the variable is shared with some assembly code and that it cannot be optimized away if not used elsewhere.
|
||||
@split (only valid on (u)word arrays) Makes the array to be placed in memory as 2 separate byte arrays; one with the LSBs one with the MSBs of the word values. Usually improves performance and code size.
|
||||
@nosplit (only valid on (u)word arrays) Store the array as a single inear array instead of a separate array for lsb and msb values
|
||||
@alignword aligns string or array variable on an even memory address
|
||||
@align64 aligns string or array variable on a 64 byte address interval (example: for C64 sprite data)
|
||||
@alignpage aligns string or array variable on a 256 byte address interval (example: to avoid page boundaries)
|
||||
|
@ -71,7 +71,7 @@ sub print_notes(ubyte n1, ubyte n2) {
|
||||
]
|
||||
|
||||
|
||||
uword[] @split music_freq_table = [
|
||||
uword[] music_freq_table = [
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
732, 778, 826, 876, 928, 978, 1042, 1100, 1170, 1238, 1312, 1390, 1464, 1556,
|
||||
1652, 1752, 1856, 1956, 2084, 2200, 2340, 2476, 2624, 2780, 2928, 3112, 3304,
|
||||
|
@ -8,14 +8,14 @@ main {
|
||||
const uword height = 200
|
||||
|
||||
; vertices
|
||||
word[] @split xcoor = [ -100, -100, -100, -100, 100, 100, 100, 100 ]
|
||||
word[] @split ycoor = [ -100, -100, 100, 100, -100, -100, 100, 100 ]
|
||||
word[] @split zcoor = [ -100, 100, -100, 100, -100, 100, -100, 100 ]
|
||||
word[] xcoor = [ -100, -100, -100, -100, 100, 100, 100, 100 ]
|
||||
word[] ycoor = [ -100, -100, 100, 100, -100, -100, 100, 100 ]
|
||||
word[] zcoor = [ -100, 100, -100, 100, -100, 100, -100, 100 ]
|
||||
|
||||
; storage for rotated coordinates
|
||||
word[len(xcoor)] @split rotatedx
|
||||
word[len(ycoor)] @split rotatedy
|
||||
word[len(zcoor)] @split rotatedz
|
||||
word[len(xcoor)] rotatedx
|
||||
word[len(ycoor)] rotatedy
|
||||
word[len(zcoor)] rotatedz
|
||||
|
||||
|
||||
sub start() {
|
||||
|
@ -6,14 +6,14 @@
|
||||
main {
|
||||
|
||||
; vertices
|
||||
word[] @split xcoor = [ -40, -40, -40, -40, 40, 40, 40, 40 ]
|
||||
word[] @split ycoor = [ -40, -40, 40, 40, -40, -40, 40, 40 ]
|
||||
word[] @split zcoor = [ -40, 40, -40, 40, -40, 40, -40, 40 ]
|
||||
word[] xcoor = [ -40, -40, -40, -40, 40, 40, 40, 40 ]
|
||||
word[] ycoor = [ -40, -40, 40, 40, -40, -40, 40, 40 ]
|
||||
word[] zcoor = [ -40, 40, -40, 40, -40, 40, -40, 40 ]
|
||||
|
||||
; storage for rotated coordinates
|
||||
word[len(xcoor)] @split rotatedx
|
||||
word[len(ycoor)] @split rotatedy
|
||||
word[len(zcoor)] @split rotatedz
|
||||
word[len(xcoor)] rotatedx
|
||||
word[len(ycoor)] rotatedy
|
||||
word[len(zcoor)] rotatedz
|
||||
|
||||
sub start() {
|
||||
|
||||
|
@ -7,14 +7,14 @@
|
||||
main {
|
||||
|
||||
; vertices
|
||||
word[] @split xcoor = [ -100, -100, -100, -100, 100, 100, 100, 100 ]
|
||||
word[] @split ycoor = [ -100, -100, 100, 100, -100, -100, 100, 100 ]
|
||||
word[] @split zcoor = [ -100, 100, -100, 100, -100, 100, -100, 100 ]
|
||||
word[] xcoor = [ -100, -100, -100, -100, 100, 100, 100, 100 ]
|
||||
word[] ycoor = [ -100, -100, 100, 100, -100, -100, 100, 100 ]
|
||||
word[] zcoor = [ -100, 100, -100, 100, -100, 100, -100, 100 ]
|
||||
|
||||
; storage for rotated coordinates
|
||||
word[len(xcoor)] @split rotatedx
|
||||
word[len(ycoor)] @split rotatedy
|
||||
word[len(zcoor)] @split rotatedz
|
||||
word[len(xcoor)] rotatedx
|
||||
word[len(ycoor)] rotatedy
|
||||
word[len(zcoor)] rotatedz
|
||||
|
||||
; edges
|
||||
ubyte[] edgesFrom = [ 0, 2, 6, 4, 1, 3, 7, 5, 0, 2, 6, 4]
|
||||
|
@ -115,7 +115,7 @@ main {
|
||||
$3532, $322e, $2e29, $2926, $2730, $242c, $2027, $1420
|
||||
]
|
||||
|
||||
uword[] @split vera_freqs = [
|
||||
uword[] vera_freqs = [
|
||||
0,0,0,0,0,0,0,0,0,0, ; first 10 notes are not used
|
||||
120, 127, 135, 143, 152, 160, 170, 180, 191, 203,
|
||||
215, 227, 240, 255, 270, 287, 304, 320, 341, 360,
|
||||
|
@ -5,8 +5,8 @@
|
||||
main {
|
||||
const ubyte MAX_NUM_CIRCLES = 80
|
||||
const ubyte GROWTH_RATE = 2
|
||||
uword[MAX_NUM_CIRCLES] @split circle_x
|
||||
uword[MAX_NUM_CIRCLES] @split circle_y
|
||||
uword[MAX_NUM_CIRCLES] circle_x
|
||||
uword[MAX_NUM_CIRCLES] circle_y
|
||||
ubyte[MAX_NUM_CIRCLES] circle_radius
|
||||
ubyte num_circles = 0
|
||||
ubyte background_color
|
||||
|
@ -165,9 +165,9 @@ matrix_math {
|
||||
%option verafxmuls ; accellerate all word-multiplications in this block using Vera FX hardware muls
|
||||
|
||||
; storage for rotated coordinates
|
||||
word[shipdata.totalNumberOfPoints] @split rotatedx
|
||||
word[shipdata.totalNumberOfPoints] @split rotatedy
|
||||
word[shipdata.totalNumberOfPoints] @split rotatedz
|
||||
word[shipdata.totalNumberOfPoints] rotatedx
|
||||
word[shipdata.totalNumberOfPoints] rotatedy
|
||||
word[shipdata.totalNumberOfPoints] rotatedz
|
||||
|
||||
sub rotate_vertices(ubyte ax, ubyte ay, ubyte az) {
|
||||
; rotate around origin (0,0,0)
|
||||
@ -230,9 +230,9 @@ const ubyte totalNumberOfFaces = 22
|
||||
const ubyte totalNumberOfPoints = 34
|
||||
str shipName = "cobra-mk3"
|
||||
; vertices
|
||||
word[totalNumberOfPoints] @split xcoor = [ 32,-32,0,-120,120,-88,88,128,-128,0,-32,32,-36,-8,8,36,36,8,-8,-36,-1,-1,-80,-80,-88,80,88,80,1,1,1,1,-1,-1 ]
|
||||
word[totalNumberOfPoints] @split ycoor = [ 0,0,26,-3,-3,16,16,-8,-8,26,-24,-24,8,12,12,8,-12,-16,-16,-12,-1,-1,-6,6,0,6,0,-6,-1,-1,1,1,1,1 ]
|
||||
word[totalNumberOfPoints] @split zcoor = [ 76,76,24,-8,-8,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,76,90,-40,-40,-40,-40,-40,-40,76,90,76,90,76,90 ]
|
||||
word[totalNumberOfPoints] xcoor = [ 32,-32,0,-120,120,-88,88,128,-128,0,-32,32,-36,-8,8,36,36,8,-8,-36,-1,-1,-80,-80,-88,80,88,80,1,1,1,1,-1,-1 ]
|
||||
word[totalNumberOfPoints] ycoor = [ 0,0,26,-3,-3,16,16,-8,-8,26,-24,-24,8,12,12,8,-12,-16,-16,-12,-1,-1,-6,6,0,6,0,-6,-1,-1,1,1,1,1 ]
|
||||
word[totalNumberOfPoints] zcoor = [ 76,76,24,-8,-8,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,76,90,-40,-40,-40,-40,-40,-40,76,90,76,90,76,90 ]
|
||||
; edges and faces
|
||||
ubyte[totalNumberOfEdges] edgesFrom = [ 0,1,0,10,1,0,2,0,4,0,4,7,2,1,1,3,8,3,2,5,6,5,6,16,15,14,14,18,13,12,12,26,25,25,22,23,22,20,28,21,20,28,29,30,31,30,32,20,21,20,20 ]
|
||||
ubyte[totalNumberOfEdges] edgesTo = [ 1,2,2,11,10,11,6,6,6,4,7,11,5,5,3,5,10,8,9,9,9,8,7,17,16,15,17,19,18,13,19,27,26,27,23,24,24,28,29,29,21,30,31,31,33,32,33,32,33,33,29 ]
|
||||
|
@ -58,14 +58,14 @@ matrix_math {
|
||||
%option verafxmuls ; accellerate all word-multiplications in this block using Vera FX hardware muls
|
||||
|
||||
; vertices
|
||||
word[] @split xcoor = [ -40, -40, -40, -40, 40, 40, 40, 40 ]
|
||||
word[] @split ycoor = [ -40, -40, 40, 40, -40, -40, 40, 40 ]
|
||||
word[] @split zcoor = [ -40, 40, -40, 40, -40, 40, -40, 40 ]
|
||||
word[] xcoor = [ -40, -40, -40, -40, 40, 40, 40, 40 ]
|
||||
word[] ycoor = [ -40, -40, 40, 40, -40, -40, 40, 40 ]
|
||||
word[] zcoor = [ -40, 40, -40, 40, -40, 40, -40, 40 ]
|
||||
|
||||
; storage for rotated coordinates
|
||||
word[len(xcoor)] @split rotatedx
|
||||
word[len(ycoor)] @split rotatedy
|
||||
word[len(zcoor)] @split rotatedz
|
||||
word[len(xcoor)] rotatedx
|
||||
word[len(ycoor)] rotatedy
|
||||
word[len(zcoor)] rotatedz
|
||||
|
||||
sub rotate_vertices(ubyte ax, ubyte ay, ubyte az) {
|
||||
; rotate around origin (0,0,0)
|
||||
|
@ -29,7 +29,7 @@ adpcm {
|
||||
|
||||
|
||||
byte[] t_index = [ -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8]
|
||||
uword[] @split t_step = [
|
||||
uword[] t_step = [
|
||||
7, 8, 9, 10, 11, 12, 13, 14,
|
||||
16, 17, 19, 21, 23, 25, 28, 31,
|
||||
34, 37, 41, 45, 50, 55, 60, 66,
|
||||
|
@ -316,8 +316,8 @@ main {
|
||||
cx16.VERA_DATA0 = msb(fill_rgb)
|
||||
}
|
||||
|
||||
uword[22] @split outline_color = [$090,$190,$290,$390,$490,$590,$690,$790,$990,$980,$970,$960,$950,$940,$a30,$a00,$a00,$a00,$a00,$a00, $111, $148]
|
||||
uword[22] @split fill_color = [$0f0,$2f0,$4f0,$6f0,$8f0,$af0,$cf0,$ef0,$ff0,$fe0,$fc0,$fa0,$f80,$f60,$f40,$f00,$f01,$f02,$f03,$f04, $000, $28f]
|
||||
uword[22] outline_color = [$090,$190,$290,$390,$490,$590,$690,$790,$990,$980,$970,$960,$950,$940,$a30,$a00,$a00,$a00,$a00,$a00, $111, $148]
|
||||
uword[22] fill_color = [$0f0,$2f0,$4f0,$6f0,$8f0,$af0,$cf0,$ef0,$ff0,$fe0,$fc0,$fa0,$f80,$f60,$f40,$f00,$f01,$f02,$f03,$f04, $000, $28f]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,9 +5,9 @@ main {
|
||||
sub start() {
|
||||
gfx_lores.graphics_mode()
|
||||
|
||||
uword[128] @split flakes1_xx
|
||||
uword[128] flakes1_xx
|
||||
ubyte[128] flakes1_yy
|
||||
uword[128] @split flakes2_xx
|
||||
uword[128] flakes2_xx
|
||||
ubyte[128] flakes2_yy
|
||||
|
||||
ubyte @zp idx
|
||||
|
@ -18,10 +18,10 @@ main {
|
||||
const ubyte CIRCLE_SKIP = 256/NUM_STARS
|
||||
|
||||
ubyte[NUM_STARS] color
|
||||
uword[NUM_STARS] @split radius
|
||||
uword[NUM_STARS] @split accel
|
||||
uword[NUM_STARS] @split speed
|
||||
uword[NUM_STARS] @split prev_x
|
||||
uword[NUM_STARS] radius
|
||||
uword[NUM_STARS] accel
|
||||
uword[NUM_STARS] speed
|
||||
uword[NUM_STARS] prev_x
|
||||
ubyte[NUM_STARS] prev_y
|
||||
|
||||
gfx_lores.graphics_mode()
|
||||
|
@ -1,18 +1,15 @@
|
||||
%import textio
|
||||
%zeropage basicsafe
|
||||
|
||||
main {
|
||||
uword[] array = [1000, 2000, 9000, 8000, 5000]
|
||||
sub start() {
|
||||
goto $3000
|
||||
goto labeltje
|
||||
|
||||
goto cx16.r0
|
||||
|
||||
goto cx16.r0+cx16.r1
|
||||
|
||||
if cx16.r0==0
|
||||
goto cx16.r0+cx16.r1
|
||||
|
||||
if cx16.r0>2000
|
||||
goto cx16.r0+cx16.r1
|
||||
|
||||
labeltje:
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,8 @@
|
||||
main {
|
||||
|
||||
sub start() {
|
||||
word[128] @split particleX
|
||||
word[128] @split particleY
|
||||
word[128] particleX
|
||||
word[128] particleY
|
||||
byte[128] particleDX
|
||||
byte[128] particleDY
|
||||
|
||||
|
@ -289,7 +289,7 @@ class IRFileReader {
|
||||
val (name, size, align) = match.destructured
|
||||
val dummyNode = PtVariable(
|
||||
name,
|
||||
DataType.arrayFor(BaseDataType.UBYTE),
|
||||
DataType.arrayFor(BaseDataType.UBYTE, false),
|
||||
ZeropageWish.NOT_IN_ZEROPAGE,
|
||||
0u,
|
||||
null,
|
||||
@ -514,14 +514,12 @@ class IRFileReader {
|
||||
private fun parseDatatype(type: String, isArray: Boolean): DataType {
|
||||
if(isArray) {
|
||||
return when(type) {
|
||||
"bool" -> DataType.arrayFor(BaseDataType.BOOL)
|
||||
"byte" -> DataType.arrayFor(BaseDataType.BYTE)
|
||||
"ubyte", "str" -> DataType.arrayFor(BaseDataType.UBYTE)
|
||||
"word" -> DataType.arrayFor(BaseDataType.WORD)
|
||||
"uword" -> DataType.arrayFor(BaseDataType.UWORD)
|
||||
"float" -> DataType.arrayFor(BaseDataType.FLOAT)
|
||||
"uword_split" -> DataType.arrayFor(BaseDataType.UWORD, true)
|
||||
"word_split" -> DataType.arrayFor(BaseDataType.WORD, true)
|
||||
"bool" -> DataType.arrayFor(BaseDataType.BOOL, false)
|
||||
"byte" -> DataType.arrayFor(BaseDataType.BYTE, false)
|
||||
"ubyte", "str" -> DataType.arrayFor(BaseDataType.UBYTE, false)
|
||||
"word" -> DataType.arrayFor(BaseDataType.WORD, false)
|
||||
"uword" -> DataType.arrayFor(BaseDataType.UWORD, false)
|
||||
"float" -> DataType.arrayFor(BaseDataType.FLOAT, false)
|
||||
else -> throw IRParseException("invalid dt $type")
|
||||
}
|
||||
} else {
|
||||
|
@ -30,8 +30,8 @@ fun DataType.typeString(length: Int?): String {
|
||||
}
|
||||
BaseDataType.ARRAY_SPLITW -> {
|
||||
when(this.sub?.dt) {
|
||||
BaseDataType.UWORD -> "@split uword[$lengthStr]" // should be 2 separate byte arrays by now really?
|
||||
BaseDataType.WORD -> "@split word[$lengthStr]" // should be 2 separate byte arrays by now really?
|
||||
BaseDataType.UWORD -> "uword[$lengthStr]" // should be 2 separate byte arrays by now really?
|
||||
BaseDataType.WORD -> "word[$lengthStr]" // should be 2 separate byte arrays by now really?
|
||||
else -> throw IllegalArgumentException("invalid sub type")
|
||||
}
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ ZEROPAGENOT: '@nozp' ;
|
||||
|
||||
SHARED : '@shared' ;
|
||||
|
||||
SPLIT: '@split' ;
|
||||
NOSPLIT: '@nosplit' ;
|
||||
|
||||
ALIGNWORD: '@alignword' ;
|
||||
|
||||
@ -159,7 +159,7 @@ directivearg : stringliteral | identifier | integerliteral ;
|
||||
|
||||
vardecl: datatype (arrayindex | ARRAYSIG)? decloptions identifier (',' identifier)* ;
|
||||
|
||||
decloptions: (SHARED | ZEROPAGE | ZEROPAGEREQUIRE | ZEROPAGENOT | SPLIT | ALIGNWORD | ALIGN64 | ALIGNPAGE | DIRTY)* ;
|
||||
decloptions: (SHARED | ZEROPAGE | ZEROPAGEREQUIRE | ZEROPAGENOT | NOSPLIT | ALIGNWORD | ALIGN64 | ALIGNPAGE | DIRTY)* ;
|
||||
|
||||
varinitializer : vardecl '=' expression ;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user