mirror of
https://github.com/irmen/prog8.git
synced 2024-11-16 22:09:56 +00:00
assignments and stuff
This commit is contained in:
parent
a23673fe83
commit
f4e2641f7c
@ -7,10 +7,10 @@
|
||||
|
||||
sub start() {
|
||||
|
||||
ubyte pixely = 255
|
||||
ubyte ub = 0
|
||||
byte b = 99
|
||||
byte b2 = 100
|
||||
ubyte ub = 255
|
||||
ubyte ub2 = 0
|
||||
word w = 999
|
||||
word w2 = 3
|
||||
uword uw = 40000
|
||||
@ -48,179 +48,15 @@ sub start() {
|
||||
memory word[3] mwarr1 = $e100
|
||||
memory uword[3] muwarr1 = $e100
|
||||
|
||||
label:
|
||||
|
||||
Y=42
|
||||
AY=42
|
||||
AY=42555
|
||||
Y = ub
|
||||
AY= ub
|
||||
AY= uw
|
||||
; all possible assignments to a BYTE VARIABLE
|
||||
A = 42
|
||||
A = Y
|
||||
A = ub
|
||||
A = mubyte
|
||||
A = ubarr1[2]
|
||||
A = ubmatrix1[1,2]
|
||||
|
||||
Y = mubyte
|
||||
AY = mubyte
|
||||
AY = muword
|
||||
|
||||
Y = ubarr1[2]
|
||||
AY = ubarr1[2]
|
||||
AY = uwarr1[2]
|
||||
Y = mubarr1[2]
|
||||
AY = mubarr1[2]
|
||||
AY = muwarr1[2]
|
||||
|
||||
ub=Y
|
||||
uw=AY
|
||||
mubyte=Y
|
||||
muword=AY
|
||||
ubarr1[2]=Y
|
||||
uwarr1[2]=AY
|
||||
Y=A
|
||||
AY=Y
|
||||
|
||||
|
||||
barr1[2]=42
|
||||
ubarr1[2]=42
|
||||
warr1[2]=12555
|
||||
uwarr1[2]=42555
|
||||
farr1[2]=42.5678
|
||||
|
||||
ubarr1[2]=X
|
||||
uwarr1[2]=XY
|
||||
|
||||
; farr1[2]=Y ; @todo via regular evaluation
|
||||
; farr1[2]=XY ; @todo via regular evaluation
|
||||
; farr1[X]=Y ; @todo via regular evaluation
|
||||
; farr1[Y]=XY ; @todo via regular evaluation
|
||||
; farr1[b]=XY ; @todo via regular evaluation
|
||||
; farr1[ub]=XY ; @todo via regular evaluation
|
||||
; farr1[mbyte]=XY ; @todo via regular evaluation
|
||||
; farr1[mubyte]=XY ; @todo via regular evaluation
|
||||
|
||||
farr1[w]=XY ; @todo error message about index 0..255
|
||||
farr1[uw]=XY ; @todo error message about index 0..255
|
||||
farr1[mword]=XY ; @todo error message about index 0..255
|
||||
farr1[muword]=XY ; @todo error message about index 0..255
|
||||
|
||||
barr1[2] = b
|
||||
ubarr1[2] = ub
|
||||
warr1[2] = w
|
||||
uwarr1[2] = uw
|
||||
farr1[2] = fl1
|
||||
|
||||
barr1[2] = mbyte
|
||||
ubarr1[2] = mubyte
|
||||
warr1[2] = mword
|
||||
uwarr1[2] = muword
|
||||
farr1[2] = mfloat
|
||||
|
||||
b= barr1[2]
|
||||
ub = ubarr1[2]
|
||||
w = warr1[2]
|
||||
uw = uwarr1[2]
|
||||
; fl1 = farr1[2] ; @todo
|
||||
; fl1 = farr1[X] ; @todo
|
||||
; fl1 = farr1[b] ; @todo
|
||||
; fl1 = farr1[ub] ; @todo
|
||||
; fl1 = farr1[mbyte] ; @todo
|
||||
; fl1 = farr1[mubyte] ; @todo
|
||||
fl1 = farr1[w] ; @todo error message about index 0..255
|
||||
fl1 = farr1[uw] ; @todo error message about index 0..255
|
||||
fl1 = farr1[mword] ; @todo error message about index 0..255
|
||||
fl1 = farr1[muword] ; @todo error message about index 0..255
|
||||
|
||||
;farr1[3] = farr2[4] ; @todo
|
||||
;farr1[X] = farr2[Y] ; @todo
|
||||
farr1[XY] = farr2[AY] ; @todo error message about index 0..255
|
||||
;farr1[b] = farr2[b2] ; @todo
|
||||
;farr1[mbyte] = farr2[mbyte2] ; @todo
|
||||
|
||||
|
||||
mbyte= barr1[2]
|
||||
mubyte = ubarr1[2]
|
||||
mword = warr1[2]
|
||||
muword = uwarr1[2]
|
||||
; mfloat = farr1[2] ; @todo
|
||||
|
||||
barr1[2] = barr2[3]
|
||||
ubarr1[2] = ubarr2[3]
|
||||
warr1[2] = warr2[3]
|
||||
uwarr1[2] = uwarr2[3]
|
||||
; farr1[2] = farr2[3] ; @todo
|
||||
|
||||
|
||||
XY[2]=42
|
||||
XY[2] = ub
|
||||
XY[2] = mubyte
|
||||
ub = XY[2]
|
||||
uw = XY[2]
|
||||
; fl1 = XY[2] ; @todo via regular evaluation
|
||||
mubyte = XY[2]
|
||||
muword = XY[2]
|
||||
;mfloat = XY[2] ; @todo via regular evaluation
|
||||
|
||||
XY[33] = ubarr2[2]
|
||||
XY[33] = mubarr1[2]
|
||||
ubarr2[2] = XY[33]
|
||||
mubarr1[2] = XY[33]
|
||||
Y = AY[33]
|
||||
AY[33] = Y
|
||||
|
||||
|
||||
b = 1
|
||||
ub = 1
|
||||
w = 1
|
||||
uw = 1
|
||||
fl1 = 2.345
|
||||
|
||||
b = b2
|
||||
ub = pixely
|
||||
w = b2
|
||||
w = w2
|
||||
w = ub
|
||||
uw = ub
|
||||
uw = uw2
|
||||
fl1 = ub
|
||||
fl1 = b2
|
||||
fl1 = uw2
|
||||
fl1 = w2
|
||||
fl1 = X
|
||||
fl1 = AY
|
||||
fl1 = fl2
|
||||
|
||||
b = mbyte
|
||||
ub = mubyte
|
||||
w = mword
|
||||
w = mbyte
|
||||
w = mubyte
|
||||
uw = mubyte
|
||||
uw = muword
|
||||
fl1 = mfloat
|
||||
fl1 = mbyte
|
||||
fl1 = mword
|
||||
fl1 = mubyte
|
||||
fl1 = muword
|
||||
|
||||
mbyte = 1
|
||||
mubyte = 1
|
||||
mword = 1
|
||||
muword = 1
|
||||
mfloat = 3.456
|
||||
|
||||
%breakpoint
|
||||
|
||||
mbyte = b
|
||||
mubyte = ub
|
||||
mword = w
|
||||
muword = uw
|
||||
mfloat = fl2
|
||||
|
||||
%breakpoint
|
||||
|
||||
mbyte = mbyte2
|
||||
mubyte = mubyte2
|
||||
mword = mword2
|
||||
muword = muword2
|
||||
mfloat = mfloat2
|
||||
|
||||
|
||||
return
|
||||
|
@ -231,7 +231,7 @@ interface IAstProcessor {
|
||||
|
||||
fun process(arrayIndexedExpression: ArrayIndexedExpression): IExpression {
|
||||
arrayIndexedExpression.identifier?.process(this)
|
||||
arrayIndexedExpression.array.process(this)
|
||||
arrayIndexedExpression.arrayspec.process(this)
|
||||
return arrayIndexedExpression
|
||||
}
|
||||
|
||||
@ -622,7 +622,7 @@ class VarDecl(val type: VarDeclType,
|
||||
DataType.WORD -> DataType.ARRAY_W
|
||||
DataType.FLOAT -> DataType.ARRAY_F
|
||||
else -> {
|
||||
datatypeErrors.add(SyntaxError("array can only contain bytes/words/floats", position))
|
||||
datatypeErrors.add(SyntaxError("arrayspec can only contain bytes/words/floats", position))
|
||||
DataType.UBYTE
|
||||
}
|
||||
}
|
||||
@ -898,13 +898,13 @@ class BinaryExpression(var left: IExpression, var operator: String, var right: I
|
||||
|
||||
class ArrayIndexedExpression(val identifier: IdentifierReference?,
|
||||
val register: Register?,
|
||||
var array: ArraySpec,
|
||||
var arrayspec: ArraySpec,
|
||||
override val position: Position) : IExpression {
|
||||
override lateinit var parent: Node
|
||||
override fun linkParents(parent: Node) {
|
||||
this.parent = parent
|
||||
identifier?.linkParents(this)
|
||||
array.linkParents(this)
|
||||
arrayspec.linkParents(this)
|
||||
}
|
||||
|
||||
override fun isIterable(namespace: INameScope, heap: HeapValues) = false
|
||||
@ -930,6 +930,10 @@ class ArrayIndexedExpression(val identifier: IdentifierReference?,
|
||||
}
|
||||
throw FatalAstException("cannot get indexed element on $target")
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "ArrayIndexed(ident=$identifier, reg=$register, arrayspec=$arrayspec; pos=$position)"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1046,8 +1050,8 @@ class LiteralValue(val type: DataType,
|
||||
else "str:$strvalue"
|
||||
}
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W, DataType.ARRAY_F -> {
|
||||
if(heapId!=null) "array:#$heapId"
|
||||
else "array:$arrayvalue"
|
||||
if(heapId!=null) "arrayspec:#$heapId"
|
||||
else "arrayspec:$arrayvalue"
|
||||
}
|
||||
DataType.MATRIX_UB, DataType.MATRIX_B -> {
|
||||
if(heapId!=null) "matrix:#$heapId"
|
||||
@ -1936,7 +1940,7 @@ private fun prog8Parser.ExpressionContext.toAst() : IExpression {
|
||||
litval.charliteral()!=null -> LiteralValue(DataType.UBYTE, bytevalue = Petscii.encodePetscii(litval.charliteral().text.unescape(), true)[0], position = litval.toPosition())
|
||||
litval.arrayliteral()!=null -> {
|
||||
val array = litval.arrayliteral()?.toAst()
|
||||
// the actual type of the array can not yet be determined here (missing namespace & heap)
|
||||
// the actual type of the arrayspec can not yet be determined here (missing namespace & heap)
|
||||
// the ConstantFolder takes care of that and converts the type if needed.
|
||||
LiteralValue(DataType.ARRAY_UB, arrayvalue = array, position = litval.toPosition())
|
||||
}
|
||||
|
@ -247,7 +247,7 @@ class AstChecker(private val namespace: INameScope,
|
||||
if(param.second.register==Register.AX || param.second.register==Register.AY ||
|
||||
param.second.register==Register.XY) {
|
||||
if(param.first.type!=DataType.UWORD && param.first.type !in StringDatatypes && param.first.type !in ArrayDatatypes)
|
||||
err("parameter '${param.first.name}' should be uword/str/array")
|
||||
err("parameter '${param.first.name}' should be uword/str/arrayspec")
|
||||
}
|
||||
}
|
||||
for(ret in subroutine.returntypes.withIndex().zip(subroutine.asmReturnvaluesRegisters)) {
|
||||
@ -260,7 +260,7 @@ class AstChecker(private val namespace: INameScope,
|
||||
ret.second.register==Register.XY) {
|
||||
if(ret.first.value!=DataType.UWORD && ret.first.value != DataType.UBYTE &&
|
||||
ret.first.value !in StringDatatypes && ret.first.value !in ArrayDatatypes)
|
||||
err("return value #${ret.first.index+1} should be uword/ubyte/string/array")
|
||||
err("return value #${ret.first.index+1} should be uword/ubyte/string/arrayspec")
|
||||
}
|
||||
}
|
||||
|
||||
@ -338,9 +338,9 @@ class AstChecker(private val namespace: INameScope,
|
||||
}
|
||||
}
|
||||
|
||||
// it is not possible to assign a new array to something.
|
||||
// it is not possible to assign a new arrayspec to something.
|
||||
if(assignment.value.resultingDatatype(namespace, heap) in ArrayDatatypes)
|
||||
checkResult.add(SyntaxError("it's not possible to assign an array literal value to something, use it as a variable decl initializer instead", assignment.position))
|
||||
checkResult.add(SyntaxError("it's not possible to assign an arrayspec literal value to something, use it as a variable decl initializer instead", assignment.position))
|
||||
|
||||
if(assignment.aug_op!=null) {
|
||||
// check augmented assignment:
|
||||
@ -451,13 +451,13 @@ class AstChecker(private val namespace: INameScope,
|
||||
when(decl.datatype) {
|
||||
DataType.ARRAY_B, DataType.ARRAY_UB ->
|
||||
if(arraySize > 256)
|
||||
err("byte array length must be 1-256")
|
||||
err("byte arrayspec length must be 1-256")
|
||||
DataType.ARRAY_W, DataType.ARRAY_UW ->
|
||||
if(arraySize > 128)
|
||||
err("word array length must be 1-128")
|
||||
err("word arrayspec length must be 1-128")
|
||||
DataType.ARRAY_F ->
|
||||
if(arraySize > 51)
|
||||
err("float array length must be 1-51")
|
||||
err("float arrayspec length must be 1-51")
|
||||
DataType.MATRIX_B, DataType.MATRIX_UB ->
|
||||
if(arraySize > 256)
|
||||
err("invalid matrix size, must be 1-256")
|
||||
@ -570,7 +570,7 @@ class AstChecker(private val namespace: INameScope,
|
||||
}
|
||||
in ArrayDatatypes -> {
|
||||
if(lv.heapId==null)
|
||||
throw FatalAstException("array/matrix should have been moved to heap at ${lv.position}")
|
||||
throw FatalAstException("arrayspec/matrix should have been moved to heap at ${lv.position}")
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
@ -702,7 +702,7 @@ class AstChecker(private val namespace: INameScope,
|
||||
val indexedRegister = postIncrDecr.target.arrayindexed?.register
|
||||
if(indexedRegister!=null) {
|
||||
if(indexedRegister==Register.A || indexedRegister==Register.X || indexedRegister==Register.Y)
|
||||
checkResult.add(SyntaxError("array indexing on registers requires register pair variable", postIncrDecr.position))
|
||||
checkResult.add(SyntaxError("arrayspec indexing on registers requires register pair variable", postIncrDecr.position))
|
||||
} else {
|
||||
val target = postIncrDecr.target.arrayindexed?.identifier?.targetStatement(namespace)
|
||||
if(target==null) {
|
||||
@ -724,25 +724,37 @@ class AstChecker(private val namespace: INameScope,
|
||||
val target = arrayIndexedExpression.identifier!!.targetStatement(namespace)
|
||||
if(target is VarDecl) {
|
||||
if(target.datatype !in IterableDatatypes)
|
||||
checkResult.add(SyntaxError("array indexing requires an iterable variable", arrayIndexedExpression.position))
|
||||
checkResult.add(SyntaxError("arrayspec indexing requires an iterable variable", arrayIndexedExpression.position))
|
||||
val arraysize = target.arrayspec?.size()
|
||||
if(arraysize!=null) {
|
||||
// check out of bounds
|
||||
if((arrayIndexedExpression.array.y as? LiteralValue)?.asIntegerValue != null) {
|
||||
if((arrayIndexedExpression.arrayspec.y as? LiteralValue)?.asIntegerValue != null) {
|
||||
throw FatalAstException("constant y dimension of index should have been const-folded with x into one value")
|
||||
}
|
||||
val index = (arrayIndexedExpression.array.x as? LiteralValue)?.asIntegerValue
|
||||
val index = (arrayIndexedExpression.arrayspec.x as? LiteralValue)?.asIntegerValue
|
||||
if(index!=null && (index<0 || index>=arraysize))
|
||||
checkResult.add(ExpressionError("array index out of bounds", arrayIndexedExpression.array.position))
|
||||
checkResult.add(ExpressionError("arrayspec index out of bounds", arrayIndexedExpression.arrayspec.position))
|
||||
}
|
||||
} else
|
||||
checkResult.add(SyntaxError("array indexing requires a variable to act upon", arrayIndexedExpression.position))
|
||||
checkResult.add(SyntaxError("arrayspec indexing requires a variable to act upon", arrayIndexedExpression.position))
|
||||
} else if(reg==Register.A || reg==Register.X || reg==Register.Y) {
|
||||
checkResult.add(SyntaxError("array indexing on registers requires register pair variable", arrayIndexedExpression.position))
|
||||
} else if(arrayIndexedExpression.array.y!=null) {
|
||||
checkResult.add(SyntaxError("array indexing on registers can only use one index dimension", arrayIndexedExpression.position))
|
||||
checkResult.add(SyntaxError("arrayspec indexing on registers requires register pair variable", arrayIndexedExpression.position))
|
||||
} else if(arrayIndexedExpression.arrayspec.y!=null) {
|
||||
checkResult.add(SyntaxError("arrayspec 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))) {
|
||||
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))
|
||||
checkResult.add(SyntaxError("array indexing is limited to byte size 0..255", arrayIndexedExpression.position))
|
||||
|
||||
return super.process(arrayIndexedExpression)
|
||||
}
|
||||
|
||||
@ -785,7 +797,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 array/matrix size, expected $expectedSize found $rangeSize", range.position))
|
||||
checkResult.add(ExpressionError("range size doesn't match arrayspec/matrix size, expected $expectedSize found $rangeSize", range.position))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@ -850,61 +862,61 @@ class AstChecker(private val namespace: INameScope,
|
||||
return err("string length must be 0-255")
|
||||
}
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B -> {
|
||||
// value may be either a single byte, or a byte array (of all constant values)
|
||||
// value may be either a single byte, or a byte arrayspec (of all constant values)
|
||||
if(value.type==targetDt) {
|
||||
val arraySpecSize = arrayspec.size()
|
||||
val arraySize = value.arrayvalue?.size ?: heap.get(value.heapId!!).arraysize
|
||||
if(arraySpecSize!=null && arraySpecSize>0) {
|
||||
if(arraySpecSize<1 || arraySpecSize>256)
|
||||
return err("byte array length must be 1-256")
|
||||
return err("byte arrayspec length must be 1-256")
|
||||
val constX = arrayspec.x.constValue(namespace, heap)
|
||||
if(constX?.asIntegerValue==null)
|
||||
return err("array size specifier must be constant integer value")
|
||||
return err("arrayspec size specifier must be constant integer value")
|
||||
val expectedSize = constX.asIntegerValue
|
||||
if (arraySize != expectedSize)
|
||||
return err("initializer array size mismatch (expecting $expectedSize, got $arraySize)")
|
||||
return err("initializer arrayspec size mismatch (expecting $expectedSize, got $arraySize)")
|
||||
return true
|
||||
}
|
||||
return err("invalid byte array size, must be 1-256")
|
||||
return err("invalid byte arrayspec size, must be 1-256")
|
||||
}
|
||||
return err("invalid byte array initialization value ${value.type}, expected $targetDt")
|
||||
return err("invalid byte arrayspec initialization value ${value.type}, expected $targetDt")
|
||||
}
|
||||
DataType.ARRAY_UW, DataType.ARRAY_W -> {
|
||||
// value may be either a single word, or a word array
|
||||
// value may be either a single word, or a word arrayspec
|
||||
if(value.type==targetDt) {
|
||||
val arraySpecSize = arrayspec.size()
|
||||
val arraySize = value.arrayvalue?.size ?: heap.get(value.heapId!!).arraysize
|
||||
if(arraySpecSize!=null && arraySpecSize>0) {
|
||||
if(arraySpecSize<1 || arraySpecSize>128)
|
||||
return err("word array length must be 1-128")
|
||||
return err("word arrayspec length must be 1-128")
|
||||
val constX = arrayspec.x.constValue(namespace, heap)
|
||||
if(constX?.asIntegerValue==null)
|
||||
return err("array size specifier must be constant integer value")
|
||||
return err("arrayspec size specifier must be constant integer value")
|
||||
val expectedSize = constX.asIntegerValue
|
||||
if (arraySize != expectedSize)
|
||||
return err("initializer array size mismatch (expecting $expectedSize, got $arraySize)")
|
||||
return err("initializer arrayspec size mismatch (expecting $expectedSize, got $arraySize)")
|
||||
return true
|
||||
}
|
||||
return err("invalid word array size, must be 1-128")
|
||||
return err("invalid word arrayspec size, must be 1-128")
|
||||
}
|
||||
return err("invalid word array initialization value ${value.type}, expected $targetDt")
|
||||
return err("invalid word arrayspec initialization value ${value.type}, expected $targetDt")
|
||||
}
|
||||
DataType.ARRAY_F -> {
|
||||
// value may be either a single float, or a float array
|
||||
// value may be either a single float, or a float arrayspec
|
||||
if(value.type==targetDt) {
|
||||
val arraySize = value.arrayvalue?.size ?: heap.get(value.heapId!!).doubleArray!!.size
|
||||
val arraySpecSize = arrayspec.size()
|
||||
if(arraySpecSize!=null && arraySpecSize>0) {
|
||||
if(arraySpecSize < 1 || arraySpecSize>51)
|
||||
return err("float array length must be 1-51")
|
||||
return err("float arrayspec length must be 1-51")
|
||||
val constX = arrayspec.x.constValue(namespace, heap)
|
||||
if(constX?.asIntegerValue==null)
|
||||
return err("array size specifier must be constant integer value")
|
||||
return err("arrayspec size specifier must be constant integer value")
|
||||
val expectedSize = constX.asIntegerValue
|
||||
if (arraySize != expectedSize)
|
||||
return err("initializer array size mismatch (expecting $expectedSize, got $arraySize)")
|
||||
return err("initializer arrayspec size mismatch (expecting $expectedSize, got $arraySize)")
|
||||
} else
|
||||
return err("invalid float array size, must be 1-51")
|
||||
return err("invalid float arrayspec size, must be 1-51")
|
||||
|
||||
// check if the floating point values are all within range
|
||||
val doubles = if(value.arrayvalue!=null)
|
||||
@ -915,10 +927,10 @@ class AstChecker(private val namespace: INameScope,
|
||||
return err("floating point value overflow")
|
||||
return true
|
||||
}
|
||||
return err("invalid float array initialization value ${value.type}, expected $targetDt")
|
||||
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 array (which represents the matrix)
|
||||
// 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)) {
|
||||
@ -939,7 +951,7 @@ class AstChecker(private val namespace: INameScope,
|
||||
}
|
||||
return err("invalid matrix size, must be 1-256")
|
||||
}
|
||||
return err("invalid matrix initialization value of type ${value.type} - expecting byte array")
|
||||
return err("invalid matrix initialization value of type ${value.type} - expecting byte arrayspec")
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
@ -628,7 +628,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F, DataType.MATRIX_UB,
|
||||
DataType.ARRAY_B, DataType.ARRAY_W, DataType.MATRIX_B -> {
|
||||
if(lv.heapId==null)
|
||||
throw CompilerException("array/matrix should have been moved into heap ${lv.position}")
|
||||
throw CompilerException("arrayspec/matrix should have been moved into heap ${lv.position}")
|
||||
prog.instr(Opcode.PUSH_WORD, Value(lv.type, lv.heapId))
|
||||
}
|
||||
}
|
||||
@ -1046,14 +1046,14 @@ 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.array.y!=null)
|
||||
if(arrayindexed.arrayspec.y!=null)
|
||||
throw CompilerException("when using an address, can only use one index dimension")
|
||||
reg.toString()
|
||||
} else {
|
||||
variable!!.scopedname
|
||||
}
|
||||
translate(arrayindexed.array.x)
|
||||
val y = arrayindexed.array.y
|
||||
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)
|
||||
@ -1172,7 +1172,7 @@ 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 array/matrix, clear it with that value?
|
||||
// todo: maybe if you assign byte or word to arrayspec/matrix, 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")
|
||||
|
@ -16,15 +16,15 @@ abstract class Zeropage(private val options: CompilationOptions) {
|
||||
|
||||
val size =
|
||||
if(vardecl.arrayspec!=null) {
|
||||
printWarning("allocating a large value (array) in zeropage", vardecl.position)
|
||||
printWarning("allocating a large value (arrayspec) in zeropage", vardecl.position)
|
||||
val y = (vardecl.arrayspec.y as? LiteralValue)?.asIntegerValue
|
||||
if(y==null) {
|
||||
// 1 dimensional array
|
||||
// 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("array can only be of byte, word, float")
|
||||
else -> throw CompilerException("arrayspec can only be of byte, word, float")
|
||||
}
|
||||
} else {
|
||||
// 2 dimensional matrix (only bytes for now)
|
||||
|
@ -289,7 +289,7 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
||||
DataType.ARRAY_UB, DataType.ARRAY_UW, DataType.ARRAY_F -> {
|
||||
val litval = (decl.value as LiteralValue)
|
||||
if(litval.heapId==null)
|
||||
throw CompilerException("array/matrix should already be in the heap")
|
||||
throw CompilerException("arrayspec/matrix 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 / array / matrix)
|
||||
PUSH_WORD, // push word value (or 'address' of string / arrayspec / matrix)
|
||||
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
|
||||
@ -187,7 +187,7 @@ enum class Opcode {
|
||||
NOTEQUAL_WORD,
|
||||
NOTEQUAL_F,
|
||||
|
||||
// array access
|
||||
// arrayspec access
|
||||
READ_INDEXED_VAR_BYTE,
|
||||
READ_INDEXED_VAR_WORD,
|
||||
READ_INDEXED_VAR_FLOAT,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -100,7 +100,7 @@ fun builtinFunctionReturnType(function: String, args: List<IExpression>, namespa
|
||||
if(arglist.type==DataType.ARRAY_UB || arglist.type==DataType.ARRAY_UW || arglist.type==DataType.ARRAY_F || arglist.type==DataType.MATRIX_UB) {
|
||||
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 array of numeric values")
|
||||
throw FatalAstException("fuction $function only accepts arrayspec of numeric values")
|
||||
}
|
||||
if(dt.any { it==DataType.FLOAT }) return DataType.FLOAT
|
||||
if(dt.any { it==DataType.UWORD }) return DataType.UWORD
|
||||
@ -119,10 +119,10 @@ fun builtinFunctionReturnType(function: String, args: List<IExpression>, namespa
|
||||
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 array $function")
|
||||
null -> throw FatalAstException("function requires one argument which is an arrayspec $function")
|
||||
}
|
||||
}
|
||||
throw FatalAstException("function requires one argument which is an array $function")
|
||||
throw FatalAstException("function requires one argument which is an arrayspec $function")
|
||||
}
|
||||
|
||||
val func = BuiltinFunctions[function]!!
|
||||
@ -237,7 +237,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 array/matrix argument", position)
|
||||
val array = heap.get(iterable.heapId!!).array ?: throw SyntaxError("function requires arrayspec/matrix argument", position)
|
||||
function(array.map { it.toDouble() })
|
||||
}
|
||||
return LiteralValue.fromBoolean(result, position)
|
||||
@ -313,7 +313,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 array/matrix argument", position)
|
||||
throw SyntaxError("avg requires arrayspec/matrix argument", position)
|
||||
val iterable = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
|
||||
|
||||
val result = if(iterable.arrayvalue!=null) {
|
||||
@ -323,7 +323,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 array/matrix argument", position)
|
||||
val array = heap.get(iterable.heapId!!).array ?: throw SyntaxError("avg requires arrayspec/matrix argument", position)
|
||||
array.average()
|
||||
}
|
||||
return numericLiteral(result, args[0].position)
|
||||
|
@ -56,10 +56,10 @@ 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 -> {
|
||||
val litval = decl.value as? LiteralValue
|
||||
if(litval?.type==DataType.FLOAT)
|
||||
errors.add(ExpressionError("array requires only integers here", litval.position))
|
||||
errors.add(ExpressionError("arrayspec requires only integers here", litval.position))
|
||||
val size = decl.arrayspec!!.size()
|
||||
if(litval!=null && litval.isArray) {
|
||||
// array initializer value is an array already, keep as-is (or convert to WORDs if needed)
|
||||
// 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)
|
||||
@ -79,7 +79,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
|
||||
}
|
||||
}
|
||||
} else if (size != null) {
|
||||
// array initializer is empty or a single int, and we know the size; create the array.
|
||||
// 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 -> {
|
||||
@ -109,7 +109,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
|
||||
val litval = decl.value as? LiteralValue
|
||||
val size = decl.arrayspec!!.size()
|
||||
if(litval!=null && litval.isArray) {
|
||||
// array initializer value is an array already, make sure to convert to floats
|
||||
// arrayspec initializer value is an arrayspec already, make sure to convert to floats
|
||||
if(litval.heapId!=null) {
|
||||
val array = heap.get(litval.heapId)
|
||||
if (array.doubleArray == null) {
|
||||
@ -119,7 +119,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
|
||||
}
|
||||
}
|
||||
} else if (size != null) {
|
||||
// array initializer is empty or a single int, and we know the size; create the array.
|
||||
// arrayspec initializer is empty or a single int, and we know the size; create the arrayspec.
|
||||
val fillvalue = if (litval == null) 0.0 else litval.asNumericValue?.toDouble() ?: 0.0
|
||||
if(fillvalue< FLOAT_MAX_NEGATIVE || fillvalue> FLOAT_MAX_POSITIVE)
|
||||
errors.add(ExpressionError("float value overflow", litval?.position ?: decl.position))
|
||||
@ -492,7 +492,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("array/matrix literal can contain only constant values", arraylit.position))
|
||||
addError(ExpressionError("arrayspec/matrix literal can contain only constant values", arraylit.position))
|
||||
return arraylit
|
||||
} else {
|
||||
val valuesInArray = array.map { it.constValue(namespace, heap)!!.asNumericValue!! }
|
||||
@ -533,24 +533,24 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
|
||||
DataType.MATRIX_UB,
|
||||
DataType.MATRIX_B -> heap.add(arrayDt, integerArray)
|
||||
DataType.ARRAY_F -> heap.add(arrayDt, doubleArray)
|
||||
else -> throw CompilerException("invalid array type")
|
||||
else -> throw CompilerException("invalid arrayspec type")
|
||||
}
|
||||
return LiteralValue(arrayDt, heapId = heapId, position = arraylit.position)
|
||||
}
|
||||
}
|
||||
|
||||
override fun process(arrayIndexedExpression: ArrayIndexedExpression): IExpression {
|
||||
if(arrayIndexedExpression.array.y!=null) {
|
||||
if(arrayIndexedExpression.array.size()!=null) {
|
||||
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.array.x as LiteralValue).asIntegerValue!!
|
||||
val y = (arrayIndexedExpression.array.y as LiteralValue).asIntegerValue!!
|
||||
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.array = ArraySpec(LiteralValue.optimalInteger(index, arrayIndexedExpression.array.position), null, arrayIndexedExpression.array.position)
|
||||
arrayIndexedExpression.arrayspec = ArraySpec(LiteralValue.optimalInteger(index, arrayIndexedExpression.arrayspec.position), null, arrayIndexedExpression.arrayspec.position)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -222,7 +222,7 @@ class Program (val name: String,
|
||||
DataType.MATRIX_UB,
|
||||
DataType.MATRIX_B -> {
|
||||
if(!valueStr.startsWith("heap:"))
|
||||
throw VmExecutionException("invalid array/matrix value, should be a heap reference")
|
||||
throw VmExecutionException("invalid arrayspec/matrix value, should be a heap reference")
|
||||
else {
|
||||
val heapId = valueStr.substring(5).toInt()
|
||||
Value(type, heapId)
|
||||
|
@ -1229,13 +1229,13 @@ class StackVm(private var traceOutputFile: String?) {
|
||||
// assume the variable is a pointer (address) and get the ubyte value from that memory location
|
||||
evalstack.push(Value(DataType.UBYTE, mem.getUByte(variable.integerValue())))
|
||||
} else {
|
||||
// get indexed byte element from the array
|
||||
// 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.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 array/matrix/string variable with byte elements")
|
||||
else -> throw VmExecutionException("not a proper arrayspec/matrix/string variable with byte elements")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1247,12 +1247,12 @@ class StackVm(private var traceOutputFile: String?) {
|
||||
// assume the variable is a pointer (address) and get the word value from that memory location
|
||||
evalstack.push(Value(DataType.UWORD, mem.getUWord(variable.integerValue())))
|
||||
} else {
|
||||
// get indexed word element from the array
|
||||
// get indexed word element from the arrayspec
|
||||
val array = heap.get(variable.heapId)
|
||||
when(array.type){
|
||||
DataType.ARRAY_UW -> evalstack.push(Value(DataType.UWORD, array.array!![index]))
|
||||
DataType.ARRAY_W -> evalstack.push(Value(DataType.WORD, array.array!![index]))
|
||||
else -> throw VmExecutionException("not a proper array var with word elements")
|
||||
else -> throw VmExecutionException("not a proper arrayspec var with word elements")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1264,10 +1264,10 @@ class StackVm(private var traceOutputFile: String?) {
|
||||
// assume the variable is a pointer (address) and get the float value from that memory location
|
||||
evalstack.push(Value(DataType.UWORD, mem.getFloat(variable.integerValue())))
|
||||
} else {
|
||||
// get indexed float element from the array
|
||||
// get indexed float element from the arrayspec
|
||||
val array = heap.get(variable.heapId)
|
||||
if(array.type!=DataType.ARRAY_F)
|
||||
throw VmExecutionException("not a proper array var with float elements")
|
||||
throw VmExecutionException("not a proper arrayspec var with float elements")
|
||||
evalstack.push(Value(DataType.FLOAT, array.doubleArray!![index]))
|
||||
}
|
||||
}
|
||||
@ -1281,7 +1281,7 @@ class StackVm(private var traceOutputFile: String?) {
|
||||
// assume the variable is a pointer (address) and write the byte value to that memory location
|
||||
mem.setUByte(variable.integerValue(), value.integerValue().toShort())
|
||||
} else {
|
||||
// set indexed byte element in the array
|
||||
// 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()
|
||||
@ -1294,7 +1294,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 array/matrix/string var with byte elements")
|
||||
else -> throw VmExecutionException("not a proper arrayspec/matrix/string var with byte elements")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1308,12 +1308,12 @@ class StackVm(private var traceOutputFile: String?) {
|
||||
// assume the variable is a pointer (address) and write the word value to that memory location
|
||||
mem.setUWord(variable.integerValue(), value.integerValue())
|
||||
} else {
|
||||
// set indexed word element in the array
|
||||
// set indexed word element in the arrayspec
|
||||
val array = heap.get(variable.heapId)
|
||||
when(array.type) {
|
||||
DataType.ARRAY_UW -> array.array!![index] = value.integerValue()
|
||||
DataType.ARRAY_W -> array.array!![index] = value.integerValue()
|
||||
else -> throw VmExecutionException("not a proper array var with word elements")
|
||||
else -> throw VmExecutionException("not a proper arrayspec var with word elements")
|
||||
}
|
||||
|
||||
}
|
||||
@ -1328,10 +1328,10 @@ class StackVm(private var traceOutputFile: String?) {
|
||||
// assume the variable is a pointer (address) and write the float value to that memory location
|
||||
mem.setFloat(variable.integerValue(), value.numericValue().toDouble())
|
||||
} else {
|
||||
// set indexed float element in the array
|
||||
// set indexed float element in the arrayspec
|
||||
val array = heap.get(variable.heapId)
|
||||
if(array.type!=DataType.ARRAY_F)
|
||||
throw VmExecutionException("not a proper array var with float elements")
|
||||
throw VmExecutionException("not a proper arrayspec var with float elements")
|
||||
array.doubleArray!![index] = value.numericValue().toDouble()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user