mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
taking down the heapvalue mess further
This commit is contained in:
parent
c717f4573d
commit
8eff51904e
@ -4,7 +4,6 @@ import prog8.ast.base.*
|
||||
import prog8.ast.expressions.Expression
|
||||
import prog8.ast.expressions.IdentifierReference
|
||||
import prog8.ast.statements.*
|
||||
import prog8.compiler.HeapValues
|
||||
import prog8.functions.BuiltinFunctions
|
||||
import java.nio.file.Path
|
||||
|
||||
@ -166,7 +165,6 @@ interface INameScope {
|
||||
|
||||
class Program(val name: String, val modules: MutableList<Module>) {
|
||||
val namespace = GlobalNamespace(modules)
|
||||
val heap = HeapValues()
|
||||
|
||||
val definedLoadAddress: Int
|
||||
get() = modules.first().loadAddress
|
||||
|
@ -429,7 +429,7 @@ private fun prog8Parser.ExpressionContext.toAst() : Expression {
|
||||
else -> throw FatalAstException("invalid datatype for numeric literal")
|
||||
}
|
||||
litval.floatliteral()!=null -> NumericLiteralValue(DataType.FLOAT, litval.floatliteral().toAst(), litval.toPosition())
|
||||
litval.stringliteral()!=null -> StringLiteralValue(DataType.STR, unescape(litval.stringliteral().text, litval.toPosition()), null, litval.toPosition())
|
||||
litval.stringliteral()!=null -> StringLiteralValue(DataType.STR, unescape(litval.stringliteral().text, litval.toPosition()), litval.toPosition())
|
||||
litval.charliteral()!=null -> {
|
||||
try {
|
||||
NumericLiteralValue(DataType.UBYTE, Petscii.encodePetscii(unescape(litval.charliteral().text, litval.toPosition()), true)[0], litval.toPosition())
|
||||
|
@ -12,8 +12,6 @@ import prog8.ast.statements.ArrayIndex
|
||||
import prog8.ast.statements.BuiltinFunctionStatementPlaceholder
|
||||
import prog8.ast.statements.Subroutine
|
||||
import prog8.ast.statements.VarDecl
|
||||
import prog8.compiler.HeapValues
|
||||
import prog8.compiler.IntegerOrAddressOf
|
||||
import prog8.compiler.target.c64.Petscii
|
||||
import prog8.functions.BuiltinFunctions
|
||||
import prog8.functions.NotConstArgumentException
|
||||
@ -414,7 +412,6 @@ class StructLiteralValue(var values: List<Expression>,
|
||||
|
||||
class StringLiteralValue(val type: DataType, // only string types
|
||||
val value: String,
|
||||
var heapId: Int?,
|
||||
override val position: Position) : Expression() {
|
||||
override lateinit var parent: Node
|
||||
|
||||
@ -435,16 +432,18 @@ class StringLiteralValue(val type: DataType, // only string types
|
||||
return value==other.value && type==other.type
|
||||
}
|
||||
|
||||
fun addToHeap(heap: HeapValues) {
|
||||
if (heapId != null)
|
||||
return
|
||||
else {
|
||||
val encodedStr = Petscii.encodePetscii(value, true)
|
||||
heapId = heap.addIntegerArray(DataType.ARRAY_UB, encodedStr.map { IntegerOrAddressOf(it.toInt(), null)}.toTypedArray())
|
||||
}
|
||||
var heapId: Int? = null
|
||||
private set
|
||||
|
||||
fun addToHeap() {
|
||||
if(heapId==null)
|
||||
heapId = ++heapIdSequence
|
||||
}
|
||||
}
|
||||
|
||||
private var heapIdSequence = 0
|
||||
|
||||
|
||||
class ArrayLiteralValue(val type: DataType, // only array types
|
||||
val value: Array<Expression>,
|
||||
initHeapId: Int? =null,
|
||||
@ -497,32 +496,9 @@ class ArrayLiteralValue(val type: DataType, // only array types
|
||||
return null // invalid type conversion from $this to $targettype
|
||||
}
|
||||
|
||||
fun addToHeap(heap: HeapValues) {
|
||||
if (heapId != null)
|
||||
return
|
||||
else {
|
||||
if(value.any {it is AddressOf }) {
|
||||
val intArrayWithAddressOfs = value.map {
|
||||
when (it) {
|
||||
is AddressOf -> IntegerOrAddressOf(null, it)
|
||||
is NumericLiteralValue -> IntegerOrAddressOf(it.number.toInt(), null)
|
||||
else -> throw FatalAstException("invalid datatype in array")
|
||||
}
|
||||
}
|
||||
heapId = heap.addIntegerArray(type, intArrayWithAddressOfs.toTypedArray())
|
||||
} else {
|
||||
val valuesInArray = value.map { (it as? NumericLiteralValue)?.number }
|
||||
if(null !in valuesInArray) {
|
||||
heapId = if (type == DataType.ARRAY_F) {
|
||||
val doubleArray = valuesInArray.map { it!!.toDouble() }.toDoubleArray()
|
||||
heap.addDoublesArray(doubleArray)
|
||||
} else {
|
||||
val integerArray = valuesInArray.map { it!!.toInt() }
|
||||
heap.addIntegerArray(type, integerArray.map { IntegerOrAddressOf(it, null) }.toTypedArray())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fun addToHeap() {
|
||||
if(heapId==null)
|
||||
heapId = ++heapIdSequence
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1205,53 +1205,56 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
|
||||
private fun checkArrayValues(value: ArrayLiteralValue, type: DataType): Boolean {
|
||||
if(value.heapId==null) {
|
||||
if (value.heapId == null) {
|
||||
// hmm weird, array literal that hasn't been moved to the heap yet?
|
||||
val array = value.value.mapNotNull { it.constValue(program) }
|
||||
val correct: Boolean
|
||||
when(type) {
|
||||
when (type) {
|
||||
DataType.ARRAY_UB -> {
|
||||
correct=array.all { it.type==DataType.UBYTE && it.number.toInt() in 0..255 }
|
||||
correct = array.all { it.type == DataType.UBYTE && it.number.toInt() in 0..255 }
|
||||
}
|
||||
DataType.ARRAY_B -> {
|
||||
correct=array.all { it.type==DataType.BYTE && it.number.toInt() in -128..127 }
|
||||
correct = array.all { it.type == DataType.BYTE && it.number.toInt() in -128..127 }
|
||||
}
|
||||
DataType.ARRAY_UW -> {
|
||||
correct=array.all { it.type==DataType.UWORD && it.number.toInt() in 0..65535 }
|
||||
correct = array.all { it.type == DataType.UWORD && it.number.toInt() in 0..65535 }
|
||||
}
|
||||
DataType.ARRAY_W -> {
|
||||
correct=array.all { it.type==DataType.WORD && it.number.toInt() in -32768..32767}
|
||||
correct = array.all { it.type == DataType.WORD && it.number.toInt() in -32768..32767 }
|
||||
}
|
||||
DataType.ARRAY_F -> correct = true
|
||||
else -> throw AstException("invalid array type $type")
|
||||
}
|
||||
if(!correct)
|
||||
if (!correct)
|
||||
checkResult.add(ExpressionError("array value out of range for type $type", value.position))
|
||||
return correct
|
||||
}
|
||||
|
||||
val array = program.heap.get(value.heapId!!) // TODO use value.array directly?
|
||||
if(array.type !in ArrayDatatypes || (array.array==null && array.doubleArray==null))
|
||||
throw FatalAstException("should have an array in the heapvar $array")
|
||||
|
||||
val array = value.value.map {
|
||||
if(it is NumericLiteralValue)
|
||||
it.number.toInt()
|
||||
else if(it is AddressOf)
|
||||
it.identifier.heapId(program.namespace)
|
||||
else -9999999
|
||||
}
|
||||
val correct: Boolean
|
||||
when(type) {
|
||||
when (type) {
|
||||
DataType.ARRAY_UB -> {
|
||||
correct= array.array?.all { it.integer!=null && it.integer in 0..255 } ?: false
|
||||
correct = array.all { it in 0..255 }
|
||||
}
|
||||
DataType.ARRAY_B -> {
|
||||
correct=array.array?.all { it.integer!=null && it.integer in -128..127 } ?: false
|
||||
correct = array.all { it in -128..127 }
|
||||
}
|
||||
DataType.ARRAY_UW -> {
|
||||
correct=array.array?.all { (it.integer!=null && it.integer in 0..65535) || it.addressOf!=null} ?: false
|
||||
correct = array.all { (it in 0..65535) }
|
||||
}
|
||||
DataType.ARRAY_W -> {
|
||||
correct=array.array?.all { it.integer!=null && it.integer in -32768..32767 } ?: false
|
||||
correct = array.all { it in -32768..32767 }
|
||||
}
|
||||
DataType.ARRAY_F -> correct = array.doubleArray!=null
|
||||
DataType.ARRAY_F -> correct = true
|
||||
else -> throw AstException("invalid array type $type")
|
||||
}
|
||||
if(!correct)
|
||||
if (!correct)
|
||||
checkResult.add(ExpressionError("array value out of range for type $type", value.position))
|
||||
return correct
|
||||
}
|
||||
|
@ -260,7 +260,7 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi
|
||||
if (string.value.length !in 1..255)
|
||||
checkResult.add(ExpressionError("string literal length must be between 1 and 255", string.position))
|
||||
else {
|
||||
string.addToHeap(program.heap)
|
||||
string.addToHeap()
|
||||
}
|
||||
return if (vardecl != null)
|
||||
string
|
||||
@ -289,7 +289,7 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi
|
||||
// a referencetype literal value that's not declared as a variable
|
||||
// we need to introduce an auto-generated variable for this to be able to refer to the value
|
||||
// note: if the var references the same literal value, it is not yet de-duplicated here.
|
||||
array.addToHeap(program.heap)
|
||||
array.addToHeap()
|
||||
val scope = array.definingScope()
|
||||
val variable = VarDecl.createAuto(array)
|
||||
return replaceWithIdentifier(variable, scope, array.parent)
|
||||
@ -299,7 +299,7 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi
|
||||
// a referencetype literal value that's not declared as a variable
|
||||
// we need to introduce an auto-generated variable for this to be able to refer to the value
|
||||
// note: if the var references the same literal value, it is not yet de-duplicated here.
|
||||
string.addToHeap(program.heap)
|
||||
string.addToHeap()
|
||||
val scope = string.definingScope()
|
||||
val variable = VarDecl.createAuto(string)
|
||||
return replaceWithIdentifier(variable, scope, string.parent)
|
||||
@ -340,14 +340,14 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi
|
||||
// repeat a string a number of times
|
||||
val idt = string.inferType(program)
|
||||
return StringLiteralValue(idt.typeOrElse(DataType.STR),
|
||||
string.value.repeat(constvalue.number.toInt()), null, expr.position)
|
||||
string.value.repeat(constvalue.number.toInt()), expr.position)
|
||||
}
|
||||
}
|
||||
if(expr.operator == "+" && operand is StringLiteralValue) {
|
||||
// concatenate two strings
|
||||
val idt = string.inferType(program)
|
||||
return StringLiteralValue(idt.typeOrElse(DataType.STR),
|
||||
"${string.value}${operand.value}", null, expr.position)
|
||||
"${string.value}${operand.value}", expr.position)
|
||||
}
|
||||
return expr
|
||||
}
|
||||
@ -426,7 +426,7 @@ internal fun fixupArrayDatatype(array: ArrayLiteralValue, vardecl: VarDecl, prog
|
||||
}
|
||||
vardecl.value = litval2
|
||||
litval2.linkParents(vardecl)
|
||||
litval2.addToHeap(program.heap)
|
||||
litval2.addToHeap()
|
||||
return litval2
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ internal class VarInitValueAndAddressOfCreator(private val program: Program): IA
|
||||
val array = ArrayLiteralValue(decl.datatype,
|
||||
Array(arraysize) { NumericLiteralValue.optimalInteger(0, decl.position) },
|
||||
null, decl.position)
|
||||
array.addToHeap(program.heap)
|
||||
array.addToHeap()
|
||||
decl.value = array
|
||||
}
|
||||
|
||||
|
@ -1,53 +0,0 @@
|
||||
package prog8.compiler
|
||||
|
||||
import prog8.ast.base.ArrayDatatypes
|
||||
import prog8.ast.base.DataType
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* The 'heapvalues' is the collection of variables that are allocated globally.
|
||||
* Arrays and strings belong here.
|
||||
* They get assigned a heapId to be able to retrieve them later.
|
||||
*/
|
||||
class HeapValues {
|
||||
data class HeapValue(val type: DataType, val array: Array<IntegerOrAddressOf>?, val doubleArray: DoubleArray?) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
other as HeapValue
|
||||
return type==other.type && Arrays.equals(array, other.array) && Arrays.equals(doubleArray, other.doubleArray)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = Objects.hash(type, array, doubleArray)
|
||||
}
|
||||
|
||||
private val heap = mutableMapOf<Int, HeapValue>()
|
||||
private var heapId = 1
|
||||
|
||||
fun size(): Int = heap.size
|
||||
|
||||
fun addIntegerArray(type: DataType, array: Array<IntegerOrAddressOf>): Int {
|
||||
// arrays are never shared, don't check for existing
|
||||
if(type !in ArrayDatatypes)
|
||||
throw CompilerException("wrong array type $type")
|
||||
val newId = heapId++
|
||||
heap[newId] = HeapValue(type, array, null)
|
||||
return newId
|
||||
}
|
||||
|
||||
fun addDoublesArray(darray: DoubleArray): Int {
|
||||
// arrays are never shared, don't check for existing
|
||||
val newId = heapId++
|
||||
heap[newId] = HeapValue(DataType.ARRAY_F, null, darray)
|
||||
return newId
|
||||
}
|
||||
|
||||
fun get(heapId: Int): HeapValue {
|
||||
return heap[heapId] ?:
|
||||
throw IllegalArgumentException("heapId $heapId not found in heap")
|
||||
}
|
||||
|
||||
fun remove(heapId: Int) {
|
||||
heap.remove(heapId)
|
||||
}
|
||||
}
|
@ -96,7 +96,7 @@ fun compileProgram(filepath: Path,
|
||||
programAst.checkValid(compilerOptions) // check if final tree is valid
|
||||
programAst.checkRecursion() // check if there are recursive subroutine calls
|
||||
|
||||
printAst(programAst)
|
||||
// printAst(programAst)
|
||||
|
||||
if(writeAssembly) {
|
||||
// asm generation directly from the Ast, no need for intermediate code
|
||||
|
@ -199,7 +199,7 @@ fun builtinFunctionReturnType(function: String, args: List<Expression>, program:
|
||||
}
|
||||
|
||||
|
||||
class NotConstArgumentException: AstException("not a const argument to a built-in function") // TODO: ugly, remove throwing exceptions for control flow
|
||||
class NotConstArgumentException: AstException("not a const argument to a built-in function")
|
||||
|
||||
|
||||
private fun oneDoubleArg(args: List<Expression>, position: Position, program: Program, function: (arg: Double)->Number): NumericLiteralValue {
|
||||
|
@ -124,7 +124,7 @@ class ConstantFolding(private val program: Program) : IAstModifyingVisitor {
|
||||
// create the array itself, filled with the fillvalue.
|
||||
val array = Array(size) {fillvalue}.map { NumericLiteralValue.optimalInteger(it, numericLv.position) as Expression}.toTypedArray()
|
||||
val refValue = ArrayLiteralValue(decl.datatype, array, position = numericLv.position)
|
||||
refValue.addToHeap(program.heap)
|
||||
refValue.addToHeap()
|
||||
decl.value = refValue
|
||||
refValue.parent=decl
|
||||
optimizationsDone++
|
||||
@ -146,7 +146,7 @@ class ConstantFolding(private val program: Program) : IAstModifyingVisitor {
|
||||
// create the array itself, filled with the fillvalue.
|
||||
val array = Array(size) {fillvalue}.map { NumericLiteralValue(DataType.FLOAT, it, litval.position) as Expression}.toTypedArray()
|
||||
val refValue = ArrayLiteralValue(DataType.ARRAY_F, array, position = litval.position)
|
||||
refValue.addToHeap(program.heap)
|
||||
refValue.addToHeap()
|
||||
decl.value = refValue
|
||||
refValue.parent=decl
|
||||
optimizationsDone++
|
||||
@ -610,8 +610,7 @@ class ConstantFolding(private val program: Program) : IAstModifyingVisitor {
|
||||
override fun visit(arrayLiteral: ArrayLiteralValue): Expression {
|
||||
val array = super.visit(arrayLiteral)
|
||||
if(array is ArrayLiteralValue) {
|
||||
if(array.heapId==null)
|
||||
array.addToHeap(program.heap)
|
||||
array.addToHeap()
|
||||
val vardecl = array.parent as? VarDecl
|
||||
return if (vardecl!=null) {
|
||||
fixupArrayDatatype(array, vardecl, program)
|
||||
|
@ -615,8 +615,6 @@ internal class SimplifyExpressions(private val program: Program) : IAstModifying
|
||||
if(leftVal==null && rightVal==null)
|
||||
return expr
|
||||
|
||||
// TODO fix bug in this routine!
|
||||
|
||||
// cannot shuffle assiciativity with division!
|
||||
if(rightVal!=null) {
|
||||
// right value is a constant, see if we can optimize
|
||||
|
@ -186,7 +186,6 @@ internal class StatementOptimizer(private val program: Program) : IAstModifyingV
|
||||
functionCallStatement.arglist.add(NumericLiteralValue.optimalInteger(encodedString[0].toInt(), functionCallStatement.position))
|
||||
functionCallStatement.target = IdentifierReference(listOf("c64", "CHROUT"), functionCallStatement.target.position)
|
||||
vardeclsToRemove.add(vardecl)
|
||||
program.heap.remove(string.heapId!!)
|
||||
optimizationsDone++
|
||||
return functionCallStatement
|
||||
} else if(string.value.length==2) {
|
||||
@ -196,7 +195,6 @@ internal class StatementOptimizer(private val program: Program) : IAstModifyingV
|
||||
scope.statements.add(FunctionCallStatement(IdentifierReference(listOf("c64", "CHROUT"), functionCallStatement.target.position),
|
||||
mutableListOf(NumericLiteralValue.optimalInteger(encodedString[1].toInt(), functionCallStatement.position)), functionCallStatement.position))
|
||||
vardeclsToRemove.add(vardecl)
|
||||
program.heap.remove(string.heapId!!)
|
||||
optimizationsDone++
|
||||
return scope
|
||||
}
|
||||
|
@ -575,10 +575,10 @@ class RuntimeValueNumeric(type: DataType, num: Number): RuntimeValueBase(type) {
|
||||
}
|
||||
|
||||
|
||||
class RuntimeValueString(type: DataType, val str: String): RuntimeValueBase(type) {
|
||||
class RuntimeValueString(type: DataType, val str: String, val heapId: Int?): RuntimeValueBase(type) {
|
||||
companion object {
|
||||
fun fromLv(string: StringLiteralValue): RuntimeValueString {
|
||||
return RuntimeValueString(string.type, str = string.value)
|
||||
return RuntimeValueString(string.type, string.value, string.heapId!!)
|
||||
}
|
||||
}
|
||||
|
||||
@ -610,13 +610,13 @@ class RuntimeValueString(type: DataType, val str: String): RuntimeValueBase(type
|
||||
}
|
||||
|
||||
|
||||
open class RuntimeValueArray(type: DataType, val array: Array<Number>): RuntimeValueBase(type) {
|
||||
open class RuntimeValueArray(type: DataType, val array: Array<Number>, val heapId: Int?): RuntimeValueBase(type) {
|
||||
|
||||
companion object {
|
||||
fun fromLv(array: ArrayLiteralValue): RuntimeValueArray {
|
||||
return if (array.type == DataType.ARRAY_F) {
|
||||
val doubleArray = array.value.map { (it as NumericLiteralValue).number }.toTypedArray()
|
||||
RuntimeValueArray(array.type, array = doubleArray)
|
||||
RuntimeValueArray(array.type, doubleArray, array.heapId!!)
|
||||
} else {
|
||||
val resultArray = mutableListOf<Number>()
|
||||
for (elt in array.value.withIndex()) {
|
||||
@ -626,7 +626,7 @@ open class RuntimeValueArray(type: DataType, val array: Array<Number>): RuntimeV
|
||||
TODO("ADDRESSOF ${elt.value}")
|
||||
}
|
||||
}
|
||||
RuntimeValueArray(array.type, array = resultArray.toTypedArray())
|
||||
RuntimeValueArray(array.type, resultArray.toTypedArray(), array.heapId!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -662,7 +662,7 @@ open class RuntimeValueArray(type: DataType, val array: Array<Number>): RuntimeV
|
||||
}
|
||||
|
||||
|
||||
class RuntimeValueRange(type: DataType, val range: IntProgression): RuntimeValueArray(type, range.toList().toTypedArray()) {
|
||||
class RuntimeValueRange(type: DataType, val range: IntProgression): RuntimeValueArray(type, range.toList().toTypedArray(), null) {
|
||||
override fun iterator(): Iterator<Number> {
|
||||
return range.iterator()
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import prog8.ast.expressions.Expression
|
||||
import prog8.ast.expressions.IdentifierReference
|
||||
import prog8.ast.expressions.NumericLiteralValue
|
||||
import prog8.ast.statements.*
|
||||
import prog8.compiler.IntegerOrAddressOf
|
||||
import prog8.compiler.target.c64.MachineDefinition
|
||||
import prog8.compiler.target.c64.Petscii
|
||||
import prog8.vm.*
|
||||
@ -75,6 +74,10 @@ class RuntimeVariables {
|
||||
val where = vars.getValue(scope)
|
||||
where[name] = initialValue
|
||||
vars[scope] = where
|
||||
if(initialValue is RuntimeValueString)
|
||||
byHeapId[initialValue.heapId!!] = initialValue
|
||||
else if(initialValue is RuntimeValueArray)
|
||||
byHeapId[initialValue.heapId!!] = initialValue
|
||||
}
|
||||
|
||||
fun defineMemory(scope: INameScope, name: String, address: Int) {
|
||||
@ -95,8 +98,14 @@ class RuntimeVariables {
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} expected ${existing.type} for $name")
|
||||
where[name] = value
|
||||
vars[scope] = where
|
||||
if(value is RuntimeValueString)
|
||||
byHeapId[value.heapId!!] = value
|
||||
else if(value is RuntimeValueArray)
|
||||
byHeapId[value.heapId!!] = value
|
||||
}
|
||||
|
||||
fun getByHeapId(heapId: Int): RuntimeValueBase = byHeapId.getValue(heapId)
|
||||
|
||||
fun get(scope: INameScope, name: String): RuntimeValueBase {
|
||||
val where = vars.getValue(scope)
|
||||
return where[name] ?: throw NoSuchElementException("no such runtime variable: ${scope.name}.$name")
|
||||
@ -118,6 +127,7 @@ class RuntimeVariables {
|
||||
|
||||
private val vars = mutableMapOf<INameScope, MutableMap<String, RuntimeValueBase>>().withDefault { mutableMapOf() }
|
||||
private val memvars = mutableMapOf<INameScope, MutableMap<String, Int>>().withDefault { mutableMapOf() }
|
||||
private val byHeapId = mutableMapOf<Int, RuntimeValueBase>()
|
||||
}
|
||||
|
||||
|
||||
@ -620,7 +630,7 @@ class AstVm(val program: Program) {
|
||||
val ident = contextStmt.definingScope().lookup(targetArrayIndexed.identifier.nameInSource, contextStmt) as? VarDecl
|
||||
?: throw VmExecutionException("can't find assignment target ${target.identifier}")
|
||||
val identScope = ident.definingScope()
|
||||
runtimeVariables.set(identScope, ident.name, RuntimeValueString(array.type, newstr))
|
||||
runtimeVariables.set(identScope, ident.name, RuntimeValueString(array.type, newstr, array.heapId))
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -662,7 +672,7 @@ class AstVm(val program: Program) {
|
||||
"c64scr.print" -> {
|
||||
// if the argument is an UWORD, consider it to be the "address" of the string (=heapId)
|
||||
if (args[0].wordval != null) {
|
||||
val encodedStr = program.heap.get(args[0].wordval!!).array!!.map { it.integer!!.toShort() }
|
||||
val encodedStr = getEncodedStringFromRuntimeVars(args[0].wordval!!)
|
||||
dialog.canvas.printText(encodedStr)
|
||||
} else
|
||||
throw VmExecutionException("print non-heap string")
|
||||
@ -738,9 +748,9 @@ class AstVm(val program: Program) {
|
||||
}
|
||||
val inputStr = input.joinToString("")
|
||||
val heapId = args[0].wordval!!
|
||||
val origStrLength = program.heap.get(heapId).array!!.size
|
||||
val origStrLength = getEncodedStringFromRuntimeVars(heapId).size
|
||||
val encodedStr = Petscii.encodePetscii(inputStr, true).take(origStrLength).toMutableList()
|
||||
while(encodedStr.size<origStrLength)
|
||||
while(encodedStr.size < origStrLength)
|
||||
encodedStr.add(0)
|
||||
result = RuntimeValueNumeric(DataType.UBYTE, encodedStr.indexOf(0))
|
||||
}
|
||||
@ -762,8 +772,8 @@ class AstVm(val program: Program) {
|
||||
}
|
||||
"c64utils.str2uword" -> {
|
||||
val heapId = args[0].wordval!!
|
||||
val argString = program.heap.get(heapId).array!!.map { it.integer!!.toChar() }
|
||||
val numericpart = argString.takeWhile { it.isDigit() }.toString()
|
||||
val argString = getEncodedStringFromRuntimeVars(heapId)
|
||||
val numericpart = argString.takeWhile { it.toChar().isDigit() }.toString()
|
||||
result = RuntimeValueNumeric(DataType.UWORD, numericpart.toInt() and 65535)
|
||||
}
|
||||
else -> TODO("syscall ${sub.scopedname} $sub")
|
||||
@ -772,6 +782,20 @@ class AstVm(val program: Program) {
|
||||
return result
|
||||
}
|
||||
|
||||
private fun getEncodedStringFromRuntimeVars(heapId: Int): List<Short> {
|
||||
val stringvar = runtimeVariables.getByHeapId(heapId) as RuntimeValueString
|
||||
return when {
|
||||
stringvar.type==DataType.STR -> Petscii.encodePetscii(stringvar.str, true)
|
||||
stringvar.type==DataType.STR_S -> Petscii.encodeScreencode(stringvar.str, true)
|
||||
else -> throw VmExecutionException("weird string type")
|
||||
}
|
||||
}
|
||||
|
||||
private fun getArrayFromRuntimeVars(heapId: Int): IntArray {
|
||||
val arrayvar = runtimeVariables.getByHeapId(heapId) as RuntimeValueArray
|
||||
return arrayvar.array.map { it.toInt() }.toIntArray()
|
||||
}
|
||||
|
||||
private fun performBuiltinFunction(name: String, args: List<RuntimeValueBase>, statusflags: StatusFlags): RuntimeValueNumeric? {
|
||||
return when (name) {
|
||||
"rnd" -> RuntimeValueNumeric(DataType.UBYTE, rnd.nextInt() and 255)
|
||||
@ -886,30 +910,30 @@ class AstVm(val program: Program) {
|
||||
}
|
||||
"memset" -> {
|
||||
val heapId = (args[0] as RuntimeValueNumeric).wordval!!
|
||||
val target = program.heap.get(heapId).array ?: throw VmExecutionException("memset target is not an array")
|
||||
val target = getArrayFromRuntimeVars(heapId)
|
||||
val amount = args[1].integerValue()
|
||||
val value = args[2].integerValue()
|
||||
for (i in 0 until amount) {
|
||||
target[i] = IntegerOrAddressOf(value, null)
|
||||
target[i] = value
|
||||
}
|
||||
null
|
||||
}
|
||||
"memsetw" -> {
|
||||
val heapId = (args[0] as RuntimeValueNumeric).wordval!!
|
||||
val target = program.heap.get(heapId).array ?: throw VmExecutionException("memset target is not an array")
|
||||
val target = getArrayFromRuntimeVars(heapId)
|
||||
val amount = args[1].integerValue()
|
||||
val value = args[2].integerValue()
|
||||
for (i in 0 until amount step 2) {
|
||||
target[i * 2] = IntegerOrAddressOf(value and 255, null)
|
||||
target[i * 2 + 1] = IntegerOrAddressOf(value ushr 8, null)
|
||||
target[i * 2] = value and 255
|
||||
target[i * 2 + 1] = value ushr 8
|
||||
}
|
||||
null
|
||||
}
|
||||
"memcopy" -> {
|
||||
val sourceHeapId = (args[0] as RuntimeValueNumeric).wordval!!
|
||||
val destHeapId = (args[1] as RuntimeValueNumeric).wordval!!
|
||||
val source = program.heap.get(sourceHeapId).array!!
|
||||
val dest = program.heap.get(destHeapId).array!!
|
||||
val source = getArrayFromRuntimeVars(sourceHeapId)
|
||||
val dest = getArrayFromRuntimeVars(destHeapId)
|
||||
val amount = args[2].integerValue()
|
||||
for(i in 0 until amount) {
|
||||
dest[i] = source[i]
|
||||
@ -982,5 +1006,4 @@ class AstVm(val program: Program) {
|
||||
else -> TODO("builtin function $name")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -124,8 +124,8 @@ fun evaluate(expr: Expression, ctx: EvalContext): RuntimeValueBase {
|
||||
DataType.UWORD -> RuntimeValueNumeric(DataType.UWORD, ctx.mem.getUWord(address))
|
||||
DataType.WORD -> RuntimeValueNumeric(DataType.WORD, ctx.mem.getSWord(address))
|
||||
DataType.FLOAT -> RuntimeValueNumeric(DataType.FLOAT, ctx.mem.getFloat(address))
|
||||
DataType.STR -> RuntimeValueString(DataType.STR, ctx.mem.getString(address))
|
||||
DataType.STR_S -> RuntimeValueString(DataType.STR_S, ctx.mem.getScreencodeString(address)!!)
|
||||
DataType.STR -> RuntimeValueString(DataType.STR, ctx.mem.getString(address), null)
|
||||
DataType.STR_S -> RuntimeValueString(DataType.STR_S, ctx.mem.getScreencodeString(address)!!, null)
|
||||
else -> throw VmExecutionException("unexpected datatype $variable")
|
||||
}
|
||||
}
|
||||
|
@ -52,10 +52,17 @@ class VariablesCreator(private val runtimeVariables: RuntimeVariables) : IAstMod
|
||||
val value = if(numericLv!=null) {
|
||||
RuntimeValueNumeric.fromLv(numericLv)
|
||||
} else {
|
||||
if(decl.value is StringLiteralValue)
|
||||
RuntimeValueString.fromLv(decl.value as StringLiteralValue)
|
||||
else
|
||||
RuntimeValueArray.fromLv(decl.value as ArrayLiteralValue)
|
||||
val strLv = decl.value as? StringLiteralValue
|
||||
val arrayLv = decl.value as? ArrayLiteralValue
|
||||
when {
|
||||
strLv!=null -> {
|
||||
RuntimeValueString.fromLv(strLv)
|
||||
}
|
||||
arrayLv!=null -> {
|
||||
RuntimeValueArray.fromLv(arrayLv)
|
||||
}
|
||||
else -> throw VmExecutionException("weird var type")
|
||||
}
|
||||
}
|
||||
runtimeVariables.define(decl.definingScope(), decl.name, value)
|
||||
}
|
||||
|
@ -83,8 +83,8 @@ class TestParserNumericLiteralValue {
|
||||
|
||||
@Test
|
||||
fun testEqualsRef() {
|
||||
assertTrue(StringLiteralValue(DataType.STR, "hello", null, dummyPos) == StringLiteralValue(DataType.STR, "hello", null, dummyPos))
|
||||
assertFalse(StringLiteralValue(DataType.STR, "hello", null, dummyPos) == StringLiteralValue(DataType.STR, "bye", null, dummyPos))
|
||||
assertTrue(StringLiteralValue(DataType.STR, "hello", dummyPos) == StringLiteralValue(DataType.STR, "hello", dummyPos))
|
||||
assertFalse(StringLiteralValue(DataType.STR, "hello", dummyPos) == StringLiteralValue(DataType.STR, "bye", dummyPos))
|
||||
|
||||
val lvOne = NumericLiteralValue(DataType.UBYTE, 1, dummyPos)
|
||||
val lvTwo = NumericLiteralValue(DataType.UBYTE, 2, dummyPos)
|
||||
|
@ -371,8 +371,8 @@ class TestPetscii {
|
||||
assertTrue(ten <= ten)
|
||||
assertFalse(ten < ten)
|
||||
|
||||
val abc = StringLiteralValue(DataType.STR, "abc", null, Position("", 0, 0, 0))
|
||||
val abd = StringLiteralValue(DataType.STR, "abd", null, Position("", 0, 0, 0))
|
||||
val abc = StringLiteralValue(DataType.STR, "abc", Position("", 0, 0, 0))
|
||||
val abd = StringLiteralValue(DataType.STR, "abd", Position("", 0, 0, 0))
|
||||
assertEquals(abc, abc)
|
||||
assertTrue(abc!=abd)
|
||||
assertFalse(abc!=abc)
|
||||
|
155
examples/test.p8
155
examples/test.p8
@ -12,94 +12,79 @@ main {
|
||||
str_s strs2 = "test"
|
||||
|
||||
sub start() {
|
||||
str str1x = "irmen"
|
||||
str str2x = "test"
|
||||
str_s strs1x = "irmen"
|
||||
str_s strs2x = "test"
|
||||
|
||||
str foo1 = "1\n"
|
||||
str foo2 = "12\n"
|
||||
c64scr.print(str1)
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print(str2)
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print(str1x)
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print(str2x)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
c64scr.print(foo1)
|
||||
c64scr.print(foo2)
|
||||
c64scr.print("\n")
|
||||
c64scr.print("1\n")
|
||||
c64scr.print("12\n")
|
||||
c64scr.print("\n")
|
||||
c64scr.print("1\n")
|
||||
c64scr.print("12\n")
|
||||
str1[0]='a'
|
||||
str2[0]='a'
|
||||
str1x[0]='a'
|
||||
str2x[0]='a'
|
||||
strs1x[0]='a'
|
||||
strs2x[0]='a'
|
||||
strs1[0]='a'
|
||||
strs2[0]='a'
|
||||
|
||||
; str str1x = "irmen"
|
||||
; str str2x = "test"
|
||||
; str_s strs1x = "irmen"
|
||||
; str_s strs2x = "test"
|
||||
;
|
||||
; c64scr.print("yoooooo")
|
||||
; c64scr.print(str1)
|
||||
; c64.CHROUT('\n')
|
||||
; c64scr.print(str2)
|
||||
; c64.CHROUT('\n')
|
||||
; c64scr.print(str1x)
|
||||
; c64.CHROUT('\n')
|
||||
; c64scr.print(str2x)
|
||||
; c64.CHROUT('\n')
|
||||
;
|
||||
; str1[0]='a'
|
||||
; str2[0]='a'
|
||||
; str1x[0]='a'
|
||||
; str2x[0]='a'
|
||||
; strs1x[0]='a'
|
||||
; strs2x[0]='a'
|
||||
; strs1[0]='a'
|
||||
; strs2[0]='a'
|
||||
;
|
||||
; ; @TODO fix AstVm handling of strings (they're not modified right now) NOTE: array's seem to work fine
|
||||
; c64scr.print(str1)
|
||||
; c64.CHROUT('\n')
|
||||
; c64scr.print(str2)
|
||||
; c64.CHROUT('\n')
|
||||
; c64scr.print(str1x)
|
||||
; c64.CHROUT('\n')
|
||||
; c64scr.print(str2x)
|
||||
; c64.CHROUT('\n')
|
||||
;
|
||||
;
|
||||
; byte[] barr = [1,2,3]
|
||||
; word[] warr = [1000,2000,3000]
|
||||
; float[] farr = [1.1, 2.2, 3.3]
|
||||
;
|
||||
; byte bb
|
||||
; word ww
|
||||
; float ff
|
||||
; for bb in barr {
|
||||
; c64scr.print_b(bb)
|
||||
; c64.CHROUT(',')
|
||||
; }
|
||||
; c64.CHROUT('\n')
|
||||
; for ww in warr {
|
||||
; c64scr.print_w(ww)
|
||||
; c64.CHROUT(',')
|
||||
; }
|
||||
; c64.CHROUT('\n')
|
||||
; for bb in 0 to len(farr)-1 {
|
||||
; c64flt.print_f(farr[bb])
|
||||
; c64.CHROUT(',')
|
||||
; }
|
||||
; c64.CHROUT('\n')
|
||||
;
|
||||
; barr[0] = 99
|
||||
; warr[0] = 99
|
||||
; farr[0] = 99.9
|
||||
; for bb in barr {
|
||||
; c64scr.print_b(bb)
|
||||
; c64.CHROUT(',')
|
||||
; }
|
||||
; c64.CHROUT('\n')
|
||||
; for ww in warr {
|
||||
; c64scr.print_w(ww)
|
||||
; c64.CHROUT(',')
|
||||
; }
|
||||
; c64.CHROUT('\n')
|
||||
; for bb in 0 to len(farr)-1 {
|
||||
; c64flt.print_f(farr[bb])
|
||||
; c64.CHROUT(',')
|
||||
; }
|
||||
c64scr.print(str1)
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print(str2)
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print(str1x)
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print(str2x)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
|
||||
byte[] barr = [1,2,3]
|
||||
word[] warr = [1000,2000,3000]
|
||||
float[] farr = [1.1, 2.2, 3.3]
|
||||
|
||||
byte bb
|
||||
word ww
|
||||
float ff
|
||||
for bb in barr {
|
||||
c64scr.print_b(bb)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
c64.CHROUT('\n')
|
||||
for ww in warr {
|
||||
c64scr.print_w(ww)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
c64.CHROUT('\n')
|
||||
for bb in 0 to len(farr)-1 {
|
||||
c64flt.print_f(farr[bb])
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
c64.CHROUT('\n')
|
||||
|
||||
barr[0] = 99
|
||||
warr[0] = 99
|
||||
farr[0] = 99.9
|
||||
for bb in barr {
|
||||
c64scr.print_b(bb)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
c64.CHROUT('\n')
|
||||
for ww in warr {
|
||||
c64scr.print_w(ww)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
c64.CHROUT('\n')
|
||||
for bb in 0 to len(farr)-1 {
|
||||
c64flt.print_f(farr[bb])
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user