mirror of
https://github.com/irmen/prog8.git
synced 2025-01-12 19:29:50 +00:00
fix array processing and ASM code gen of arrays with addressOf in them
This commit is contained in:
parent
9f302cc640
commit
3f93b87745
@ -210,6 +210,7 @@ interface IAstProcessor {
|
||||
}
|
||||
|
||||
fun process(literalValue: LiteralValue): LiteralValue {
|
||||
literalValue.arrayvalue?.forEach { it.process(this) }
|
||||
return literalValue
|
||||
}
|
||||
|
||||
@ -290,6 +291,7 @@ interface IAstProcessor {
|
||||
}
|
||||
|
||||
fun process(addressOf: AddressOf): IExpression {
|
||||
process(addressOf.identifier)
|
||||
return addressOf
|
||||
}
|
||||
}
|
||||
@ -1018,6 +1020,7 @@ data class AddressOf(val identifier: IdentifierReference, override val position:
|
||||
identifier.parent=this
|
||||
}
|
||||
|
||||
var scopedname: String? = null // will be set in a later state by the compiler
|
||||
override fun isIterable(namespace: INameScope, heap: HeapValues) = false
|
||||
override fun constValue(namespace: INameScope, heap: HeapValues): LiteralValue? = null
|
||||
override fun referencesIdentifier(name: String) = false
|
||||
|
@ -464,7 +464,9 @@ private class AstChecker(private val namespace: INameScope,
|
||||
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", addressOf.position))
|
||||
}
|
||||
return addressOf
|
||||
if(addressOf.scopedname==null)
|
||||
throw FatalAstException("the scopedname of AddressOf should have been set by now $addressOf")
|
||||
return super.process(addressOf)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -20,7 +20,7 @@ fun Module.checkIdentifiers(namespace: INameScope) {
|
||||
val parent = variable.first.parent
|
||||
when {
|
||||
parent is Assignment && parent.value === variable.first -> {
|
||||
val idref = IdentifierReference(listOf("$${variable.first.heapId}"), variable.first.position)
|
||||
val idref = IdentifierReference(listOf("$autoHeapValuePrefix${variable.first.heapId}"), variable.first.position)
|
||||
idref.linkParents(parent)
|
||||
parent.value = idref
|
||||
}
|
||||
@ -229,6 +229,14 @@ private class AstIdentifiersChecker(private val namespace: INameScope) : IAstPro
|
||||
}
|
||||
return super.process(literalValue)
|
||||
}
|
||||
|
||||
override fun process(addressOf: AddressOf): IExpression {
|
||||
// register the scoped name of the referenced identifier
|
||||
val variable= addressOf.identifier.targetStatement(namespace) as? VarDecl ?: return addressOf
|
||||
addressOf.scopedname = variable.scopedname
|
||||
return super.process(addressOf)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal const val autoHeapValuePrefix = "auto_heap_value_"
|
||||
|
@ -279,6 +279,7 @@ private class VarInitValueAndAddressOfCreator(private val namespace: INameScope)
|
||||
val variable = idref.targetStatement(namespace) as? VarDecl
|
||||
if(variable!=null && (variable.datatype in StringDatatypes || variable.datatype in ArrayDatatypes)) {
|
||||
val pointerExpr = AddressOf(idref, idref.position)
|
||||
pointerExpr.scopedname = (idref.parent as IStatement).makeScopedName(idref.nameInSource.single())
|
||||
pointerExpr.linkParents(arglist[argparam.first.index].parent)
|
||||
arglist[argparam.first.index] = pointerExpr
|
||||
}
|
||||
@ -289,6 +290,7 @@ private class VarInitValueAndAddressOfCreator(private val namespace: INameScope)
|
||||
val autoVarName = "$autoHeapValuePrefix${strvalue.heapId}"
|
||||
val autoHeapvarRef = IdentifierReference(listOf(autoVarName), strvalue.position)
|
||||
val pointerExpr = AddressOf(autoHeapvarRef, strvalue.position)
|
||||
pointerExpr.scopedname = (strvalue.parent as IStatement).makeScopedName(autoVarName)
|
||||
pointerExpr.linkParents(arglist[argparam.first.index].parent)
|
||||
arglist[argparam.first.index] = pointerExpr
|
||||
// add a vardecl so that the autovar can be resolved in later lookups
|
||||
@ -296,7 +298,6 @@ private class VarInitValueAndAddressOfCreator(private val namespace: INameScope)
|
||||
addVarDecl(strvalue.definingScope(), variable)
|
||||
}
|
||||
}
|
||||
else throw FatalAstException("expected either an identifier or a literal as argument to $subroutine")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import prog8.stackvm.Syscall
|
||||
import java.io.File
|
||||
import java.nio.file.Path
|
||||
import java.util.*
|
||||
import javax.lang.model.type.ArrayType
|
||||
import kotlin.math.abs
|
||||
|
||||
|
||||
@ -81,15 +82,17 @@ class HeapValues {
|
||||
|
||||
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")
|
||||
val newId = heapId++
|
||||
heap[newId] = HeapValue(type, null, array, null)
|
||||
return newId
|
||||
}
|
||||
|
||||
fun addDoublesArray(type: DataType, darray: DoubleArray): Int {
|
||||
fun addDoublesArray(darray: DoubleArray): Int {
|
||||
// arrays are never shared, don't check for existing
|
||||
val newId = heapId++
|
||||
heap[newId] = HeapValue(type, null, null, darray)
|
||||
heap[newId] = HeapValue(DataType.ARRAY_F, null, null, darray)
|
||||
return newId
|
||||
}
|
||||
|
||||
@ -2134,16 +2137,16 @@ internal class Compiler(private val rootModule: Module,
|
||||
}
|
||||
}
|
||||
|
||||
private fun translate(ptrof: AddressOf) {
|
||||
val target = ptrof.identifier.targetStatement(namespace) as VarDecl
|
||||
private fun translate(addrof: AddressOf) {
|
||||
val target = addrof.identifier.targetStatement(namespace) as VarDecl
|
||||
if(target.datatype in ArrayDatatypes || target.datatype in StringDatatypes|| target.datatype==DataType.FLOAT) {
|
||||
pushHeapVarAddress(ptrof.identifier, false)
|
||||
pushHeapVarAddress(addrof.identifier, false)
|
||||
}
|
||||
else if(target.datatype==DataType.FLOAT) {
|
||||
pushFloatAddress(ptrof.identifier)
|
||||
pushFloatAddress(addrof.identifier)
|
||||
}
|
||||
else
|
||||
throw CompilerException("cannot take memory pointer $ptrof")
|
||||
throw CompilerException("cannot take memory pointer $addrof")
|
||||
}
|
||||
|
||||
private fun translateAsmInclude(args: List<DirectiveArg>, importedFrom: Path) {
|
||||
|
@ -14,9 +14,9 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
||||
class ProgramBlock(val name: String,
|
||||
var address: Int?,
|
||||
val instructions: MutableList<Instruction> = mutableListOf(),
|
||||
val variables: MutableMap<String, Value> = mutableMapOf(),
|
||||
val variables: MutableMap<String, Value> = mutableMapOf(), // names are fully scoped
|
||||
val memoryPointers: MutableMap<String, Pair<Int, DataType>> = mutableMapOf(),
|
||||
val labels: MutableMap<String, Instruction> = mutableMapOf(),
|
||||
val labels: MutableMap<String, Instruction> = mutableMapOf(), // names are fully scoped
|
||||
val force_output: Boolean)
|
||||
{
|
||||
val numVariables: Int
|
||||
@ -468,7 +468,12 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
||||
val arrayvalues = it.value.array!!.map { av ->
|
||||
when {
|
||||
av.integer!=null -> av.integer.toString()
|
||||
av.addressOf!=null -> "&${av.addressOf.identifier}"
|
||||
av.addressOf!=null -> {
|
||||
if(av.addressOf.scopedname==null)
|
||||
throw CompilerException("AddressOf scopedname should have been set")
|
||||
else
|
||||
"&${av.addressOf.scopedname}"
|
||||
}
|
||||
else -> throw CompilerException("weird array value")
|
||||
}
|
||||
}
|
||||
|
@ -364,10 +364,11 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
// byte array can never contain pointer-to types, so treat values as all integers
|
||||
array.map { "$"+it.integer!!.toString(16).padStart(2, '0') }
|
||||
value.type==DataType.ARRAY_UW -> array.map {
|
||||
if(it.integer!=null)
|
||||
"$"+it.integer.toString(16).padStart(2, '0')
|
||||
else
|
||||
TODO("deal with addressOf")
|
||||
when {
|
||||
it.integer!=null -> "$"+it.integer.toString(16).padStart(2, '0')
|
||||
it.addressOf!=null -> symname(it.addressOf.scopedname!!, block)
|
||||
else -> throw AssemblyError("weird type in array")
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("invalid arrayspec type")
|
||||
}
|
||||
|
@ -82,8 +82,8 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
|
||||
if(fillvalue< FLOAT_MAX_NEGATIVE || fillvalue> FLOAT_MAX_POSITIVE)
|
||||
errors.add(ExpressionError("float value overflow", litval?.position ?: decl.position))
|
||||
else {
|
||||
val heapId = heap.addDoublesArray(decl.datatype, DoubleArray(size) { fillvalue })
|
||||
decl.value = LiteralValue(decl.datatype, heapId = heapId, position = litval?.position ?: decl.position)
|
||||
val heapId = heap.addDoublesArray(DoubleArray(size) { fillvalue })
|
||||
decl.value = LiteralValue(DataType.ARRAY_F, heapId = heapId, position = litval?.position ?: decl.position)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -551,10 +551,15 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
|
||||
addError(ExpressionError("array literal can only consist of constant primitive numerical values or memory pointers", arraylit.position))
|
||||
return arraylit
|
||||
} else if(array.any {it is AddressOf}) {
|
||||
val arrayDt = DataType.UWORD
|
||||
val intArrayWithAddressOfs = mutableListOf<IntegerOrAddressOf>()
|
||||
// TODO AddressOf: FILL THIS ARRAY
|
||||
val heapId = heap.addIntegerArray(DataType.UWORD, intArrayWithAddressOfs.toTypedArray())
|
||||
val arrayDt = DataType.ARRAY_UW
|
||||
val intArrayWithAddressOfs = array.map {
|
||||
when (it) {
|
||||
is AddressOf -> IntegerOrAddressOf(null, it)
|
||||
is LiteralValue -> IntegerOrAddressOf(it.asIntegerValue, null)
|
||||
else -> throw CompilerException("invalid datatype in array")
|
||||
}
|
||||
}
|
||||
val heapId = heap.addIntegerArray(arrayDt, intArrayWithAddressOfs.toTypedArray())
|
||||
return LiteralValue(arrayDt, heapId = heapId, position = arraylit.position)
|
||||
} else {
|
||||
// array is only constant numerical values
|
||||
@ -594,7 +599,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
|
||||
DataType.ARRAY_B,
|
||||
DataType.ARRAY_UW,
|
||||
DataType.ARRAY_W -> heap.addIntegerArray(arrayDt, integerArray.map { IntegerOrAddressOf(it, null) }.toTypedArray())
|
||||
DataType.ARRAY_F -> heap.addDoublesArray(arrayDt, doubleArray)
|
||||
DataType.ARRAY_F -> heap.addDoublesArray(doubleArray)
|
||||
else -> throw CompilerException("invalid arrayspec type")
|
||||
}
|
||||
return LiteralValue(arrayDt, heapId = heapId, position = arraylit.position)
|
||||
|
@ -92,13 +92,25 @@ class Program (val name: String,
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B,
|
||||
DataType.ARRAY_UW, DataType.ARRAY_W -> {
|
||||
val numbers = it.third.substring(1, it.third.length-1).split(',')
|
||||
val intarray = numbers.map{number->IntegerOrAddressOf(number.trim().toInt(), null)}.toTypedArray()
|
||||
val intarray = numbers.map{number->
|
||||
val num=number.trim()
|
||||
if(num.startsWith("&")) {
|
||||
// it's AddressOf
|
||||
val scopedname = num.substring(1)
|
||||
val iref = IdentifierReference(scopedname.split('.'), Position("<intermediate>", 0,0,0))
|
||||
val addrOf = AddressOf(iref, Position("<intermediate>", 0,0,0))
|
||||
addrOf.scopedname=scopedname
|
||||
IntegerOrAddressOf(null, addrOf)
|
||||
} else {
|
||||
IntegerOrAddressOf(num.toInt(), null)
|
||||
}
|
||||
}.toTypedArray()
|
||||
heap.addIntegerArray(it.second, intarray)
|
||||
}
|
||||
DataType.ARRAY_F -> {
|
||||
val numbers = it.third.substring(1, it.third.length-1).split(',')
|
||||
val doublearray = numbers.map{number->number.trim().toDouble()}.toDoubleArray()
|
||||
heap.addDoublesArray(it.second, doublearray)
|
||||
heap.addDoublesArray(doublearray)
|
||||
}
|
||||
in NumericDatatypes -> throw VmExecutionException("invalid heap value type ${it.second}")
|
||||
else -> throw VmExecutionException("weird datatype")
|
||||
|
@ -1659,10 +1659,16 @@ class StackVm(private var traceOutputFile: String?) {
|
||||
when(array.type){
|
||||
DataType.ARRAY_UW -> {
|
||||
val value = array.array!![index]
|
||||
if(value.integer!=null)
|
||||
Value(DataType.UWORD, value.integer)
|
||||
else
|
||||
TODO("deal with addressOf $value")
|
||||
when {
|
||||
value.integer!=null -> Value(DataType.UWORD, value.integer)
|
||||
value.addressOf!=null -> {
|
||||
val heapId = variables.getValue(value.addressOf.scopedname!!).heapId
|
||||
if(heapId<0)
|
||||
throw VmExecutionException("expected variable on heap")
|
||||
evalstack.push(Value(DataType.UWORD, heapId)) // push the "address" of the string or array variable (this is taken care of properly in the assembly code generator)
|
||||
}
|
||||
else -> throw VmExecutionException("strange array value")
|
||||
}
|
||||
}
|
||||
DataType.ARRAY_W -> Value(DataType.WORD, array.array!![index].integer!!)
|
||||
else -> throw VmExecutionException("not a proper arrayspec var with word elements")
|
||||
@ -2287,6 +2293,13 @@ class StackVm(private var traceOutputFile: String?) {
|
||||
val number = lo+256*hi
|
||||
canvas?.printText(number.toString(), 1, true)
|
||||
}
|
||||
Syscall.SYSASM_c64scr_print_uwhex -> {
|
||||
val prefix = if(this.P_carry) "$" else ""
|
||||
val lo = variables.getValue("A").integerValue()
|
||||
val hi = variables.getValue("Y").integerValue()
|
||||
val number = lo+256*hi
|
||||
canvas?.printText("$prefix${number.toString(16).padStart(4, '0')}", 1, true)
|
||||
}
|
||||
Syscall.SYSASM_c64scr_print_w -> {
|
||||
val lo = variables.getValue("A").integerValue()
|
||||
val hi = variables.getValue("Y").integerValue()
|
||||
|
@ -23,7 +23,7 @@
|
||||
pointer2 = &array2
|
||||
pointer3 = &string1
|
||||
|
||||
; uword[4] pointers = [&array1, &array2, &string1, &string2] ; @todo make it possible to initialize array with pointers
|
||||
uword[4] pointers = [&array1, &array2, &string1, &string2] ; @todo make it possible to initialize array with pointers
|
||||
|
||||
|
||||
ptrsubasm("moet werken")
|
||||
@ -72,3 +72,11 @@
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
~ test {
|
||||
|
||||
sub testsub() {
|
||||
uword[4] pointers = [&main.start.array1, &main.start.array2, &main.start.string1, &main.start.string2] ; @todo make it possible to initialize array with pointers
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user