w.i.p pointer-to

This commit is contained in:
Irmen de Jong 2019-04-04 21:02:24 +02:00
parent 3e7e44acfe
commit 1069b5f5d5
12 changed files with 1079 additions and 915 deletions

View File

@ -42,13 +42,10 @@ enum class DataType {
UWORD -> targetType == UWORD || targetType == FLOAT UWORD -> targetType == UWORD || targetType == FLOAT
WORD -> targetType == WORD || targetType==UWORD || targetType == FLOAT WORD -> targetType == WORD || targetType==UWORD || targetType == FLOAT
FLOAT -> targetType == FLOAT FLOAT -> targetType == FLOAT
STR -> targetType == STR || targetType==STR_S || targetType == UWORD STR -> targetType == STR || targetType==STR_S
STR_S -> targetType == STR || targetType==STR_S || targetType == UWORD STR_S -> targetType == STR || targetType==STR_S
ARRAY_UB -> targetType == UWORD || targetType==ARRAY_UB in ArrayDatatypes -> targetType === this
ARRAY_B -> targetType == UWORD || targetType==ARRAY_B else -> false
ARRAY_UW -> targetType == UWORD || targetType==ARRAY_UW
ARRAY_W -> targetType == UWORD || targetType==ARRAY_W
ARRAY_F -> targetType == UWORD || targetType==ARRAY_F
} }
@ -291,6 +288,10 @@ interface IAstProcessor {
memwrite.addressExpression = memwrite.addressExpression.process(this) memwrite.addressExpression = memwrite.addressExpression.process(this)
return memwrite return memwrite
} }
fun process(pointerOf: PointerOf): IExpression {
return pointerOf
}
} }
@ -1009,6 +1010,22 @@ class TypecastExpression(var expression: IExpression, var type: DataType, overri
} }
data class PointerOf(val identifier: IdentifierReference, override val position: Position) : IExpression {
override lateinit var parent: Node
override fun linkParents(parent: Node) {
this.parent = parent
identifier.parent=this
}
override fun isIterable(namespace: INameScope, heap: HeapValues) = false
override fun constValue(namespace: INameScope, heap: HeapValues): LiteralValue? = null
override fun referencesIdentifier(name: String) = false
override fun resultingDatatype(namespace: INameScope, heap: HeapValues) = DataType.UWORD
override fun process(processor: IAstProcessor) = processor.process(this)
}
class DirectMemoryRead(var addressExpression: IExpression, override val position: Position) : IExpression { class DirectMemoryRead(var addressExpression: IExpression, override val position: Position) : IExpression {
override lateinit var parent: Node override lateinit var parent: Node
@ -2196,6 +2213,9 @@ private fun prog8Parser.ExpressionContext.toAst() : IExpression {
if(directmemory()!=null) if(directmemory()!=null)
return DirectMemoryRead(directmemory().expression().toAst(), toPosition()) return DirectMemoryRead(directmemory().expression().toAst(), toPosition())
if(pointerof()!=null)
return PointerOf(pointerof().scoped_identifier().toAst(), toPosition())
throw FatalAstException(text) throw FatalAstException(text)
} }

View File

@ -58,7 +58,7 @@ private class AstChecker(private val namespace: INameScope,
private val heapStringSentinel: Int private val heapStringSentinel: Int
init { init {
val stringSentinel = heap.allEntries().firstOrNull {it.value.str==""} val stringSentinel = heap.allEntries().firstOrNull {it.value.str==""}
heapStringSentinel = stringSentinel?.key ?: heap.add(DataType.STR, "") heapStringSentinel = stringSentinel?.key ?: heap.addString(DataType.STR, "")
} }
fun result(): List<AstException> { fun result(): List<AstException> {
@ -401,22 +401,9 @@ private class AstChecker(private val namespace: INameScope,
checkResult.add(ExpressionError("cannot assign new value to a constant", assignment.position)) checkResult.add(ExpressionError("cannot assign new value to a constant", assignment.position))
return assignment return assignment
} }
if(assignment.value.resultingDatatype(namespace, heap) in ArrayDatatypes) {
if(targetSymbol.datatype==DataType.UWORD)
return assignment // array can be assigned to UWORD (it's address should be taken as the value then)
} }
} }
} }
}
// it is only possible to assign an array to something that is an UWORD or UWORD array (in which case the address of the array value is used as the value)
if(assignment.value.resultingDatatype(namespace, heap) in ArrayDatatypes) {
// the UWORD case has been handled above already, check for UWORD array
val arrayVar = target.arrayindexed?.identifier?.targetStatement(namespace)
if(arrayVar is VarDecl && arrayVar.datatype==DataType.ARRAY_UW)
return assignment
checkResult.add(SyntaxError("it's not possible to assign an array to something other than an UWORD, use it as a variable decl initializer instead", assignment.position))
}
if(assignment.aug_op!=null) { if(assignment.aug_op!=null) {
// check augmented assignment (and convert it into a normal assignment!) // check augmented assignment (and convert it into a normal assignment!)
@ -468,6 +455,16 @@ private class AstChecker(private val namespace: INameScope,
return assignment return assignment
} }
override fun process(pointerOf: PointerOf): IExpression {
val variable=pointerOf.identifier.targetStatement(namespace) as? VarDecl
if(variable==null)
checkResult.add(ExpressionError("pointer-of operand must be the name of a heap variable", pointerOf.position))
else {
if(variable.datatype !in ArrayDatatypes && variable.datatype !in StringDatatypes)
checkResult.add(ExpressionError("pointer-of operand must be the name of a string or array heap variable", pointerOf.position))
}
return pointerOf
}
/** /**
* Check the variable declarations (values within range etc) * Check the variable declarations (values within range etc)
@ -984,8 +981,6 @@ private class AstChecker(private val namespace: INameScope,
return err("value '$number' out of range for byte") return err("value '$number' out of range for byte")
} }
DataType.UWORD -> { DataType.UWORD -> {
if(value.isString || value.isArray) // string or array are assignable to uword; their memory address is used.
return true
val number = value.asIntegerValue ?: return if (value.floatvalue!=null) val number = value.asIntegerValue ?: return if (value.floatvalue!=null)
err("unsigned word value expected instead of float; possible loss of precision") err("unsigned word value expected instead of float; possible loss of precision")
else else
@ -1091,16 +1086,16 @@ private class AstChecker(private val namespace: INameScope,
val correct: Boolean val correct: Boolean
when(type) { when(type) {
DataType.ARRAY_UB -> { DataType.ARRAY_UB -> {
correct=array.array!=null && array.array.all { it in 0..255 } correct=array.array!=null && array.array.all { it.integer!=null && it.integer in 0..255 }
} }
DataType.ARRAY_B -> { DataType.ARRAY_B -> {
correct=array.array!=null && array.array.all { it in -128..127 } correct=array.array!=null && array.array.all { it.integer!=null && it.integer in -128..127 }
} }
DataType.ARRAY_UW -> { DataType.ARRAY_UW -> {
correct=array.array!=null && array.array.all { it in 0..65535 } correct=array.array!=null && array.array.all { (it.integer!=null && it.integer in 0..65535) || it.pointerOf!=null}
} }
DataType.ARRAY_W -> { DataType.ARRAY_W -> {
correct=array.array!=null && array.array.all { it in -32768..32767 } correct=array.array!=null && array.array.all { it.integer!=null && it.integer in -32768..32767 }
} }
DataType.ARRAY_F -> correct = array.doubleArray!=null DataType.ARRAY_F -> correct = array.doubleArray!=null
else -> throw AstException("invalid array type $type") else -> throw AstException("invalid array type $type")
@ -1123,7 +1118,7 @@ private class AstChecker(private val namespace: INameScope,
DataType.BYTE -> sourceDatatype==DataType.BYTE DataType.BYTE -> sourceDatatype==DataType.BYTE
DataType.UBYTE -> sourceDatatype==DataType.UBYTE DataType.UBYTE -> sourceDatatype==DataType.UBYTE
DataType.WORD -> sourceDatatype==DataType.BYTE || sourceDatatype==DataType.UBYTE || sourceDatatype==DataType.WORD DataType.WORD -> sourceDatatype==DataType.BYTE || sourceDatatype==DataType.UBYTE || sourceDatatype==DataType.WORD
DataType.UWORD -> sourceDatatype in setOf(DataType.UBYTE, DataType.UWORD, DataType.STR, DataType.STR_S) || sourceDatatype in ArrayDatatypes DataType.UWORD -> sourceDatatype==DataType.UBYTE || sourceDatatype==DataType.UWORD
DataType.FLOAT -> sourceDatatype in NumericDatatypes DataType.FLOAT -> sourceDatatype in NumericDatatypes
DataType.STR -> sourceDatatype==DataType.STR DataType.STR -> sourceDatatype==DataType.STR
DataType.STR_S -> sourceDatatype==DataType.STR_S DataType.STR_S -> sourceDatatype==DataType.STR_S

View File

@ -36,8 +36,11 @@ fun Number.toHex(): String {
} }
data class IntegerOrPointerOf(val integer: Int?, val pointerOf: PointerOf?)
class HeapValues { class HeapValues {
data class HeapValue(val type: DataType, val str: String?, val array: IntArray?, val doubleArray: DoubleArray?) { data class HeapValue(val type: DataType, val str: String?, val array: Array<IntegerOrPointerOf>?, val doubleArray: DoubleArray?) {
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (javaClass != other?.javaClass) return false if (javaClass != other?.javaClass) return false
@ -61,7 +64,7 @@ class HeapValues {
fun size(): Int = heap.size fun size(): Int = heap.size
fun add(type: DataType, str: String): Int { fun addString(type: DataType, str: String): Int {
if (str.length > 255) if (str.length > 255)
throw IllegalArgumentException("string length must be 0-255") throw IllegalArgumentException("string length must be 0-255")
@ -76,14 +79,14 @@ class HeapValues {
return newId return newId
} }
fun add(type: DataType, array: IntArray): Int { fun addIntegerArray(type: DataType, array: Array<IntegerOrPointerOf>): Int {
// arrays are never shared, don't check for existing // arrays are never shared, don't check for existing
val newId = heapId++ val newId = heapId++
heap[newId] = HeapValue(type, null, array, null) heap[newId] = HeapValue(type, null, array, null)
return newId return newId
} }
fun add(type: DataType, darray: DoubleArray): Int { fun addDoublesArray(type: DataType, darray: DoubleArray): Int {
// arrays are never shared, don't check for existing // arrays are never shared, don't check for existing
val newId = heapId++ val newId = heapId++
heap[newId] = HeapValue(type, null, null, darray) heap[newId] = HeapValue(type, null, null, darray)
@ -653,6 +656,7 @@ internal class Compiler(private val rootModule: Module,
is TypecastExpression -> translate(expr) is TypecastExpression -> translate(expr)
is DirectMemoryRead -> translate(expr) is DirectMemoryRead -> translate(expr)
is DirectMemoryWrite -> translate(expr) is DirectMemoryWrite -> translate(expr)
is PointerOf -> translate(expr)
else -> { else -> {
val lv = expr.constValue(namespace, heap) ?: throw CompilerException("constant expression required, not $expr") val lv = expr.constValue(namespace, heap) ?: throw CompilerException("constant expression required, not $expr")
when(lv.type) { when(lv.type) {
@ -1081,12 +1085,13 @@ internal class Compiler(private val rootModule: Module,
translate(assignA) translate(assignA)
translate(assignX) translate(assignX)
} }
DataType.UWORD -> { in WordDatatypes -> {
translate(arg.first) translate(arg.first)
prog.instr(Opcode.POP_REGAX_WORD) prog.instr(Opcode.POP_REGAX_WORD)
} }
// TODO auto-converting str/float/array to their pointer value should be done by explicitly rewriting the Ast into a pointer-of expression, once that is available
DataType.STR, DataType.STR_S -> { DataType.STR, DataType.STR_S -> {
pushStringAddress(arg.first, false) pushHeapVarAddress(arg.first, false)
prog.instr(Opcode.POP_REGAX_WORD) prog.instr(Opcode.POP_REGAX_WORD)
} }
DataType.FLOAT -> { DataType.FLOAT -> {
@ -1094,7 +1099,7 @@ internal class Compiler(private val rootModule: Module,
prog.instr(Opcode.POP_REGAX_WORD) prog.instr(Opcode.POP_REGAX_WORD)
} }
in ArrayDatatypes -> { in ArrayDatatypes -> {
pushStringAddress(arg.first, false) pushHeapVarAddress(arg.first, false)
prog.instr(Opcode.POP_REGAX_WORD) prog.instr(Opcode.POP_REGAX_WORD)
} }
else -> TODO("pass parameter of type $paramDt in registers AX at $callPosition") else -> TODO("pass parameter of type $paramDt in registers AX at $callPosition")
@ -1119,8 +1124,9 @@ internal class Compiler(private val rootModule: Module,
translate(arg.first) translate(arg.first)
prog.instr(Opcode.POP_REGAY_WORD) prog.instr(Opcode.POP_REGAY_WORD)
} }
// TODO auto-converting str/float/array to their pointer value should be done by explicitly rewriting the Ast into a pointer-of expression, once that is available
DataType.STR, DataType.STR_S -> { DataType.STR, DataType.STR_S -> {
pushStringAddress(arg.first, false) pushHeapVarAddress(arg.first, false)
prog.instr(Opcode.POP_REGAY_WORD) prog.instr(Opcode.POP_REGAY_WORD)
} }
DataType.FLOAT -> { DataType.FLOAT -> {
@ -1128,7 +1134,7 @@ internal class Compiler(private val rootModule: Module,
prog.instr(Opcode.POP_REGAY_WORD) prog.instr(Opcode.POP_REGAY_WORD)
} }
in ArrayDatatypes -> { in ArrayDatatypes -> {
pushStringAddress(arg.first, false) pushHeapVarAddress(arg.first, false)
prog.instr(Opcode.POP_REGAY_WORD) prog.instr(Opcode.POP_REGAY_WORD)
} }
else -> TODO("pass parameter of type $paramDt in registers AY at $callPosition") else -> TODO("pass parameter of type $paramDt in registers AY at $callPosition")
@ -1153,12 +1159,13 @@ internal class Compiler(private val rootModule: Module,
translate(assignX) translate(assignX)
translate(assignY) translate(assignY)
} }
DataType.UWORD -> { in WordDatatypes -> {
translate(arg.first) translate(arg.first)
prog.instr(Opcode.POP_REGXY_WORD) prog.instr(Opcode.POP_REGXY_WORD)
} }
// TODO auto-converting str/float/array to their pointer value should be done by explicitly rewriting the Ast into a pointer-of expression, once that is available
DataType.STR, DataType.STR_S -> { DataType.STR, DataType.STR_S -> {
pushStringAddress(arg.first, false) pushHeapVarAddress(arg.first, false)
prog.instr(Opcode.POP_REGXY_WORD) prog.instr(Opcode.POP_REGXY_WORD)
} }
DataType.FLOAT -> { DataType.FLOAT -> {
@ -1166,7 +1173,7 @@ internal class Compiler(private val rootModule: Module,
prog.instr(Opcode.POP_REGXY_WORD) prog.instr(Opcode.POP_REGXY_WORD)
} }
in ArrayDatatypes -> { in ArrayDatatypes -> {
pushStringAddress(arg.first, false) pushHeapVarAddress(arg.first, false)
prog.instr(Opcode.POP_REGXY_WORD) prog.instr(Opcode.POP_REGXY_WORD)
} }
else -> TODO("pass parameter of type $paramDt in registers XY at $callPosition") else -> TODO("pass parameter of type $paramDt in registers XY at $callPosition")
@ -1524,7 +1531,7 @@ internal class Compiler(private val rootModule: Module,
when (valueDt) { when (valueDt) {
DataType.UBYTE -> prog.instr(Opcode.CAST_UB_TO_UW) DataType.UBYTE -> prog.instr(Opcode.CAST_UB_TO_UW)
DataType.BYTE -> prog.instr(Opcode.CAST_B_TO_UW) DataType.BYTE -> prog.instr(Opcode.CAST_B_TO_UW)
DataType.STR, DataType.STR_S -> pushStringAddress(stmt.value, true) DataType.STR, DataType.STR_S -> pushHeapVarAddress(stmt.value, true)
DataType.ARRAY_B, DataType.ARRAY_UB, DataType.ARRAY_W, DataType.ARRAY_UW, DataType.ARRAY_F -> { DataType.ARRAY_B, DataType.ARRAY_UB, DataType.ARRAY_W, DataType.ARRAY_UW, DataType.ARRAY_F -> {
if (stmt.value is IdentifierReference) { if (stmt.value is IdentifierReference) {
val vardecl = (stmt.value as IdentifierReference).targetStatement(namespace) as VarDecl val vardecl = (stmt.value as IdentifierReference).targetStatement(namespace) as VarDecl
@ -1548,7 +1555,7 @@ internal class Compiler(private val rootModule: Module,
} }
in StringDatatypes -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt") in StringDatatypes -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
in ArrayDatatypes -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt") in ArrayDatatypes -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
else -> throw CompilerException("weird/unknonwn targetdt") else -> throw CompilerException("weird/unknown targetdt")
} }
} }
@ -1560,9 +1567,9 @@ internal class Compiler(private val rootModule: Module,
popValueIntoTarget(assignTarget, datatype) popValueIntoTarget(assignTarget, datatype)
} }
private fun pushStringAddress(value: IExpression, removeLastOpcode: Boolean) { private fun pushHeapVarAddress(value: IExpression, removeLastOpcode: Boolean) {
when (value) { when (value) {
is LiteralValue -> throw CompilerException("can only push address of string that is a variable on the heap") is LiteralValue -> throw CompilerException("can only push address of string or array (value on the heap)")
is IdentifierReference -> { is IdentifierReference -> {
val vardecl = value.targetStatement(namespace) as VarDecl val vardecl = value.targetStatement(namespace) as VarDecl
if(removeLastOpcode) prog.removeLastInstruction() if(removeLastOpcode) prog.removeLastInstruction()
@ -2163,6 +2170,18 @@ internal class Compiler(private val rootModule: Module,
} }
} }
private fun translate(ptrof: PointerOf) {
val target = ptrof.identifier.targetStatement(namespace) as VarDecl
if(target.datatype in ArrayDatatypes || target.datatype in StringDatatypes|| target.datatype==DataType.FLOAT) {
pushHeapVarAddress(ptrof.identifier, false)
}
else if(target.datatype==DataType.FLOAT) {
pushFloatAddress(ptrof.identifier)
}
else
throw CompilerException("cannot take memory pointer $ptrof")
}
private fun translateAsmInclude(args: List<DirectiveArg>, importedFrom: Path) { private fun translateAsmInclude(args: List<DirectiveArg>, importedFrom: Path) {
val scopeprefix = if(args[1].str!!.isNotBlank()) "${args[1].str}\t.proc\n" else "" val scopeprefix = if(args[1].str!!.isNotBlank()) "${args[1].str}\t.proc\n" else ""
val scopeprefixEnd = if(args[1].str!!.isNotBlank()) "\t.pend\n" else "" val scopeprefixEnd = if(args[1].str!!.isNotBlank()) "\t.pend\n" else ""

View File

@ -359,20 +359,25 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
private fun makeArrayFillDataUnsigned(value: Value): List<String> { private fun makeArrayFillDataUnsigned(value: Value): List<String> {
val array = heap.get(value.heapId).array!! val array = heap.get(value.heapId).array!!
return if (value.type == DataType.ARRAY_UB || value.type == DataType.ARRAY_UW) if(value.type==DataType.ARRAY_UB) {
array.map { "$"+it.toString(16).padStart(2, '0') } TODO("deal with byte array")
//return array.map { "$"+it.toString(16).padStart(2, '0') }
} else if(value.type==DataType.ARRAY_UW) {
TODO("deal with pointerto")
}
else else
throw AssemblyError("invalid arrayspec type") throw AssemblyError("invalid arrayspec type")
} }
private fun makeArrayFillDataSigned(value: Value): List<String> { private fun makeArrayFillDataSigned(value: Value): List<String> {
val array = heap.get(value.heapId).array!! val array = heap.get(value.heapId).array!!
// note: array of signed value can never contain pointer-to type, so simply process values as being all integers
return if (value.type == DataType.ARRAY_B || value.type == DataType.ARRAY_W) { return if (value.type == DataType.ARRAY_B || value.type == DataType.ARRAY_W) {
array.map { array.map {
if(it>=0) if(it.integer!!>=0)
"$"+it.toString(16).padStart(2, '0') "$"+it.integer.toString(16).padStart(2, '0')
else else
"-$"+abs(it).toString(16).padStart(2, '0') "-$"+abs(it.integer).toString(16).padStart(2, '0')
} }
} }
else throw AssemblyError("invalid arrayspec type") else throw AssemblyError("invalid arrayspec type")
@ -923,23 +928,21 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
if(mulIns.opcode == Opcode.MUL_B || mulIns.opcode==Opcode.MUL_UB) { if(mulIns.opcode == Opcode.MUL_B || mulIns.opcode==Opcode.MUL_UB) {
if(amount in setOf(0,1,2,4,8,16,32,64,128,256)) if(amount in setOf(0,1,2,4,8,16,32,64,128,256))
throw AssemblyError("multiplication by power of 2 should have been converted into a left shift instruction already") printWarning("multiplication by power of 2 should have been optimized into a left shift instruction: $mulIns $amount")
if(amount in setOf(3,5,6,7,9,10,11,12,13,14,15,20,25,40)) if(amount in setOf(3,5,6,7,9,10,11,12,13,14,15,20,25,40))
return " jsr math.mul_byte_$amount" return " jsr math.mul_byte_$amount"
if(mulIns.opcode == Opcode.MUL_B && amount in setOf(-3,-5,-6,-7,-9,-10,-11,-12,-13,-14,-15,-20,-25,-40)) if(mulIns.opcode == Opcode.MUL_B && amount in setOf(-3,-5,-6,-7,-9,-10,-11,-12,-13,-14,-15,-20,-25,-40))
return " jsr prog8_lib.neg_b | jsr math.mul_byte_${-amount}" return " jsr prog8_lib.neg_b | jsr math.mul_byte_${-amount}"
} }
else if(mulIns.opcode == Opcode.MUL_UW) { else if(mulIns.opcode == Opcode.MUL_UW) {
if(amount in setOf(0,1,2,4,8,16,32,64,128,256)) if(amount in setOf(0,1,2,4,8,16,32,64,128,256))
throw AssemblyError("multiplication by power of 2 should have been converted into a left shift instruction already") printWarning("multiplication by power of 2 should have been optimized into a left shift instruction: $mulIns $amount")
if(amount in setOf(3,5,6,7,9,10,12,15,20,25,40)) if(amount in setOf(3,5,6,7,9,10,12,15,20,25,40))
return " jsr math.mul_word_$amount" return " jsr math.mul_word_$amount"
} }
else if(mulIns.opcode == Opcode.MUL_W) { else if(mulIns.opcode == Opcode.MUL_W) {
if(amount in setOf(0,1,2,4,8,16,32,64,128,256)) if(amount in setOf(0,1,2,4,8,16,32,64,128,256))
throw AssemblyError("multiplication by power of 2 should have been converted into a left shift instruction already") printWarning("multiplication by power of 2 should have been optimized into a left shift instruction: $mulIns $amount")
if(amount in setOf(3,5,6,7,9,10,12,15,20,25,40)) if(amount in setOf(3,5,6,7,9,10,12,15,20,25,40))
return " jsr math.mul_word_$amount" return " jsr math.mul_word_$amount"
if(amount in setOf(-3,-5,-6,-7,-9,-10,-12,-15,-20,-25,-40)) if(amount in setOf(-3,-5,-6,-7,-9,-10,-12,-15,-20,-25,-40))

View File

@ -245,7 +245,12 @@ private fun collectionArgOutputNumber(args: List<IExpression>, position: Positio
if(iterable.heapId==null) if(iterable.heapId==null)
throw FatalAstException("iterable value should be on the heap") throw FatalAstException("iterable value should be on the heap")
val array = heap.get(iterable.heapId).array ?: throw SyntaxError("function expects an iterable type", position) val array = heap.get(iterable.heapId).array ?: throw SyntaxError("function expects an iterable type", position)
function(array.map { it.toDouble() }) function(array.map {
if(it.integer!=null)
it.integer.toDouble()
else
throw FatalAstException("cannot perform function over array that contains other values besides constant integers")
})
} }
} }
} }
@ -266,7 +271,12 @@ private fun collectionArgOutputBoolean(args: List<IExpression>, position: Positi
function(constants.map { it!!.toDouble() }) function(constants.map { it!!.toDouble() })
} else { } else {
val array = heap.get(iterable.heapId!!).array ?: throw SyntaxError("function requires array argument", position) val array = heap.get(iterable.heapId!!).array ?: throw SyntaxError("function requires array argument", position)
function(array.map { it.toDouble() }) function(array.map {
if(it.integer!=null)
it.integer.toDouble()
else
throw FatalAstException("cannot perform function over array that contains other values besides constant integers")
})
} }
return LiteralValue.fromBoolean(result, position) return LiteralValue.fromBoolean(result, position)
} }
@ -298,7 +308,12 @@ private fun builtinAvg(args: List<IExpression>, position: Position, namespace:IN
} }
else { else {
val array = heap.get(iterable.heapId!!).array ?: throw SyntaxError("avg requires array argument", position) val array = heap.get(iterable.heapId!!).array ?: throw SyntaxError("avg requires array argument", position)
array.average() if(array.all {it.integer!=null}) {
array.map { it.integer!! }.average()
} else {
throw ExpressionError("cannot avg() over array that does not only contain constant integer values", position)
}
// TODO what about avg() on floating point array variable!
} }
return numericLiteral(result, args[0].position) return numericLiteral(result, args[0].position)
} }

View File

@ -3,6 +3,7 @@ package prog8.optimizing
import prog8.ast.* import prog8.ast.*
import prog8.compiler.CompilerException import prog8.compiler.CompilerException
import prog8.compiler.HeapValues import prog8.compiler.HeapValues
import prog8.compiler.IntegerOrPointerOf
import prog8.compiler.target.c64.FLOAT_MAX_NEGATIVE import prog8.compiler.target.c64.FLOAT_MAX_NEGATIVE
import prog8.compiler.target.c64.FLOAT_MAX_POSITIVE import prog8.compiler.target.c64.FLOAT_MAX_POSITIVE
import kotlin.math.floor import kotlin.math.floor
@ -69,8 +70,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
} }
else -> {} else -> {}
} }
val fillArray = IntArray(size) { fillvalue } val heapId = heap.addIntegerArray(decl.datatype, Array(size) { IntegerOrPointerOf(fillvalue, null) })
val heapId = heap.add(decl.datatype, fillArray)
decl.value = LiteralValue(decl.datatype, heapId = heapId, position = litval?.position ?: decl.position) decl.value = LiteralValue(decl.datatype, heapId = heapId, position = litval?.position ?: decl.position)
} }
} }
@ -82,8 +82,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
if(fillvalue< FLOAT_MAX_NEGATIVE || fillvalue> FLOAT_MAX_POSITIVE) if(fillvalue< FLOAT_MAX_NEGATIVE || fillvalue> FLOAT_MAX_POSITIVE)
errors.add(ExpressionError("float value overflow", litval?.position ?: decl.position)) errors.add(ExpressionError("float value overflow", litval?.position ?: decl.position))
else { else {
val fillArray = DoubleArray(size) { fillvalue } val heapId = heap.addDoublesArray(decl.datatype, DoubleArray(size) { fillvalue })
val heapId = heap.add(decl.datatype, fillArray)
decl.value = LiteralValue(decl.datatype, heapId = heapId, position = litval?.position ?: decl.position) decl.value = LiteralValue(decl.datatype, heapId = heapId, position = litval?.position ?: decl.position)
} }
} }
@ -112,7 +111,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
DataType.ARRAY_F -> { DataType.ARRAY_F -> {
if(array.array!=null) { if(array.array!=null) {
// convert a non-float array to floats // convert a non-float array to floats
val doubleArray = array.array.map { it.toDouble() }.toDoubleArray() val doubleArray = array.array.map { it.integer!!.toDouble() }.toDoubleArray()
heap.update(heapId, HeapValues.HeapValue(DataType.ARRAY_F, null, null, doubleArray)) heap.update(heapId, HeapValues.HeapValue(DataType.ARRAY_F, null, null, doubleArray))
decl.value = LiteralValue(decl.datatype, heapId = heapId, position = litval.position) decl.value = LiteralValue(decl.datatype, heapId = heapId, position = litval.position)
} }
@ -534,7 +533,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
if(literalValue.strvalue(heap).length !in 1..255) if(literalValue.strvalue(heap).length !in 1..255)
addError(ExpressionError("string literal length must be between 1 and 255", literalValue.position)) addError(ExpressionError("string literal length must be between 1 and 255", literalValue.position))
else { else {
val heapId = heap.add(literalValue.type, literalValue.strvalue(heap)) // TODO: we don't know the actual string type yet, STR != STR_S etc... val heapId = heap.addString(literalValue.type, literalValue.strvalue(heap)) // TODO: we don't know the actual string type yet, STR != STR_S etc...
val newValue = LiteralValue(literalValue.type, heapId = heapId, position = literalValue.position) val newValue = LiteralValue(literalValue.type, heapId = heapId, position = literalValue.position)
return super.process(newValue) return super.process(newValue)
} }
@ -547,13 +546,20 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
private fun moveArrayToHeap(arraylit: LiteralValue): LiteralValue { private fun moveArrayToHeap(arraylit: LiteralValue): LiteralValue {
val array: Array<IExpression> = arraylit.arrayvalue!!.map { it.process(this) }.toTypedArray() val array: Array<IExpression> = arraylit.arrayvalue!!.map { it.process(this) }.toTypedArray()
val allElementsAreConstant = array.fold(true) { c, expr-> c and (expr is LiteralValue)} val allElementsAreConstantOrPointerOf = array.fold(true) { c, expr-> c and (expr is LiteralValue || expr is PointerOf)}
if(!allElementsAreConstant) { if(!allElementsAreConstantOrPointerOf) {
addError(ExpressionError("array literal can contain only constant values", arraylit.position)) addError(ExpressionError("array literal can only consist of constant primitive numerical values or memory pointers", arraylit.position))
return arraylit return arraylit
} else if(array.any {it is PointerOf}) {
val arrayDt = DataType.UWORD
val intArrayWithPointers = mutableListOf<IntegerOrPointerOf>()
// TODO FILL THIS ARRAY
val heapId = heap.addIntegerArray(DataType.UWORD, intArrayWithPointers.toTypedArray())
return LiteralValue(arrayDt, heapId = heapId, position = arraylit.position)
} else { } else {
// array is only constant numerical values
val valuesInArray = array.map { it.constValue(namespace, heap)!!.asNumericValue!! } val valuesInArray = array.map { it.constValue(namespace, heap)!!.asNumericValue!! }
val integerArray = valuesInArray.map{it.toInt()}.toIntArray() val integerArray = valuesInArray.map{ it.toInt() }
val doubleArray = valuesInArray.map{it.toDouble()}.toDoubleArray() val doubleArray = valuesInArray.map{it.toDouble()}.toDoubleArray()
val typesInArray: Set<DataType> = array.mapNotNull { it.resultingDatatype(namespace, heap) }.toSet() val typesInArray: Set<DataType> = array.mapNotNull { it.resultingDatatype(namespace, heap) }.toSet()
@ -587,8 +593,8 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
DataType.ARRAY_UB, DataType.ARRAY_UB,
DataType.ARRAY_B, DataType.ARRAY_B,
DataType.ARRAY_UW, DataType.ARRAY_UW,
DataType.ARRAY_W -> heap.add(arrayDt, integerArray) DataType.ARRAY_W -> heap.addIntegerArray(arrayDt, integerArray.map { IntegerOrPointerOf(it, null) }.toTypedArray())
DataType.ARRAY_F -> heap.add(arrayDt, doubleArray) DataType.ARRAY_F -> heap.addDoublesArray(arrayDt, doubleArray)
else -> throw CompilerException("invalid arrayspec type") else -> throw CompilerException("invalid arrayspec type")
} }
return LiteralValue(arrayDt, heapId = heapId, position = arraylit.position) return LiteralValue(arrayDt, heapId = heapId, position = arraylit.position)

View File

@ -2,6 +2,7 @@ package prog8.stackvm
import prog8.ast.* import prog8.ast.*
import prog8.compiler.HeapValues import prog8.compiler.HeapValues
import prog8.compiler.IntegerOrPointerOf
import prog8.compiler.intermediate.* import prog8.compiler.intermediate.*
import java.io.File import java.io.File
import java.util.* import java.util.*
@ -87,17 +88,17 @@ class Program (val name: String,
} }
heapvalues.sortedBy { it.first }.forEach { heapvalues.sortedBy { it.first }.forEach {
when(it.second) { when(it.second) {
DataType.STR, DataType.STR_S -> heap.add(it.second, unescape(it.third.substring(1, it.third.length-1), Position("<stackvmsource>", 0, 0, 0))) DataType.STR, DataType.STR_S -> heap.addString(it.second, unescape(it.third.substring(1, it.third.length-1), Position("<stackvmsource>", 0, 0, 0)))
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UB, DataType.ARRAY_B,
DataType.ARRAY_UW, DataType.ARRAY_W -> { DataType.ARRAY_UW, DataType.ARRAY_W -> {
val numbers = it.third.substring(1, it.third.length-1).split(',') val numbers = it.third.substring(1, it.third.length-1).split(',')
val intarray = numbers.map{number->number.trim().toInt()}.toIntArray() val intarray = numbers.map{number->IntegerOrPointerOf(number.trim().toInt(), null)}.toTypedArray()
heap.add(it.second, intarray) heap.addIntegerArray(it.second, intarray)
} }
DataType.ARRAY_F -> { DataType.ARRAY_F -> {
val numbers = it.third.substring(1, it.third.length-1).split(',') val numbers = it.third.substring(1, it.third.length-1).split(',')
val doublearray = numbers.map{number->number.trim().toDouble()}.toDoubleArray() val doublearray = numbers.map{number->number.trim().toDouble()}.toDoubleArray()
heap.add(it.second, doublearray) heap.addDoublesArray(it.second, doublearray)
} }
in NumericDatatypes -> throw VmExecutionException("invalid heap value type ${it.second}") in NumericDatatypes -> throw VmExecutionException("invalid heap value type ${it.second}")
else -> throw VmExecutionException("weird datatype") else -> throw VmExecutionException("weird datatype")

View File

@ -2,6 +2,7 @@ package prog8.stackvm
import prog8.ast.* import prog8.ast.*
import prog8.compiler.HeapValues import prog8.compiler.HeapValues
import prog8.compiler.IntegerOrPointerOf
import prog8.compiler.intermediate.Instruction import prog8.compiler.intermediate.Instruction
import prog8.compiler.intermediate.Opcode import prog8.compiler.intermediate.Opcode
import prog8.compiler.intermediate.Value import prog8.compiler.intermediate.Value
@ -1602,8 +1603,8 @@ class StackVm(private var traceOutputFile: String?) {
// get indexed byte element from the arrayspec // get indexed byte element from the arrayspec
val array = heap.get(variable.heapId) val array = heap.get(variable.heapId)
when (array.type) { when (array.type) {
DataType.ARRAY_UB -> Value(DataType.UBYTE, array.array!![index]) DataType.ARRAY_UB -> Value(DataType.UBYTE, array.array!![index].integer!!)
DataType.ARRAY_B -> Value(DataType.BYTE, array.array!![index]) DataType.ARRAY_B -> Value(DataType.BYTE, array.array!![index].integer!!)
DataType.STR, DataType.STR_S -> Value(DataType.UBYTE, Petscii.encodePetscii(array.str!![index].toString(), true)[0]) DataType.STR, DataType.STR_S -> Value(DataType.UBYTE, Petscii.encodePetscii(array.str!![index].toString(), true)[0])
else -> throw VmExecutionException("not a proper array/string variable with byte elements") else -> throw VmExecutionException("not a proper array/string variable with byte elements")
} }
@ -1634,8 +1635,14 @@ class StackVm(private var traceOutputFile: String?) {
// get indexed word element from the arrayspec // get indexed word element from the arrayspec
val array = heap.get(variable.heapId) val array = heap.get(variable.heapId)
when(array.type){ when(array.type){
DataType.ARRAY_UW -> Value(DataType.UWORD, array.array!![index]) DataType.ARRAY_UW -> {
DataType.ARRAY_W -> Value(DataType.WORD, array.array!![index]) val value = array.array!![index]
if(value.integer!=null)
Value(DataType.UWORD, value.integer)
else
TODO("deal with pointerTo $value")
}
DataType.ARRAY_W -> Value(DataType.WORD, array.array!![index].integer!!)
else -> throw VmExecutionException("not a proper arrayspec var with word elements") else -> throw VmExecutionException("not a proper arrayspec var with word elements")
} }
} }
@ -1701,8 +1708,8 @@ class StackVm(private var traceOutputFile: String?) {
// set indexed byte element in the arrayspec // set indexed byte element in the arrayspec
val array = heap.get(variable.heapId) val array = heap.get(variable.heapId)
when (array.type) { when (array.type) {
DataType.ARRAY_UB -> array.array!![index] = value.integerValue() DataType.ARRAY_UB -> array.array!![index] = IntegerOrPointerOf(value.integerValue(), null)
DataType.ARRAY_B -> array.array!![index] = value.integerValue() DataType.ARRAY_B -> array.array!![index] = IntegerOrPointerOf(value.integerValue(), null)
DataType.STR, DataType.STR_S -> { DataType.STR, DataType.STR_S -> {
val chars = array.str!!.toCharArray() val chars = array.str!!.toCharArray()
val ps = Petscii.decodePetscii(listOf(value.integerValue().toShort()), true)[0] val ps = Petscii.decodePetscii(listOf(value.integerValue().toShort()), true)[0]
@ -1749,8 +1756,8 @@ class StackVm(private var traceOutputFile: String?) {
// set indexed word element in the arrayspec // set indexed word element in the arrayspec
val array = heap.get(variable.heapId) val array = heap.get(variable.heapId)
when (array.type) { when (array.type) {
DataType.ARRAY_UW -> array.array!![index] = value.integerValue() DataType.ARRAY_UW -> array.array!![index] = IntegerOrPointerOf(value.integerValue(), null)
DataType.ARRAY_W -> array.array!![index] = value.integerValue() DataType.ARRAY_W -> array.array!![index] = IntegerOrPointerOf(value.integerValue(), null)
else -> throw VmExecutionException("not a proper arrayspec var with word elements") else -> throw VmExecutionException("not a proper arrayspec var with word elements")
} }
} }
@ -2051,92 +2058,130 @@ class StackVm(private var traceOutputFile: String?) {
Syscall.FUNC_MAX_UB -> { Syscall.FUNC_MAX_UB -> {
val iterable = evalstack.pop() val iterable = evalstack.pop()
val value = heap.get(iterable.heapId) val value = heap.get(iterable.heapId)
val result = value.array!!.max() ?: 0 if(value.array!!.any{it.integer==null})
throw VmExecutionException("cannot deal with PointerTo value in array $value")
val result = value.array.map{it.integer!!}.max() ?: 0
evalstack.push(Value(DataType.UBYTE, result)) evalstack.push(Value(DataType.UBYTE, result))
} }
Syscall.FUNC_MAX_B -> { Syscall.FUNC_MAX_B -> {
val iterable = evalstack.pop() val iterable = evalstack.pop()
val value = heap.get(iterable.heapId) val value = heap.get(iterable.heapId)
val result = value.array!!.max() ?: 0 if(value.array!!.any{it.integer==null})
throw VmExecutionException("cannot deal with PointerTo value in array $value")
val result = value.array.map{it.integer!!}.max() ?: 0
evalstack.push(Value(DataType.BYTE, result)) evalstack.push(Value(DataType.BYTE, result))
} }
Syscall.FUNC_MAX_UW -> { Syscall.FUNC_MAX_UW -> {
val iterable = evalstack.pop() val iterable = evalstack.pop()
val value = heap.get(iterable.heapId) val value = heap.get(iterable.heapId)
val result = value.array!!.max() ?: 0 if(value.array!!.any{it.integer==null})
throw VmExecutionException("cannot deal with PointerTo value in array $value")
val result = value.array.map{it.integer!!}.max() ?: 0
evalstack.push(Value(DataType.UWORD, result)) evalstack.push(Value(DataType.UWORD, result))
} }
Syscall.FUNC_MAX_W -> { Syscall.FUNC_MAX_W -> {
val iterable = evalstack.pop() val iterable = evalstack.pop()
val value = heap.get(iterable.heapId) val value = heap.get(iterable.heapId)
val result = value.array!!.max() ?: 0 if(value.array!!.any{it.integer==null})
throw VmExecutionException("cannot deal with PointerTo value in array $value")
val result = value.array.map{it.integer!!}.max() ?: 0
evalstack.push(Value(DataType.WORD, result)) evalstack.push(Value(DataType.WORD, result))
} }
Syscall.FUNC_MAX_F -> { Syscall.FUNC_MAX_F -> {
val iterable = evalstack.pop() val iterable = evalstack.pop()
val value = heap.get(iterable.heapId) val value = heap.get(iterable.heapId)
val result = value.array!!.max() ?: 0 // TODO CHECK max(floatarray) correctness
val result = value.doubleArray!!.max() ?: 0.0
evalstack.push(Value(DataType.FLOAT, result)) evalstack.push(Value(DataType.FLOAT, result))
} }
Syscall.FUNC_MIN_UB -> { Syscall.FUNC_MIN_UB -> {
val iterable = evalstack.pop() val iterable = evalstack.pop()
val value = heap.get(iterable.heapId) val value = heap.get(iterable.heapId)
val result = value.array!!.min() ?: 0 if(value.array!!.any{it.integer==null})
throw VmExecutionException("cannot deal with PointerTo value in array $value")
val result = value.array.map{it.integer!!}.min() ?: 0
evalstack.push(Value(DataType.UBYTE, result)) evalstack.push(Value(DataType.UBYTE, result))
} }
Syscall.FUNC_MIN_B -> { Syscall.FUNC_MIN_B -> {
val iterable = evalstack.pop() val iterable = evalstack.pop()
val value = heap.get(iterable.heapId) val value = heap.get(iterable.heapId)
val result = value.array!!.min() ?: 0 if(value.array!!.any{it.integer==null})
throw VmExecutionException("cannot deal with PointerTo value in array $value")
val result = value.array.map{it.integer!!}.min() ?: 0
evalstack.push(Value(DataType.BYTE, result)) evalstack.push(Value(DataType.BYTE, result))
} }
Syscall.FUNC_MIN_UW -> { Syscall.FUNC_MIN_UW -> {
val iterable = evalstack.pop() val iterable = evalstack.pop()
val value = heap.get(iterable.heapId) val value = heap.get(iterable.heapId)
val result = value.array!!.min() ?: 0 if(value.array!!.any{it.integer==null})
throw VmExecutionException("cannot deal with PointerTo value in array $value")
val result = value.array.map{it.integer!!}.min() ?: 0
evalstack.push(Value(DataType.UWORD, result)) evalstack.push(Value(DataType.UWORD, result))
} }
Syscall.FUNC_MIN_W -> { Syscall.FUNC_MIN_W -> {
val iterable = evalstack.pop() val iterable = evalstack.pop()
val value = heap.get(iterable.heapId) val value = heap.get(iterable.heapId)
val result = value.array!!.min() ?: 0 if(value.array!!.any{it.integer==null})
throw VmExecutionException("cannot deal with PointerTo value in array $value")
val result = value.array.map{it.integer!!}.min() ?: 0
evalstack.push(Value(DataType.WORD, result)) evalstack.push(Value(DataType.WORD, result))
} }
Syscall.FUNC_MIN_F -> { Syscall.FUNC_MIN_F -> {
val iterable = evalstack.pop() val iterable = evalstack.pop()
val value = heap.get(iterable.heapId) val value = heap.get(iterable.heapId)
val result = value.array!!.min() ?: 0 // TODO check min(floatarray) correctness
val result = value.doubleArray!!.min() ?: 0.0
evalstack.push(Value(DataType.FLOAT, result)) evalstack.push(Value(DataType.FLOAT, result))
} }
Syscall.FUNC_AVG_UB, Syscall.FUNC_AVG_B, Syscall.FUNC_AVG_UW, Syscall.FUNC_AVG_W, Syscall.FUNC_AVG_F -> { Syscall.FUNC_AVG_UB, Syscall.FUNC_AVG_B, Syscall.FUNC_AVG_UW, Syscall.FUNC_AVG_W -> {
val iterable = evalstack.pop() val iterable = evalstack.pop()
val value = heap.get(iterable.heapId) val value = heap.get(iterable.heapId)
evalstack.push(Value(DataType.FLOAT, value.array!!.average())) if(value.array!!.any{it.integer==null})
throw VmExecutionException("cannot deal with PointerTo value in array $value")
evalstack.push(Value(DataType.FLOAT, value.array.map{it.integer!!}.average()))
}
Syscall.FUNC_AVG_F -> {
val iterable = evalstack.pop()
val value = heap.get(iterable.heapId)
// TODO check avg(floatarray) correctness
evalstack.push(Value(DataType.FLOAT, value.doubleArray!!.average()))
} }
Syscall.FUNC_SUM_UB -> { Syscall.FUNC_SUM_UB -> {
val iterable = evalstack.pop() val iterable = evalstack.pop()
val value = heap.get(iterable.heapId) val value = heap.get(iterable.heapId)
evalstack.push(Value(DataType.UWORD, value.array!!.sum())) if(value.array!!.any{it.integer==null})
throw VmExecutionException("cannot deal with PointerTo value in array $value")
evalstack.push(Value(DataType.UWORD, value.array.map{it.integer!!}.sum()))
} }
Syscall.FUNC_SUM_B -> { Syscall.FUNC_SUM_B -> {
val iterable = evalstack.pop() val iterable = evalstack.pop()
val value = heap.get(iterable.heapId) val value = heap.get(iterable.heapId)
evalstack.push(Value(DataType.WORD, value.array!!.sum())) if(value.array!!.any{it.integer==null})
throw VmExecutionException("cannot deal with PointerTo value in array $value")
evalstack.push(Value(DataType.WORD, value.array.map{it.integer!!}.sum()))
} }
Syscall.FUNC_SUM_UW, Syscall.FUNC_SUM_W, Syscall.FUNC_SUM_F -> { Syscall.FUNC_SUM_UW, Syscall.FUNC_SUM_W -> {
val iterable = evalstack.pop() val iterable = evalstack.pop()
val value = heap.get(iterable.heapId) val value = heap.get(iterable.heapId)
evalstack.push(Value(DataType.FLOAT, value.array!!.sum())) if(value.array!!.any{it.integer==null})
throw VmExecutionException("cannot deal with PointerTo value in array $value")
evalstack.push(Value(DataType.FLOAT, value.array.map{it.integer!!}.sum()))
}
Syscall.FUNC_SUM_F -> {
// TODO check sum(floatarray) correctness
val iterable = evalstack.pop()
val value = heap.get(iterable.heapId)
evalstack.push(Value(DataType.FLOAT, value.doubleArray!!.sum()))
} }
Syscall.FUNC_ANY_B, Syscall.FUNC_ANY_W, Syscall.FUNC_ANY_F -> { Syscall.FUNC_ANY_B, Syscall.FUNC_ANY_W, Syscall.FUNC_ANY_F -> {
val iterable = evalstack.pop() val iterable = evalstack.pop()
val value = heap.get(iterable.heapId) val value = heap.get(iterable.heapId)
evalstack.push(Value(DataType.UBYTE, if (value.array!!.any { v -> v != 0 }) 1 else 0)) evalstack.push(Value(DataType.UBYTE, if (value.array!!.any { v -> v.pointerOf!=null || (v.integer!=null && v.integer != 0) }) 1 else 0))
} }
Syscall.FUNC_ALL_B, Syscall.FUNC_ALL_W, Syscall.FUNC_ALL_F -> { Syscall.FUNC_ALL_B, Syscall.FUNC_ALL_W, Syscall.FUNC_ALL_F -> {
val iterable = evalstack.pop() val iterable = evalstack.pop()
val value = heap.get(iterable.heapId) val value = heap.get(iterable.heapId)
evalstack.push(Value(DataType.UBYTE, if (value.array!!.all { v -> v != 0 }) 1 else 0)) evalstack.push(Value(DataType.UBYTE, if (value.array!!.all { v -> v.pointerOf!=null || (v.integer!=null && v.integer != 0) }) 1 else 0))
} }
Syscall.FUNC_MEMCOPY -> { Syscall.FUNC_MEMCOPY -> {
val numbytes = evalstack.pop().integerValue() val numbytes = evalstack.pop().integerValue()

View File

@ -1,35 +1,48 @@
%zeropage basicsafe %zeropage basicsafe
%option enable_floats
%import c64flt
~ main { ~ main {
sub start() { sub start() {
ubyte ub='^'
ubyte ub2=7 ; TODO what about avg() on floating point array variable!
uword uw=2
uword uw2=5
float fl=2.3
float fl2=20
fl = (ub as float) ** 4 ubyte[3] array1
fl = 2.3 ubyte[3] array2
fl = fl ** 20.0 ubyte[3] array3
c64flt.print_f(fl)
c64.CHROUT('\n')
fl = 2.3 str string1="hello"
fl = fl ** fl2 str string2="bye"
c64flt.print_f(fl)
c64.CHROUT('\n')
fl = 2.3 uword pointer = &array1
fl **=20.0 byte bt
c64flt.print_f(fl)
c64.CHROUT('\n') pointer = &array2
pointer = &string1
uword[4] pointers = [&array1, &array2, &string1, &string2] ; @todo make it possible to initialize array with pointers
;ptrsubasm("moet werken") ; @todo rewrite ast into pointer-of expression (and remove special cases from Compiler)
;pointersub("moet werken") ; @todo rewrite ast into pointer-of expression (and remove special cases from Compiler)
;myprintasm("moet werken3") ; @todo rewrite ast into pointer-of expression (and remove special cases from Compiler)
ptrsubasm(&array1)
ptrsubasm(&string1)
pointersub(&array1)
pointersub(&string1)
} }
sub pointersub(uword arg) {
A=lsb(arg)
}
asmsub ptrsubasm(uword arg @ AY) -> clobbers() -> () {
A=4
}
asmsub myprintasm(str arg @ AY) -> clobbers() -> () {
A=4
}
} }

View File

@ -154,6 +154,7 @@ expression :
| scoped_identifier | scoped_identifier
| arrayindexed | arrayindexed
| directmemory | directmemory
| pointerof
| expression typecast | expression typecast
| '(' expression ')' | '(' expression ')'
; ;
@ -166,6 +167,8 @@ arrayindexed : scoped_identifier arrayspec ;
directmemory : '@' '(' expression ')'; directmemory : '@' '(' expression ')';
pointerof : <assoc=right> '&' scoped_identifier ;
functioncall : scoped_identifier '(' expression_list? ')' ; functioncall : scoped_identifier '(' expression_list? ')' ;

View File

@ -1,4 +1,4 @@
// Generated from ./parser/antlr/prog8.g4 by ANTLR 4.7.2 // Generated from prog8.g4 by ANTLR 4.7.2
package prog8.parser; package prog8.parser;

File diff suppressed because it is too large Load Diff