fixed some node update issues in Modifying Ast visitor

This commit is contained in:
Irmen de Jong 2019-07-28 15:18:53 +02:00
parent fed020825a
commit b7502c7eaa
11 changed files with 264 additions and 145 deletions

View File

@ -247,8 +247,8 @@ class BinaryExpression(var left: Expression, var operator: String, var right: Ex
}
}
class ArrayIndexedExpression(val identifier: IdentifierReference,
var arrayspec: ArrayIndex,
class ArrayIndexedExpression(var identifier: IdentifierReference,
val arrayspec: ArrayIndex,
override val position: Position) : Expression() {
override lateinit var 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 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")
}
}
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,

View File

@ -370,8 +370,9 @@ internal class AstChecker(private val program: Program,
}
val assignment = assignTarget.parent as Statement
if (assignTarget.identifier != null) {
val targetName = assignTarget.identifier.nameInSource
val targetIdentifier = assignTarget.identifier
if (targetIdentifier != null) {
val targetName = targetIdentifier.nameInSource
val targetSymbol = program.namespace.lookup(targetName, assignment)
when (targetSymbol) {
null -> {

View File

@ -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))
if(forLoop.loopRegister == Register.X)
printWarning("writing to the X register is dangerous, because it's used as an internal pointer", forLoop.position)
} else if(forLoop.loopVar!=null) {
val varName = forLoop.loopVar.nameInSource.last()
if(forLoop.decltype!=null) {
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, varName, null, null,
isArray = false, autogeneratedDontRemove = true, position = forLoop.loopVar.position)
vardecl.linkParents(forLoop.body)
forLoop.body.statements.add(0, vardecl)
forLoop.loopVar.parent = forLoop.body // loopvar 'is defined in the body'
} else {
val loopVar = forLoop.loopVar
if (loopVar != null) {
val varName = loopVar.nameInSource.last()
if (forLoop.decltype != null) {
val existing = if (forLoop.body.containsNoCodeNorVars()) null else forLoop.body.lookup(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, varName, null, null,
isArray = false, autogeneratedDontRemove = true, position = loopVar.position)
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(existing==null) {
// create loop iteration counter variable (without value, to avoid an assignment)
val vardecl = VarDecl(VarDeclType.VAR, DataType.UBYTE, ZeropageWish.PREFER_ZEROPAGE, null, ForLoop.iteratorLoopcounterVarname, null, null,
isArray = false, autogeneratedDontRemove = true, position = forLoop.loopVar.position)
vardecl.linkParents(forLoop.body)
forLoop.body.statements.add(0, vardecl)
forLoop.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 (existing == null) {
// create loop iteration counter variable (without value, to avoid an assignment)
val vardecl = VarDecl(VarDeclType.VAR, DataType.UBYTE, ZeropageWish.PREFER_ZEROPAGE, null, ForLoop.iteratorLoopcounterVarname, null, null,
isArray = false, autogeneratedDontRemove = true, position = loopVar.position)
vardecl.linkParents(forLoop.body)
forLoop.body.statements.add(0, vardecl)
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
// we need to introduce an auto-generated variable for this to be able to refer to the value
refLiteral.addToHeap(program.heap)
val variable = VarDecl.createAuto(refLiteral, program.heap)
addVarDecl(refLiteral.definingScope(), variable)
val scope = refLiteral.definingScope()
var variable = VarDecl.createAuto(refLiteral, program.heap)
variable = addVarDecl(scope, variable)
// replace the reference literal by a identifier reference
val identifier = IdentifierReference(listOf(variable.name), variable.position)
identifier.parent = refLiteral.parent
@ -290,12 +293,17 @@ internal class AstIdentifiersChecker(private val program: Program) : IAstModifyi
return expr
}
private fun addVarDecl(scope: INameScope, variable: VarDecl) {
private fun addVarDecl(scope: INameScope, variable: VarDecl): VarDecl {
if(scope !in vardeclsToAdd)
vardeclsToAdd[scope] = mutableListOf()
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)
variable
}
}
}

View File

@ -2,6 +2,7 @@ package prog8.ast.processing
import prog8.ast.Module
import prog8.ast.Program
import prog8.ast.base.FatalAstException
import prog8.ast.expressions.*
import prog8.ast.statements.*
@ -36,7 +37,7 @@ interface IAstModifyingVisitor {
fun visit(decl: VarDecl): Statement {
decl.value = decl.value?.accept(this)
decl.arraysize?.accept(this)
decl.arraysize = decl.arraysize?.accept(this)
return decl
}
@ -49,6 +50,8 @@ interface IAstModifyingVisitor {
val newtarget = functionCall.target.accept(this)
if(newtarget is IdentifierReference)
functionCall.target = newtarget
else
throw FatalAstException("cannot change class of function call target")
functionCall.arglist = functionCall.arglist.map { it.accept(this) }.toMutableList()
return functionCall
}
@ -57,6 +60,8 @@ interface IAstModifyingVisitor {
val newtarget = functionCallStatement.target.accept(this)
if(newtarget is IdentifierReference)
functionCallStatement.target = newtarget
else
throw FatalAstException("cannot change class of function call target")
functionCallStatement.arglist = functionCallStatement.arglist.map { it.accept(this) }.toMutableList()
return functionCallStatement
}
@ -135,7 +140,12 @@ interface IAstModifyingVisitor {
}
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.body = forLoop.body.accept(this) as AnonymousScope
return forLoop
@ -158,15 +168,24 @@ interface IAstModifyingVisitor {
return returnStmt
}
fun visit(arrayIndexedExpression: ArrayIndexedExpression): Expression {
arrayIndexedExpression.identifier.accept(this)
fun visit(arrayIndexedExpression: ArrayIndexedExpression): ArrayIndexedExpression {
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)
return arrayIndexedExpression
}
fun visit(assignTarget: AssignTarget): AssignTarget {
assignTarget.arrayindexed?.accept(this)
assignTarget.identifier?.accept(this)
val ident = 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) }
return assignTarget
}
@ -191,7 +210,11 @@ interface IAstModifyingVisitor {
}
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
}
@ -212,14 +235,19 @@ interface IAstModifyingVisitor {
}
fun visit(whenStatement: WhenStatement): Statement {
whenStatement.condition.accept(this)
whenStatement.condition = whenStatement.condition.accept(this)
whenStatement.choices.forEach { it.accept(this) }
return whenStatement
}
fun visit(whenChoice: WhenChoice) {
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 {

View File

@ -198,7 +198,6 @@ class VarDecl(val type: VarDeclType,
throw FatalAstException("can only create autovar for a ref lv that has a heapid $refLv")
val autoVarName = "$autoHeapValuePrefix${refLv.heapId}"
return if(refLv.isArray) {
val declaredType = ArrayElementTypes.getValue(refLv.type)
val arraysize = ArrayIndex.forArray(refLv, heap)
@ -281,6 +280,12 @@ class VarDecl(val type: VarDeclType,
structHasBeenFlattened = true
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 {
@ -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)
return this
}
fun accept(visitor: IAstVisitor) {
index.accept(visitor)
}
@ -337,9 +344,9 @@ class VariableInitializationAssignment(target: AssignTarget, aug_op: String?, va
: Assignment(target, aug_op, value, position)
data class AssignTarget(val register: Register?,
val identifier: IdentifierReference?,
val arrayindexed: ArrayIndexedExpression?,
var memoryAddress: DirectMemoryWrite?,
var identifier: IdentifierReference?,
var arrayindexed: ArrayIndexedExpression?,
val memoryAddress: DirectMemoryWrite?,
override val position: Position) : Node {
override lateinit var parent: Node
@ -370,12 +377,12 @@ data class AssignTarget(val register: Register?,
return DataType.UBYTE
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(arrayindexed!=null) {
val dt = arrayindexed.inferType(program)
val dt = arrayindexed!!.inferType(program)
if(dt!=null)
return dt
}
@ -390,12 +397,12 @@ data class AssignTarget(val register: Register?,
return when {
this.memoryAddress!=null -> false
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 &&
value.identifier.nameInSource==arrayindexed.identifier.nameInSource &&
value.identifier.nameInSource==arrayindexed!!.identifier.nameInSource &&
value.arrayspec.size()!=null &&
arrayindexed.arrayspec.size()!=null &&
value.arrayspec.size()==arrayindexed.arrayspec.size()
arrayindexed!!.arrayspec.size()!=null &&
value.arrayspec.size()==arrayindexed!!.arrayspec.size()
else -> false
}
}
@ -406,16 +413,16 @@ data class AssignTarget(val register: Register?,
if(this.register!=null && other.register!=null)
return this.register==other.register
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) {
val addr1 = this.memoryAddress!!.addressExpression.constValue(program)
val addr2 = other.memoryAddress!!.addressExpression.constValue(program)
val addr1 = this.memoryAddress.addressExpression.constValue(program)
val addr2 = other.memoryAddress.addressExpression.constValue(program)
return addr1!=null && addr2!=null && addr1==addr2
}
if(this.arrayindexed!=null && other.arrayindexed!=null) {
if(this.arrayindexed.identifier.nameInSource == other.arrayindexed.identifier.nameInSource) {
val x1 = this.arrayindexed.arrayspec.index.constValue(program)
val x2 = other.arrayindexed.arrayspec.index.constValue(program)
if(this.arrayindexed!!.identifier.nameInSource == other.arrayindexed!!.identifier.nameInSource) {
val x1 = this.arrayindexed!!.arrayspec.index.constValue(program)
val x2 = other.arrayindexed!!.arrayspec.index.constValue(program)
return x1!=null && x2!=null && x1==x2
}
}
@ -428,12 +435,12 @@ data class AssignTarget(val register: Register?,
if(this.memoryAddress!=null)
return false
if(this.arrayindexed!=null) {
val targetStmt = this.arrayindexed.identifier.targetVarDecl(namespace)
val targetStmt = this.arrayindexed!!.identifier.targetVarDecl(namespace)
if(targetStmt!=null)
return targetStmt.type!= VarDeclType.MEMORY
}
if(this.identifier!=null) {
val targetStmt = this.identifier.targetVarDecl(namespace)
val targetStmt = this.identifier!!.targetVarDecl(namespace)
if(targetStmt!=null)
return targetStmt.type!= VarDeclType.MEMORY
}
@ -684,7 +691,7 @@ class BranchStatement(var condition: BranchCondition,
class ForLoop(val loopRegister: Register?,
val decltype: DataType?,
val zeropage: ZeropageWish,
val loopVar: IdentifierReference?,
var loopVar: IdentifierReference?,
var iterable: Expression,
var body: AnonymousScope,
override val position: Position) : Statement() {
@ -742,7 +749,7 @@ class RepeatLoop(var body: AnonymousScope,
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
}
class WhenStatement(val condition: Expression,
class WhenStatement(var condition: Expression,
val choices: MutableList<WhenChoice>,
override val position: Position): Statement() {
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
val statements: AnonymousScope,
var statements: AnonymousScope,
override val position: Position) : Node {
override lateinit var parent: Node

View File

@ -5,7 +5,7 @@ import prog8.ast.Program
import prog8.ast.base.*
import prog8.ast.statements.Directive
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.optimizer.constantFold
import prog8.optimizer.optimizeStatements
@ -92,7 +92,7 @@ fun compileProgram(filepath: Path,
if(writeAssembly) {
// asm generation directly from the Ast, no need for intermediate code
val zeropage = MachineDefinition.C64Zeropage(compilerOptions)
AnonymousScopeCleanup.moveVarsFromAnonymousScopesToSubroutines(programAst)
AnonymousScopeVarsCleanup.moveVarsToSubroutine(programAst)
val assembly = AsmGen2(programAst, compilerOptions, zeropage).compileToAssembly(optimize)
assembly.assemble(compilerOptions)
programName = assembly.name

View File

@ -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)
}
}

View File

@ -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
}
}
}

View File

@ -548,7 +548,7 @@ internal class AsmGen2(val program: Program,
}
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)
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) {
val targetIdent = target.identifier
when {
target.register!=null -> {
if(target.register==Register.X)
throw AssemblyError("can't pop into X register - use variable instead")
out(" inx | ld${target.register.name.toLowerCase()} $ESTACK_LO_HEX,x ")
}
target.identifier!=null -> {
val targetName = asmIdentifierName(target.identifier)
val targetDt = target.identifier.inferType(program)!!
targetIdent!=null -> {
val targetName = asmIdentifierName(targetIdent)
val targetDt = targetIdent.inferType(program)!!
when(targetDt) {
DataType.UBYTE, DataType.BYTE -> {
out(" inx | lda $ESTACK_LO_HEX,x | sta $targetName")
@ -1222,7 +1223,7 @@ internal class AsmGen2(val program: Program,
}
}
target.memoryAddress!=null -> {
val address = target.memoryAddress!!.addressExpression
val address = target.memoryAddress.addressExpression
if(address is NumericLiteralValue) {
out(" inx | lda $ESTACK_LO_HEX,x | sta ${address.number.toHex()}")
} else {
@ -1237,9 +1238,10 @@ internal class AsmGen2(val program: Program,
}
private fun assignAddressOf(target: AssignTarget, name: IdentifierReference, scopedname: String) {
val targetIdent = target.identifier
when {
target.identifier!=null -> {
val targetName = asmIdentifierName(target.identifier)
targetIdent!=null -> {
val targetName = asmIdentifierName(targetIdent)
val struct = name.memberOfStruct(program.namespace)
if(struct!=null) {
// 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) {
val sourceName = asmIdentifierName(variable)
val targetIdent = target.identifier
when {
target.identifier!=null -> {
val targetName = asmIdentifierName(target.identifier)
targetIdent!=null -> {
val targetName = asmIdentifierName(targetIdent)
out("""
lda $sourceName
ldy $sourceName+1
@ -1287,9 +1290,10 @@ internal class AsmGen2(val program: Program,
private fun assignFloatVariable(target: AssignTarget, variable: IdentifierReference) {
val sourceName = asmIdentifierName(variable)
val targetIdent = target.identifier
when {
target.identifier!=null -> {
val targetName = asmIdentifierName(target.identifier)
targetIdent!=null -> {
val targetName = asmIdentifierName(targetIdent)
out("""
lda $sourceName
sta $targetName
@ -1309,12 +1313,13 @@ internal class AsmGen2(val program: Program,
private fun assignByteVariable(target: AssignTarget, variable: IdentifierReference) {
val sourceName = asmIdentifierName(variable)
val targetIdent = target.identifier
when {
target.register!=null -> {
out(" ld${target.register.name.toLowerCase()} $sourceName")
}
target.identifier!=null -> {
val targetName = asmIdentifierName(target.identifier)
targetIdent!=null -> {
val targetName = asmIdentifierName(targetIdent)
out("""
lda $sourceName
sta $targetName
@ -1325,9 +1330,11 @@ internal class AsmGen2(val program: Program,
}
private fun assignRegister(target: AssignTarget, register: Register) {
val targetIdent = target.identifier
val targetArrayIdx = target.arrayindexed
when {
target.identifier!=null -> {
val targetName = asmIdentifierName(target.identifier)
targetIdent!=null -> {
val targetName = asmIdentifierName(targetIdent)
out(" st${register.name.toLowerCase()} $targetName")
}
target.register!=null -> {
@ -1370,8 +1377,9 @@ internal class AsmGen2(val program: Program,
}
private fun assignWordConstant(target: AssignTarget, word: Int) {
if(target.identifier!=null) {
val targetName = asmIdentifierName(target.identifier)
val targetIdent = target.identifier
if(targetIdent!=null) {
val targetName = asmIdentifierName(targetIdent)
if(word ushr 8 == word and 255) {
// lsb=msb
out("""
@ -1393,12 +1401,13 @@ internal class AsmGen2(val program: Program,
}
private fun assignByteConstant(target: AssignTarget, byte: Short) {
val targetIdent = target.identifier
when {
target.register!=null -> {
out(" ld${target.register.name.toLowerCase()} #${byte.toHex()}")
}
target.identifier!=null -> {
val targetName = asmIdentifierName(target.identifier)
targetIdent!=null -> {
val targetName = asmIdentifierName(targetIdent)
out(" lda #${byte.toHex()} | sta $targetName ")
}
else -> TODO("assign byte $byte to $target")
@ -1406,10 +1415,11 @@ internal class AsmGen2(val program: Program,
}
private fun assignFloatConstant(target: AssignTarget, float: Double) {
val targetIdent = target.identifier
if(float==0.0) {
// optimized case for float zero
if (target.identifier != null) {
val targetName = asmIdentifierName(target.identifier)
if (targetIdent != null) {
val targetName = asmIdentifierName(targetIdent)
out("""
lda #0
sta $targetName
@ -1424,8 +1434,8 @@ internal class AsmGen2(val program: Program,
} else {
// non-zero value
val constFloat = getFloatConst(float)
if (target.identifier != null) {
val targetName = asmIdentifierName(target.identifier)
if (targetIdent != null) {
val targetName = asmIdentifierName(targetIdent)
out("""
lda $constFloat
sta $targetName
@ -1445,13 +1455,14 @@ internal class AsmGen2(val program: Program,
}
private fun assignMemoryByte(target: AssignTarget, address: Int?, identifier: IdentifierReference?) {
val targetIdent = target.identifier
if(address!=null) {
when {
target.register!=null -> {
out(" ld${target.register.name.toLowerCase()} ${address.toHex()}")
}
target.identifier!=null -> {
val targetName = asmIdentifierName(target.identifier)
targetIdent!=null -> {
val targetName = asmIdentifierName(targetIdent)
out("""
lda ${address.toHex()}
sta $targetName
@ -1474,8 +1485,8 @@ internal class AsmGen2(val program: Program,
Register.Y -> out(" tay")
}
}
target.identifier!=null -> {
val targetName = asmIdentifierName(target.identifier)
targetIdent!=null -> {
val targetName = asmIdentifierName(targetIdent)
out("""
ldy #0
lda ($sourceName),y

View File

@ -472,7 +472,7 @@ class AstVm(val program: Program) {
loopvar = IdentifierReference(listOf(stmt.loopRegister.name), stmt.position)
} else {
loopvarDt = stmt.loopVar!!.inferType(program)!!
loopvar = stmt.loopVar
loopvar = stmt.loopVar!!
}
val iterator = iterable.iterator()
for (loopvalue in iterator) {
@ -545,10 +545,12 @@ class AstVm(val program: Program) {
}
fun performAssignment(target: AssignTarget, value: RuntimeValue, contextStmt: Statement, evalCtx: EvalContext) {
val targetIdent = target.identifier
val targetArrayIndexed = target.arrayindexed
when {
target.identifier != null -> {
val decl = contextStmt.definingScope().lookup(target.identifier.nameInSource, contextStmt) as? VarDecl
?: throw VmExecutionException("can't find assignment target ${target.identifier}")
targetIdent != null -> {
val decl = contextStmt.definingScope().lookup(targetIdent.nameInSource, contextStmt) as? VarDecl
?: throw VmExecutionException("can't find assignment target $targetIdent")
if (decl.type == VarDeclType.MEMORY) {
val address = runtimeVariables.getMemoryAddress(decl.definingScope(), decl.name)
when (decl.datatype) {
@ -565,14 +567,14 @@ class AstVm(val program: Program) {
runtimeVariables.set(decl.definingScope(), decl.name, value)
}
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!!)
}
target.arrayindexed != null -> {
val vardecl = target.arrayindexed.identifier.targetVarDecl(program.namespace)!!
targetArrayIndexed != null -> {
val vardecl = targetArrayIndexed.identifier.targetVarDecl(program.namespace)!!
if(vardecl.type==VarDeclType.VAR) {
val array = evaluate(target.arrayindexed.identifier, evalCtx)
val index = evaluate(target.arrayindexed.arrayspec.index, evalCtx)
val array = evaluate(targetArrayIndexed.identifier, evalCtx)
val index = evaluate(targetArrayIndexed.arrayspec.index, evalCtx)
when (array.type) {
DataType.ARRAY_UB -> {
if (value.type != DataType.UBYTE)
@ -606,7 +608,7 @@ class AstVm(val program: Program) {
val indexInt = index.integerValue()
val newchr = Petscii.decodePetscii(listOf(value.numericValue().toShort()), true)
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}")
val identScope = ident.definingScope()
program.heap.update(array.heapId!!, newstr)
@ -615,8 +617,8 @@ class AstVm(val program: Program) {
}
else {
val address = (vardecl.value as NumericLiteralValue).number.toInt()
val index = evaluate(target.arrayindexed.arrayspec.index, evalCtx).integerValue()
val elementType = target.arrayindexed.inferType(program)!!
val index = evaluate(targetArrayIndexed.arrayspec.index, evalCtx).integerValue()
val elementType = targetArrayIndexed.inferType(program)!!
when(elementType) {
DataType.UBYTE -> mem.setUByte(address+index, value.byteval!!)
DataType.BYTE -> mem.setSByte(address+index, value.byteval!!)
@ -952,4 +954,3 @@ class AstVm(val program: Program) {
}
}

View File

@ -6,18 +6,37 @@
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')
c64scr.print_ub(f1==f2)
c64.CHROUT('\n')
if true {
ubyte ub1 = 33
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")
}
}