proper error message for arrays that are declared too big

This commit is contained in:
Irmen de Jong 2020-08-18 14:47:52 +02:00
parent 353f1954a5
commit 77c1376d6d
7 changed files with 52 additions and 29 deletions

View File

@ -492,8 +492,7 @@ internal class AstChecker(private val program: Program,
when(decl.value) {
null -> {
// a vardecl without an initial value, don't bother with the rest
return super.visit(decl)
// a vardecl without an initial value, don't bother with it
}
is RangeExpr -> throw FatalAstException("range expression should have been converted to a true array value")
is StringLiteralValue -> {
@ -577,6 +576,26 @@ internal class AstChecker(private val program: Program,
}
}
// array length limits
if(decl.isArray) {
val length = decl.arraysize!!.size() ?: 1
when (decl.datatype) {
DataType.STR, DataType.ARRAY_UB, DataType.ARRAY_B -> {
if(length==0 || length>256)
err("string and byte array length must be 1-256")
}
DataType.ARRAY_UW, DataType.ARRAY_W -> {
if(length==0 || length>128)
err("word array length must be 1-128")
}
DataType.ARRAY_F -> {
if(length==0 || length>51)
err("float array length must be 1-51")
}
else -> {}
}
}
super.visit(decl)
}

View File

@ -266,7 +266,6 @@ $endLabel inx""")
}
private fun translateForOverIterableVar(stmt: ForLoop, iterableDt: DataType, ident: IdentifierReference) {
// TODO optimize this more
val loopLabel = asmgen.makeLabel("for_loop")
val endLabel = asmgen.makeLabel("for_end")
asmgen.loopEndLabels.push(endLabel)
@ -291,9 +290,9 @@ $loopLabel lda ${65535.toHex()} ; modified
$endLabel""")
}
DataType.ARRAY_UB, DataType.ARRAY_B -> {
// TODO: optimize loop code when the length of the array is < 256 (i.e. always)
// TODO: optimize loop code when the length of the array is 255 or less instead of 256
val length = decl.arraysize!!.size()!!
val counterLabel = asmgen.makeLabel("for_counter") // todo allocate dynamically, zero page preferred if iterations >= 8
val counterLabel = asmgen.makeLabel("for_counter") // todo allocate dynamically, zero page preferred if len >= 16
val modifiedLabel = asmgen.makeLabel("for_modified")
asmgen.out("""
lda #<$iterableName
@ -315,9 +314,9 @@ $counterLabel .byte 0
$endLabel""")
}
DataType.ARRAY_W, DataType.ARRAY_UW -> {
// TODO: optimize loop code when the length of the array is < 256 (i.e. always)
// TODO: optimize loop code when the length of the array is 255 or less instead of 256
val length = decl.arraysize!!.size()!! * 2
val counterLabel = asmgen.makeLabel("for_counter") // todo allocate dynamically, zero page preferred if iterations >= 8
val counterLabel = asmgen.makeLabel("for_counter") // todo allocate dynamically, zero page preferred if len >= 16
val modifiedLabel = asmgen.makeLabel("for_modified")
val modifiedLabel2 = asmgen.makeLabel("for_modified2")
val loopvarName = asmgen.asmIdentifierName(stmt.loopVar)

View File

@ -274,22 +274,16 @@ private fun builtinLen(args: List<Expression>, position: Position, program: Prog
arraySize = target.arraysize?.size()
if(arraySize==null)
throw CannotEvaluateException("len", "arraysize unknown")
if(arraySize>256)
throw CompilerException("array length exceeds byte limit ${target.position}")
NumericLiteralValue.optimalInteger(arraySize, args[0].position)
}
DataType.ARRAY_F -> {
arraySize = target.arraysize?.size()
if(arraySize==null)
throw CannotEvaluateException("len", "arraysize unknown")
if(arraySize>256)
throw CompilerException("array length exceeds byte limit ${target.position}")
NumericLiteralValue.optimalInteger(arraySize, args[0].position)
}
DataType.STR -> {
val refLv = target.value as StringLiteralValue
if(refLv.value.length>255)
throw CompilerException("string length exceeds byte limit ${refLv.position}")
NumericLiteralValue.optimalInteger(refLv.value.length, args[0].position)
}
in NumericDatatypes -> throw SyntaxError("len of weird argument ${args[0]}", position)

View File

@ -257,6 +257,16 @@ Note that the various keywords for the data type and variable type (``byte``, ``
can't be used as *identifiers* elsewhere. You can't make a variable, block or subroutine with the name ``byte``
for instance.
**Arrays at a specific memory location:**
Using the memory-mapped syntax it is possible to define an array to be located at a specific memory location.
For instance to reference the first 5 rows of the Commodore 64's screen matrix as an array, you can define::
&ubyte[5*40] top5screenrows = $0400
This way you can set the second character on the second row from the top like this::
top5screenrows[41] = '!'
Strings
^^^^^^^

View File

@ -306,6 +306,7 @@ should be allocated by the compiler. Instead, the (mandatory) value assigned to
should be the *memory address* where the value is located::
&byte BORDERCOLOR = $d020
&ubyte[5*40] top5screenrows = $0400 ; works for array as well
Direct access to memory locations

View File

@ -2,8 +2,8 @@
TODO
====
- optimize assignment codegeneration
- get rid of all TODO's ;-)
- allow declaring arrays on specific memory location and page-aligned
- option to load the built-in library files from a directory instead of the embedded ones (for easier library development/debugging)
- aliases for imported symbols for example perhaps '%alias print = c64scr.print' ?
- investigate support for 8bitguy's Commander X16 platform https://www.commanderx16.com and https://github.com/commanderx16/x16-docs

View File

@ -24,20 +24,20 @@ main {
; c64.CHROUT('\n')
; ubyte bb
; ubyte from = 10
; ubyte end = 20
;
; for bb in from to end step 3 {
; c64scr.print_ub(bb)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
; for bb in end to from step -3 {
; c64scr.print_ub(bb)
; c64.CHROUT(',')
; }
; c64.CHROUT('\n')
ubyte bb
ubyte from = 10
ubyte end = 20
for bb in from to end step 3 {
c64scr.print_ub(bb)
c64.CHROUT(',')
}
c64.CHROUT('\n')
for bb in end to from step -3 {
c64scr.print_ub(bb)
c64.CHROUT(',')
}
c64.CHROUT('\n')
word ww
word fromw = -10