mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
array on heap fix
This commit is contained in:
parent
a3004555a8
commit
5f5a1447e0
@ -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())
|
||||
}
|
||||
|
||||
|
@ -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 -> {
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user