From dc3095956aee6f0a0ec9989a731b7e4cca1f292e Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 1 Sep 2018 23:24:25 +0200 Subject: [PATCH] parent now lateinit (not-null) --- il65/src/il65/ast/AST.kt | 77 +++++++++++++------------ il65/src/il65/ast/AstChecker.kt | 7 ++- il65/src/il65/ast/ImportedAstChecker.kt | 1 - il65/src/il65/compiler/Compiler.kt | 12 ++-- il65/src/il65/stackvm/StackVm.kt | 38 +++++++++++- 5 files changed, 88 insertions(+), 47 deletions(-) diff --git a/il65/src/il65/ast/AST.kt b/il65/src/il65/ast/AST.kt index 96438b96b..3ee941638 100644 --- a/il65/src/il65/ast/AST.kt +++ b/il65/src/il65/ast/AST.kt @@ -141,8 +141,8 @@ interface IAstProcessor { interface Node { - var position: Position? // optional for the sake of easy unit testing - var parent: Node? // will be linked correctly later + var position: Position? // optional for the sake of easy unit testing + var parent: Node // will be linked correctly later (late init) fun linkParents(parent: Node) } @@ -152,7 +152,7 @@ interface IStatement : Node { fun makeScopedName(name: String): List { val scope = mutableListOf() var statementScope = this.parent - while(statementScope!=null && statementScope !is Module) { + while(statementScope !is ParentSentinel && statementScope !is Module) { if(statementScope is INameScope) { scope.add(0, statementScope.name) } @@ -198,15 +198,12 @@ interface INameScope { foundScope.subScopes()[scopedName.last()] as IStatement? } else { // unqualified name, find the scope the statement is in, look in that first - var statementScope: Node? = statement + var statementScope: Node = statement while(true) { - while (statementScope !is INameScope && statementScope?.parent != null) + while (statementScope !is INameScope && statementScope !is ParentSentinel) statementScope = statementScope.parent - if (statementScope == null) + if (statementScope is ParentSentinel) return null - if(statementScope.parent==null && statementScope !is Module) - throw AstException("non-Module node has no parent! node: $statementScope at ${statementScope.position}") - val localScope = statementScope as INameScope val result = localScope.definedNames()[scopedName[0]] if (result != null) @@ -245,7 +242,7 @@ interface INameScope { * Inserted into the Ast in place of modified nodes (not inserted directly as a parser result) * It can hold zero or more replacement statements that have to be inserted at that point. */ -data class AnonymousStatementList(override var parent: Node?, var statements: List) : IStatement { +data class AnonymousStatementList(override var parent: Node, var statements: List) : IStatement { override var position: Position? = null override fun linkParents(parent: Node) { @@ -260,17 +257,24 @@ data class AnonymousStatementList(override var parent: Node?, var statements: Li } +object ParentSentinel : Node { + override var position: Position? = null + override var parent: Node = this + override fun linkParents(parent: Node) {} +} + + data class Module(override val name: String, override var statements: MutableList) : Node, INameScope { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent=parent } fun linkParents() { - parent = null + parent = ParentSentinel statements.forEach {it.linkParents(this)} } @@ -292,6 +296,7 @@ data class Module(override val name: String, // pseudo functions always exist, return a dummy statement for them val pseudo = Label("pseudo::${scopedName.last()}") pseudo.position = statement.position + pseudo.parent = ParentSentinel return pseudo } val stmt = super.lookup(scopedName, statement) @@ -325,7 +330,7 @@ data class Block(override val name: String, val address: Int?, override var statements: MutableList) : IStatement, INameScope { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent @@ -345,7 +350,7 @@ data class Block(override val name: String, data class Directive(val directive: String, val args: List) : IStatement { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent @@ -358,7 +363,7 @@ data class Directive(val directive: String, val args: List) : ISta data class DirectiveArg(val str: String?, val name: String?, val int: Int?) : Node { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent @@ -368,7 +373,7 @@ data class DirectiveArg(val str: String?, val name: String?, val int: Int?) : No data class Label(val name: String) : IStatement { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent @@ -380,7 +385,7 @@ data class Label(val name: String) : IStatement { data class Return(var values: List) : IStatement { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent @@ -396,7 +401,7 @@ data class Return(var values: List) : IStatement { data class ArraySpec(var x: IExpression, var y: IExpression?) : Node { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent @@ -423,7 +428,7 @@ data class VarDecl(val type: VarDeclType, val name: String, var value: IExpression?) : IStatement { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent @@ -447,7 +452,7 @@ data class VarDecl(val type: VarDeclType, data class Assignment(var target: AssignTarget, val aug_op : String?, var value: IExpression) : IStatement { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent @@ -464,7 +469,7 @@ data class Assignment(var target: AssignTarget, val aug_op : String?, var value: data class AssignTarget(val register: Register?, val identifier: IdentifierReference?) : Node { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent @@ -486,7 +491,7 @@ interface IExpression: Node { data class PrefixExpression(val operator: String, var expression: IExpression) : IExpression { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent @@ -501,7 +506,7 @@ data class PrefixExpression(val operator: String, var expression: IExpression) : data class BinaryExpression(var left: IExpression, val operator: String, var right: IExpression) : IExpression { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent @@ -522,7 +527,7 @@ data class LiteralValue(val intvalue: Int? = null, val strvalue: String? = null, val arrayvalue: List? = null) : IExpression { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun referencesIdentifier(name: String) = arrayvalue?.any { it.referencesIdentifier(name) } ?: false fun asInt(errorIfNotNumeric: Boolean=true): Int? { @@ -567,7 +572,7 @@ data class LiteralValue(val intvalue: Int? = null, data class RangeExpr(var from: IExpression, var to: IExpression) : IExpression { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent @@ -583,7 +588,7 @@ data class RangeExpr(var from: IExpression, var to: IExpression) : IExpression { data class RegisterExpr(val register: Register) : IExpression { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent @@ -597,7 +602,7 @@ data class RegisterExpr(val register: Register) : IExpression { data class IdentifierReference(val nameInSource: List) : IExpression { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent @@ -623,7 +628,7 @@ data class IdentifierReference(val nameInSource: List) : IExpression { data class PostIncrDecr(var target: AssignTarget, val operator: String) : IStatement { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent @@ -639,7 +644,7 @@ data class PostIncrDecr(var target: AssignTarget, val operator: String) : IState data class Jump(val address: Int?, val identifier: IdentifierReference?) : IStatement { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent @@ -652,7 +657,7 @@ data class Jump(val address: Int?, val identifier: IdentifierReference?) : IStat data class FunctionCall(override var target: IdentifierReference, override var arglist: List) : IExpression, IFunctionCall { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent @@ -690,7 +695,7 @@ data class FunctionCall(override var target: IdentifierReference, override var a data class FunctionCallStatement(override var target: IdentifierReference, override var arglist: List) : IStatement, IFunctionCall { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent @@ -704,7 +709,7 @@ data class FunctionCallStatement(override var target: IdentifierReference, overr data class InlineAssembly(val assembly: String) : IStatement { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent @@ -720,7 +725,7 @@ data class Subroutine(override val name: String, val address: Int?, override var statements: MutableList) : IStatement, INameScope { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent @@ -742,7 +747,7 @@ data class Subroutine(override val name: String, data class SubroutineParameter(val name: String, val register: Register) : Node { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent @@ -752,7 +757,7 @@ data class SubroutineParameter(val name: String, val register: Register) : Node data class SubroutineReturnvalue(val register: Register, val clobbered: Boolean) : Node { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent @@ -764,7 +769,7 @@ data class IfStatement(var condition: IExpression, var statements: List, var elsepart: List) : IStatement { override var position: Position? = null - override var parent: Node? = null + override lateinit var parent: Node override fun linkParents(parent: Node) { this.parent = parent diff --git a/il65/src/il65/ast/AstChecker.kt b/il65/src/il65/ast/AstChecker.kt index d0cc32689..8d110337f 100644 --- a/il65/src/il65/ast/AstChecker.kt +++ b/il65/src/il65/ast/AstChecker.kt @@ -294,9 +294,10 @@ class AstChecker(private val globalNamespace: INameScope) : IAstProcessor { override fun process(functionCall: FunctionCall): IExpression { // this function call is (part of) an expression, which should be in a statement somewhere. - var statementNode: Node? = functionCall - while(statementNode !is IStatement && statementNode?.parent != null) statementNode = statementNode.parent - if(statementNode==null) + var statementNode: Node = functionCall + while(statementNode !is IStatement && statementNode !is ParentSentinel) + statementNode = statementNode.parent + if(statementNode is ParentSentinel) throw FatalAstException("cannot determine statement scope of function call expression at ${functionCall.position}") checkFunctionExists(functionCall.target, statementNode as IStatement) diff --git a/il65/src/il65/ast/ImportedAstChecker.kt b/il65/src/il65/ast/ImportedAstChecker.kt index 8fe5b1056..57c2b4809 100644 --- a/il65/src/il65/ast/ImportedAstChecker.kt +++ b/il65/src/il65/ast/ImportedAstChecker.kt @@ -37,7 +37,6 @@ class ImportedAstChecker : IAstProcessor { val moduleLevelDirectives = listOf("%output", "%launcher", "%zeropage", "%address") for (sourceStmt in module.statements) { val stmt = sourceStmt.process(this) - if(stmt.parent == null) throw AstException("should have linked parents") if(stmt is Directive && stmt.parent is Module) { if(moduleLevelDirectives.contains(stmt.directive)) { println("${stmt.position} Warning: ignoring module directive because it was imported: ${stmt.directive}") diff --git a/il65/src/il65/compiler/Compiler.kt b/il65/src/il65/compiler/Compiler.kt index 749ed8fb4..0fd18f56c 100644 --- a/il65/src/il65/compiler/Compiler.kt +++ b/il65/src/il65/compiler/Compiler.kt @@ -64,13 +64,13 @@ data class Mflpt5(val b0: Short, val b1: Short, val b2: Short, val b3: Short, va exponent>255 -> throw CompilerException("floating point overflow: $this") exponent==0 -> zero else -> { - val mant_long = mantissa.toLong() + val mantLong = mantissa.toLong() Mflpt5( exponent.toShort(), - (mant_long.and(0x7f000000L) ushr 24).or(sign).toShort(), - (mant_long.and(0x00ff0000L) ushr 16).toShort(), - (mant_long.and(0x0000ff00L) ushr 8).toShort(), - (mant_long.and(0x000000ffL)).toShort()) + (mantLong.and(0x7f000000L) ushr 24).or(sign).toShort(), + (mantLong.and(0x00ff0000L) ushr 16).toShort(), + (mantLong.and(0x0000ff00L) ushr 8).toShort(), + (mantLong.and(0x000000ffL)).toShort()) } } } @@ -87,7 +87,7 @@ data class Mflpt5(val b0: Short, val b1: Short, val b2: Short, val b3: Short, va } -class Compiler(val options: CompilationOptions, val namespace: INameScope) { +class Compiler(private val options: CompilationOptions, val namespace: INameScope) { init { val zeropage = Zeropage(options) } diff --git a/il65/src/il65/stackvm/StackVm.kt b/il65/src/il65/stackvm/StackVm.kt index d502505f4..500f64fef 100644 --- a/il65/src/il65/stackvm/StackVm.kt +++ b/il65/src/il65/stackvm/StackVm.kt @@ -1,5 +1,7 @@ package il65.stackvm +import kotlin.experimental.and + enum class Opcode { // pushing values on the (evaluation) stack @@ -97,8 +99,42 @@ enum class Opcode { } private class Memory { - val mem = ByteArray(65536) + private val mem = ShortArray(65536) // shorts because byte is signed and we store values 0..255 + fun getByte(address: Int): Short { + return mem[address] + } + fun setByte(address: Int, value: Short) { + mem[address] = value + } + + fun getWord(address: Int): Int { + return 256*mem[address] + mem[address+1] + } + + fun setWord(address: Int, value: Short) { + mem[address] = (value / 256).toShort() + mem[address+1] = value.and(255) + } + + fun getCopy() = mem.copyOf() +} + + +data class Instruction(val opcode: Opcode, val args: List) { + lateinit var next: Instruction + lateinit var nextAlt: Instruction +} + + +class StackVm { + private val mem = Memory() + + fun memDump() = mem.getCopy() + + init { + val x=Instruction(Opcode.ADD, emptyList()) + } }