got rid of matrix type

This commit is contained in:
Irmen de Jong 2018-10-30 20:29:03 +01:00
parent 98a8ff4587
commit 5bf2c4a798
21 changed files with 631 additions and 901 deletions

View File

@ -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 ;

View File

@ -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>

View File

@ -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

View File

@ -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 =

View File

@ -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
}

View File

@ -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)

View File

@ -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) {

View File

@ -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)
}
}

View File

@ -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

View File

@ -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')

View File

@ -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)
}

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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
}
}

View File

@ -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)))

View File

@ -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

View File

@ -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

View File

@ -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