mirror of
https://github.com/irmen/prog8.git
synced 2025-02-20 03:29:01 +00:00
fixed some node update issues in Modifying Ast visitor
This commit is contained in:
parent
fed020825a
commit
b7502c7eaa
@ -247,8 +247,8 @@ class BinaryExpression(var left: Expression, var operator: String, var right: Ex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ArrayIndexedExpression(val identifier: IdentifierReference,
|
class ArrayIndexedExpression(var identifier: IdentifierReference,
|
||||||
var arrayspec: ArrayIndex,
|
val arrayspec: ArrayIndex,
|
||||||
override val position: Position) : Expression() {
|
override val position: Position) : Expression() {
|
||||||
override lateinit var parent: Node
|
override lateinit var parent: Node
|
||||||
override fun linkParents(parent: Node) {
|
override fun linkParents(parent: Node) {
|
||||||
@ -304,7 +304,7 @@ class TypecastExpression(var expression: Expression, var type: DataType, val imp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class AddressOf(val identifier: IdentifierReference, override val position: Position) : Expression() {
|
data class AddressOf(var identifier: IdentifierReference, override val position: Position) : Expression() {
|
||||||
override lateinit var parent: Node
|
override lateinit var parent: Node
|
||||||
|
|
||||||
override fun linkParents(parent: Node) {
|
override fun linkParents(parent: Node) {
|
||||||
@ -753,6 +753,13 @@ data class IdentifierReference(val nameInSource: List<String>, override val posi
|
|||||||
else -> throw FatalAstException("requires a reference value")
|
else -> throw FatalAstException("requires a reference value")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun withPrefixedName(nameprefix: String): IdentifierReference {
|
||||||
|
val prefixed = nameInSource.dropLast(1) + listOf(nameprefix+nameInSource.last())
|
||||||
|
val new = IdentifierReference(prefixed, position)
|
||||||
|
new.parent = parent
|
||||||
|
return new
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FunctionCall(override var target: IdentifierReference,
|
class FunctionCall(override var target: IdentifierReference,
|
||||||
|
@ -370,8 +370,9 @@ internal class AstChecker(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
val assignment = assignTarget.parent as Statement
|
val assignment = assignTarget.parent as Statement
|
||||||
if (assignTarget.identifier != null) {
|
val targetIdentifier = assignTarget.identifier
|
||||||
val targetName = assignTarget.identifier.nameInSource
|
if (targetIdentifier != null) {
|
||||||
|
val targetName = targetIdentifier.nameInSource
|
||||||
val targetSymbol = program.namespace.lookup(targetName, assignment)
|
val targetSymbol = program.namespace.lookup(targetName, assignment)
|
||||||
when (targetSymbol) {
|
when (targetSymbol) {
|
||||||
null -> {
|
null -> {
|
||||||
|
@ -166,30 +166,32 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi
|
|||||||
checkResult.add(SyntaxError("register loop variables have a fixed implicit datatype", forLoop.position))
|
checkResult.add(SyntaxError("register loop variables have a fixed implicit datatype", forLoop.position))
|
||||||
if(forLoop.loopRegister == Register.X)
|
if(forLoop.loopRegister == Register.X)
|
||||||
printWarning("writing to the X register is dangerous, because it's used as an internal pointer", forLoop.position)
|
printWarning("writing to the X register is dangerous, because it's used as an internal pointer", forLoop.position)
|
||||||
} else if(forLoop.loopVar!=null) {
|
} else {
|
||||||
val varName = forLoop.loopVar.nameInSource.last()
|
val loopVar = forLoop.loopVar
|
||||||
if(forLoop.decltype!=null) {
|
if (loopVar != null) {
|
||||||
val existing = if(forLoop.body.containsNoCodeNorVars()) null else forLoop.body.lookup(forLoop.loopVar.nameInSource, forLoop.body.statements.first())
|
val varName = loopVar.nameInSource.last()
|
||||||
if(existing==null) {
|
if (forLoop.decltype != null) {
|
||||||
// create the local scoped for loop variable itself
|
val existing = if (forLoop.body.containsNoCodeNorVars()) null else forLoop.body.lookup(loopVar.nameInSource, forLoop.body.statements.first())
|
||||||
val vardecl = VarDecl(VarDeclType.VAR, forLoop.decltype, forLoop.zeropage, null, varName, null, null,
|
if (existing == null) {
|
||||||
isArray = false, autogeneratedDontRemove = true, position = forLoop.loopVar.position)
|
// create the local scoped for loop variable itself
|
||||||
vardecl.linkParents(forLoop.body)
|
val vardecl = VarDecl(VarDeclType.VAR, forLoop.decltype, forLoop.zeropage, null, varName, null, null,
|
||||||
forLoop.body.statements.add(0, vardecl)
|
isArray = false, autogeneratedDontRemove = true, position = loopVar.position)
|
||||||
forLoop.loopVar.parent = forLoop.body // loopvar 'is defined in the body'
|
vardecl.linkParents(forLoop.body)
|
||||||
|
forLoop.body.statements.add(0, vardecl)
|
||||||
|
loopVar.parent = forLoop.body // loopvar 'is defined in the body'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
if (forLoop.iterable !is RangeExpr) {
|
||||||
|
val existing = if (forLoop.body.containsNoCodeNorVars()) null else forLoop.body.lookup(listOf(ForLoop.iteratorLoopcounterVarname), forLoop.body.statements.first())
|
||||||
if(forLoop.iterable !is RangeExpr) {
|
if (existing == null) {
|
||||||
val existing = if(forLoop.body.containsNoCodeNorVars()) null else forLoop.body.lookup(listOf(ForLoop.iteratorLoopcounterVarname), forLoop.body.statements.first())
|
// create loop iteration counter variable (without value, to avoid an assignment)
|
||||||
if(existing==null) {
|
val vardecl = VarDecl(VarDeclType.VAR, DataType.UBYTE, ZeropageWish.PREFER_ZEROPAGE, null, ForLoop.iteratorLoopcounterVarname, null, null,
|
||||||
// create loop iteration counter variable (without value, to avoid an assignment)
|
isArray = false, autogeneratedDontRemove = true, position = loopVar.position)
|
||||||
val vardecl = VarDecl(VarDeclType.VAR, DataType.UBYTE, ZeropageWish.PREFER_ZEROPAGE, null, ForLoop.iteratorLoopcounterVarname, null, null,
|
vardecl.linkParents(forLoop.body)
|
||||||
isArray = false, autogeneratedDontRemove = true, position = forLoop.loopVar.position)
|
forLoop.body.statements.add(0, vardecl)
|
||||||
vardecl.linkParents(forLoop.body)
|
loopVar.parent = forLoop.body // loopvar 'is defined in the body'
|
||||||
forLoop.body.statements.add(0, vardecl)
|
}
|
||||||
forLoop.loopVar.parent = forLoop.body // loopvar 'is defined in the body'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -233,8 +235,9 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi
|
|||||||
// a referencetype literal value that's not declared as a variable
|
// 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
|
// we need to introduce an auto-generated variable for this to be able to refer to the value
|
||||||
refLiteral.addToHeap(program.heap)
|
refLiteral.addToHeap(program.heap)
|
||||||
val variable = VarDecl.createAuto(refLiteral, program.heap)
|
val scope = refLiteral.definingScope()
|
||||||
addVarDecl(refLiteral.definingScope(), variable)
|
var variable = VarDecl.createAuto(refLiteral, program.heap)
|
||||||
|
variable = addVarDecl(scope, variable)
|
||||||
// replace the reference literal by a identifier reference
|
// replace the reference literal by a identifier reference
|
||||||
val identifier = IdentifierReference(listOf(variable.name), variable.position)
|
val identifier = IdentifierReference(listOf(variable.name), variable.position)
|
||||||
identifier.parent = refLiteral.parent
|
identifier.parent = refLiteral.parent
|
||||||
@ -290,12 +293,17 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi
|
|||||||
return expr
|
return expr
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addVarDecl(scope: INameScope, variable: VarDecl) {
|
private fun addVarDecl(scope: INameScope, variable: VarDecl): VarDecl {
|
||||||
if(scope !in vardeclsToAdd)
|
if(scope !in vardeclsToAdd)
|
||||||
vardeclsToAdd[scope] = mutableListOf()
|
vardeclsToAdd[scope] = mutableListOf()
|
||||||
val declList = vardeclsToAdd.getValue(scope)
|
val declList = vardeclsToAdd.getValue(scope)
|
||||||
if(declList.all{it.name!=variable.name})
|
val existing = declList.singleOrNull { it.name==variable.name }
|
||||||
|
return if(existing!=null) {
|
||||||
|
existing
|
||||||
|
} else {
|
||||||
declList.add(variable)
|
declList.add(variable)
|
||||||
|
variable
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package prog8.ast.processing
|
|||||||
|
|
||||||
import prog8.ast.Module
|
import prog8.ast.Module
|
||||||
import prog8.ast.Program
|
import prog8.ast.Program
|
||||||
|
import prog8.ast.base.FatalAstException
|
||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ interface IAstModifyingVisitor {
|
|||||||
|
|
||||||
fun visit(decl: VarDecl): Statement {
|
fun visit(decl: VarDecl): Statement {
|
||||||
decl.value = decl.value?.accept(this)
|
decl.value = decl.value?.accept(this)
|
||||||
decl.arraysize?.accept(this)
|
decl.arraysize = decl.arraysize?.accept(this)
|
||||||
return decl
|
return decl
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,6 +50,8 @@ interface IAstModifyingVisitor {
|
|||||||
val newtarget = functionCall.target.accept(this)
|
val newtarget = functionCall.target.accept(this)
|
||||||
if(newtarget is IdentifierReference)
|
if(newtarget is IdentifierReference)
|
||||||
functionCall.target = newtarget
|
functionCall.target = newtarget
|
||||||
|
else
|
||||||
|
throw FatalAstException("cannot change class of function call target")
|
||||||
functionCall.arglist = functionCall.arglist.map { it.accept(this) }.toMutableList()
|
functionCall.arglist = functionCall.arglist.map { it.accept(this) }.toMutableList()
|
||||||
return functionCall
|
return functionCall
|
||||||
}
|
}
|
||||||
@ -57,6 +60,8 @@ interface IAstModifyingVisitor {
|
|||||||
val newtarget = functionCallStatement.target.accept(this)
|
val newtarget = functionCallStatement.target.accept(this)
|
||||||
if(newtarget is IdentifierReference)
|
if(newtarget is IdentifierReference)
|
||||||
functionCallStatement.target = newtarget
|
functionCallStatement.target = newtarget
|
||||||
|
else
|
||||||
|
throw FatalAstException("cannot change class of function call target")
|
||||||
functionCallStatement.arglist = functionCallStatement.arglist.map { it.accept(this) }.toMutableList()
|
functionCallStatement.arglist = functionCallStatement.arglist.map { it.accept(this) }.toMutableList()
|
||||||
return functionCallStatement
|
return functionCallStatement
|
||||||
}
|
}
|
||||||
@ -135,7 +140,12 @@ interface IAstModifyingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun visit(forLoop: ForLoop): Statement {
|
fun visit(forLoop: ForLoop): Statement {
|
||||||
forLoop.loopVar?.accept(this)
|
val newloopvar = forLoop.loopVar?.accept(this)
|
||||||
|
when(newloopvar) {
|
||||||
|
is IdentifierReference -> forLoop.loopVar = newloopvar
|
||||||
|
null -> forLoop.loopVar = null
|
||||||
|
else -> throw FatalAstException("can't change class of loopvar")
|
||||||
|
}
|
||||||
forLoop.iterable = forLoop.iterable.accept(this)
|
forLoop.iterable = forLoop.iterable.accept(this)
|
||||||
forLoop.body = forLoop.body.accept(this) as AnonymousScope
|
forLoop.body = forLoop.body.accept(this) as AnonymousScope
|
||||||
return forLoop
|
return forLoop
|
||||||
@ -158,15 +168,24 @@ interface IAstModifyingVisitor {
|
|||||||
return returnStmt
|
return returnStmt
|
||||||
}
|
}
|
||||||
|
|
||||||
fun visit(arrayIndexedExpression: ArrayIndexedExpression): Expression {
|
fun visit(arrayIndexedExpression: ArrayIndexedExpression): ArrayIndexedExpression {
|
||||||
arrayIndexedExpression.identifier.accept(this)
|
val ident = arrayIndexedExpression.identifier.accept(this)
|
||||||
|
if(ident is IdentifierReference)
|
||||||
|
arrayIndexedExpression.identifier = ident
|
||||||
|
else
|
||||||
|
throw FatalAstException("can't change class of indexed identifier")
|
||||||
arrayIndexedExpression.arrayspec.accept(this)
|
arrayIndexedExpression.arrayspec.accept(this)
|
||||||
return arrayIndexedExpression
|
return arrayIndexedExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
fun visit(assignTarget: AssignTarget): AssignTarget {
|
fun visit(assignTarget: AssignTarget): AssignTarget {
|
||||||
assignTarget.arrayindexed?.accept(this)
|
val ident = assignTarget.identifier?.accept(this)
|
||||||
assignTarget.identifier?.accept(this)
|
when (ident) {
|
||||||
|
is IdentifierReference -> assignTarget.identifier = ident
|
||||||
|
null -> assignTarget.identifier = null
|
||||||
|
else -> throw FatalAstException("can't change class of assign target identifier")
|
||||||
|
}
|
||||||
|
assignTarget.arrayindexed = assignTarget.arrayindexed?.accept(this)
|
||||||
assignTarget.memoryAddress?.let { visit(it) }
|
assignTarget.memoryAddress?.let { visit(it) }
|
||||||
return assignTarget
|
return assignTarget
|
||||||
}
|
}
|
||||||
@ -191,7 +210,11 @@ interface IAstModifyingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun visit(addressOf: AddressOf): Expression {
|
fun visit(addressOf: AddressOf): Expression {
|
||||||
addressOf.identifier.accept(this)
|
val ident = addressOf.identifier.accept(this)
|
||||||
|
if(ident is IdentifierReference)
|
||||||
|
addressOf.identifier = ident
|
||||||
|
else
|
||||||
|
throw FatalAstException("can't change class of addressof identifier")
|
||||||
return addressOf
|
return addressOf
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,14 +235,19 @@ interface IAstModifyingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun visit(whenStatement: WhenStatement): Statement {
|
fun visit(whenStatement: WhenStatement): Statement {
|
||||||
whenStatement.condition.accept(this)
|
whenStatement.condition = whenStatement.condition.accept(this)
|
||||||
whenStatement.choices.forEach { it.accept(this) }
|
whenStatement.choices.forEach { it.accept(this) }
|
||||||
return whenStatement
|
return whenStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
fun visit(whenChoice: WhenChoice) {
|
fun visit(whenChoice: WhenChoice) {
|
||||||
whenChoice.values?.forEach { it.accept(this) }
|
whenChoice.values?.forEach { it.accept(this) }
|
||||||
whenChoice.statements.accept(this)
|
val stmt = whenChoice.statements.accept(this)
|
||||||
|
if(stmt is AnonymousScope)
|
||||||
|
whenChoice.statements = stmt
|
||||||
|
else {
|
||||||
|
whenChoice.statements = AnonymousScope(mutableListOf(stmt), stmt.position)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun visit(structDecl: StructDecl): Statement {
|
fun visit(structDecl: StructDecl): Statement {
|
||||||
|
@ -198,7 +198,6 @@ class VarDecl(val type: VarDeclType,
|
|||||||
throw FatalAstException("can only create autovar for a ref lv that has a heapid $refLv")
|
throw FatalAstException("can only create autovar for a ref lv that has a heapid $refLv")
|
||||||
|
|
||||||
val autoVarName = "$autoHeapValuePrefix${refLv.heapId}"
|
val autoVarName = "$autoHeapValuePrefix${refLv.heapId}"
|
||||||
|
|
||||||
return if(refLv.isArray) {
|
return if(refLv.isArray) {
|
||||||
val declaredType = ArrayElementTypes.getValue(refLv.type)
|
val declaredType = ArrayElementTypes.getValue(refLv.type)
|
||||||
val arraysize = ArrayIndex.forArray(refLv, heap)
|
val arraysize = ArrayIndex.forArray(refLv, heap)
|
||||||
@ -281,6 +280,12 @@ class VarDecl(val type: VarDeclType,
|
|||||||
structHasBeenFlattened = true
|
structHasBeenFlattened = true
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun withPrefixedName(nameprefix: String): Statement {
|
||||||
|
val new = VarDecl(type, declaredDatatype, zeropage, arraysize, nameprefix+name, structName, value, isArray, autogeneratedDontRemove, position)
|
||||||
|
new.parent = parent
|
||||||
|
return new
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ArrayIndex(var index: Expression, override val position: Position) : Node {
|
class ArrayIndex(var index: Expression, override val position: Position) : Node {
|
||||||
@ -298,9 +303,11 @@ class ArrayIndex(var index: Expression, override val position: Position) : Node
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun accept(visitor: IAstModifyingVisitor) {
|
fun accept(visitor: IAstModifyingVisitor): ArrayIndex {
|
||||||
index = index.accept(visitor)
|
index = index.accept(visitor)
|
||||||
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun accept(visitor: IAstVisitor) {
|
fun accept(visitor: IAstVisitor) {
|
||||||
index.accept(visitor)
|
index.accept(visitor)
|
||||||
}
|
}
|
||||||
@ -337,9 +344,9 @@ class VariableInitializationAssignment(target: AssignTarget, aug_op: String?, va
|
|||||||
: Assignment(target, aug_op, value, position)
|
: Assignment(target, aug_op, value, position)
|
||||||
|
|
||||||
data class AssignTarget(val register: Register?,
|
data class AssignTarget(val register: Register?,
|
||||||
val identifier: IdentifierReference?,
|
var identifier: IdentifierReference?,
|
||||||
val arrayindexed: ArrayIndexedExpression?,
|
var arrayindexed: ArrayIndexedExpression?,
|
||||||
var memoryAddress: DirectMemoryWrite?,
|
val memoryAddress: DirectMemoryWrite?,
|
||||||
override val position: Position) : Node {
|
override val position: Position) : Node {
|
||||||
override lateinit var parent: Node
|
override lateinit var parent: Node
|
||||||
|
|
||||||
@ -370,12 +377,12 @@ data class AssignTarget(val register: Register?,
|
|||||||
return DataType.UBYTE
|
return DataType.UBYTE
|
||||||
|
|
||||||
if(identifier!=null) {
|
if(identifier!=null) {
|
||||||
val symbol = program.namespace.lookup(identifier.nameInSource, stmt) ?: return null
|
val symbol = program.namespace.lookup(identifier!!.nameInSource, stmt) ?: return null
|
||||||
if (symbol is VarDecl) return symbol.datatype
|
if (symbol is VarDecl) return symbol.datatype
|
||||||
}
|
}
|
||||||
|
|
||||||
if(arrayindexed!=null) {
|
if(arrayindexed!=null) {
|
||||||
val dt = arrayindexed.inferType(program)
|
val dt = arrayindexed!!.inferType(program)
|
||||||
if(dt!=null)
|
if(dt!=null)
|
||||||
return dt
|
return dt
|
||||||
}
|
}
|
||||||
@ -390,12 +397,12 @@ data class AssignTarget(val register: Register?,
|
|||||||
return when {
|
return when {
|
||||||
this.memoryAddress!=null -> false
|
this.memoryAddress!=null -> false
|
||||||
this.register!=null -> value is RegisterExpr && value.register==register
|
this.register!=null -> value is RegisterExpr && value.register==register
|
||||||
this.identifier!=null -> value is IdentifierReference && value.nameInSource==identifier.nameInSource
|
this.identifier!=null -> value is IdentifierReference && value.nameInSource==identifier!!.nameInSource
|
||||||
this.arrayindexed!=null -> value is ArrayIndexedExpression &&
|
this.arrayindexed!=null -> value is ArrayIndexedExpression &&
|
||||||
value.identifier.nameInSource==arrayindexed.identifier.nameInSource &&
|
value.identifier.nameInSource==arrayindexed!!.identifier.nameInSource &&
|
||||||
value.arrayspec.size()!=null &&
|
value.arrayspec.size()!=null &&
|
||||||
arrayindexed.arrayspec.size()!=null &&
|
arrayindexed!!.arrayspec.size()!=null &&
|
||||||
value.arrayspec.size()==arrayindexed.arrayspec.size()
|
value.arrayspec.size()==arrayindexed!!.arrayspec.size()
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -406,16 +413,16 @@ data class AssignTarget(val register: Register?,
|
|||||||
if(this.register!=null && other.register!=null)
|
if(this.register!=null && other.register!=null)
|
||||||
return this.register==other.register
|
return this.register==other.register
|
||||||
if(this.identifier!=null && other.identifier!=null)
|
if(this.identifier!=null && other.identifier!=null)
|
||||||
return this.identifier.nameInSource==other.identifier.nameInSource
|
return this.identifier!!.nameInSource==other.identifier!!.nameInSource
|
||||||
if(this.memoryAddress!=null && other.memoryAddress!=null) {
|
if(this.memoryAddress!=null && other.memoryAddress!=null) {
|
||||||
val addr1 = this.memoryAddress!!.addressExpression.constValue(program)
|
val addr1 = this.memoryAddress.addressExpression.constValue(program)
|
||||||
val addr2 = other.memoryAddress!!.addressExpression.constValue(program)
|
val addr2 = other.memoryAddress.addressExpression.constValue(program)
|
||||||
return addr1!=null && addr2!=null && addr1==addr2
|
return addr1!=null && addr2!=null && addr1==addr2
|
||||||
}
|
}
|
||||||
if(this.arrayindexed!=null && other.arrayindexed!=null) {
|
if(this.arrayindexed!=null && other.arrayindexed!=null) {
|
||||||
if(this.arrayindexed.identifier.nameInSource == other.arrayindexed.identifier.nameInSource) {
|
if(this.arrayindexed!!.identifier.nameInSource == other.arrayindexed!!.identifier.nameInSource) {
|
||||||
val x1 = this.arrayindexed.arrayspec.index.constValue(program)
|
val x1 = this.arrayindexed!!.arrayspec.index.constValue(program)
|
||||||
val x2 = other.arrayindexed.arrayspec.index.constValue(program)
|
val x2 = other.arrayindexed!!.arrayspec.index.constValue(program)
|
||||||
return x1!=null && x2!=null && x1==x2
|
return x1!=null && x2!=null && x1==x2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -428,12 +435,12 @@ data class AssignTarget(val register: Register?,
|
|||||||
if(this.memoryAddress!=null)
|
if(this.memoryAddress!=null)
|
||||||
return false
|
return false
|
||||||
if(this.arrayindexed!=null) {
|
if(this.arrayindexed!=null) {
|
||||||
val targetStmt = this.arrayindexed.identifier.targetVarDecl(namespace)
|
val targetStmt = this.arrayindexed!!.identifier.targetVarDecl(namespace)
|
||||||
if(targetStmt!=null)
|
if(targetStmt!=null)
|
||||||
return targetStmt.type!= VarDeclType.MEMORY
|
return targetStmt.type!= VarDeclType.MEMORY
|
||||||
}
|
}
|
||||||
if(this.identifier!=null) {
|
if(this.identifier!=null) {
|
||||||
val targetStmt = this.identifier.targetVarDecl(namespace)
|
val targetStmt = this.identifier!!.targetVarDecl(namespace)
|
||||||
if(targetStmt!=null)
|
if(targetStmt!=null)
|
||||||
return targetStmt.type!= VarDeclType.MEMORY
|
return targetStmt.type!= VarDeclType.MEMORY
|
||||||
}
|
}
|
||||||
@ -684,7 +691,7 @@ class BranchStatement(var condition: BranchCondition,
|
|||||||
class ForLoop(val loopRegister: Register?,
|
class ForLoop(val loopRegister: Register?,
|
||||||
val decltype: DataType?,
|
val decltype: DataType?,
|
||||||
val zeropage: ZeropageWish,
|
val zeropage: ZeropageWish,
|
||||||
val loopVar: IdentifierReference?,
|
var loopVar: IdentifierReference?,
|
||||||
var iterable: Expression,
|
var iterable: Expression,
|
||||||
var body: AnonymousScope,
|
var body: AnonymousScope,
|
||||||
override val position: Position) : Statement() {
|
override val position: Position) : Statement() {
|
||||||
@ -742,7 +749,7 @@ class RepeatLoop(var body: AnonymousScope,
|
|||||||
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
|
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
class WhenStatement(val condition: Expression,
|
class WhenStatement(var condition: Expression,
|
||||||
val choices: MutableList<WhenChoice>,
|
val choices: MutableList<WhenChoice>,
|
||||||
override val position: Position): Statement() {
|
override val position: Position): Statement() {
|
||||||
override lateinit var parent: Node
|
override lateinit var parent: Node
|
||||||
@ -776,7 +783,7 @@ class WhenStatement(val condition: Expression,
|
|||||||
}
|
}
|
||||||
|
|
||||||
class WhenChoice(val values: List<Expression>?, // if null, this is the 'else' part
|
class WhenChoice(val values: List<Expression>?, // if null, this is the 'else' part
|
||||||
val statements: AnonymousScope,
|
var statements: AnonymousScope,
|
||||||
override val position: Position) : Node {
|
override val position: Position) : Node {
|
||||||
override lateinit var parent: Node
|
override lateinit var parent: Node
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import prog8.ast.Program
|
|||||||
import prog8.ast.base.*
|
import prog8.ast.base.*
|
||||||
import prog8.ast.statements.Directive
|
import prog8.ast.statements.Directive
|
||||||
import prog8.compiler.target.c64.MachineDefinition
|
import prog8.compiler.target.c64.MachineDefinition
|
||||||
import prog8.compiler.target.c64.codegen2.AnonymousScopeCleanup
|
import prog8.compiler.target.c64.codegen2.AnonymousScopeVarsCleanup
|
||||||
import prog8.compiler.target.c64.codegen2.AsmGen2
|
import prog8.compiler.target.c64.codegen2.AsmGen2
|
||||||
import prog8.optimizer.constantFold
|
import prog8.optimizer.constantFold
|
||||||
import prog8.optimizer.optimizeStatements
|
import prog8.optimizer.optimizeStatements
|
||||||
@ -92,7 +92,7 @@ fun compileProgram(filepath: Path,
|
|||||||
if(writeAssembly) {
|
if(writeAssembly) {
|
||||||
// asm generation directly from the Ast, no need for intermediate code
|
// asm generation directly from the Ast, no need for intermediate code
|
||||||
val zeropage = MachineDefinition.C64Zeropage(compilerOptions)
|
val zeropage = MachineDefinition.C64Zeropage(compilerOptions)
|
||||||
AnonymousScopeCleanup.moveVarsFromAnonymousScopesToSubroutines(programAst)
|
AnonymousScopeVarsCleanup.moveVarsToSubroutine(programAst)
|
||||||
val assembly = AsmGen2(programAst, compilerOptions, zeropage).compileToAssembly(optimize)
|
val assembly = AsmGen2(programAst, compilerOptions, zeropage).compileToAssembly(optimize)
|
||||||
assembly.assemble(compilerOptions)
|
assembly.assemble(compilerOptions)
|
||||||
programName = assembly.name
|
programName = assembly.name
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
package prog8.compiler.target.c64.codegen2
|
|
||||||
|
|
||||||
import prog8.ast.Program
|
|
||||||
import prog8.ast.processing.IAstVisitor
|
|
||||||
import prog8.ast.statements.AnonymousScope
|
|
||||||
import prog8.ast.statements.VarDecl
|
|
||||||
|
|
||||||
class AnonymousScopeCleanup(val program: Program): IAstVisitor {
|
|
||||||
companion object {
|
|
||||||
fun moveVarsFromAnonymousScopesToSubroutines(programAst: Program) {
|
|
||||||
val cleanup = AnonymousScopeCleanup(programAst)
|
|
||||||
cleanup.visit(programAst)
|
|
||||||
|
|
||||||
for((scope, decls) in cleanup.varsToMove) {
|
|
||||||
decls.forEach { scope.remove(it) }
|
|
||||||
val sub = scope.definingSubroutine()!!
|
|
||||||
sub.statements.addAll(0, decls)
|
|
||||||
decls.forEach { it.parent=sub }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val varsToMove: MutableMap<AnonymousScope, List<VarDecl>> = mutableMapOf()
|
|
||||||
|
|
||||||
override fun visit(scope: AnonymousScope) {
|
|
||||||
val vardecls = scope.statements.filterIsInstance<VarDecl>()
|
|
||||||
varsToMove[scope] = vardecls
|
|
||||||
super.visit(scope)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,68 @@
|
|||||||
|
package prog8.compiler.target.c64.codegen2
|
||||||
|
|
||||||
|
import prog8.ast.Program
|
||||||
|
import prog8.ast.base.FatalAstException
|
||||||
|
import prog8.ast.expressions.Expression
|
||||||
|
import prog8.ast.expressions.IdentifierReference
|
||||||
|
import prog8.ast.processing.IAstModifyingVisitor
|
||||||
|
import prog8.ast.statements.AnonymousScope
|
||||||
|
import prog8.ast.statements.Statement
|
||||||
|
import prog8.ast.statements.VarDecl
|
||||||
|
|
||||||
|
class AnonymousScopeVarsCleanup(val program: Program): IAstModifyingVisitor {
|
||||||
|
companion object {
|
||||||
|
fun moveVarsToSubroutine(programAst: Program) {
|
||||||
|
val cleanup = AnonymousScopeVarsCleanup(programAst)
|
||||||
|
cleanup.visit(programAst)
|
||||||
|
|
||||||
|
for((scope, decls) in cleanup.varsToMove) {
|
||||||
|
decls.forEach { scope.remove(it) }
|
||||||
|
val sub = scope.definingSubroutine()!!
|
||||||
|
val existingVariables = sub.statements.filterIsInstance<VarDecl>().map { it.name }.toSet()
|
||||||
|
sub.statements.addAll(0, decls)
|
||||||
|
decls.forEach {
|
||||||
|
it.parent=sub
|
||||||
|
if(it.name in existingVariables) {
|
||||||
|
throw FatalAstException("variable ${it.name} already exists in ${sub.name}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val varsToMove: MutableMap<AnonymousScope, List<VarDecl>> = mutableMapOf()
|
||||||
|
|
||||||
|
override fun visit(scope: AnonymousScope): Statement {
|
||||||
|
val scope2 = super.visit(scope) as AnonymousScope
|
||||||
|
val vardecls = scope2.statements.filterIsInstance<VarDecl>()
|
||||||
|
varsToMove[scope2] = vardecls
|
||||||
|
return scope2
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun nameprefix(scope: AnonymousScope) = scope.name.replace("<", "").replace(">", "").replace("-", "") + "_"
|
||||||
|
|
||||||
|
override fun visit(decl: VarDecl): Statement {
|
||||||
|
val decl2 = super.visit(decl) as VarDecl
|
||||||
|
val scope = decl2.definingScope()
|
||||||
|
if(scope is AnonymousScope) {
|
||||||
|
return decl2.withPrefixedName(nameprefix(scope))
|
||||||
|
}
|
||||||
|
return decl2
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visit(identifier: IdentifierReference): Expression {
|
||||||
|
val ident = super.visit(identifier)
|
||||||
|
if(ident !is IdentifierReference)
|
||||||
|
return ident
|
||||||
|
|
||||||
|
val scope = ident.definingScope() as? AnonymousScope ?: return ident
|
||||||
|
val vardecl = ident.targetVarDecl(program.namespace)
|
||||||
|
return if(vardecl!=null) {
|
||||||
|
// prefix the variable name reference
|
||||||
|
ident.withPrefixedName(nameprefix(scope))
|
||||||
|
} else {
|
||||||
|
ident
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -548,7 +548,7 @@ internal class AsmGen2(val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translateSubroutineCall(stmt: IFunctionCall) {
|
private fun translateSubroutineCall(stmt: IFunctionCall) {
|
||||||
val sub = stmt.target.targetSubroutine(program.namespace)!!
|
val sub = stmt.target.targetSubroutine(program.namespace) ?: throw AssemblyError("undefined subroutine ${stmt.target}")
|
||||||
if(Register.X in sub.asmClobbers)
|
if(Register.X in sub.asmClobbers)
|
||||||
out(" stx c64.SCRATCH_ZPREGX") // we only save X for now (required! is the eval stack pointer), screw A and Y...
|
out(" stx c64.SCRATCH_ZPREGX") // we only save X for now (required! is the eval stack pointer), screw A and Y...
|
||||||
|
|
||||||
@ -1189,15 +1189,16 @@ internal class AsmGen2(val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun assignEvalResult(target: AssignTarget) {
|
private fun assignEvalResult(target: AssignTarget) {
|
||||||
|
val targetIdent = target.identifier
|
||||||
when {
|
when {
|
||||||
target.register!=null -> {
|
target.register!=null -> {
|
||||||
if(target.register==Register.X)
|
if(target.register==Register.X)
|
||||||
throw AssemblyError("can't pop into X register - use variable instead")
|
throw AssemblyError("can't pop into X register - use variable instead")
|
||||||
out(" inx | ld${target.register.name.toLowerCase()} $ESTACK_LO_HEX,x ")
|
out(" inx | ld${target.register.name.toLowerCase()} $ESTACK_LO_HEX,x ")
|
||||||
}
|
}
|
||||||
target.identifier!=null -> {
|
targetIdent!=null -> {
|
||||||
val targetName = asmIdentifierName(target.identifier)
|
val targetName = asmIdentifierName(targetIdent)
|
||||||
val targetDt = target.identifier.inferType(program)!!
|
val targetDt = targetIdent.inferType(program)!!
|
||||||
when(targetDt) {
|
when(targetDt) {
|
||||||
DataType.UBYTE, DataType.BYTE -> {
|
DataType.UBYTE, DataType.BYTE -> {
|
||||||
out(" inx | lda $ESTACK_LO_HEX,x | sta $targetName")
|
out(" inx | lda $ESTACK_LO_HEX,x | sta $targetName")
|
||||||
@ -1222,7 +1223,7 @@ internal class AsmGen2(val program: Program,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
target.memoryAddress!=null -> {
|
target.memoryAddress!=null -> {
|
||||||
val address = target.memoryAddress!!.addressExpression
|
val address = target.memoryAddress.addressExpression
|
||||||
if(address is NumericLiteralValue) {
|
if(address is NumericLiteralValue) {
|
||||||
out(" inx | lda $ESTACK_LO_HEX,x | sta ${address.number.toHex()}")
|
out(" inx | lda $ESTACK_LO_HEX,x | sta ${address.number.toHex()}")
|
||||||
} else {
|
} else {
|
||||||
@ -1237,9 +1238,10 @@ internal class AsmGen2(val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun assignAddressOf(target: AssignTarget, name: IdentifierReference, scopedname: String) {
|
private fun assignAddressOf(target: AssignTarget, name: IdentifierReference, scopedname: String) {
|
||||||
|
val targetIdent = target.identifier
|
||||||
when {
|
when {
|
||||||
target.identifier!=null -> {
|
targetIdent!=null -> {
|
||||||
val targetName = asmIdentifierName(target.identifier)
|
val targetName = asmIdentifierName(targetIdent)
|
||||||
val struct = name.memberOfStruct(program.namespace)
|
val struct = name.memberOfStruct(program.namespace)
|
||||||
if(struct!=null) {
|
if(struct!=null) {
|
||||||
// take the address of the first struct member instead
|
// take the address of the first struct member instead
|
||||||
@ -1271,9 +1273,10 @@ internal class AsmGen2(val program: Program,
|
|||||||
|
|
||||||
private fun assignWordVariable(target: AssignTarget, variable: IdentifierReference) {
|
private fun assignWordVariable(target: AssignTarget, variable: IdentifierReference) {
|
||||||
val sourceName = asmIdentifierName(variable)
|
val sourceName = asmIdentifierName(variable)
|
||||||
|
val targetIdent = target.identifier
|
||||||
when {
|
when {
|
||||||
target.identifier!=null -> {
|
targetIdent!=null -> {
|
||||||
val targetName = asmIdentifierName(target.identifier)
|
val targetName = asmIdentifierName(targetIdent)
|
||||||
out("""
|
out("""
|
||||||
lda $sourceName
|
lda $sourceName
|
||||||
ldy $sourceName+1
|
ldy $sourceName+1
|
||||||
@ -1287,9 +1290,10 @@ internal class AsmGen2(val program: Program,
|
|||||||
|
|
||||||
private fun assignFloatVariable(target: AssignTarget, variable: IdentifierReference) {
|
private fun assignFloatVariable(target: AssignTarget, variable: IdentifierReference) {
|
||||||
val sourceName = asmIdentifierName(variable)
|
val sourceName = asmIdentifierName(variable)
|
||||||
|
val targetIdent = target.identifier
|
||||||
when {
|
when {
|
||||||
target.identifier!=null -> {
|
targetIdent!=null -> {
|
||||||
val targetName = asmIdentifierName(target.identifier)
|
val targetName = asmIdentifierName(targetIdent)
|
||||||
out("""
|
out("""
|
||||||
lda $sourceName
|
lda $sourceName
|
||||||
sta $targetName
|
sta $targetName
|
||||||
@ -1309,12 +1313,13 @@ internal class AsmGen2(val program: Program,
|
|||||||
|
|
||||||
private fun assignByteVariable(target: AssignTarget, variable: IdentifierReference) {
|
private fun assignByteVariable(target: AssignTarget, variable: IdentifierReference) {
|
||||||
val sourceName = asmIdentifierName(variable)
|
val sourceName = asmIdentifierName(variable)
|
||||||
|
val targetIdent = target.identifier
|
||||||
when {
|
when {
|
||||||
target.register!=null -> {
|
target.register!=null -> {
|
||||||
out(" ld${target.register.name.toLowerCase()} $sourceName")
|
out(" ld${target.register.name.toLowerCase()} $sourceName")
|
||||||
}
|
}
|
||||||
target.identifier!=null -> {
|
targetIdent!=null -> {
|
||||||
val targetName = asmIdentifierName(target.identifier)
|
val targetName = asmIdentifierName(targetIdent)
|
||||||
out("""
|
out("""
|
||||||
lda $sourceName
|
lda $sourceName
|
||||||
sta $targetName
|
sta $targetName
|
||||||
@ -1325,9 +1330,11 @@ internal class AsmGen2(val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun assignRegister(target: AssignTarget, register: Register) {
|
private fun assignRegister(target: AssignTarget, register: Register) {
|
||||||
|
val targetIdent = target.identifier
|
||||||
|
val targetArrayIdx = target.arrayindexed
|
||||||
when {
|
when {
|
||||||
target.identifier!=null -> {
|
targetIdent!=null -> {
|
||||||
val targetName = asmIdentifierName(target.identifier)
|
val targetName = asmIdentifierName(targetIdent)
|
||||||
out(" st${register.name.toLowerCase()} $targetName")
|
out(" st${register.name.toLowerCase()} $targetName")
|
||||||
}
|
}
|
||||||
target.register!=null -> {
|
target.register!=null -> {
|
||||||
@ -1370,8 +1377,9 @@ internal class AsmGen2(val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun assignWordConstant(target: AssignTarget, word: Int) {
|
private fun assignWordConstant(target: AssignTarget, word: Int) {
|
||||||
if(target.identifier!=null) {
|
val targetIdent = target.identifier
|
||||||
val targetName = asmIdentifierName(target.identifier)
|
if(targetIdent!=null) {
|
||||||
|
val targetName = asmIdentifierName(targetIdent)
|
||||||
if(word ushr 8 == word and 255) {
|
if(word ushr 8 == word and 255) {
|
||||||
// lsb=msb
|
// lsb=msb
|
||||||
out("""
|
out("""
|
||||||
@ -1393,12 +1401,13 @@ internal class AsmGen2(val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun assignByteConstant(target: AssignTarget, byte: Short) {
|
private fun assignByteConstant(target: AssignTarget, byte: Short) {
|
||||||
|
val targetIdent = target.identifier
|
||||||
when {
|
when {
|
||||||
target.register!=null -> {
|
target.register!=null -> {
|
||||||
out(" ld${target.register.name.toLowerCase()} #${byte.toHex()}")
|
out(" ld${target.register.name.toLowerCase()} #${byte.toHex()}")
|
||||||
}
|
}
|
||||||
target.identifier!=null -> {
|
targetIdent!=null -> {
|
||||||
val targetName = asmIdentifierName(target.identifier)
|
val targetName = asmIdentifierName(targetIdent)
|
||||||
out(" lda #${byte.toHex()} | sta $targetName ")
|
out(" lda #${byte.toHex()} | sta $targetName ")
|
||||||
}
|
}
|
||||||
else -> TODO("assign byte $byte to $target")
|
else -> TODO("assign byte $byte to $target")
|
||||||
@ -1406,10 +1415,11 @@ internal class AsmGen2(val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun assignFloatConstant(target: AssignTarget, float: Double) {
|
private fun assignFloatConstant(target: AssignTarget, float: Double) {
|
||||||
|
val targetIdent = target.identifier
|
||||||
if(float==0.0) {
|
if(float==0.0) {
|
||||||
// optimized case for float zero
|
// optimized case for float zero
|
||||||
if (target.identifier != null) {
|
if (targetIdent != null) {
|
||||||
val targetName = asmIdentifierName(target.identifier)
|
val targetName = asmIdentifierName(targetIdent)
|
||||||
out("""
|
out("""
|
||||||
lda #0
|
lda #0
|
||||||
sta $targetName
|
sta $targetName
|
||||||
@ -1424,8 +1434,8 @@ internal class AsmGen2(val program: Program,
|
|||||||
} else {
|
} else {
|
||||||
// non-zero value
|
// non-zero value
|
||||||
val constFloat = getFloatConst(float)
|
val constFloat = getFloatConst(float)
|
||||||
if (target.identifier != null) {
|
if (targetIdent != null) {
|
||||||
val targetName = asmIdentifierName(target.identifier)
|
val targetName = asmIdentifierName(targetIdent)
|
||||||
out("""
|
out("""
|
||||||
lda $constFloat
|
lda $constFloat
|
||||||
sta $targetName
|
sta $targetName
|
||||||
@ -1445,13 +1455,14 @@ internal class AsmGen2(val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun assignMemoryByte(target: AssignTarget, address: Int?, identifier: IdentifierReference?) {
|
private fun assignMemoryByte(target: AssignTarget, address: Int?, identifier: IdentifierReference?) {
|
||||||
|
val targetIdent = target.identifier
|
||||||
if(address!=null) {
|
if(address!=null) {
|
||||||
when {
|
when {
|
||||||
target.register!=null -> {
|
target.register!=null -> {
|
||||||
out(" ld${target.register.name.toLowerCase()} ${address.toHex()}")
|
out(" ld${target.register.name.toLowerCase()} ${address.toHex()}")
|
||||||
}
|
}
|
||||||
target.identifier!=null -> {
|
targetIdent!=null -> {
|
||||||
val targetName = asmIdentifierName(target.identifier)
|
val targetName = asmIdentifierName(targetIdent)
|
||||||
out("""
|
out("""
|
||||||
lda ${address.toHex()}
|
lda ${address.toHex()}
|
||||||
sta $targetName
|
sta $targetName
|
||||||
@ -1474,8 +1485,8 @@ internal class AsmGen2(val program: Program,
|
|||||||
Register.Y -> out(" tay")
|
Register.Y -> out(" tay")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
target.identifier!=null -> {
|
targetIdent!=null -> {
|
||||||
val targetName = asmIdentifierName(target.identifier)
|
val targetName = asmIdentifierName(targetIdent)
|
||||||
out("""
|
out("""
|
||||||
ldy #0
|
ldy #0
|
||||||
lda ($sourceName),y
|
lda ($sourceName),y
|
||||||
|
@ -472,7 +472,7 @@ class AstVm(val program: Program) {
|
|||||||
loopvar = IdentifierReference(listOf(stmt.loopRegister.name), stmt.position)
|
loopvar = IdentifierReference(listOf(stmt.loopRegister.name), stmt.position)
|
||||||
} else {
|
} else {
|
||||||
loopvarDt = stmt.loopVar!!.inferType(program)!!
|
loopvarDt = stmt.loopVar!!.inferType(program)!!
|
||||||
loopvar = stmt.loopVar
|
loopvar = stmt.loopVar!!
|
||||||
}
|
}
|
||||||
val iterator = iterable.iterator()
|
val iterator = iterable.iterator()
|
||||||
for (loopvalue in iterator) {
|
for (loopvalue in iterator) {
|
||||||
@ -545,10 +545,12 @@ class AstVm(val program: Program) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun performAssignment(target: AssignTarget, value: RuntimeValue, contextStmt: Statement, evalCtx: EvalContext) {
|
fun performAssignment(target: AssignTarget, value: RuntimeValue, contextStmt: Statement, evalCtx: EvalContext) {
|
||||||
|
val targetIdent = target.identifier
|
||||||
|
val targetArrayIndexed = target.arrayindexed
|
||||||
when {
|
when {
|
||||||
target.identifier != null -> {
|
targetIdent != null -> {
|
||||||
val decl = contextStmt.definingScope().lookup(target.identifier.nameInSource, contextStmt) as? VarDecl
|
val decl = contextStmt.definingScope().lookup(targetIdent.nameInSource, contextStmt) as? VarDecl
|
||||||
?: throw VmExecutionException("can't find assignment target ${target.identifier}")
|
?: throw VmExecutionException("can't find assignment target $targetIdent")
|
||||||
if (decl.type == VarDeclType.MEMORY) {
|
if (decl.type == VarDeclType.MEMORY) {
|
||||||
val address = runtimeVariables.getMemoryAddress(decl.definingScope(), decl.name)
|
val address = runtimeVariables.getMemoryAddress(decl.definingScope(), decl.name)
|
||||||
when (decl.datatype) {
|
when (decl.datatype) {
|
||||||
@ -565,14 +567,14 @@ class AstVm(val program: Program) {
|
|||||||
runtimeVariables.set(decl.definingScope(), decl.name, value)
|
runtimeVariables.set(decl.definingScope(), decl.name, value)
|
||||||
}
|
}
|
||||||
target.memoryAddress != null -> {
|
target.memoryAddress != null -> {
|
||||||
val address = evaluate(target.memoryAddress!!.addressExpression, evalCtx).wordval!!
|
val address = evaluate(target.memoryAddress.addressExpression, evalCtx).wordval!!
|
||||||
evalCtx.mem.setUByte(address, value.byteval!!)
|
evalCtx.mem.setUByte(address, value.byteval!!)
|
||||||
}
|
}
|
||||||
target.arrayindexed != null -> {
|
targetArrayIndexed != null -> {
|
||||||
val vardecl = target.arrayindexed.identifier.targetVarDecl(program.namespace)!!
|
val vardecl = targetArrayIndexed.identifier.targetVarDecl(program.namespace)!!
|
||||||
if(vardecl.type==VarDeclType.VAR) {
|
if(vardecl.type==VarDeclType.VAR) {
|
||||||
val array = evaluate(target.arrayindexed.identifier, evalCtx)
|
val array = evaluate(targetArrayIndexed.identifier, evalCtx)
|
||||||
val index = evaluate(target.arrayindexed.arrayspec.index, evalCtx)
|
val index = evaluate(targetArrayIndexed.arrayspec.index, evalCtx)
|
||||||
when (array.type) {
|
when (array.type) {
|
||||||
DataType.ARRAY_UB -> {
|
DataType.ARRAY_UB -> {
|
||||||
if (value.type != DataType.UBYTE)
|
if (value.type != DataType.UBYTE)
|
||||||
@ -606,7 +608,7 @@ class AstVm(val program: Program) {
|
|||||||
val indexInt = index.integerValue()
|
val indexInt = index.integerValue()
|
||||||
val newchr = Petscii.decodePetscii(listOf(value.numericValue().toShort()), true)
|
val newchr = Petscii.decodePetscii(listOf(value.numericValue().toShort()), true)
|
||||||
val newstr = array.str!!.replaceRange(indexInt, indexInt + 1, newchr)
|
val newstr = array.str!!.replaceRange(indexInt, indexInt + 1, newchr)
|
||||||
val ident = contextStmt.definingScope().lookup(target.arrayindexed.identifier.nameInSource, contextStmt) as? VarDecl
|
val ident = contextStmt.definingScope().lookup(targetArrayIndexed.identifier.nameInSource, contextStmt) as? VarDecl
|
||||||
?: throw VmExecutionException("can't find assignment target ${target.identifier}")
|
?: throw VmExecutionException("can't find assignment target ${target.identifier}")
|
||||||
val identScope = ident.definingScope()
|
val identScope = ident.definingScope()
|
||||||
program.heap.update(array.heapId!!, newstr)
|
program.heap.update(array.heapId!!, newstr)
|
||||||
@ -615,8 +617,8 @@ class AstVm(val program: Program) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val address = (vardecl.value as NumericLiteralValue).number.toInt()
|
val address = (vardecl.value as NumericLiteralValue).number.toInt()
|
||||||
val index = evaluate(target.arrayindexed.arrayspec.index, evalCtx).integerValue()
|
val index = evaluate(targetArrayIndexed.arrayspec.index, evalCtx).integerValue()
|
||||||
val elementType = target.arrayindexed.inferType(program)!!
|
val elementType = targetArrayIndexed.inferType(program)!!
|
||||||
when(elementType) {
|
when(elementType) {
|
||||||
DataType.UBYTE -> mem.setUByte(address+index, value.byteval!!)
|
DataType.UBYTE -> mem.setUByte(address+index, value.byteval!!)
|
||||||
DataType.BYTE -> mem.setSByte(address+index, value.byteval!!)
|
DataType.BYTE -> mem.setSByte(address+index, value.byteval!!)
|
||||||
@ -952,4 +954,3 @@ class AstVm(val program: Program) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,18 +6,37 @@
|
|||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
|
|
||||||
float f1 = 1.1
|
;
|
||||||
float f2 = 2.2
|
; float f1 = 1.1
|
||||||
|
; float f2 = 2.2
|
||||||
|
;
|
||||||
|
; @(1024) = f1==f2
|
||||||
|
;
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
; c64scr.print_ub(f1==f2)
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; if f1 ==0.0
|
||||||
|
; c64scr.print("error\n")
|
||||||
|
; else
|
||||||
|
; c64scr.print("ok\n")
|
||||||
|
|
||||||
@(1024) = f1==f2
|
str s1 = "hello"
|
||||||
|
str s2 = "hello"
|
||||||
|
str s3 = "hello"
|
||||||
|
str s4 = "hello"
|
||||||
|
|
||||||
c64.CHROUT('\n')
|
if true {
|
||||||
c64scr.print_ub(f1==f2)
|
ubyte ub1 = 33
|
||||||
c64.CHROUT('\n')
|
A=ub1
|
||||||
|
c64scr.print("irmen")
|
||||||
|
}
|
||||||
|
|
||||||
|
if true {
|
||||||
|
ubyte ub1 = 33
|
||||||
|
A=ub1
|
||||||
|
c64scr.print("irmen")
|
||||||
|
}
|
||||||
|
|
||||||
if f1 ==0.0
|
|
||||||
c64scr.print("error\n")
|
|
||||||
else
|
|
||||||
c64scr.print("ok\n")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user