array indexer complexity is now dealt with in the asm-generator only

This commit is contained in:
Irmen de Jong 2021-03-22 19:33:57 +01:00
parent cbc3e37a89
commit bd295ffc99
13 changed files with 104 additions and 183 deletions

View File

@ -228,4 +228,45 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: I
}
return noModifications
}
override fun after(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> {
val index = arrayIndexedExpression.indexer.indexExpr
if(index !is NumericLiteralValue && index !is IdentifierReference) {
// replace complex indexing expression with a temp variable to hold the computed index first
return getAutoIndexerVarFor(arrayIndexedExpression)
}
return noModifications
}
private fun getAutoIndexerVarFor(expr: ArrayIndexedExpression): MutableList<IAstModification> {
val modifications = mutableListOf<IAstModification>()
val subroutine = expr.definingSubroutine()!!
val statement = expr.containingStatement()
val indexerVarPrefix = "prog8_autovar_index_"
val repo = subroutine.asmGenInfo.usedAutoArrayIndexerForStatements
// TODO [codegen] make this a bit smarter so it can reuse indexer variables. BUT BEWARE of scoping+initialization problems then
// for instance when dealing with multiple complex array indices in a single statement...
// ... use cx16's virtual registers for this instead of adding new variables?
// add another loop index var to be used for this expression
val indexerVarName = "$indexerVarPrefix${expr.indexer.hashCode()}"
val indexerVar = AsmGenInfo.ArrayIndexerInfo(indexerVarName, expr.indexer)
repo.add(indexerVar)
// create the indexer var at block level scope
val vardecl = VarDecl(VarDeclType.VAR, DataType.UBYTE, ZeropageWish.PREFER_ZEROPAGE,
null, indexerVarName, null, null, isArray = false, autogeneratedDontRemove = true, position = expr.position)
modifications.add(IAstModification.InsertFirst(vardecl, subroutine))
// replace the indexer with just the variable
// assign the indexing expression to the helper variable, but only if that hasn't been done already
val target = AssignTarget(IdentifierReference(listOf(indexerVar.name), expr.indexer.position), null, null, expr.indexer.position)
val assign = Assignment(target, expr.indexer.indexExpr, expr.indexer.position)
modifications.add(IAstModification.InsertBefore(statement, assign, statement.definingScope()))
modifications.add(IAstModification.ReplaceNode(expr.indexer.indexExpr, target.identifier!!.copy(), expr.indexer)) // TODO is this ok now?
return modifications
}
}

View File

