assignments and stuff

This commit is contained in:
Irmen de Jong 2018-10-27 21:26:32 +02:00
parent a23673fe83
commit f4e2641f7c
12 changed files with 569 additions and 650 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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 / 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,
@ -261,4 +261,4 @@ val popOpcodes = setOf(
Opcode.POP_VAR_BYTE,
Opcode.POP_VAR_WORD,
Opcode.POP_VAR_FLOAT
)
)

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@ -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)
@ -303,4 +303,4 @@ class Program (val name: String,
}
}
}
}
}

View File

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