mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
got rid of matrix type
This commit is contained in:
parent
98a8ff4587
commit
5bf2c4a798
@ -105,7 +105,7 @@ memoryvardecl: 'memory' varinitializer;
|
||||
|
||||
datatype: 'ubyte' | 'byte' | 'uword' | 'word' | 'float' | 'str' | 'str_p' | 'str_s' | 'str_ps' ;
|
||||
|
||||
arrayspec: '[' expression (',' expression)? ']' ;
|
||||
arrayspec: '[' expression ']' ;
|
||||
|
||||
assignment : assign_target '=' expression ;
|
||||
|
||||
|
@ -3,17 +3,14 @@
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/res" type="java-resource" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/src/compiled_java" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/src/compiled_java/prog8" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/src/compiled_java/prog8/parser" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="lib" level="project" />
|
||||
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
|
||||
<orderEntry type="library" name="testlibs" level="project" />
|
||||
<orderEntry type="library" name="antlr-4.7.1" level="project" />
|
||||
<orderEntry type="library" name="lib1" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
</module>
|
||||
|
@ -28,10 +28,6 @@ sub start() {
|
||||
uword[5] uwarr2
|
||||
float[5] farr1
|
||||
float[5] farr2
|
||||
byte[2,3] bmatrix1
|
||||
byte[2,3] bmatrix2
|
||||
ubyte[2,3] ubmatrix1
|
||||
ubyte[2,3] ubmatrix2
|
||||
|
||||
memory byte mbyte = $c000
|
||||
memory byte mbyte2 = $d000
|
||||
@ -71,16 +67,6 @@ byte_assignment_to_register:
|
||||
A = AY[Y]
|
||||
A = AY[b]
|
||||
A = AY[ub]
|
||||
A = ubmatrix1[1,2]
|
||||
;A = ubmatrix1[1,Y] ; todo via evaluation
|
||||
;A = ubmatrix1[X,2] ; todo via evaluation
|
||||
;A = ubmatrix1[X,Y] ; todo via evaluation
|
||||
;A = ubmatrix1[1,b2] ; todo via evaluation
|
||||
;A = ubmatrix1[X,b2] ; todo via evaluation
|
||||
;A = ubmatrix1[b2,2] ; todo via evaluation
|
||||
;A = ubmatrix1[b2,X] ; todo via evaluation
|
||||
;A = ubmatrix1[b,b2] ; todo via evaluation
|
||||
;A = ubmatrix1[ub,ub2] ; todo via evaluation
|
||||
|
||||
ubyte_assignment_to_ubytevar:
|
||||
ub = 42
|
||||
@ -99,16 +85,6 @@ ubyte_assignment_to_ubytevar:
|
||||
ub = AY[Y]
|
||||
ub = AY[b]
|
||||
ub = AY[ub]
|
||||
ub = ubmatrix1[1,2]
|
||||
;ub = ubmatrix1[1,Y] ; todo via evaluation
|
||||
;ub = ubmatrix1[X,2] ; todo via evaluation
|
||||
;ub = ubmatrix1[X,Y] ; todo via evaluation
|
||||
;ub = ubmatrix1[1,b2] ; todo via evaluation
|
||||
;ub = ubmatrix1[X,b2] ; todo via evaluation
|
||||
;ub = ubmatrix1[b2,2] ; todo via evaluation
|
||||
;ub = ubmatrix1[b2,X] ; todo via evaluation
|
||||
;ub = ubmatrix1[b,b2] ; todo via evaluation
|
||||
;ub = ubmatrix1[ub,ub2] ; todo via evaluation
|
||||
|
||||
|
||||
ubyte_assignment_to_ubytemem:
|
||||
@ -128,16 +104,6 @@ ubyte_assignment_to_ubytemem:
|
||||
mubyte = AY[Y]
|
||||
mubyte = AY[b]
|
||||
mubyte = AY[ub]
|
||||
mubyte = ubmatrix1[1,2]
|
||||
;mubyte = ubmatrix1[1,Y] ; todo via evaluation
|
||||
;mubyte = ubmatrix1[X,2] ; todo via evaluation
|
||||
;mubyte = ubmatrix1[X,Y] ; todo via evaluation
|
||||
;mubyte = ubmatrix1[1,b2] ; todo via evaluation
|
||||
;mubyte = ubmatrix1[X,b2] ; todo via evaluation
|
||||
;mubyte = ubmatrix1[b2,2] ; todo via evaluation
|
||||
;mubyte = ubmatrix1[b2,X] ; todo via evaluation
|
||||
;mubyte = ubmatrix1[b,b2] ; todo via evaluation
|
||||
;mubyte = ubmatrix1[ub,ub2] ; todo via evaluation
|
||||
|
||||
byte_assignment_to_bytevar:
|
||||
b = -42
|
||||
@ -147,16 +113,6 @@ byte_assignment_to_bytevar:
|
||||
b = barr1[X]
|
||||
b = barr1[b]
|
||||
b = barr1[ub]
|
||||
b = bmatrix1[1,2]
|
||||
;b = bmatrix1[1,Y] ; todo via evaluation
|
||||
;b = bmatrix1[X,2] ; todo via evaluation
|
||||
;b = bmatrix1[X,Y] ; todo via evaluation
|
||||
;b = bmatrix1[1,b2] ; todo via evaluation
|
||||
;b = bmatrix1[X,b2] ; todo via evaluation
|
||||
;b = bmatrix1[b2,2] ; todo via evaluation
|
||||
;b = bmatrix1[b2,X] ; todo via evaluation
|
||||
;b = bmatrix1[b,b2] ; todo via evaluation
|
||||
;b = bmatrix1[ub,ub2] ; todo via evaluation
|
||||
|
||||
|
||||
byte_assignment_to_bytemem:
|
||||
@ -167,16 +123,6 @@ byte_assignment_to_bytemem:
|
||||
mbyte = barr1[X]
|
||||
mbyte = barr1[b]
|
||||
mbyte = barr1[ub]
|
||||
mbyte = bmatrix1[1,2]
|
||||
;mbyte = bmatrix1[1,Y] ; todo via evaluation
|
||||
;mbyte = bmatrix1[X,2] ; todo via evaluation
|
||||
;mbyte = bmatrix1[X,Y] ; todo via evaluation
|
||||
;mbyte = bmatrix1[1,b2] ; todo via evaluation
|
||||
;mbyte = bmatrix1[X,b2] ; todo via evaluation
|
||||
;mbyte = bmatrix1[b2,2] ; todo via evaluation
|
||||
;mbyte = bmatrix1[b2,X] ; todo via evaluation
|
||||
;mbyte = bmatrix1[b,b2] ; todo via evaluation
|
||||
;mbyte = bmatrix1[ub,ub2] ; todo via evaluation
|
||||
|
||||
|
||||
ubyte_assignment_to_ubytearray:
|
||||
@ -208,7 +154,6 @@ ubyte_assignment_to_ubytearray:
|
||||
AY[3] = ubarr1[X]
|
||||
AY[3] = ubarr1[b]
|
||||
AY[3] = ubarr1[ub]
|
||||
AY[3] = ubmatrix1[1,2]
|
||||
string[4] = 42
|
||||
string[4] = 'B'
|
||||
string[4] = X
|
||||
@ -217,16 +162,6 @@ ubyte_assignment_to_ubytearray:
|
||||
string[4] = AY[4]
|
||||
string[4] = ubarr1[2]
|
||||
string[4] = string[3]
|
||||
ubarr2[3] = ubmatrix1[1,2]
|
||||
;ubarr2[3] = ubmatrix1[1,Y] ; todo via evaluation
|
||||
;ubarr2[3] = ubmatrix1[X,2] ; todo via evaluation
|
||||
;ubarr2[3] = ubmatrix1[X,Y] ; todo via evaluation
|
||||
;ubarr2[3] = ubmatrix1[1,b2] ; todo via evaluation
|
||||
;ubarr2[3] = ubmatrix1[X,b2] ; todo via evaluation
|
||||
;ubarr2[3] = ubmatrix1[b2,2] ; todo via evaluation
|
||||
;ubarr2[3] = ubmatrix1[b2,X] ; todo via evaluation
|
||||
;ubarr2[3] = ubmatrix1[b,b2] ; todo via evaluation
|
||||
;ubarr2[3] = ubmatrix1[ub,ub2] ; todo via evaluation
|
||||
|
||||
|
||||
ubarr2[Y] = 42
|
||||
@ -257,7 +192,6 @@ ubyte_assignment_to_ubytearray:
|
||||
AY[Y] = ubarr1[X]
|
||||
AY[Y] = ubarr1[b]
|
||||
AY[Y] = ubarr1[ub]
|
||||
AY[Y] = ubmatrix1[1,2]
|
||||
string[Y] = 42
|
||||
string[Y] = 'B'
|
||||
string[Y] = X
|
||||
@ -266,18 +200,8 @@ ubyte_assignment_to_ubytearray:
|
||||
string[Y] = AY[4]
|
||||
string[Y] = ubarr1[2]
|
||||
string[Y] = string[Y]
|
||||
ubarr2[Y] = ubmatrix1[1,2]
|
||||
;ubarr2[Y] = ubmatrix1[1,Y] ; todo via evaluation
|
||||
;ubarr2[Y] = ubmatrix1[X,2] ; todo via evaluation
|
||||
;ubarr2[Y] = ubmatrix1[X,Y] ; todo via evaluation
|
||||
;ubarr2[Y] = ubmatrix1[1,b2] ; todo via evaluation
|
||||
;ubarr2[Y] = ubmatrix1[X,b2] ; todo via evaluation
|
||||
;ubarr2[Y] = ubmatrix1[b2,2] ; todo via evaluation
|
||||
;ubarr2[Y] = ubmatrix1[b2,X] ; todo via evaluation
|
||||
;ubarr2[Y] = ubmatrix1[b,b2] ; todo via evaluation
|
||||
;ubarr2[Y] = ubmatrix1[ub,ub2] ; todo via evaluation
|
||||
|
||||
|
||||
|
||||
|
||||
ubarr2[ub2] = 42
|
||||
ubarr2[ub2] = X
|
||||
ubarr2[ub2] = ub2
|
||||
@ -306,7 +230,6 @@ ubyte_assignment_to_ubytearray:
|
||||
AY[ub2] = ubarr1[X]
|
||||
AY[ub2] = ubarr1[b]
|
||||
AY[ub2] = ubarr1[ub]
|
||||
AY[ub2] = ubmatrix1[1,2]
|
||||
string[ub2] = 42
|
||||
string[ub2] = 'B'
|
||||
string[ub2] = X
|
||||
@ -315,16 +238,6 @@ ubyte_assignment_to_ubytearray:
|
||||
string[ub2] = AY[4]
|
||||
string[ub2] = ubarr1[2]
|
||||
string[ub2] = string[ub2]
|
||||
ubarr2[ub2] = ubmatrix1[1,2]
|
||||
;ubarr2[ub2] = ubmatrix1[1,Y] ; todo via evaluation
|
||||
;ubarr2[ub2] = ubmatrix1[X,2] ; todo via evaluation
|
||||
;ubarr2[ub2] = ubmatrix1[X,Y] ; todo via evaluation
|
||||
;ubarr2[ub2] = ubmatrix1[1,b2] ; todo via evaluation
|
||||
;ubarr2[ub2] = ubmatrix1[X,b2] ; todo via evaluation
|
||||
;ubarr2[ub2] = ubmatrix1[b2,2] ; todo via evaluation
|
||||
;ubarr2[ub2] = ubmatrix1[b2,X] ; todo via evaluation
|
||||
;ubarr2[ub2] = ubmatrix1[b,b2] ; todo via evaluation
|
||||
;ubarr2[ub2] = ubmatrix1[ub,ub2] ; todo via evaluation
|
||||
|
||||
ubarr2[mubyte2] = 42
|
||||
ubarr2[mubyte2] = X
|
||||
@ -354,7 +267,6 @@ ubyte_assignment_to_ubytearray:
|
||||
AY[mubyte2] = ubarr1[X]
|
||||
AY[mubyte2] = ubarr1[b]
|
||||
AY[mubyte2] = ubarr1[ub]
|
||||
AY[mubyte2] = ubmatrix1[1,2]
|
||||
string[mubyte2] = 42
|
||||
string[mubyte2] = 'B'
|
||||
string[mubyte2] = X
|
||||
@ -363,21 +275,11 @@ ubyte_assignment_to_ubytearray:
|
||||
string[mubyte2] = AY[4]
|
||||
string[mubyte2] = ubarr1[2]
|
||||
string[mubyte2] = string[mubyte2]
|
||||
ubarr2[mubyte2] = ubmatrix1[1,2]
|
||||
;ubarr2[mubyte2] = ubmatrix1[1,Y] ; todo via evaluation
|
||||
;ubarr2[mubyte2] = ubmatrix1[X,2] ; todo via evaluation
|
||||
;ubarr2[mubyte2] = ubmatrix1[X,Y] ; todo via evaluation
|
||||
;ubarr2[mubyte2] = ubmatrix1[1,b2] ; todo via evaluation
|
||||
;ubarr2[mubyte2] = ubmatrix1[X,b2] ; todo via evaluation
|
||||
;ubarr2[mubyte2] = ubmatrix1[b2,2] ; todo via evaluation
|
||||
;ubarr2[mubyte2] = ubmatrix1[b2,X] ; todo via evaluation
|
||||
;ubarr2[mubyte2] = ubmatrix1[b,b2] ; todo via evaluation
|
||||
;ubarr2[mubyte2] = ubmatrix1[ub,ub2] ; todo via evaluation
|
||||
|
||||
ubarr1[ubarr2[X]] = ubarr2[ubarr1[Y]] ; todo via evaluation
|
||||
|
||||
|
||||
|
||||
|
||||
byte_assignment_to_bytearray:
|
||||
; @todo
|
||||
|
||||
@ -395,7 +297,6 @@ byte_assignment_to_bytearray:
|
||||
; AY = ub
|
||||
; AY = mubyte
|
||||
; AY = ubarr1[2]
|
||||
; AY = ubmatrix1[1,2]
|
||||
; AY = string[4]
|
||||
; AY = uw
|
||||
; AY = muword
|
||||
@ -417,8 +318,6 @@ byte_assignment_to_bytearray:
|
||||
; w = barr1[2]
|
||||
; w = ubarr1[2]
|
||||
; w = warr1[2]
|
||||
; w = bmatrix1[1,2]
|
||||
; w = ubmatrix1[1,2]
|
||||
; w = string[4]
|
||||
; w = AY[4]
|
||||
;
|
||||
@ -433,7 +332,6 @@ byte_assignment_to_bytearray:
|
||||
; uw = muword
|
||||
; uw = ubarr1[2]
|
||||
; uw = uwarr1[2]
|
||||
; uw = ubmatrix1[1,2]
|
||||
; uw = string[4]
|
||||
; uw = AY[4]
|
||||
;
|
||||
@ -457,8 +355,6 @@ byte_assignment_to_bytearray:
|
||||
; fl1 = ubarr1[2]
|
||||
; fl1 = warr1[2]
|
||||
; fl1 = uwarr1[2]
|
||||
; fl1 = bmatrix1[1,2]
|
||||
; fl1 = ubmatrix1[1,2]
|
||||
; fl1 = string[4]
|
||||
|
||||
return
|
||||
|
@ -30,9 +30,7 @@ enum class DataType {
|
||||
ARRAY_B,
|
||||
ARRAY_UW,
|
||||
ARRAY_W,
|
||||
ARRAY_F,
|
||||
MATRIX_UB,
|
||||
MATRIX_B
|
||||
ARRAY_F
|
||||
}
|
||||
|
||||
enum class Register {
|
||||
@ -70,12 +68,12 @@ val IterableDatatypes = setOf(
|
||||
DataType.STR, DataType.STR_S, // note: the STR_P/STR_PS types aren't iterable because they store their length as the first byte
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B,
|
||||
DataType.ARRAY_UW, DataType.ARRAY_W,
|
||||
DataType.ARRAY_F, DataType.MATRIX_UB, DataType.MATRIX_B)
|
||||
DataType.ARRAY_F)
|
||||
|
||||
val StringDatatypes = setOf(DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS)
|
||||
val NumericDatatypes = setOf(DataType.UBYTE, DataType.BYTE, DataType.UWORD, DataType.WORD, DataType.FLOAT)
|
||||
val IntegerDatatypes = setOf(DataType.UBYTE, DataType.BYTE, DataType.UWORD, DataType.WORD)
|
||||
val ArrayDatatypes = setOf(DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W, DataType.ARRAY_F, DataType.MATRIX_UB, DataType.MATRIX_B)
|
||||
val ArrayDatatypes = setOf(DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W, DataType.ARRAY_F)
|
||||
|
||||
|
||||
class FatalAstException (override var message: String) : Exception(message)
|
||||
@ -553,40 +551,30 @@ class Break(override val position: Position) : IStatement {
|
||||
}
|
||||
|
||||
|
||||
class ArraySpec(var x: IExpression, var y: IExpression?, override val position: Position) : Node {
|
||||
class ArraySpec(var x: IExpression, override val position: Position) : Node {
|
||||
override lateinit var parent: Node
|
||||
|
||||
override fun linkParents(parent: Node) {
|
||||
this.parent = parent
|
||||
x.linkParents(this)
|
||||
y?.linkParents(this)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun forArray(v: LiteralValue, heap: HeapValues): ArraySpec {
|
||||
val arraySize = v.arrayvalue?.size ?: heap.get(v.heapId!!).arraysize
|
||||
return ArraySpec(LiteralValue.optimalNumeric(arraySize, v.position), null, v.position)
|
||||
return ArraySpec(LiteralValue.optimalNumeric(arraySize, v.position), v.position)
|
||||
}
|
||||
}
|
||||
|
||||
fun process(processor: IAstProcessor) {
|
||||
x = x.process(processor)
|
||||
y = y?.process(processor)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return("ArraySpec(x: $x, y: $y, pos=$position)")
|
||||
return("ArraySpec($x, pos=$position)")
|
||||
}
|
||||
|
||||
fun size() : Int? {
|
||||
if(y==null) {
|
||||
return (x as? LiteralValue)?.asIntegerValue
|
||||
} else {
|
||||
val sizeX = (x as? LiteralValue)?.asIntegerValue ?: return null
|
||||
val sizeY = (y as? LiteralValue)?.asIntegerValue ?: return null
|
||||
return sizeX * sizeY
|
||||
}
|
||||
}
|
||||
fun size() = (x as? LiteralValue)?.asIntegerValue
|
||||
}
|
||||
|
||||
|
||||
@ -605,29 +593,19 @@ class VarDecl(val type: VarDeclType,
|
||||
override lateinit var parent: Node
|
||||
|
||||
val datatypeErrors = mutableListOf<SyntaxError>() // don't crash at init time, report them in the AstChecker
|
||||
val datatype = when {
|
||||
arrayspec == null -> declaredDatatype
|
||||
arrayspec.y != null -> when (declaredDatatype) {
|
||||
DataType.UBYTE -> DataType.MATRIX_UB
|
||||
DataType.BYTE -> DataType.MATRIX_B
|
||||
else -> {
|
||||
datatypeErrors.add(SyntaxError("matrix can only contain bytes", position))
|
||||
DataType.UBYTE
|
||||
val datatype =
|
||||
if (arrayspec == null) declaredDatatype
|
||||
else when (declaredDatatype) {
|
||||
DataType.UBYTE -> DataType.ARRAY_UB
|
||||
DataType.BYTE -> DataType.ARRAY_B
|
||||
DataType.UWORD -> DataType.ARRAY_UW
|
||||
DataType.WORD -> DataType.ARRAY_W
|
||||
DataType.FLOAT -> DataType.ARRAY_F
|
||||
else -> {
|
||||
datatypeErrors.add(SyntaxError("array can only contain bytes/words/floats", position))
|
||||
DataType.UBYTE
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> when (declaredDatatype) {
|
||||
DataType.UBYTE -> DataType.ARRAY_UB
|
||||
DataType.BYTE -> DataType.ARRAY_B
|
||||
DataType.UWORD -> DataType.ARRAY_UW
|
||||
DataType.WORD -> DataType.ARRAY_W
|
||||
DataType.FLOAT -> DataType.ARRAY_F
|
||||
else -> {
|
||||
datatypeErrors.add(SyntaxError("arrayspec can only contain bytes/words/floats", position))
|
||||
DataType.UBYTE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun linkParents(parent: Node) {
|
||||
this.parent = parent
|
||||
@ -920,8 +898,8 @@ class ArrayIndexedExpression(val identifier: IdentifierReference?,
|
||||
return when (target.datatype) {
|
||||
in NumericDatatypes -> null
|
||||
in StringDatatypes -> DataType.UBYTE
|
||||
DataType.ARRAY_UB, DataType.MATRIX_UB -> DataType.UBYTE
|
||||
DataType.ARRAY_B, DataType.MATRIX_B -> DataType.BYTE
|
||||
DataType.ARRAY_UB -> DataType.UBYTE
|
||||
DataType.ARRAY_B -> DataType.BYTE
|
||||
DataType.ARRAY_UW -> DataType.UWORD
|
||||
DataType.ARRAY_W -> DataType.WORD
|
||||
DataType.ARRAY_F -> DataType.FLOAT
|
||||
@ -1053,10 +1031,6 @@ class LiteralValue(val type: DataType,
|
||||
if(heapId!=null) "arrayspec:#$heapId"
|
||||
else "arrayspec:$arrayvalue"
|
||||
}
|
||||
DataType.MATRIX_UB, DataType.MATRIX_B -> {
|
||||
if(heapId!=null) "matrix:#$heapId"
|
||||
else "matrix:$arrayvalue"
|
||||
}
|
||||
}
|
||||
return "LiteralValue($vstr)"
|
||||
}
|
||||
@ -1865,7 +1839,7 @@ private fun prog8Parser.DatatypeContext.toAst() = DataType.valueOf(text.toUpperC
|
||||
|
||||
|
||||
private fun prog8Parser.ArrayspecContext.toAst() : ArraySpec =
|
||||
ArraySpec(expression(0).toAst(), if (expression().size > 1) expression(1).toAst() else null, toPosition())
|
||||
ArraySpec(expression().toAst(), toPosition())
|
||||
|
||||
|
||||
private fun prog8Parser.DirectiveContext.toAst() : Directive =
|
||||
|
@ -121,12 +121,12 @@ class AstChecker(private val namespace: INameScope,
|
||||
// loop register
|
||||
when (forLoop.loopRegister) {
|
||||
Register.A, Register.X, Register.Y -> {
|
||||
if (iterableDt != DataType.UBYTE && iterableDt!=DataType.ARRAY_UB && iterableDt!=DataType.MATRIX_UB && iterableDt !in StringDatatypes)
|
||||
if (iterableDt != DataType.UBYTE && iterableDt!=DataType.ARRAY_UB && iterableDt !in StringDatatypes)
|
||||
checkResult.add(ExpressionError("register can only loop over bytes", forLoop.position))
|
||||
}
|
||||
Register.AX, Register.AY, Register.XY -> {
|
||||
if (iterableDt != DataType.UWORD && iterableDt != DataType.UBYTE && iterableDt !in StringDatatypes &&
|
||||
iterableDt !=DataType.ARRAY_UB && iterableDt!=DataType.ARRAY_UW && iterableDt!=DataType.MATRIX_UB)
|
||||
iterableDt !=DataType.ARRAY_UB && iterableDt!=DataType.ARRAY_UW)
|
||||
checkResult.add(ExpressionError("register pair can only loop over bytes or words", forLoop.position))
|
||||
}
|
||||
}
|
||||
@ -139,12 +139,12 @@ class AstChecker(private val namespace: INameScope,
|
||||
} else {
|
||||
when (loopvar.datatype) {
|
||||
DataType.UBYTE -> {
|
||||
if(iterableDt!=DataType.UBYTE && iterableDt!=DataType.ARRAY_UB && iterableDt!=DataType.MATRIX_UB && iterableDt !in StringDatatypes)
|
||||
if(iterableDt!=DataType.UBYTE && iterableDt!=DataType.ARRAY_UB && iterableDt !in StringDatatypes)
|
||||
checkResult.add(ExpressionError("byte loop variable can only loop over bytes", forLoop.position))
|
||||
}
|
||||
DataType.UWORD -> {
|
||||
if(iterableDt!=DataType.UBYTE && iterableDt!=DataType.UWORD && iterableDt !in StringDatatypes &&
|
||||
iterableDt !=DataType.ARRAY_UB && iterableDt!=DataType.ARRAY_UW && iterableDt!=DataType.MATRIX_UB)
|
||||
iterableDt !=DataType.ARRAY_UB && iterableDt!=DataType.ARRAY_UW)
|
||||
checkResult.add(ExpressionError("word loop variable can only loop over bytes or words", forLoop.position))
|
||||
}
|
||||
// there's no support for a floating-point loop variable
|
||||
@ -369,7 +369,7 @@ class AstChecker(private val namespace: INameScope,
|
||||
targetVar?.arrayspec
|
||||
} else null
|
||||
checkValueTypeAndRange(targetDatatype,
|
||||
arrayspec ?: ArraySpec(LiteralValue.optimalInteger(-1, assignment.position), null, assignment.position),
|
||||
arrayspec ?: ArraySpec(LiteralValue.optimalInteger(-1, assignment.position), assignment.position),
|
||||
constVal, heap)
|
||||
} else {
|
||||
val sourceDatatype: DataType? = assignment.value.resultingDatatype(namespace, heap)
|
||||
@ -398,9 +398,7 @@ class AstChecker(private val namespace: INameScope,
|
||||
}
|
||||
|
||||
// the initializer value can't refer to the variable itself (recursive definition)
|
||||
if(decl.value?.referencesIdentifier(decl.name) == true||
|
||||
decl.arrayspec?.x?.referencesIdentifier(decl.name) == true ||
|
||||
decl.arrayspec?.y?.referencesIdentifier(decl.name) == true) {
|
||||
if(decl.value?.referencesIdentifier(decl.name) == true || decl.arrayspec?.x?.referencesIdentifier(decl.name) == true) {
|
||||
err("recursive var declaration")
|
||||
}
|
||||
|
||||
@ -437,7 +435,7 @@ class AstChecker(private val namespace: INameScope,
|
||||
if((decl.value as LiteralValue).isArray)
|
||||
ArraySpec.forArray(decl.value as LiteralValue, heap)
|
||||
else
|
||||
ArraySpec(LiteralValue.optimalInteger(-2, decl.position), null, decl.position)
|
||||
ArraySpec(LiteralValue.optimalInteger(-2, decl.position), decl.position)
|
||||
)
|
||||
checkValueTypeAndRange(decl.datatype, arraySpec, decl.value as LiteralValue, heap)
|
||||
}
|
||||
@ -460,9 +458,6 @@ class AstChecker(private val namespace: INameScope,
|
||||
DataType.ARRAY_F ->
|
||||
if(arraySize > 51)
|
||||
err("float arrayspec length must be 1-51")
|
||||
DataType.MATRIX_B, DataType.MATRIX_UB ->
|
||||
if(arraySize > 32768)
|
||||
err("invalid matrix size, must be 1-32768")
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
@ -561,7 +556,7 @@ class AstChecker(private val namespace: INameScope,
|
||||
if(literalValue.isArray)
|
||||
ArraySpec.forArray(literalValue, heap)
|
||||
else
|
||||
ArraySpec(LiteralValue.optimalInteger(-3, literalValue.position), null, literalValue.position)
|
||||
ArraySpec(LiteralValue.optimalInteger(-3, literalValue.position), literalValue.position)
|
||||
checkValueTypeAndRange(literalValue.type, arrayspec, literalValue, heap)
|
||||
|
||||
val lv = super.process(literalValue)
|
||||
@ -572,7 +567,7 @@ class AstChecker(private val namespace: INameScope,
|
||||
}
|
||||
in ArrayDatatypes -> {
|
||||
if(lv.heapId==null)
|
||||
throw FatalAstException("arrayspec/matrix should have been moved to heap at ${lv.position}")
|
||||
throw FatalAstException("array should have been moved to heap at ${lv.position}")
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
@ -731,14 +726,10 @@ class AstChecker(private val namespace: INameScope,
|
||||
if(arraysize!=null) {
|
||||
// check out of bounds
|
||||
val index = (arrayIndexedExpression.arrayspec.x as? LiteralValue)?.asIntegerValue
|
||||
if(index != null && (arrayIndexedExpression.arrayspec.y as? LiteralValue)?.asIntegerValue != null) {
|
||||
throw FatalAstException("constant y dimension of index should have been const-folded with x into one value ${arrayIndexedExpression.arrayspec.position}")
|
||||
}
|
||||
if(index!=null && (index<0 || index>=arraysize))
|
||||
checkResult.add(ExpressionError("arrayspec index out of bounds", arrayIndexedExpression.arrayspec.position))
|
||||
} else if(target.datatype in StringDatatypes) {
|
||||
// check string lengths
|
||||
(arrayIndexedExpression.arrayspec.y as? LiteralValue)?.asIntegerValue
|
||||
val heapId = (target.value as LiteralValue).heapId!!
|
||||
val stringLen = heap.get(heapId).str!!.length
|
||||
val index = (arrayIndexedExpression.arrayspec.x as? LiteralValue)?.asIntegerValue
|
||||
@ -749,20 +740,15 @@ class AstChecker(private val namespace: INameScope,
|
||||
checkResult.add(SyntaxError("indexing requires a variable to act upon", arrayIndexedExpression.position))
|
||||
} else if(reg==Register.A || reg==Register.X || reg==Register.Y) {
|
||||
checkResult.add(SyntaxError("indexing on registers requires register pair variable", arrayIndexedExpression.position))
|
||||
} else if(arrayIndexedExpression.arrayspec.y!=null) {
|
||||
checkResult.add(SyntaxError("indexing on registers can only use one index dimension", arrayIndexedExpression.position))
|
||||
}
|
||||
|
||||
// check index value 0..255
|
||||
val regx = (arrayIndexedExpression.arrayspec.x as? RegisterExpr)?.register
|
||||
val regy = (arrayIndexedExpression.arrayspec.y as? RegisterExpr)?.register
|
||||
if((regx in setOf(Register.AX, Register.AY, Register.XY)) ||
|
||||
(regy in setOf(Register.AX, Register.AY, Register.XY))) {
|
||||
if((regx in setOf(Register.AX, Register.AY, Register.XY))) {
|
||||
checkResult.add(SyntaxError("array indexing is limited to byte size 0..255", arrayIndexedExpression.position))
|
||||
}
|
||||
val dtx = arrayIndexedExpression.arrayspec.x.resultingDatatype(namespace, heap)
|
||||
val dty = arrayIndexedExpression.arrayspec.y?.resultingDatatype(namespace, heap)
|
||||
if(dtx!=DataType.UBYTE && dtx!=DataType.BYTE || (dty!=null && dty != DataType.UBYTE && dty != DataType.BYTE))
|
||||
if(dtx!=DataType.UBYTE && dtx!=DataType.BYTE)
|
||||
checkResult.add(SyntaxError("array indexing is limited to byte size 0..255", arrayIndexedExpression.position))
|
||||
|
||||
return super.process(arrayIndexedExpression)
|
||||
@ -807,7 +793,7 @@ class AstChecker(private val namespace: INameScope,
|
||||
val expectedSize = arrayspec!!.size()
|
||||
val rangeSize=range.size()
|
||||
if(rangeSize!=null && rangeSize != expectedSize) {
|
||||
checkResult.add(ExpressionError("range size doesn't match arrayspec/matrix size, expected $expectedSize found $rangeSize", range.position))
|
||||
checkResult.add(ExpressionError("range size doesn't match array size, expected $expectedSize found $rangeSize", range.position))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@ -939,30 +925,6 @@ class AstChecker(private val namespace: INameScope,
|
||||
}
|
||||
return err("invalid float arrayspec initialization value ${value.type}, expected $targetDt")
|
||||
}
|
||||
DataType.MATRIX_UB, DataType.MATRIX_B -> {
|
||||
// value can only be a single byte, or a byte arrayspec (which represents the matrix)
|
||||
if(value.type==targetDt ||
|
||||
(targetDt==DataType.MATRIX_UB && value.type==DataType.ARRAY_UB) ||
|
||||
(targetDt==DataType.MATRIX_B && value.type==DataType.ARRAY_B)) {
|
||||
val arraySpecSize = arrayspec.size()
|
||||
if(arraySpecSize!=null && arraySpecSize>0) {
|
||||
if(arraySpecSize<1 || arraySpecSize>32768)
|
||||
return err("invalid matrix size, must be 1-32768")
|
||||
val constX = arrayspec.x.constValue(namespace, heap)
|
||||
val constY = arrayspec.y?.constValue(namespace, heap)
|
||||
if (constX?.asIntegerValue == null || (constY!=null && constY.asIntegerValue == null))
|
||||
return err("matrix size specifiers must be constant integer values")
|
||||
val matrix = heap.get(value.heapId!!).array!!
|
||||
val expectedSize =
|
||||
if(constY==null) constX.asIntegerValue else constX.asIntegerValue * constY.asIntegerValue!!
|
||||
if (matrix.size != expectedSize)
|
||||
return err("initializer matrix size mismatch (expecting $expectedSize, got ${matrix.size} elements)")
|
||||
return true
|
||||
}
|
||||
return err("invalid matrix size, must be 1-32768")
|
||||
}
|
||||
return err("invalid matrix initialization value of type ${value.type} - expecting byte arrayspec")
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -254,8 +254,8 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
DataType.UWORD, DataType.WORD -> Opcode.PUSH_WORD
|
||||
DataType.FLOAT -> Opcode.PUSH_FLOAT
|
||||
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS,
|
||||
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F, DataType.MATRIX_UB,
|
||||
DataType.ARRAY_B, DataType.ARRAY_W, DataType.MATRIX_B -> Opcode.PUSH_WORD
|
||||
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F,
|
||||
DataType.ARRAY_B, DataType.ARRAY_W -> Opcode.PUSH_WORD
|
||||
}
|
||||
}
|
||||
|
||||
@ -287,8 +287,8 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
DataType.UWORD, DataType.WORD -> Opcode.PUSH_VAR_WORD
|
||||
DataType.FLOAT -> Opcode.PUSH_VAR_FLOAT
|
||||
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS,
|
||||
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F, DataType.MATRIX_UB,
|
||||
DataType.ARRAY_B, DataType.ARRAY_W, DataType.MATRIX_B -> Opcode.PUSH_VAR_WORD
|
||||
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F,
|
||||
DataType.ARRAY_B, DataType.ARRAY_W -> Opcode.PUSH_VAR_WORD
|
||||
}
|
||||
}
|
||||
|
||||
@ -311,7 +311,6 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B -> Opcode.READ_INDEXED_VAR_BYTE
|
||||
DataType.ARRAY_UW, DataType.ARRAY_W -> Opcode.READ_INDEXED_VAR_WORD
|
||||
DataType.ARRAY_F -> Opcode.READ_INDEXED_VAR_FLOAT
|
||||
DataType.MATRIX_UB, DataType.MATRIX_B -> Opcode.READ_INDEXED_VAR_BYTE
|
||||
DataType.STR, DataType.STR_S -> Opcode.READ_INDEXED_VAR_BYTE
|
||||
DataType.STR_P, DataType.STR_PS -> throw CompilerException("cannot access pascal-string type $dt with index")
|
||||
else -> throw CompilerException("invalid dt for indexed access $dt")
|
||||
@ -323,7 +322,6 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B -> Opcode.WRITE_INDEXED_VAR_BYTE
|
||||
DataType.ARRAY_UW, DataType.ARRAY_W -> Opcode.WRITE_INDEXED_VAR_WORD
|
||||
DataType.ARRAY_F -> Opcode.WRITE_INDEXED_VAR_FLOAT
|
||||
DataType.MATRIX_UB, DataType.MATRIX_B -> Opcode.WRITE_INDEXED_VAR_BYTE
|
||||
DataType.STR, DataType.STR_S -> Opcode.WRITE_INDEXED_VAR_BYTE
|
||||
DataType.STR_P, DataType.STR_PS -> throw CompilerException("cannot access pascal-string type $dt with index")
|
||||
else -> throw CompilerException("invalid dt for indexed access $dt")
|
||||
@ -336,8 +334,8 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
DataType.UWORD, DataType.WORD -> Opcode.DISCARD_WORD
|
||||
DataType.FLOAT -> Opcode.DISCARD_FLOAT
|
||||
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS,
|
||||
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F, DataType.MATRIX_UB,
|
||||
DataType.ARRAY_B, DataType.ARRAY_W, DataType.MATRIX_B -> Opcode.DISCARD_WORD
|
||||
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F,
|
||||
DataType.ARRAY_B, DataType.ARRAY_W -> Opcode.DISCARD_WORD
|
||||
}
|
||||
}
|
||||
|
||||
@ -347,8 +345,8 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
DataType.UWORD, DataType.WORD -> Opcode.POP_VAR_WORD
|
||||
DataType.FLOAT -> Opcode.POP_VAR_FLOAT
|
||||
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS,
|
||||
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F, DataType.MATRIX_UB,
|
||||
DataType.ARRAY_B, DataType.ARRAY_W, DataType.MATRIX_B -> Opcode.POP_VAR_WORD
|
||||
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F,
|
||||
DataType.ARRAY_B, DataType.ARRAY_W -> Opcode.POP_VAR_WORD
|
||||
}
|
||||
}
|
||||
|
||||
@ -358,8 +356,8 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
DataType.UWORD, DataType.WORD -> Opcode.POP_MEM_WORD
|
||||
DataType.FLOAT -> Opcode.POP_MEM_FLOAT
|
||||
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS,
|
||||
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F, DataType.MATRIX_UB,
|
||||
DataType.ARRAY_B, DataType.ARRAY_W, DataType.MATRIX_B -> Opcode.POP_MEM_WORD
|
||||
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F,
|
||||
DataType.ARRAY_B, DataType.ARRAY_W -> Opcode.POP_MEM_WORD
|
||||
}
|
||||
}
|
||||
|
||||
@ -627,10 +625,10 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
throw CompilerException("string should have been moved into heap ${lv.position}")
|
||||
prog.instr(Opcode.PUSH_WORD, Value(lv.type, lv.heapId))
|
||||
}
|
||||
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F, DataType.MATRIX_UB,
|
||||
DataType.ARRAY_B, DataType.ARRAY_W, DataType.MATRIX_B -> {
|
||||
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F,
|
||||
DataType.ARRAY_B, DataType.ARRAY_W -> {
|
||||
if(lv.heapId==null)
|
||||
throw CompilerException("arrayspec/matrix should have been moved into heap ${lv.position}")
|
||||
throw CompilerException("array should have been moved into heap ${lv.position}")
|
||||
prog.instr(Opcode.PUSH_WORD, Value(lv.type, lv.heapId))
|
||||
}
|
||||
}
|
||||
@ -1048,22 +1046,11 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
val reg=arrayindexed.register
|
||||
if(reg==Register.A || reg==Register.X || reg==Register.Y)
|
||||
throw CompilerException("requires register pair")
|
||||
if(arrayindexed.arrayspec.y!=null)
|
||||
throw CompilerException("when using an address, can only use one index dimension")
|
||||
reg.toString()
|
||||
} else {
|
||||
variable!!.scopedname
|
||||
}
|
||||
translate(arrayindexed.arrayspec.x)
|
||||
val y = arrayindexed.arrayspec.y
|
||||
if(y!=null) {
|
||||
// calc matrix index i=y*columns+x
|
||||
// (the const-folding will have removed this for us when both x and y are constants)
|
||||
translate(y)
|
||||
prog.instr(Opcode.PUSH_BYTE, Value(DataType.UWORD, (variable!!.arrayspec!!.x as LiteralValue).asIntegerValue!!))
|
||||
prog.instr(Opcode.MUL_UW)
|
||||
prog.instr(Opcode.ADD_UW)
|
||||
}
|
||||
|
||||
if(variable!=null) {
|
||||
if (write)
|
||||
@ -1174,10 +1161,9 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
else -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
|
||||
}
|
||||
}
|
||||
// todo: maybe if you assign byte or word to arrayspec/matrix, clear it with that value?
|
||||
// todo: maybe if you assign byte or word to arrayspec, clear it with that value?
|
||||
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W,
|
||||
DataType.ARRAY_F, DataType.MATRIX_UB, DataType.MATRIX_B -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W, DataType.ARRAY_F -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
|
||||
null -> throw CompilerException("could not determine targetdt")
|
||||
}
|
||||
}
|
||||
@ -1402,7 +1388,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
}
|
||||
|
||||
private fun translateForOverIterableVar(loop: ForLoop, loopvarDt: DataType, iterableValue: LiteralValue) {
|
||||
if(loopvarDt==DataType.UBYTE && iterableValue.type !in setOf(DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS, DataType.ARRAY_UB, DataType.MATRIX_UB))
|
||||
if(loopvarDt==DataType.UBYTE && iterableValue.type !in setOf(DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS, DataType.ARRAY_UB))
|
||||
throw CompilerException("loop variable type doesn't match iterableValue type")
|
||||
else if(loopvarDt==DataType.UWORD && iterableValue.type != DataType.ARRAY_UW)
|
||||
throw CompilerException("loop variable type doesn't match iterableValue type")
|
||||
@ -1422,8 +1408,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
indexVar = if(numElements>255) "XY" else "X"
|
||||
}
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B,
|
||||
DataType.ARRAY_UW, DataType.ARRAY_W,
|
||||
DataType.MATRIX_UB, DataType.MATRIX_B -> {
|
||||
DataType.ARRAY_UW, DataType.ARRAY_W -> {
|
||||
numElements = iterableValue.arrayvalue?.size ?: heap.get(iterableValue.heapId!!).arraysize
|
||||
indexVar = if(numElements>255) "XY" else "X"
|
||||
}
|
||||
@ -1467,7 +1452,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
AssignTarget(loop.loopRegister, null, null, loop.position)
|
||||
else
|
||||
AssignTarget(null, loop.loopVar!!.copy(), null, loop.position)
|
||||
val arrayspec = ArraySpec(RegisterExpr(Register.valueOf(indexVar), loop.position), null, loop.position)
|
||||
val arrayspec = ArraySpec(RegisterExpr(Register.valueOf(indexVar), loop.position), loop.position)
|
||||
val assignLv = Assignment(assignTarget, null, ArrayIndexedExpression((loop.iterable as IdentifierReference).copy(), null, arrayspec, loop.position), loop.position)
|
||||
assignLv.linkParents(loop.body)
|
||||
translate(assignLv)
|
||||
|
@ -17,21 +17,11 @@ abstract class Zeropage(private val options: CompilationOptions) {
|
||||
val size =
|
||||
if(vardecl.arrayspec!=null) {
|
||||
printWarning("allocating a large value (arrayspec) in zeropage", vardecl.position)
|
||||
val y = (vardecl.arrayspec.y as? LiteralValue)?.asIntegerValue
|
||||
if(y==null) {
|
||||
// 1 dimensional arrayspec
|
||||
when(vardecl.datatype) {
|
||||
DataType.UBYTE -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!!
|
||||
DataType.UWORD -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!! * 2
|
||||
DataType.FLOAT -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!! * 5
|
||||
else -> throw CompilerException("arrayspec can only be of byte, word, float")
|
||||
}
|
||||
} else {
|
||||
// 2 dimensional matrix (only bytes for now)
|
||||
when(vardecl.datatype) {
|
||||
DataType.UBYTE -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!! * y
|
||||
else -> throw CompilerException("matrix can only contain bytes")
|
||||
}
|
||||
when(vardecl.datatype) {
|
||||
DataType.UBYTE -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!!
|
||||
DataType.UWORD -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!! * 2
|
||||
DataType.FLOAT -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!! * 5
|
||||
else -> throw CompilerException("arrayspec can only be of byte, word, float")
|
||||
}
|
||||
} else {
|
||||
when (vardecl.datatype) {
|
||||
|
@ -278,11 +278,11 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
||||
throw CompilerException("string should already be in the heap")
|
||||
Value(decl.datatype, litval.heapId)
|
||||
}
|
||||
DataType.ARRAY_B, DataType.ARRAY_W, DataType.MATRIX_B, DataType.MATRIX_UB,
|
||||
DataType.ARRAY_B, DataType.ARRAY_W,
|
||||
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F -> {
|
||||
val litval = (decl.value as LiteralValue)
|
||||
if(litval.heapId==null)
|
||||
throw CompilerException("arrayspec/matrix should already be in the heap")
|
||||
throw CompilerException("array should already be in the heap")
|
||||
Value(decl.datatype, litval.heapId)
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ enum class Opcode {
|
||||
|
||||
// pushing values on the (evaluation) stack
|
||||
PUSH_BYTE, // push byte value
|
||||
PUSH_WORD, // push word value (or 'address' of string / arrayspec / matrix)
|
||||
PUSH_WORD, // push word value (or 'address' of string / array)
|
||||
PUSH_FLOAT, // push float value
|
||||
PUSH_MEM_B, // push byte value from memory to stack
|
||||
PUSH_MEM_UB, // push unsigned byte value from memory to stack
|
||||
|
@ -217,7 +217,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
for (chunk in bytes.chunked(16))
|
||||
out("\t.byte " + chunk.joinToString())
|
||||
}
|
||||
DataType.ARRAY_UB, DataType.MATRIX_UB -> {
|
||||
DataType.ARRAY_UB -> {
|
||||
// unsigned integer byte arrayspec
|
||||
val data = makeArrayFillDataUnsigned(v.second)
|
||||
if (data.size <= 16)
|
||||
@ -228,7 +228,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
out("\t.byte " + chunk.joinToString())
|
||||
}
|
||||
}
|
||||
DataType.ARRAY_B, DataType.MATRIX_B -> {
|
||||
DataType.ARRAY_B -> {
|
||||
// signed integer byte arrayspec
|
||||
val data = makeArrayFillDataSigned(v.second)
|
||||
if (data.size <= 16)
|
||||
@ -299,7 +299,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
|
||||
private fun makeArrayFillDataUnsigned(value: Value): List<String> {
|
||||
val array = heap.get(value.heapId).array!!
|
||||
return if (value.type == DataType.ARRAY_UB || value.type == DataType.ARRAY_UW || value.type == DataType.MATRIX_UB)
|
||||
return if (value.type == DataType.ARRAY_UB || value.type == DataType.ARRAY_UW)
|
||||
array.map { "$"+it.toString(16).padStart(2, '0') }
|
||||
else
|
||||
throw AssemblyError("invalid arrayspec type")
|
||||
@ -307,7 +307,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
|
||||
private fun makeArrayFillDataSigned(value: Value): List<String> {
|
||||
val array = heap.get(value.heapId).array!!
|
||||
return if (value.type == DataType.ARRAY_B || value.type == DataType.ARRAY_W || value.type == DataType.MATRIX_B) {
|
||||
return if (value.type == DataType.ARRAY_B || value.type == DataType.ARRAY_W) {
|
||||
array.map {
|
||||
if(it>=0)
|
||||
"$"+it.toString(16).padStart(2, '0')
|
||||
|
@ -97,7 +97,7 @@ fun builtinFunctionReturnType(function: String, args: List<IExpression>, namespa
|
||||
|
||||
fun datatypeFromListArg(arglist: IExpression): DataType {
|
||||
if(arglist is LiteralValue) {
|
||||
if(arglist.type==DataType.ARRAY_UB || arglist.type==DataType.ARRAY_UW || arglist.type==DataType.ARRAY_F || arglist.type==DataType.MATRIX_UB) {
|
||||
if(arglist.type==DataType.ARRAY_UB || arglist.type==DataType.ARRAY_UW || arglist.type==DataType.ARRAY_F) {
|
||||
val dt = arglist.arrayvalue!!.map {it.resultingDatatype(namespace, heap)}
|
||||
if(dt.any { it!=DataType.UBYTE && it!=DataType.UWORD && it!=DataType.FLOAT}) {
|
||||
throw FatalAstException("fuction $function only accepts arrayspec of numeric values")
|
||||
@ -117,8 +117,6 @@ fun builtinFunctionReturnType(function: String, args: List<IExpression>, namespa
|
||||
DataType.ARRAY_UW -> DataType.UWORD
|
||||
DataType.ARRAY_W -> DataType.WORD
|
||||
DataType.ARRAY_F -> DataType.FLOAT
|
||||
DataType.MATRIX_UB -> DataType.UBYTE
|
||||
DataType.MATRIX_B -> DataType.BYTE
|
||||
null -> throw FatalAstException("function requires one argument which is an arrayspec $function")
|
||||
}
|
||||
}
|
||||
@ -141,8 +139,6 @@ fun builtinFunctionReturnType(function: String, args: List<IExpression>, namespa
|
||||
DataType.ARRAY_UW -> DataType.UWORD
|
||||
DataType.ARRAY_W -> DataType.WORD
|
||||
DataType.ARRAY_F -> DataType.FLOAT
|
||||
DataType.MATRIX_UB -> DataType.UBYTE
|
||||
DataType.MATRIX_B -> DataType.BYTE
|
||||
}
|
||||
}
|
||||
"sum" -> {
|
||||
@ -154,8 +150,6 @@ fun builtinFunctionReturnType(function: String, args: List<IExpression>, namespa
|
||||
DataType.ARRAY_UB, DataType.ARRAY_UW -> DataType.UWORD
|
||||
DataType.ARRAY_B, DataType.ARRAY_W -> DataType.WORD
|
||||
DataType.ARRAY_F -> DataType.FLOAT
|
||||
DataType.MATRIX_UB -> DataType.UWORD
|
||||
DataType.MATRIX_B -> DataType.WORD
|
||||
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> DataType.UWORD
|
||||
}
|
||||
}
|
||||
@ -237,7 +231,7 @@ private fun collectionArgOutputBoolean(args: List<IExpression>, position: Positi
|
||||
throw NotConstArgumentException()
|
||||
function(constants.map { it!!.toDouble() })
|
||||
} else {
|
||||
val array = heap.get(iterable.heapId!!).array ?: throw SyntaxError("function requires arrayspec/matrix argument", position)
|
||||
val array = heap.get(iterable.heapId!!).array ?: throw SyntaxError("function requires array argument", position)
|
||||
function(array.map { it.toDouble() })
|
||||
}
|
||||
return LiteralValue.fromBoolean(result, position)
|
||||
@ -313,7 +307,7 @@ private fun builtinAbs(args: List<IExpression>, position: Position, namespace:IN
|
||||
|
||||
private fun builtinAvg(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue {
|
||||
if(args.size!=1)
|
||||
throw SyntaxError("avg requires arrayspec/matrix argument", position)
|
||||
throw SyntaxError("avg requires array argument", position)
|
||||
val iterable = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
|
||||
|
||||
val result = if(iterable.arrayvalue!=null) {
|
||||
@ -323,7 +317,7 @@ private fun builtinAvg(args: List<IExpression>, position: Position, namespace:IN
|
||||
(constants.map { it!!.toDouble() }).average()
|
||||
}
|
||||
else {
|
||||
val array = heap.get(iterable.heapId!!).array ?: throw SyntaxError("avg requires arrayspec/matrix argument", position)
|
||||
val array = heap.get(iterable.heapId!!).array ?: throw SyntaxError("avg requires array argument", position)
|
||||
array.average()
|
||||
}
|
||||
return numericLiteral(result, args[0].position)
|
||||
@ -342,7 +336,7 @@ private fun builtinLen(args: List<IExpression>, position: Position, namespace:IN
|
||||
?: throw NotConstArgumentException()
|
||||
}
|
||||
return when(argument.type) {
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W, DataType.MATRIX_UB, DataType.MATRIX_B -> {
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W -> {
|
||||
val arraySize = argument.arrayvalue?.size ?: heap.get(argument.heapId!!).arraysize
|
||||
LiteralValue(DataType.UWORD, wordvalue=arraySize, position=args[0].position)
|
||||
}
|
||||
|
@ -25,9 +25,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
|
||||
|
||||
override fun process(decl: VarDecl): IStatement {
|
||||
// the initializer value can't refer to the variable itself (recursive definition)
|
||||
if(decl.value?.referencesIdentifier(decl.name) == true||
|
||||
decl.arrayspec?.x?.referencesIdentifier(decl.name) == true ||
|
||||
decl.arrayspec?.y?.referencesIdentifier(decl.name) == true) {
|
||||
if(decl.value?.referencesIdentifier(decl.name) == true || decl.arrayspec?.x?.referencesIdentifier(decl.name) == true) {
|
||||
errors.add(ExpressionError("recursive var declaration", decl.position))
|
||||
return decl
|
||||
}
|
||||
@ -53,7 +51,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
|
||||
decl.value = newValue
|
||||
}
|
||||
}
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W, DataType.MATRIX_UB, DataType.MATRIX_B -> {
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W -> {
|
||||
val litval = decl.value as? LiteralValue
|
||||
if(litval?.type==DataType.FLOAT)
|
||||
errors.add(ExpressionError("arrayspec requires only integers here", litval.position))
|
||||
@ -61,10 +59,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
|
||||
if(litval!=null && litval.isArray) {
|
||||
// arrayspec initializer value is an arrayspec already, keep as-is (or convert to WORDs if needed)
|
||||
if(litval.heapId!=null) {
|
||||
if (decl.datatype == DataType.MATRIX_UB && litval.type != DataType.MATRIX_UB) {
|
||||
val array = heap.get(litval.heapId).copy(type = DataType.MATRIX_UB)
|
||||
heap.update(litval.heapId, array)
|
||||
} else if(decl.datatype==DataType.ARRAY_UW && litval.type == DataType.ARRAY_UB) {
|
||||
if(decl.datatype==DataType.ARRAY_UW && litval.type == DataType.ARRAY_UB) {
|
||||
val array = heap.get(litval.heapId)
|
||||
if(array.array!=null) {
|
||||
heap.update(litval.heapId, HeapValues.HeapValue(DataType.ARRAY_UW, null, array.array, null))
|
||||
@ -82,11 +77,11 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
|
||||
// arrayspec initializer is empty or a single int, and we know the size; create the arrayspec.
|
||||
val fillvalue = if (litval == null) 0 else litval.asIntegerValue ?: 0
|
||||
when(decl.datatype){
|
||||
DataType.ARRAY_UB, DataType.MATRIX_UB -> {
|
||||
DataType.ARRAY_UB -> {
|
||||
if(fillvalue !in 0..255)
|
||||
errors.add(ExpressionError("ubyte value overflow", litval?.position ?: decl.position))
|
||||
}
|
||||
DataType.ARRAY_B, DataType.MATRIX_B -> {
|
||||
DataType.ARRAY_B -> {
|
||||
if(fillvalue !in -128..127)
|
||||
errors.add(ExpressionError("byte value overflow", litval?.position ?: decl.position))
|
||||
}
|
||||
@ -492,7 +487,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
|
||||
val array: Array<IExpression> = arraylit.arrayvalue!!.map { it.process(this) }.toTypedArray()
|
||||
val allElementsAreConstant = array.fold(true) { c, expr-> c and (expr is LiteralValue)}
|
||||
if(!allElementsAreConstant) {
|
||||
addError(ExpressionError("arrayspec/matrix literal can contain only constant values", arraylit.position))
|
||||
addError(ExpressionError("array literal can contain only constant values", arraylit.position))
|
||||
return arraylit
|
||||
} else {
|
||||
val valuesInArray = array.map { it.constValue(namespace, heap)!!.asNumericValue!! }
|
||||
@ -529,9 +524,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
|
||||
DataType.ARRAY_UB,
|
||||
DataType.ARRAY_B,
|
||||
DataType.ARRAY_UW,
|
||||
DataType.ARRAY_W,
|
||||
DataType.MATRIX_UB,
|
||||
DataType.MATRIX_B -> heap.add(arrayDt, integerArray)
|
||||
DataType.ARRAY_W -> heap.add(arrayDt, integerArray)
|
||||
DataType.ARRAY_F -> heap.add(arrayDt, doubleArray)
|
||||
else -> throw CompilerException("invalid arrayspec type")
|
||||
}
|
||||
@ -539,25 +532,6 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
|
||||
}
|
||||
}
|
||||
|
||||
override fun process(arrayIndexedExpression: ArrayIndexedExpression): IExpression {
|
||||
if(arrayIndexedExpression.arrayspec.y!=null) {
|
||||
if(arrayIndexedExpression.arrayspec.size()!=null) {
|
||||
// both x and y are known
|
||||
// calculate the 2-dimension index i = y*columns + x
|
||||
if(arrayIndexedExpression.identifier!=null) {
|
||||
val x = (arrayIndexedExpression.arrayspec.x as LiteralValue).asIntegerValue!!
|
||||
val y = (arrayIndexedExpression.arrayspec.y as LiteralValue).asIntegerValue!!
|
||||
val variable = arrayIndexedExpression.identifier.targetStatement(namespace) as? VarDecl
|
||||
if(variable!=null) {
|
||||
val index = x + y * (variable.arrayspec!!.x as LiteralValue).asIntegerValue!!
|
||||
arrayIndexedExpression.arrayspec = ArraySpec(LiteralValue.optimalInteger(index, arrayIndexedExpression.arrayspec.position), null, arrayIndexedExpression.arrayspec.position)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.process(arrayIndexedExpression)
|
||||
}
|
||||
|
||||
override fun process(assignment: Assignment): IStatement {
|
||||
super.process(assignment)
|
||||
val lv = assignment.value as? LiteralValue
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated from ../antlr/prog8.g4 by ANTLR 4.7.1
|
||||
// Generated from /home/irmen/Projects/prog8/compiler/antlr/prog8.g4 by ANTLR 4.7
|
||||
package prog8.parser;
|
||||
import org.antlr.v4.runtime.Lexer;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
@ -11,7 +11,7 @@ import org.antlr.v4.runtime.misc.*;
|
||||
|
||||
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
|
||||
public class prog8Lexer extends Lexer {
|
||||
static { RuntimeMetaData.checkVersion("4.7.1", RuntimeMetaData.VERSION); }
|
||||
static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); }
|
||||
|
||||
protected static final DFA[] _decisionToDFA;
|
||||
protected static final PredictionContextCache _sharedContextCache =
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -87,8 +87,7 @@ class Program (val name: String,
|
||||
DataType.STR_S,
|
||||
DataType.STR_PS -> heap.add(it.second, it.third.substring(1, it.third.length-1).unescape())
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B,
|
||||
DataType.ARRAY_UW, DataType.ARRAY_W,
|
||||
DataType.MATRIX_UB, DataType.MATRIX_B -> {
|
||||
DataType.ARRAY_UW, DataType.ARRAY_W -> {
|
||||
val numbers = it.third.substring(1, it.third.length-1).split(',')
|
||||
val intarray = numbers.map{number->number.trim().toInt()}.toIntArray()
|
||||
heap.add(it.second, intarray)
|
||||
@ -208,11 +207,9 @@ class Program (val name: String,
|
||||
DataType.ARRAY_B,
|
||||
DataType.ARRAY_UW,
|
||||
DataType.ARRAY_W,
|
||||
DataType.ARRAY_F,
|
||||
DataType.MATRIX_UB,
|
||||
DataType.MATRIX_B -> {
|
||||
DataType.ARRAY_F -> {
|
||||
if(!valueStr.startsWith("heap:"))
|
||||
throw VmExecutionException("invalid arrayspec/matrix value, should be a heap reference")
|
||||
throw VmExecutionException("invalid array value, should be a heap reference")
|
||||
else {
|
||||
val heapId = valueStr.substring(5).toInt()
|
||||
Value(type, heapId)
|
||||
|
@ -1180,10 +1180,10 @@ class StackVm(private var traceOutputFile: String?) {
|
||||
// get indexed byte element from the arrayspec
|
||||
val array = heap.get(variable.heapId)
|
||||
when(array.type) {
|
||||
DataType.ARRAY_UB, DataType.MATRIX_UB -> evalstack.push(Value(DataType.UBYTE, array.array!![index]))
|
||||
DataType.ARRAY_B, DataType.MATRIX_B -> evalstack.push(Value(DataType.BYTE, array.array!![index]))
|
||||
DataType.ARRAY_UB-> evalstack.push(Value(DataType.UBYTE, array.array!![index]))
|
||||
DataType.ARRAY_B -> evalstack.push(Value(DataType.BYTE, array.array!![index]))
|
||||
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> evalstack.push(Value(DataType.UBYTE, Petscii.encodePetscii(array.str!![index].toString(), true)[0]))
|
||||
else -> throw VmExecutionException("not a proper arrayspec/matrix/string variable with byte elements")
|
||||
else -> throw VmExecutionException("not a proper array/string variable with byte elements")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1232,8 +1232,8 @@ class StackVm(private var traceOutputFile: String?) {
|
||||
// set indexed byte element in the arrayspec
|
||||
val array = heap.get(variable.heapId)
|
||||
when(array.type) {
|
||||
DataType.ARRAY_UB, DataType.MATRIX_UB -> array.array!![index] = value.integerValue()
|
||||
DataType.ARRAY_B, DataType.MATRIX_B -> array.array!![index] = value.integerValue()
|
||||
DataType.ARRAY_UB -> array.array!![index] = value.integerValue()
|
||||
DataType.ARRAY_B -> array.array!![index] = value.integerValue()
|
||||
DataType.STR,
|
||||
DataType.STR_P,
|
||||
DataType.STR_S,
|
||||
@ -1242,7 +1242,7 @@ class StackVm(private var traceOutputFile: String?) {
|
||||
chars[index] = Petscii.decodePetscii(listOf(value.integerValue().toShort()), true)[0]
|
||||
heap.update(variable.heapId, chars.joinToString(""))
|
||||
}
|
||||
else -> throw VmExecutionException("not a proper arrayspec/matrix/string var with byte elements")
|
||||
else -> throw VmExecutionException("not a proper array/string var with byte elements")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1337,7 +1337,6 @@ class StackVm(private var traceOutputFile: String?) {
|
||||
DataType.UBYTE, DataType.BYTE, DataType.UWORD, DataType.WORD, DataType.FLOAT -> print(value.numericValue())
|
||||
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> print(heap.get(value.heapId).str)
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W -> print(heap.get(value.heapId).array!!.toList())
|
||||
DataType.MATRIX_UB, DataType.MATRIX_B -> print(heap.get(value.heapId).array!!.toList())
|
||||
DataType.ARRAY_F -> print(heap.get(value.heapId).doubleArray!!.toList())
|
||||
}
|
||||
}
|
||||
@ -1417,8 +1416,8 @@ class StackVm(private var traceOutputFile: String?) {
|
||||
val value = heap.get(iterable.heapId)
|
||||
val resultDt = when(iterable.type) {
|
||||
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> DataType.UBYTE
|
||||
DataType.ARRAY_UB, DataType.MATRIX_UB -> DataType.UBYTE
|
||||
DataType.ARRAY_B, DataType.MATRIX_B -> DataType.BYTE
|
||||
DataType.ARRAY_UB -> DataType.UBYTE
|
||||
DataType.ARRAY_B -> DataType.BYTE
|
||||
DataType.ARRAY_UW -> DataType.UWORD
|
||||
DataType.ARRAY_W -> DataType.WORD
|
||||
DataType.ARRAY_F -> DataType.FLOAT
|
||||
@ -1437,8 +1436,8 @@ class StackVm(private var traceOutputFile: String?) {
|
||||
val value = heap.get(iterable.heapId)
|
||||
val resultDt = when(iterable.type) {
|
||||
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> DataType.UBYTE
|
||||
DataType.ARRAY_UB, DataType.MATRIX_UB -> DataType.UBYTE
|
||||
DataType.ARRAY_B, DataType.MATRIX_B -> DataType.BYTE
|
||||
DataType.ARRAY_UB -> DataType.UBYTE
|
||||
DataType.ARRAY_B -> DataType.BYTE
|
||||
DataType.ARRAY_UW -> DataType.UWORD
|
||||
DataType.ARRAY_W -> DataType.WORD
|
||||
DataType.ARRAY_F -> DataType.FLOAT
|
||||
|
@ -1288,8 +1288,8 @@ class TestStackVmOpcodes {
|
||||
DataType.UWORD, DataType.WORD -> Opcode.PUSH_WORD
|
||||
DataType.FLOAT -> Opcode.PUSH_FLOAT
|
||||
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS,
|
||||
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F, DataType.MATRIX_UB,
|
||||
DataType.ARRAY_B, DataType.ARRAY_W, DataType.MATRIX_B -> Opcode.PUSH_WORD
|
||||
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F,
|
||||
DataType.ARRAY_B, DataType.ARRAY_W -> Opcode.PUSH_WORD
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,11 +87,9 @@ class TestStackVmValue {
|
||||
assertFalse(sameValueAndType(Value(DataType.STR, 999), Value(DataType.STR, 222)))
|
||||
|
||||
assertTrue(sameValueAndType(Value(DataType.ARRAY_UB, 99), Value(DataType.ARRAY_UB, 99)))
|
||||
assertFalse(sameValueAndType(Value(DataType.ARRAY_UB, 99), Value(DataType.MATRIX_UB, 99)))
|
||||
assertFalse(sameValueAndType(Value(DataType.ARRAY_UB, 99), Value(DataType.ARRAY_UB, 22)))
|
||||
|
||||
assertTrue(sameValueAndType(Value(DataType.ARRAY_UW, 999), Value(DataType.ARRAY_UW, 999)))
|
||||
assertFalse(sameValueAndType(Value(DataType.ARRAY_UW, 999), Value(DataType.MATRIX_UB, 999)))
|
||||
assertFalse(sameValueAndType(Value(DataType.ARRAY_UW, 999), Value(DataType.ARRAY_UW, 222)))
|
||||
|
||||
assertTrue(sameValueAndType(Value(DataType.ARRAY_F, 999), Value(DataType.ARRAY_F, 999)))
|
||||
|
@ -194,17 +194,13 @@ Values will usually be part of an expression or assignment statement::
|
||||
byte counter = 42 ; variable of size 8 bits, with initial value 42
|
||||
|
||||
|
||||
Array and Matrix (2-dimensional array) types are also supported.
|
||||
Arrays can be made of bytes, words and floats. Matrixes can oly be made of bytes::
|
||||
Array types are also supported. They can be made of bytes, words and floats::
|
||||
|
||||
byte[4] array = [1, 2, 3, 4] ; initialize the array
|
||||
byte[99] array = 255 ; initialize array with all 255's [255, 255, 255, 255, ...]
|
||||
byte[100] array = 100 to 199 ; initialize array with [100, 101, ..., 198, 199]
|
||||
byte[2,3] matrix = [1,2,3,4,5,6] ; a 2*3 matrix with value |(1,2) (3,4) (5,6)|
|
||||
ubyte[2,3] matrix = 255 ; a matrix of 2*3=6 unsigned bytes all with value 255
|
||||
|
||||
value = array[3] ; the fourth value in the array (index is 0-based)
|
||||
value = matrix[4,2] ; the byte at the 5th column and 3rd row in the matrix
|
||||
char = string[4] ; the fifth character (=byte) in the string
|
||||
|
||||
.. note::
|
||||
@ -285,7 +281,7 @@ with has the PETSCII value of that single character.
|
||||
It's probably best that you don't change strings after they're created.
|
||||
This is because if your program exits and is restarted (without loading it again),
|
||||
it will then operate on the changed strings instead of the original ones.
|
||||
The same is true for arrays and matrixes by the way.
|
||||
The same is true for arrays by the way.
|
||||
|
||||
|
||||
Floating point numbers
|
||||
@ -547,19 +543,19 @@ deg(x)
|
||||
Radians to degrees.
|
||||
|
||||
max(x)
|
||||
Maximum of the values in the non-scalar (array or matrix) value x
|
||||
Maximum of the values in the array value x
|
||||
|
||||
min(x)
|
||||
Minimum of the values in the non-scalar (array or matrix) value x
|
||||
Minimum of the values in the array value x
|
||||
|
||||
avg(x)
|
||||
Average of the values in the non-scalar (array or matrix) value x
|
||||
Average of the values in the array value x
|
||||
|
||||
sum(x)
|
||||
Sum of the values in the non-scalar (array or matrix) value x
|
||||
Sum of the values in the array value x
|
||||
|
||||
len(x)
|
||||
Number of values in the array or matrix value x, or the number of characters in a string (excluding the size or 0-byte).
|
||||
Number of values in the array value x, or the number of characters in a string (excluding the size or 0-byte).
|
||||
Note: this can be different from the number of *bytes* in memory if the datatype isn't a byte.
|
||||
|
||||
lsb(x)
|
||||
@ -587,10 +583,10 @@ ub2b(x)
|
||||
Convert an unsigned byte to a signed byte. Uses 2's complement to deal with negative numbers.
|
||||
|
||||
any(x)
|
||||
1 ('true') if any of the values in the non-scalar (array or matrix) value x is 'true' (not zero), else 0 ('false')
|
||||
1 ('true') if any of the values in the array value x is 'true' (not zero), else 0 ('false')
|
||||
|
||||
all(x)
|
||||
1 ('true') if all of the values in the non-scalar (array or matrix) value x are 'true' (not zero), else 0 ('false')
|
||||
1 ('true') if all of the values in the array value x are 'true' (not zero), else 0 ('false')
|
||||
|
||||
rnd()
|
||||
returns a pseudo-random byte from 0..255
|
||||
|
@ -219,8 +219,6 @@ Various examples::
|
||||
word address = #counter
|
||||
byte[5] values = [11, 22, 33, 44, 55]
|
||||
byte[5] values = 255 ; initialize with five 255 bytes
|
||||
byte[5][6] empty_matrix = 0 ; initialize with 30 zero bytes
|
||||
byte[2][3] other_matrix = [1,2,3,4,5,6] ; 2*3 matrix with value | (1,2) (3,4) (5,6) |
|
||||
|
||||
|
||||
|
||||
@ -246,8 +244,6 @@ type identifier type storage size example var declara
|
||||
``word[x]`` signed word array 2*x bytes ``word[4] myvar = [1, 2, 3, 4]``
|
||||
``uword[x]`` unsigned word array 2*x bytes ``uword[4] myvar = [1, 2, 3, 4]``
|
||||
``float[x]`` floating-point array 5*x bytes ``float[4] myvar = [1.1, 2.2, 3.3, 4.4]``
|
||||
``byte[x,y]`` signed byte matrix x*y bytes ``byte[40,25] myvar = 100``
|
||||
``ubyte[x,y]`` unsigned byte matrix x*y bytes ``ubyte[40,25] myvar = 255``
|
||||
``str`` string (petscii) varies ``str myvar = "hello."``
|
||||
implicitly terminated by a 0-byte
|
||||
``str_p`` pascal-string (petscii) varies ``str_p myvar = "hello."``
|
||||
@ -325,12 +321,10 @@ If used in the place of a literal value, it expands into the actual array of val
|
||||
Array indexing
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
Strings, arrays and matrixes form a sequence of values. You can access the individual values by
|
||||
indexing into the array.
|
||||
Syntax is familiar with brackets: ``arrayvar[x]`` or ``matrixvar[x, y]`` ::
|
||||
Strings and arrays are a sequence of values. You can access the individual values by indexing.
|
||||
Syntax is familiar with brackets: ``arrayvar[x]`` ::
|
||||
|
||||
array[2] ; the third byte in the array (index is 0-based)
|
||||
matrix[4,2] ; the byte at the 5th column and 3rd row in the matrix
|
||||
string[4] ; the fifth character (=byte) in the string
|
||||
|
||||
|
||||
|
@ -14,25 +14,16 @@ Allows us to create pre calculated sine tables and such.
|
||||
Memory Block Operations
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@todo matrix,list,string memory block operations:
|
||||
|
||||
- matrix type operations (whole matrix, per row, per column, individual row/column)
|
||||
operations: set, get, copy (from another matrix with the same dimensions, or list with same length),
|
||||
shift-N (up, down, left, right, and diagonals, meant for scrolling)
|
||||
rotate-N (up, down, left, right, and diagonals, meant for scrolling)
|
||||
clear (set whole matrix to the given value, default 0)
|
||||
@todo list,string memory block operations:
|
||||
|
||||
- list operations (whole list, individual element)
|
||||
operations: set, get, copy (from another list with the same length), shift-N(left,right), rotate-N(left,right)
|
||||
clear (set whole list to the given value, default 0)
|
||||
|
||||
- list and matrix operations ofcourse work identical on vars and on memory mapped vars of these types.
|
||||
- list operations ofcourse work identical on vars and on memory mapped vars of these types.
|
||||
|
||||
- strings: identical operations as on lists.
|
||||
|
||||
- matrix with row-interleave can only be a memory mapped variable and can be used to directly
|
||||
access a rectangular area within another piece of memory - such as a rectangle on the (character) screen
|
||||
|
||||
these should call (or emit inline) optimized pieces of assembly code, so they run as fast as possible
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user