array on heap fix

This commit is contained in:
Irmen de Jong 2019-06-30 17:49:14 +02:00
parent a3004555a8
commit 5f5a1447e0
7 changed files with 49 additions and 67 deletions

View File

@ -725,9 +725,9 @@ class VarDecl(val type: VarDeclType,
private val declaredDatatype: DataType,
val zeropage: Boolean,
var arraysize: ArrayIndex?,
val isUnsizedArray: Boolean,
val name: String,
var value: IExpression?,
val isArray: Boolean,
override val position: Position) : IStatement {
override lateinit var parent: Node
override val expensiveToInline
@ -735,7 +735,7 @@ class VarDecl(val type: VarDeclType,
val datatypeErrors = mutableListOf<SyntaxError>() // don't crash at init time, report them in the AstChecker
val datatype =
if (arraysize == null && !isUnsizedArray) declaredDatatype
if (!isArray) declaredDatatype
else when (declaredDatatype) {
DataType.UBYTE -> DataType.ARRAY_UB
DataType.BYTE -> DataType.ARRAY_B
@ -759,7 +759,7 @@ class VarDecl(val type: VarDeclType,
val scopedname: String by lazy { makeScopedName(name) }
override fun toString(): String {
return "VarDecl(name=$name, vartype=$type, datatype=$datatype, value=$value, pos=$position)"
return "VarDecl(name=$name, vartype=$type, datatype=$datatype, array=$isArray, value=$value, pos=$position)"
}
fun asDefaultValueDecl(parent: Node?): VarDecl {
@ -771,7 +771,7 @@ class VarDecl(val type: VarDeclType,
DataType.FLOAT -> LiteralValue(DataType.FLOAT, floatvalue=0.0, position=position)
else -> throw FatalAstException("can only set a default value for a numeric type")
}
val decl = VarDecl(type, declaredDatatype, zeropage, arraysize, isUnsizedArray, name, constValue, position)
val decl = VarDecl(type, declaredDatatype, zeropage, arraysize, name, constValue, isArray, position)
if(parent!=null)
decl.linkParents(parent)
return decl
@ -2086,9 +2086,9 @@ private fun prog8Parser.StatementContext.toAst() : IStatement {
it.datatype().toAst(),
it.ZEROPAGE()!=null,
it.arrayindex()?.toAst(),
it.ARRAYSIG()!=null,
it.identifier().text,
null,
it.ARRAYSIG()!=null || it.arrayindex()!=null,
it.toPosition())
}
@ -2098,9 +2098,9 @@ private fun prog8Parser.StatementContext.toAst() : IStatement {
vd.datatype().toAst(),
vd.ZEROPAGE()!=null,
vd.arrayindex()?.toAst(),
vd.ARRAYSIG()!=null,
vd.identifier().text,
it.expression().toAst(),
vd.ARRAYSIG()!=null || vd.arrayindex()!=null,
it.toPosition())
}
@ -2111,9 +2111,9 @@ private fun prog8Parser.StatementContext.toAst() : IStatement {
vd.datatype().toAst(),
vd.ZEROPAGE()!=null,
vd.arrayindex()?.toAst(),
vd.ARRAYSIG()!=null,
vd.identifier().text,
cvarinit.expression().toAst(),
vd.ARRAYSIG()!=null || vd.arrayindex()!=null,
cvarinit.toPosition())
}
@ -2124,9 +2124,9 @@ private fun prog8Parser.StatementContext.toAst() : IStatement {
vd.datatype().toAst(),
vd.ZEROPAGE()!=null,
vd.arrayindex()?.toAst(),
vd.ARRAYSIG()!=null,
vd.identifier().text,
mvarinit.expression().toAst(),
vd.ARRAYSIG()!=null || vd.arrayindex()!=null,
mvarinit.toPosition())
}

View File

@ -504,7 +504,7 @@ private class AstChecker(private val program: Program,
}
// ARRAY without size specifier MUST have an iterable initializer value
if(decl.isUnsizedArray) {
if(decl.isArray && decl.arraysize==null) {
if(decl.type==VarDeclType.MEMORY)
checkResult.add(SyntaxError("memory mapped array must have a size specification", decl.position))
if(decl.value==null) {
@ -546,7 +546,7 @@ private class AstChecker(private val program: Program,
}
when {
decl.value is RangeExpr -> {
if(!decl.isUnsizedArray)
if(decl.arraysize!=null)
checkValueTypeAndRange(decl.datatype, decl.arraysize!!, decl.value as RangeExpr)
}
decl.value is LiteralValue -> {

View File

@ -134,7 +134,7 @@ private class AstIdentifiersChecker(private val namespace: INameScope) : IAstPro
subroutine.parameters
.filter { it.name !in allDefinedNames }
.forEach {
val vardecl = VarDecl(VarDeclType.VAR, it.type, false, null, false, it.name, null, subroutine.position)
val vardecl = VarDecl(VarDeclType.VAR, it.type, false, null, it.name, null, false, subroutine.position)
vardecl.linkParents(subroutine)
subroutine.statements.add(0, vardecl)
}
@ -172,7 +172,7 @@ private class AstIdentifiersChecker(private val namespace: INameScope) : IAstPro
val existing = if(forLoop.body.containsNoCodeNorVars()) null else forLoop.body.lookup(forLoop.loopVar.nameInSource, forLoop.body.statements.first())
if(existing==null) {
// create the local scoped for loop variable itself
val vardecl = VarDecl(VarDeclType.VAR, forLoop.decltype, forLoop.zeropage, null, false, varName, null, forLoop.loopVar.position)
val vardecl = VarDecl(VarDeclType.VAR, forLoop.decltype, forLoop.zeropage, null, varName, null, false, forLoop.loopVar.position)
vardecl.linkParents(forLoop.body)
forLoop.body.statements.add(0, vardecl)
forLoop.loopVar.parent = forLoop.body // loopvar 'is defined in the body'
@ -184,7 +184,7 @@ private class AstIdentifiersChecker(private val namespace: INameScope) : IAstPro
val existing = if(forLoop.body.containsNoCodeNorVars()) null else forLoop.body.lookup(listOf(ForLoop.iteratorLoopcounterVarname), forLoop.body.statements.first())
if(existing==null) {
// create loop iteration counter variable (without value, to avoid an assignment)
val vardecl = VarDecl(VarDeclType.VAR, DataType.UBYTE, true, null, false, ForLoop.iteratorLoopcounterVarname, null, forLoop.loopVar.position)
val vardecl = VarDecl(VarDeclType.VAR, DataType.UBYTE, true, null, ForLoop.iteratorLoopcounterVarname, null, false, forLoop.loopVar.position)
vardecl.linkParents(forLoop.body)
forLoop.body.statements.add(0, vardecl)
forLoop.loopVar.parent = forLoop.body // loopvar 'is defined in the body'
@ -232,7 +232,7 @@ private class AstIdentifiersChecker(private val namespace: INameScope) : IAstPro
if(literalValue.heapId!=null && literalValue.parent !is VarDecl) {
// a literal value that's not declared as a variable, which refers to something on the heap.
// we need to introduce an auto-generated variable for this to be able to refer to the value!
val variable = VarDecl(VarDeclType.VAR, literalValue.type, false, null, false, "$autoHeapValuePrefix${literalValue.heapId}", literalValue, literalValue.position)
val variable = VarDecl(VarDeclType.VAR, literalValue.type, false, null, "$autoHeapValuePrefix${literalValue.heapId}", literalValue, false, literalValue.position)
anonymousVariablesFromHeap[variable.name] = Pair(literalValue, variable)
}
return super.process(literalValue)

View File

@ -414,7 +414,7 @@ private class VarInitValueAndAddressOfCreator(private val namespace: INameScope)
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
val variable = VarDecl(VarDeclType.VAR, strvalue.type, false, null, false, autoVarName, strvalue, strvalue.position)
val variable = VarDecl(VarDeclType.VAR, strvalue.type, false, null, autoVarName, strvalue, false, strvalue.position)
addVarDecl(strvalue.definingScope(), variable)
}
}

View File

@ -13,9 +13,9 @@ class VariablesCreator(private val runtimeVariables: RuntimeVariables, private v
runtimeVariables.define(program.namespace, Register.Y.name, RuntimeValue(DataType.UBYTE, 0))
val globalpos = Position("<<global>>", 0, 0, 0)
val vdA = VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, false, Register.A.name, LiteralValue.optimalInteger(0, globalpos), globalpos)
val vdX = VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, false, Register.X.name, LiteralValue.optimalInteger(255, globalpos), globalpos)
val vdY = VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, false, Register.Y.name, LiteralValue.optimalInteger(0, globalpos), globalpos)
val vdA = VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, Register.A.name, LiteralValue.optimalInteger(0, globalpos), false, globalpos)
val vdX = VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, Register.X.name, LiteralValue.optimalInteger(255, globalpos), false, globalpos)
val vdY = VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, Register.Y.name, LiteralValue.optimalInteger(0, globalpos), false, globalpos)
vdA.linkParents(program.namespace)
vdX.linkParents(program.namespace)
vdY.linkParents(program.namespace)

View File

@ -30,8 +30,6 @@ class ConstantFolding(private val program: Program) : IAstProcessor {
return decl
}
val result = super.process(decl)
if(decl.type==VarDeclType.CONST || decl.type==VarDeclType.VAR) {
val litval = decl.value as? LiteralValue
if(litval!=null && litval.isArray && litval.heapId!=null)
@ -42,6 +40,8 @@ class ConstantFolding(private val program: Program) : IAstProcessor {
if (litval != null && litval.type in IntegerDatatypes) {
val newValue = LiteralValue(DataType.FLOAT, floatvalue = litval.asNumericValue!!.toDouble(), position = litval.position)
decl.value = newValue
optimizationsDone++
return decl
}
}
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W -> {
@ -64,12 +64,21 @@ class ConstantFolding(private val program: Program) : IAstProcessor {
.toTypedArray(), position=decl.value!!.position)
}
decl.value!!.linkParents(decl)
optimizationsDone++
return decl
}
}
if(litval?.type==DataType.FLOAT)
errors.add(ExpressionError("arraysize requires only integers here", litval.position))
if(decl.arraysize==null)
if(decl.arraysize==null) {
// see if we can deduce a proper arraysize
val arrayval = (decl.value as? LiteralValue)?.arrayvalue
if(arrayval!=null) {
decl.arraysize = ArrayIndex(LiteralValue.optimalInteger(arrayval.size, decl.position), decl.position)
optimizationsDone++
}
return decl
}
val size = decl.arraysize!!.size()
if ((litval==null || !litval.isArray) && size != null && rangeExpr==null) {
// arraysize initializer is empty or a single int, and we know the size; create the arraysize.
@ -95,6 +104,8 @@ class ConstantFolding(private val program: Program) : IAstProcessor {
}
val heapId = program.heap.addIntegerArray(decl.datatype, Array(size) { IntegerOrAddressOf(fillvalue, null) })
decl.value = LiteralValue(decl.datatype, heapId = heapId, position = litval?.position ?: decl.position)
optimizationsDone++
return decl
}
}
DataType.ARRAY_F -> {
@ -109,13 +120,18 @@ class ConstantFolding(private val program: Program) : IAstProcessor {
else {
val heapId = program.heap.addDoublesArray(DoubleArray(size) { fillvalue })
decl.value = LiteralValue(DataType.ARRAY_F, heapId = heapId, position = litval?.position ?: decl.position)
optimizationsDone++
return decl
}
}
}
else -> return result
else -> {
// nothing to do for this type
}
}
}
return result
return super.process(decl)
}
private fun fixupArrayTypeOnHeap(decl: VarDecl, litval: LiteralValue) {

View File

@ -6,52 +6,18 @@
~ main {
sub start() {
; TODO array to heap ubyte[100] arr1 = 1 to 100
; TODO array to heap ubyte[100] arr2 = 101 to 200
ubyte[10] arr1 = [1,2,3,4,5,6,7,8,9,10]
ubyte[] arr2 = [1,2,3,4,5,6,7,8,9,10]
ubyte[] arr1h = 1 to 10
ubyte[10] arr2h = 1 to 10
&ubyte m1 = $d020
&uword mw1 = $c000
ubyte[] arr1 = [1,2,3,4,5,6,7,8,9,10,11]
ubyte[] arr2 = [11,22,33,44,55,66,77,88,99,100,101]
word w1 = 1111
word w2 = 2222
sum(arr2)
if_cc goto start
if_cs goto start
if_eq goto start
if_mi goto start
if_ne goto start
if_neg goto start
if_nz goto start
if_pl goto start
if_pos goto start
if_vc goto start
if_vs goto start
if_z goto start
m1 = 0
mw1 = 65535
Y = @($d020)
@($d020) = A
ror(w1)
ror2(w1)
rol(w1)
rol2(w1)
lsr(w1)
lsl(w1)
swap(w1, w2)
swap(A, Y)
swap(arr1[4], arr2[9])
; TODO swap(arr1[4], Y)
; TODO swap(Y, arr2[9])
swap(@($d020), @($d021))
; swap(w1, w2)
; swap(A, Y)
; swap(arr1[4], arr2[9])
; ; TODO swap(arr1[4], Y)
; ; TODO swap(Y, arr2[9])
; swap(@($d020), @($d021))
}
}