@ -493,7 +493,7 @@ internal class AstChecker(private val program: Program,
fun err(msg: String, position: Position?=null) = errors.err(msg, position ?: decl.position)
// the initializer value can't refer to the variable itself (recursive definition)
if(decl.value?.referencesIdentifier(decl.name) == true || decl.arraysize?.indexVar?.referencesIdentifier(decl.name) == true)
if(decl.value?.referencesIdentifier(decl.name) == true || decl.arraysize?.indexExpr?.referencesIdentifier(decl.name) == true)
err("recursive var declaration")
// CONST can only occur on simple types (byte, word, float)
@ -1125,16 +1125,9 @@ internal class AstChecker(private val program: Program,
errors.err("indexing requires a variable to act upon", arrayIndexedExpression.position)
// check index value 0..255
val dtxNum = arrayIndexedExpression.indexer.indexNum?.inferType(program)?.typeOrElse(DataType.STRUCT)
if(dtxNum!=null && dtxNum != DataType.UBYTE && dtxNum != DataType.BYTE)
val dtxNum = arrayIndexedExpression.indexer.indexExpr.inferType(program)
if(!dtxNum.istype(DataType.UBYTE) && !dtxNum.istype(DataType.BYTE))
errors.err("array indexing is limited to byte size 0..255", arrayIndexedExpression.position)
val dtxVar = arrayIndexedExpression.indexer.indexVar?.inferType(program)?.typeOrElse(DataType.STRUCT)
if(dtxVar!=null && dtxVar != DataType.UBYTE && dtxVar != DataType.BYTE)
errors.err("array indexing is limited to byte size 0..255", arrayIndexedExpression.position)
// TODO remove this once this rewriter is moved to BeforeAsmGen
if(arrayIndexedExpression.indexer.origExpression!=null)
throw FatalAstException("array indexer should have been replaced with a temp var @ ${arrayIndexedExpression.indexer.position}")
super.visit(arrayIndexedExpression)
}

View File

@ -1,6 +1,9 @@
package prog8.compiler.astprocessing
import prog8.ast.*
import prog8.ast.IFunctionCall
import prog8.ast.Module
import prog8.ast.Node
import prog8.ast.Program
import prog8.ast.base.*
import prog8.ast.expressions.*
import prog8.ast.statements.*
@ -89,8 +92,7 @@ internal class StatementReorderer(val program: Program, val errors: IErrorReport
if(arrayVar!=null && arrayVar.datatype == DataType.UWORD) {
// rewrite pointervar[index] into @(pointervar+index)
val indexer = arrayIndexedExpression.indexer
val index = (indexer.indexNum ?: indexer.indexVar)!!
val add = BinaryExpression(arrayIndexedExpression.arrayvar, "+", index, arrayIndexedExpression.position)
val add = BinaryExpression(arrayIndexedExpression.arrayvar, "+", indexer.indexExpr, arrayIndexedExpression.position)
return if(parent is AssignTarget) {
// we're part of the target of an assignment, we have to actually change the assign target itself
val memwrite = DirectMemoryWrite(add, arrayIndexedExpression.position)
@ -102,23 +104,7 @@ internal class StatementReorderer(val program: Program, val errors: IErrorReport
}
}
when (val expr2 = arrayIndexedExpression.indexer.origExpression) {
is NumericLiteralValue -> {
arrayIndexedExpression.indexer.indexNum = expr2
arrayIndexedExpression.indexer.origExpression = null
return noModifications
}
is IdentifierReference -> {
arrayIndexedExpression.indexer.indexVar = expr2
arrayIndexedExpression.indexer.origExpression = null
return noModifications
}
is Expression -> {
// replace complex indexing with a temp variable TODO move this to BeforeAsmGeneration transformer, get rid of indexNum/indexVar/origExpression differentiation? (just use 'is Identifier' etc)?
return getAutoIndexerVarFor(arrayIndexedExpression)
}
else -> return noModifications
}
return noModifications
}
override fun after(expr: BinaryExpression, parent: Node): Iterable<IAstModification> {
@ -202,38 +188,6 @@ internal class StatementReorderer(val program: Program, val errors: IErrorReport
return noModifications
}
private fun getAutoIndexerVarFor(expr: ArrayIndexedExpression): MutableList<IAstModification> {
val modifications = mutableListOf<IAstModification>()
val subroutine = expr.definingSubroutine()!!
val statement = expr.containingStatement()
val indexerVarPrefix = "prog8_autovar_index_"
val repo = subroutine.asmGenInfo.usedAutoArrayIndexerForStatements
// TODO [codegen] make this a bit smarter so it can reuse indexer variables. BUT BEWARE of scoping+initialization problems then
// add another loop index var to be used for this expression
val indexerVarName = "$indexerVarPrefix${expr.indexer.hashCode()}"
val indexerVar = AsmGenInfo.ArrayIndexerInfo(indexerVarName, expr.indexer)
repo.add(indexerVar)
// create the indexer var at block level scope
val vardecl = VarDecl(VarDeclType.VAR, DataType.UBYTE, ZeropageWish.PREFER_ZEROPAGE,
null, indexerVarName, null, null, isArray = false, autogeneratedDontRemove = true, position = expr.position)
modifications.add(IAstModification.InsertFirst(vardecl, subroutine))
// replace the indexer with just the variable
// assign the indexing expression to the helper variable, but only if that hasn't been done already
val indexerExpression = expr.indexer.origExpression!!
val target = AssignTarget(IdentifierReference(listOf(indexerVar.name), indexerExpression.position), null, null, indexerExpression.position)
val assign = Assignment(target, indexerExpression, indexerExpression.position)
modifications.add(IAstModification.InsertBefore(statement, assign, statement.definingScope()))
modifications.add(IAstModification.SetExpression( {
expr.indexer.indexVar = it as IdentifierReference
expr.indexer.indexNum = null
expr.indexer.origExpression = null
}, target.identifier!!.copy(), expr.indexer))
return modifications
}
override fun after(whenStatement: WhenStatement, parent: Node): Iterable<IAstModification> {
val choices = whenStatement.choiceValues(program).sortedBy {
it.first?.first() ?: Int.MAX_VALUE

View File

@ -720,11 +720,9 @@ internal class AsmGen(private val program: Program,
return
}
val indexVar = expr.indexer.indexVar
val indexVar = expr.indexer.indexExpr as? IdentifierReference
?: throw AssemblyError("array indexer should have been replaced with a temp var @ ${expr.indexer.position}")
// must be indexed via variable (arbitrary expression is already replaced out)
val indexName = asmVariableName(indexVar)
if(addOneExtra) {
// add 1 to the result

View File

@ -14,11 +14,6 @@ import prog8.compiler.AssemblyError
import prog8.compiler.functions.FSignature
import prog8.compiler.target.CpuType
import prog8.compiler.target.cpu6502.codegen.assignment.*
import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignSource
import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignTarget
import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignment
import prog8.compiler.target.cpu6502.codegen.assignment.SourceStorageKind
import prog8.compiler.target.cpu6502.codegen.assignment.TargetStorageKind
import prog8.compiler.target.subroutineFloatEvalResultVar2
internal class BuiltinFunctionsAsmGen(private val program: Program, private val asmgen: AsmGen, private val assignAsmGen: AssignmentAsmGen) {
@ -469,8 +464,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
private fun translateRolRorArrayArgs(arrayvar: IdentifierReference, indexer: ArrayIndex, operation: String, dt: Char) {
asmgen.assignExpressionToVariable(AddressOf(arrayvar, arrayvar.position), "prog8_lib.${operation}_array_u${dt}._arg_target", DataType.UWORD, null)
val indexerExpr = if(indexer.indexVar!=null) indexer.indexVar!! else indexer.indexNum!!
asmgen.assignExpressionToVariable(indexerExpr, "prog8_lib.${operation}_array_u${dt}._arg_index", DataType.UBYTE, null)
asmgen.assignExpressionToVariable(indexer.indexExpr, "prog8_lib.${operation}_array_u${dt}._arg_index", DataType.UBYTE, null)
}
private fun funcVariousFloatFuncs(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, resultRegister: RegisterOrPair?, scope: Subroutine?) {
@ -685,10 +679,10 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
throw AssemblyError("unknown dt")
val elementDt = elementIDt.typeOrElse(DataType.STRUCT)
val firstNum = first.indexer.indexNum
val firstVar = first.indexer.indexVar
val secondNum = second.indexer.indexNum
val secondVar = second.indexer.indexVar
val firstNum = first.indexer.indexExpr as? NumericLiteralValue
val firstVar = first.indexer.indexExpr as? IdentifierReference
val secondNum = second.indexer.indexExpr as? NumericLiteralValue
val secondVar = second.indexer.indexExpr as? IdentifierReference
if(firstNum!=null && secondNum!=null) {
swapArrayValues(elementDt, arrayVarName1, firstNum, arrayVarName2, secondNum)

View File

@ -2055,8 +2055,9 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
throw AssemblyError("unknown dt")
val elementDt = elementIDt.typeOrElse(DataType.STRUCT)
val arrayVarName = asmgen.asmVariableName(arrayExpr.arrayvar)
if(arrayExpr.indexer.indexNum!=null) {
val indexValue = arrayExpr.indexer.constIndex()!! * program.memsizer.memorySize(elementDt)
val constIndexNum = arrayExpr.indexer.constIndex()
if(constIndexNum!=null) {
val indexValue = constIndexNum * program.memsizer.memorySize(elementDt)
when(elementDt) {
in ByteDatatypes -> {
asmgen.out(" lda $arrayVarName+$indexValue | sta P8ESTACK_LO,x | dex")
@ -2095,13 +2096,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
}
}
fun translateExpression(indexer: ArrayIndex) {
// it is either a number, or a variable
val indexNum = indexer.indexNum
val indexVar = indexer.indexVar
indexNum?.let { asmgen.translateExpression(indexNum) }
indexVar?.let { asmgen.translateExpression(indexVar) }
}
fun translateExpression(indexer: ArrayIndex) = asmgen.translateExpression(indexer.indexExpr)
private fun translateBinaryOperatorBytes(operator: String, types: DataType) {
when(operator) {

View File

@ -66,8 +66,9 @@ internal class PostIncrDecrAsmGen(private val program: Program, private val asmg
targetArrayIdx!=null -> {
val asmArrayvarname = asmgen.asmVariableName(targetArrayIdx.arrayvar)
val elementDt = targetArrayIdx.inferType(program).typeOrElse(DataType.STRUCT)
if(targetArrayIdx.indexer.indexNum!=null) {
val indexValue = targetArrayIdx.indexer.constIndex()!! * program.memsizer.memorySize(elementDt)
val constIndex = targetArrayIdx.indexer.constIndex()
if(constIndex!=null) {
val indexValue = constIndex * program.memsizer.memorySize(elementDt)
when(elementDt) {
in ByteDatatypes -> asmgen.out(if (incr) " inc $asmArrayvarname+$indexValue" else " dec $asmArrayvarname+$indexValue")
in WordDatatypes -> {

View File

@ -120,13 +120,7 @@ internal class AsmAssignSource(val kind: SourceStorageKind,
asmgen.asmVariableName(array.arrayvar)
companion object {
fun fromAstSource(indexer: ArrayIndex, program: Program, asmgen: AsmGen): AsmAssignSource {
return when {
indexer.indexNum!=null -> fromAstSource(indexer.indexNum!!, program, asmgen)
indexer.indexVar!=null -> fromAstSource(indexer.indexVar!!, program, asmgen)
else -> throw AssemblyError("weird indexer")
}
}
fun fromAstSource(indexer: ArrayIndex, program: Program, asmgen: AsmGen): AsmAssignSource = fromAstSource(indexer.indexExpr, program, asmgen)
fun fromAstSource(value: Expression, program: Program, asmgen: AsmGen): AsmAssignSource {
val cv = value.constValue(program)

View File

@ -65,9 +65,10 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
val value = assign.source.array!!
val elementDt = assign.source.datatype
val arrayVarName = asmgen.asmVariableName(value.arrayvar)
if (value.indexer.indexNum!=null) {
val constIndex = value.indexer.constIndex()
if (constIndex!=null) {
// constant array index value
val indexValue = value.indexer.constIndex()!! * program.memsizer.memorySize(elementDt)
val indexValue = constIndex * program.memsizer.memorySize(elementDt)
when (elementDt) {
in ByteDatatypes -> {
asmgen.out(" lda $arrayVarName+$indexValue")
@ -1074,11 +1075,11 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
ldy #>${target.asmVarname}
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1""")
if(target.array!!.indexer.indexNum!=null) {
val index = target.array.indexer.constIndex()!!
asmgen.out(" lda #$index")
val constIndex = target.array!!.indexer.constIndex()
if(constIndex!=null) {
asmgen.out(" lda #$constIndex")
} else {
val asmvarname = asmgen.asmVariableName(target.array.indexer.indexVar!!)
val asmvarname = asmgen.asmVariableName(target.array.indexer.indexExpr as IdentifierReference)
asmgen.out(" lda $asmvarname")
}
asmgen.out(" jsr floats.set_array_float_from_fac1")
@ -1110,11 +1111,11 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
ldy #>${target.asmVarname}
sta P8ZP_SCRATCH_W2
sty P8ZP_SCRATCH_W2+1""")
if(target.array!!.indexer.indexNum!=null) {
val index = target.array.indexer.constIndex()!!
asmgen.out(" lda #$index")
val constIndex = target.array!!.indexer.constIndex()
if(constIndex!=null) {
asmgen.out(" lda #$constIndex")
} else {
val asmvarname = asmgen.asmVariableName(target.array.indexer.indexVar!!)
val asmvarname = asmgen.asmVariableName(target.array.indexer.indexExpr as IdentifierReference)
asmgen.out(" lda $asmvarname")
}
asmgen.out(" jsr floats.set_array_float")
@ -1157,11 +1158,11 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
ldy #>${target.asmVarname}
sta P8ZP_SCRATCH_W2
sty P8ZP_SCRATCH_W2+1""")
if(target.array!!.indexer.indexNum!=null) {
val index = target.array.indexer.constIndex()!!
asmgen.out(" lda #$index")
val constIndex = target.array!!.indexer.constIndex()
if(constIndex!=null) {
asmgen.out(" lda #$constIndex")
} else {
val asmvarname = asmgen.asmVariableName(target.array.indexer.indexVar!!)
val asmvarname = asmgen.asmVariableName(target.array.indexer.indexExpr as IdentifierReference)
asmgen.out(" lda $asmvarname")
}
asmgen.out(" jsr floats.set_array_float")
@ -1369,7 +1370,8 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
CpuRegister.X -> asmgen.out(" txa")
CpuRegister.Y -> asmgen.out(" tya")
}
asmgen.out(" ldy ${asmgen.asmVariableName(target.array!!.indexer.indexVar!!)} | sta ${target.asmVarname},y")
val indexVar = target.array!!.indexer.indexExpr as IdentifierReference
asmgen.out(" ldy ${asmgen.asmVariableName(indexVar)} | sta ${target.asmVarname},y")
}
}
TargetStorageKind.REGISTER -> {
@ -1777,8 +1779,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
""")
}
TargetStorageKind.ARRAY -> {
if (target.array!!.indexer.indexNum!=null) {
val indexValue = target.array.indexer.constIndex()!! * program.memsizer.memorySize(DataType.FLOAT)
val constIndex = target.array!!.indexer.constIndex()
if (constIndex!=null) {
val indexValue = constIndex * program.memsizer.memorySize(DataType.FLOAT)
if(asmgen.isTargetCpu(CpuType.CPU65c02))
asmgen.out("""
stz ${target.asmVarname}+$indexValue
@ -1797,7 +1800,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
sta ${target.asmVarname}+$indexValue+4
""")
} else {
val asmvarname = asmgen.asmVariableName(target.array.indexer.indexVar!!)
val asmvarname = asmgen.asmVariableName(target.array.indexer.indexExpr as IdentifierReference)
asmgen.out("""
lda #<${target.asmVarname}
sta P8ZP_SCRATCH_W1
@ -1842,8 +1845,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
}
TargetStorageKind.ARRAY -> {
val arrayVarName = target.asmVarname
if (target.array!!.indexer.indexNum!=null) {
val indexValue = target.array.indexer.constIndex()!! * program.memsizer.memorySize(DataType.FLOAT)
val constIndex = target.array!!.indexer.constIndex()
if (constIndex!=null) {
val indexValue = constIndex * program.memsizer.memorySize(DataType.FLOAT)
asmgen.out("""
lda $constFloat
sta $arrayVarName+$indexValue
@ -1857,7 +1861,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
sta $arrayVarName+$indexValue+4
""")
} else {
val asmvarname = asmgen.asmVariableName(target.array.indexer.indexVar!!)
val asmvarname = asmgen.asmVariableName(target.array.indexer.indexExpr as IdentifierReference)
asmgen.out("""
lda #<${constFloat}
sta P8ZP_SCRATCH_W1

View File

@ -199,9 +199,11 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
}
TargetStorageKind.ARRAY -> {
with(target.array!!.indexer) {
val indexNum = indexExpr as? NumericLiteralValue
val indexVar = indexExpr as? IdentifierReference
when {
indexNum!=null -> {
val targetVarName = "${target.asmVarname} + ${indexNum!!.number.toInt()*program.memsizer.memorySize(target.datatype)}"
val targetVarName = "${target.asmVarname} + ${indexNum.number.toInt()*program.memsizer.memorySize(target.datatype)}"
when(target.datatype) {
in ByteDatatypes -> {
when {

View File

@ -75,7 +75,7 @@ internal class ConstantIdentifierReplacer(private val program: Program, private
override fun before(decl: VarDecl, parent: Node): Iterable<IAstModification> {
// the initializer value can't refer to the variable itself (recursive definition)
// TODO: use call graph for this?
if(decl.value?.referencesIdentifier(decl.name) == true || decl.arraysize?.indexVar?.referencesIdentifier(decl.name) == true) {
if(decl.value?.referencesIdentifier(decl.name) == true || decl.arraysize?.indexExpr?.referencesIdentifier(decl.name) == true) {
errors.err("recursive var declaration", decl.position)
return noModifications
}
@ -93,19 +93,6 @@ internal class ConstantIdentifierReplacer(private val program: Program, private
decl
))
}
} else if(arraysize.constIndex()==null) {
// see if we can calculate the size from other fields
try {
val cval = arraysize.indexVar?.constValue(program) ?: arraysize.origExpression?.constValue(program)
if (cval != null) {
arraysize.indexVar = null
arraysize.origExpression = null
arraysize.indexNum = cval
}
} catch (x: UndefinedSymbolError) {
errors.err(x.message, x.position)
return noModifications
}
}
}

View File

@ -121,8 +121,7 @@ class AstToSourceCode(val output: (text: String) -> Unit, val program: Program):
output(datatypeString(decl.datatype))
if(decl.arraysize!=null) {
decl.arraysize!!.indexNum?.accept(this)
decl.arraysize!!.indexVar?.accept(this)
decl.arraysize!!.indexExpr.accept(this)
}
if(decl.isArray)
output("]")
@ -365,8 +364,7 @@ class AstToSourceCode(val output: (text: String) -> Unit, val program: Program):
override fun visit(arrayIndexedExpression: ArrayIndexedExpression) {
arrayIndexedExpression.arrayvar.accept(this)
output("[")
arrayIndexedExpression.indexer.indexNum?.accept(this)
arrayIndexedExpression.indexer.indexVar?.accept(this)
arrayIndexedExpression.indexer.indexExpr.accept(this)
output("]")
}

View File

@ -275,46 +275,19 @@ class ParameterVarDecl(name: String, declaredDatatype: DataType, position: Posit
: VarDecl(VarDeclType.VAR, declaredDatatype, ZeropageWish.DONTCARE, null, name, null, null, false, true, position)
class ArrayIndex(var origExpression: Expression?, // will be replaced later by either the number or the identifier
class ArrayIndex(var indexExpr: Expression,
override val position: Position) : Node {
// for code simplicity, either indexed via a constant number or via a variable (no arbitrary expressions)
override lateinit var parent: Node
var indexNum: NumericLiteralValue? = origExpression as? NumericLiteralValue
var indexVar: IdentifierReference? = origExpression as? IdentifierReference
init {
if(indexNum!=null || indexVar!=null)
origExpression = null
}
override fun linkParents(parent: Node) {
this.parent = parent
origExpression?.linkParents(this)
indexNum?.linkParents(this)
indexVar?.linkParents(this)
indexExpr.linkParents(this)
}
override fun replaceChildNode(node: Node, replacement: Node) {
require(replacement is Expression)
when {
node===origExpression -> origExpression = replacement
node===indexVar -> {
when (replacement) {
is NumericLiteralValue -> {
indexVar = null
indexNum = replacement
}
is IdentifierReference -> {
indexVar = replacement
indexNum = null
}
else -> {
throw FatalAstException("invalid replace")
}
}
}
else -> throw FatalAstException("invalid replace")
}
if (node===indexExpr) indexExpr = replacement
else throw FatalAstException("invalid replace")
}
companion object {
@ -324,29 +297,16 @@ class ArrayIndex(var origExpression: Expression?, // will be replaced
}
}
fun accept(visitor: IAstVisitor) {
origExpression?.accept(visitor)
indexNum?.accept(visitor)
indexVar?.accept(visitor)
}
fun accept(visitor: AstWalker, parent: Node) {
origExpression?.accept(visitor, this)
indexNum?.accept(visitor, this)
indexVar?.accept(visitor, this)
}
fun accept(visitor: IAstVisitor) = indexExpr.accept(visitor)
fun accept(visitor: AstWalker, parent: Node) = indexExpr.accept(visitor, this)
override fun toString(): String {
return("ArrayIndex($indexNum, $indexVar, pos=$position)")
return("ArrayIndex($indexExpr, pos=$position)")
}
fun constIndex() = indexNum?.number?.toInt()
fun constIndex() = (indexExpr as? NumericLiteralValue)?.number?.toInt()
infix fun isSameAs(other: ArrayIndex): Boolean {
return if(indexNum!=null || indexVar!=null)
indexNum==other.indexNum && indexVar == other.indexVar
else
other.origExpression!=null && origExpression!! isSameAs other.origExpression!!
}
infix fun isSameAs(other: ArrayIndex): Boolean = indexExpr isSameAs other.indexExpr
}
open class Assignment(var target: AssignTarget, var value: Expression, override val position: Position) : Statement() {