add "-rpn" command line switch to transform exprs to RPN in codegen

This commit is contained in:
Irmen de Jong 2023-03-16 19:36:16 +01:00
parent 8ffca93cd5
commit 9241479da4
16 changed files with 166 additions and 105 deletions

View File

@ -53,7 +53,8 @@ sealed class PtNamedNode(var name: String, position: Position): PtNode(position)
class PtProgram( class PtProgram(
val name: String, val name: String,
val memsizer: IMemSizer, val memsizer: IMemSizer,
val encoding: IStringEncoding val encoding: IStringEncoding,
var binaryExpressionsAreRPN: Boolean = false
) : PtNode(Position.DUMMY) { ) : PtNode(Position.DUMMY) {
// fun allModuleDirectives(): Sequence<PtDirective> = // fun allModuleDirectives(): Sequence<PtDirective> =
@ -68,7 +69,8 @@ class PtProgram(
// If the code generator wants, it can transform binary expression nodes into flat RPN nodes. // If the code generator wants, it can transform binary expression nodes into flat RPN nodes.
// This will destroy the original binaryexpression nodes! // This will destroy the original binaryexpression nodes!
fun transformBinExprToRPN() { fun transformBinExprToRPN() {
if(binaryExpressionsAreRPN)
return
fun transformToRPN(originalExpr: PtBinaryExpression): PtRpn { fun transformToRPN(originalExpr: PtBinaryExpression): PtRpn {
fun makeRpn(expr: PtExpression): PtRpn { fun makeRpn(expr: PtExpression): PtRpn {
val rpn = PtRpn(expr.type, expr.position) val rpn = PtRpn(expr.type, expr.position)
@ -97,6 +99,7 @@ class PtProgram(
} }
children.forEach { transformBinExprToRPN(it, this) } children.forEach { transformBinExprToRPN(it, this) }
binaryExpressionsAreRPN = true
} }
} }

View File

@ -170,12 +170,12 @@ class PtRpn(type: DataType, position: Position): PtExpression(type, position) {
require(node is PtRpnOperator || node is PtExpression) require(node is PtRpnOperator || node is PtExpression)
if(node is PtRpn) { if(node is PtRpn) {
node.children.forEach { node.children.forEach {
children += it children.add(it)
it.parent = this it.parent = this
} }
} }
else { else {
children += node children.add(node)
node.parent = this node.parent = this
} }
} }
@ -264,19 +264,24 @@ class PtRpn(type: DataType, position: Position): PtExpression(type, position) {
} }
return Pair(maxDepths, numPushes) return Pair(maxDepths, numPushes)
} }
fun finalOperator(): String? = (children.last() as? PtRpnOperator)?.operator
fun finalFirstOperand() = children[children.size-3]
fun finalSecondOperand() = children[children.size-2]
} }
class PtRpnOperator(val operator: String, val type: DataType, val operand1Type: DataType, val operand2Type: DataType, position: Position): PtNode(position) { class PtRpnOperator(val operator: String, val type: DataType, val operand1Type: DataType, val operand2Type: DataType, position: Position): PtNode(position) {
// init { init {
// require(operand1Type equalsSize operand2Type) { // NOTE: For now, we require that the types of the operands are the same size as the output type of the operator node.
// "operator $operator : operand1 and 2 types aren't equal sizes: $operand1Type $operand2Type" require(operand1Type equalsSize operand2Type) {
// } "operand type size(s) differ: $operand1Type $operand2Type oper: $operator"
// if(operator !in ComparisonOperators) { }
// require(type equalsSize operand1Type && type equalsSize operand2Type) { if(operator !in ComparisonOperators) {
// "operator $operator : type $type size not equal to operand1 and 2 types: $operand1Type $operand2Type" require(type equalsSize operand1Type && type equalsSize operand2Type) {
// } "operand type size(s) differ from operator result type $type: $operand1Type $operand2Type oper: $operator"
// } }
// } }
}
} }

View File

@ -101,7 +101,7 @@ class PtForLoop(position: Position) : PtNode(position) {
class PtIfElse(position: Position) : PtNode(position) { class PtIfElse(position: Position) : PtNode(position) {
val condition: PtNode val condition: PtNode
get() = children[0] as PtNode get() = children[0]
val ifScope: PtNodeGroup val ifScope: PtNodeGroup
get() = children[1] as PtNodeGroup get() = children[1] as PtNodeGroup
val elseScope: PtNodeGroup val elseScope: PtNodeGroup

View File

@ -20,6 +20,7 @@ class CompilationOptions(val output: OutputType,
var asmListfile: Boolean = false, var asmListfile: Boolean = false,
var experimentalCodegen: Boolean = false, var experimentalCodegen: Boolean = false,
var varsHigh: Boolean = false, var varsHigh: Boolean = false,
var useRPN: Boolean = false,
var evalStackBaseAddress: UInt? = null, var evalStackBaseAddress: UInt? = null,
var outputDir: Path = Path(""), var outputDir: Path = Path(""),
var symbolDefs: Map<String, String> = emptyMap() var symbolDefs: Map<String, String> = emptyMap()

View File

@ -21,8 +21,8 @@ class AsmGen6502: ICodeGeneratorBackend {
options: CompilationOptions, options: CompilationOptions,
errors: IErrorReporter errors: IErrorReporter
): IAssemblyProgram? { ): IAssemblyProgram? {
// If we want RPN expressions instead, use this: if(options.useRPN)
// TODO program.transformBinExprToRPN() program.transformBinExprToRPN()
val asmgen = AsmGen6502Internal(program, symbolTable, options, errors) val asmgen = AsmGen6502Internal(program, symbolTable, options, errors)
return asmgen.compileToAssembly() return asmgen.compileToAssembly()
@ -547,35 +547,38 @@ class AsmGen6502Internal (
} }
private fun translate(stmt: PtIfElse) { private fun translate(stmt: PtIfElse) {
val condition = stmt.condition as PtBinaryExpression if(stmt.condition is PtRpn) {
requireComparisonExpression(condition) // IfStatement: condition must be of form 'x <comparison> <value>' TODO("RPN")
} else {
val condition = stmt.condition as PtBinaryExpression
requireComparisonExpression(condition) // IfStatement: condition must be of form 'x <comparison> <value>'
if (stmt.elseScope.children.isEmpty()) { if (stmt.elseScope.children.isEmpty()) {
val jump = stmt.ifScope.children.singleOrNull() val jump = stmt.ifScope.children.singleOrNull()
if(jump is PtJump) { if (jump is PtJump) {
translateCompareAndJumpIfTrue(condition, jump) translateCompareAndJumpIfTrue(condition, jump)
} else {
val endLabel = makeLabel("if_end")
translateCompareAndJumpIfFalse(condition, endLabel)
translate(stmt.ifScope)
out(endLabel)
}
} else { } else {
// both true and else parts
val elseLabel = makeLabel("if_else")
val endLabel = makeLabel("if_end") val endLabel = makeLabel("if_end")
translateCompareAndJumpIfFalse(condition, endLabel) translateCompareAndJumpIfFalse(condition, elseLabel)
translate(stmt.ifScope) translate(stmt.ifScope)
jmp(endLabel)
out(elseLabel)
translate(stmt.elseScope)
out(endLabel) out(endLabel)
} }
} }
else {
// both true and else parts
val elseLabel = makeLabel("if_else")
val endLabel = makeLabel("if_end")
translateCompareAndJumpIfFalse(condition, elseLabel)
translate(stmt.ifScope)
jmp(endLabel)
out(elseLabel)
translate(stmt.elseScope)
out(endLabel)
}
} }
private fun requireComparisonExpression(condition: PtExpression) { private fun requireComparisonExpression(condition: PtExpression) {
if(condition !is PtBinaryExpression || condition.operator !in ComparisonOperators) if (!(condition is PtRpn && condition.finalOperator() in ComparisonOperators) && !(condition is PtBinaryExpression && condition.operator in ComparisonOperators))
throw AssemblyError("expected boolean comparison expression $condition") throw AssemblyError("expected boolean comparison expression $condition")
} }
@ -980,7 +983,11 @@ $repeatLabel lda $counterVar
} }
internal fun pointerViaIndexRegisterPossible(pointerOffsetExpr: PtExpression): Pair<PtExpression, PtExpression>? { internal fun pointerViaIndexRegisterPossible(pointerOffsetExpr: PtExpression): Pair<PtExpression, PtExpression>? {
if(pointerOffsetExpr is PtBinaryExpression && pointerOffsetExpr.operator=="+") { if (pointerOffsetExpr is PtRpn) {
TODO("RPN")
}
else if (pointerOffsetExpr is PtBinaryExpression) {
if (pointerOffsetExpr.operator != "+") return null
val leftDt = pointerOffsetExpr.left.type val leftDt = pointerOffsetExpr.left.type
val rightDt = pointerOffsetExpr.left.type val rightDt = pointerOffsetExpr.left.type
if(leftDt == DataType.UWORD && rightDt == DataType.UBYTE) if(leftDt == DataType.UWORD && rightDt == DataType.UBYTE)
@ -1001,7 +1008,6 @@ $repeatLabel lda $counterVar
if(leftTc!=null && leftTc.value.type == DataType.UBYTE) if(leftTc!=null && leftTc.value.type == DataType.UBYTE)
return Pair(pointerOffsetExpr.right, leftTc.value) return Pair(pointerOffsetExpr.right, leftTc.value)
} }
} }
return null return null
} }
@ -1022,7 +1028,6 @@ $repeatLabel lda $counterVar
} }
} }
if(expr.operator=="+") { if(expr.operator=="+") {
val ptrAndIndex = pointerViaIndexRegisterPossible(expr) val ptrAndIndex = pointerViaIndexRegisterPossible(expr)
if(ptrAndIndex!=null) { if(ptrAndIndex!=null) {

View File

@ -17,8 +17,8 @@ class ExperiCodeGen: ICodeGeneratorBackend {
errors: IErrorReporter errors: IErrorReporter
): IAssemblyProgram? { ): IAssemblyProgram? {
// If we want RPN expressions instead, use this: if(options.useRPN)
// program.transformBinExprToRPN() program.transformBinExprToRPN()
// you could write a code generator directly on the PtProgram AST, // you could write a code generator directly on the PtProgram AST,
// but you can also use the Intermediate Representation to build a codegen on: // but you can also use the Intermediate Representation to build a codegen on:

View File

@ -92,10 +92,14 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
value.add(origAssign.value) value.add(origAssign.value)
} else { } else {
require(origAssign.operator.endsWith('=')) require(origAssign.operator.endsWith('='))
value = PtBinaryExpression(origAssign.operator.dropLast(1), origAssign.value.type, origAssign.value.position) if(codeGen.program.binaryExpressionsAreRPN) {
val left: PtExpression = origAssign.target.children.single() as PtExpression TODO("RPN")
value.add(left) } else {
value.add(origAssign.value) value = PtBinaryExpression(origAssign.operator.dropLast(1), origAssign.value.type, origAssign.value.position)
val left: PtExpression = origAssign.target.children.single() as PtExpression
value.add(left)
value.add(origAssign.value)
}
} }
normalAssign.add(value) normalAssign.add(value)
return translateRegularAssign(normalAssign) return translateRegularAssign(normalAssign)
@ -262,10 +266,14 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
val tr = if(itemsize==1) { val tr = if(itemsize==1) {
expressionEval.translateExpression(array.index) expressionEval.translateExpression(array.index)
} else { } else {
val mult = PtBinaryExpression("*", DataType.UBYTE, array.position) if(codeGen.program.binaryExpressionsAreRPN) {
mult.children += array.index TODO("RPN")
mult.children += PtNumber(DataType.UBYTE, itemsize.toDouble(), array.position) } else {
expressionEval.translateExpression(mult) val mult = PtBinaryExpression("*", DataType.UBYTE, array.position)
mult.children += array.index
mult.children += PtNumber(DataType.UBYTE, itemsize.toDouble(), array.position)
expressionEval.translateExpression(mult)
}
} }
addToResult(result, tr, tr.resultReg, -1) addToResult(result, tr, tr.resultReg, -1)
return Pair(result, tr.resultReg) return Pair(result, tr.resultReg)

View File

@ -898,57 +898,67 @@ class IRCodeGen(
private fun translate(ifElse: PtIfElse): IRCodeChunks { private fun translate(ifElse: PtIfElse): IRCodeChunks {
val condition = ifElse.condition val condition = ifElse.condition
if(condition is PtBinaryExpression) { when (condition) {
if(condition.operator !in ComparisonOperators) is PtBinaryExpression -> {
throw AssemblyError("if condition should only be a binary comparison expression") if(condition.operator !in ComparisonOperators)
throw AssemblyError("if condition should only be a binary comparison expression")
val signed = condition.left.type in SignedDatatypes val signed = condition.left.type in SignedDatatypes
val irDtLeft = irType(condition.left.type) val irDtLeft = irType(condition.left.type)
val goto = ifElse.ifScope.children.firstOrNull() as? PtJump val goto = ifElse.ifScope.children.firstOrNull() as? PtJump
return when { return when {
goto!=null && ifElse.elseScope.children.isEmpty() -> translateIfFollowedByJustGoto(ifElse, goto, irDtLeft, signed) goto!=null && ifElse.elseScope.children.isEmpty() -> translateIfFollowedByJustGoto(ifElse, goto, irDtLeft, signed)
constValue(condition.right) == 0.0 -> translateIfElseZeroComparison(ifElse, irDtLeft, signed) constValue(condition.right) == 0.0 -> translateIfElseZeroComparison(ifElse, irDtLeft, signed)
else -> translateIfElseNonZeroComparison(ifElse, irDtLeft, signed) else -> translateIfElseNonZeroComparison(ifElse, irDtLeft, signed)
}
}
is PtRpn -> {
TODO("RPN")
}
else -> {
TODO("weird condition node: $condition")
} }
} else {
TODO("weird condition node: $condition")
} }
} }
private fun translateIfFollowedByJustGoto(ifElse: PtIfElse, goto: PtJump, irDtLeft: IRDataType, signed: Boolean): MutableList<IRCodeChunkBase> { private fun translateIfFollowedByJustGoto(ifElse: PtIfElse, goto: PtJump, irDtLeft: IRDataType, signed: Boolean): MutableList<IRCodeChunkBase> {
val result = mutableListOf<IRCodeChunkBase>() if(program.binaryExpressionsAreRPN) {
val condition = ifElse.condition as PtBinaryExpression TODO ("RPN")
if(irDtLeft==IRDataType.FLOAT) {
val leftTr = expressionEval.translateExpression(condition.left)
addToResult(result, leftTr, -1, leftTr.resultFpReg)
val rightTr = expressionEval.translateExpression(condition.right)
addToResult(result, rightTr, -1, rightTr.resultFpReg)
result += IRCodeChunk(null,null).also {
val compResultReg = registers.nextFree()
it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=compResultReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg)
val gotoOpcode = when (condition.operator) {
"==" -> Opcode.BZ
"!=" -> Opcode.BNZ
"<" -> Opcode.BLEZS
">" -> Opcode.BGEZS
"<=" -> Opcode.BLZS
">=" -> Opcode.BGZS
else -> throw AssemblyError("weird operator")
}
it += if (goto.address != null)
IRInstruction(gotoOpcode, IRDataType.BYTE, reg1 = compResultReg, value = goto.address?.toInt())
else if (goto.generatedLabel != null)
IRInstruction(gotoOpcode, IRDataType.BYTE, reg1 = compResultReg, labelSymbol = goto.generatedLabel)
else
IRInstruction(gotoOpcode, IRDataType.BYTE, reg1 = compResultReg, labelSymbol = goto.identifier!!.name)
}
return result
} else { } else {
val rightConst = condition.right.asConstInteger() val result = mutableListOf<IRCodeChunkBase>()
return if(rightConst==0) val condition = ifElse.condition as PtBinaryExpression
ifZeroIntThenJump(result, ifElse, signed, irDtLeft, goto) if(irDtLeft==IRDataType.FLOAT) {
else { val leftTr = expressionEval.translateExpression(condition.left)
ifNonZeroIntThenJump(result, ifElse, signed, irDtLeft, goto) addToResult(result, leftTr, -1, leftTr.resultFpReg)
val rightTr = expressionEval.translateExpression(condition.right)
addToResult(result, rightTr, -1, rightTr.resultFpReg)
result += IRCodeChunk(null,null).also {
val compResultReg = registers.nextFree()
it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=compResultReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg)
val gotoOpcode = when (condition.operator) {
"==" -> Opcode.BZ
"!=" -> Opcode.BNZ
"<" -> Opcode.BLEZS
">" -> Opcode.BGEZS
"<=" -> Opcode.BLZS
">=" -> Opcode.BGZS
else -> throw AssemblyError("weird operator")
}
it += if (goto.address != null)
IRInstruction(gotoOpcode, IRDataType.BYTE, reg1 = compResultReg, value = goto.address?.toInt())
else if (goto.generatedLabel != null)
IRInstruction(gotoOpcode, IRDataType.BYTE, reg1 = compResultReg, labelSymbol = goto.generatedLabel)
else
IRInstruction(gotoOpcode, IRDataType.BYTE, reg1 = compResultReg, labelSymbol = goto.identifier!!.name)
}
return result
} else {
val rightConst = condition.right.asConstInteger()
return if(rightConst==0)
ifZeroIntThenJump(result, ifElse, signed, irDtLeft, goto)
else {
ifNonZeroIntThenJump(result, ifElse, signed, irDtLeft, goto)
}
} }
} }
} }
@ -960,6 +970,7 @@ class IRCodeGen(
irDtLeft: IRDataType, irDtLeft: IRDataType,
goto: PtJump goto: PtJump
): MutableList<IRCodeChunkBase> { ): MutableList<IRCodeChunkBase> {
require(!program.binaryExpressionsAreRPN)
val condition = ifElse.condition as PtBinaryExpression val condition = ifElse.condition as PtBinaryExpression
val leftTr = expressionEval.translateExpression(condition.left) val leftTr = expressionEval.translateExpression(condition.left)
addToResult(result, leftTr, leftTr.resultReg, -1) addToResult(result, leftTr, leftTr.resultReg, -1)
@ -988,6 +999,7 @@ class IRCodeGen(
irDtLeft: IRDataType, irDtLeft: IRDataType,
goto: PtJump goto: PtJump
): MutableList<IRCodeChunkBase> { ): MutableList<IRCodeChunkBase> {
require(!program.binaryExpressionsAreRPN)
val condition = ifElse.condition as PtBinaryExpression val condition = ifElse.condition as PtBinaryExpression
val leftTr = expressionEval.translateExpression(condition.left) val leftTr = expressionEval.translateExpression(condition.left)
addToResult(result, leftTr, leftTr.resultReg, -1) addToResult(result, leftTr, leftTr.resultReg, -1)
@ -1041,6 +1053,7 @@ class IRCodeGen(
} }
private fun translateIfElseZeroComparison(ifElse: PtIfElse, irDtLeft: IRDataType, signed: Boolean): IRCodeChunks { private fun translateIfElseZeroComparison(ifElse: PtIfElse, irDtLeft: IRDataType, signed: Boolean): IRCodeChunks {
require(!program.binaryExpressionsAreRPN)
val result = mutableListOf<IRCodeChunkBase>() val result = mutableListOf<IRCodeChunkBase>()
val elseBranch: Opcode val elseBranch: Opcode
val compResultReg: Int val compResultReg: Int
@ -1102,8 +1115,8 @@ class IRCodeGen(
} }
private fun translateIfElseNonZeroComparison(ifElse: PtIfElse, irDtLeft: IRDataType, signed: Boolean): IRCodeChunks { private fun translateIfElseNonZeroComparison(ifElse: PtIfElse, irDtLeft: IRDataType, signed: Boolean): IRCodeChunks {
require(!program.binaryExpressionsAreRPN)
val result = mutableListOf<IRCodeChunkBase>() val result = mutableListOf<IRCodeChunkBase>()
val elseBranchOpcode: Opcode val elseBranchOpcode: Opcode
val elseBranchFirstReg: Int val elseBranchFirstReg: Int
val elseBranchSecondReg: Int val elseBranchSecondReg: Int

View File

@ -17,8 +17,10 @@ class VmCodeGen: ICodeGeneratorBackend {
options: CompilationOptions, options: CompilationOptions,
errors: IErrorReporter errors: IErrorReporter
): IAssemblyProgram? { ): IAssemblyProgram? {
// If we want RPN expressions instead, use this:
// program.transformBinExprToRPN() if(options.useRPN)
program.transformBinExprToRPN()
val irCodeGen = IRCodeGen(program, symbolTable, options, errors) val irCodeGen = IRCodeGen(program, symbolTable, options, errors)
val irProgram = irCodeGen.generate() val irProgram = irCodeGen.generate()
return VmAssemblyProgram(irProgram.name, irProgram) return VmAssemblyProgram(irProgram.name, irProgram)

View File

@ -52,6 +52,7 @@ private fun compileMain(args: Array<String>): Boolean {
val startVm by cli.option(ArgType.Boolean, fullName = "vm", description = "load and run a .p8ir IR source file in the VM") val startVm by cli.option(ArgType.Boolean, fullName = "vm", description = "load and run a .p8ir IR source file in the VM")
val watchMode by cli.option(ArgType.Boolean, fullName = "watch", description = "continuous compilation mode (watch for file changes)") val watchMode by cli.option(ArgType.Boolean, fullName = "watch", description = "continuous compilation mode (watch for file changes)")
val varsHigh by cli.option(ArgType.Boolean, fullName = "varshigh", description = "put uninitialized variables in high memory area instead of at the end of the program") val varsHigh by cli.option(ArgType.Boolean, fullName = "varshigh", description = "put uninitialized variables in high memory area instead of at the end of the program")
val useRPN by cli.option(ArgType.Boolean, fullName = "rpn", description = "use RPN for expression code-generation (experimental)")
val moduleFiles by cli.argument(ArgType.String, fullName = "modules", description = "main module file(s) to compile").multiple(999) val moduleFiles by cli.argument(ArgType.String, fullName = "modules", description = "main module file(s) to compile").multiple(999)
try { try {
@ -126,6 +127,7 @@ private fun compileMain(args: Array<String>): Boolean {
asmListfile == true, asmListfile == true,
experimentalCodegen == true, experimentalCodegen == true,
varsHigh == true, varsHigh == true,
useRPN == true,
compilationTarget, compilationTarget,
evalStackAddr, evalStackAddr,
processedSymbols, processedSymbols,
@ -190,6 +192,7 @@ private fun compileMain(args: Array<String>): Boolean {
asmListfile == true, asmListfile == true,
experimentalCodegen == true, experimentalCodegen == true,
varsHigh == true, varsHigh == true,
useRPN == true,
compilationTarget, compilationTarget,
evalStackAddr, evalStackAddr,
processedSymbols, processedSymbols,

View File

@ -36,6 +36,7 @@ class CompilerArguments(val filepath: Path,
val asmListfile: Boolean, val asmListfile: Boolean,
val experimentalCodegen: Boolean, val experimentalCodegen: Boolean,
val varsHigh: Boolean, val varsHigh: Boolean,
val useRPN: Boolean,
val compilationTarget: String, val compilationTarget: String,
val evalStackBaseAddress: UInt?, val evalStackBaseAddress: UInt?,
val symbolDefs: Map<String, String>, val symbolDefs: Map<String, String>,
@ -76,6 +77,7 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
asmListfile = args.asmListfile asmListfile = args.asmListfile
experimentalCodegen = args.experimentalCodegen experimentalCodegen = args.experimentalCodegen
varsHigh = args.varsHigh varsHigh = args.varsHigh
useRPN = args.useRPN
evalStackBaseAddress = args.evalStackBaseAddress evalStackBaseAddress = args.evalStackBaseAddress
outputDir = args.outputDir.normalize() outputDir = args.outputDir.normalize()
symbolDefs = args.symbolDefs symbolDefs = args.symbolDefs

View File

@ -33,6 +33,7 @@ private fun compileTheThing(filepath: Path, optimize: Boolean, target: ICompilat
asmListfile = false, asmListfile = false,
experimentalCodegen = false, experimentalCodegen = false,
varsHigh = false, varsHigh = false,
useRPN = false,
compilationTarget = target.name, compilationTarget = target.name,
evalStackBaseAddress = null, evalStackBaseAddress = null,
symbolDefs = emptyMap(), symbolDefs = emptyMap(),

View File

@ -50,6 +50,7 @@ class TestCompilerOptionSourcedirs: FunSpec({
asmListfile = false, asmListfile = false,
experimentalCodegen = false, experimentalCodegen = false,
varsHigh = false, varsHigh = false,
useRPN = false,
compilationTarget = Cx16Target.NAME, compilationTarget = Cx16Target.NAME,
evalStackBaseAddress = null, evalStackBaseAddress = null,
symbolDefs = emptyMap(), symbolDefs = emptyMap(),

View File

@ -31,6 +31,7 @@ internal fun compileFile(
asmListfile = false, asmListfile = false,
experimentalCodegen = false, experimentalCodegen = false,
varsHigh = false, varsHigh = false,
useRPN = false,
platform.name, platform.name,
evalStackBaseAddress = null, evalStackBaseAddress = null,
symbolDefs = emptyMap(), symbolDefs = emptyMap(),

View File

@ -1,11 +1,26 @@
main { %import textio
uword[10] answers_animals %import test_stack
%zeropage basicsafe
%option no_sysinit
sub start() { main {
ubyte current_question = 1
uword previous_animals = 33 sub start() {
current_question = msb(answers_animals[current_question]) ; TODO takes 1 more vm registers than 8.10 test_stack.test()
answers_animals[current_question] = mkword(msb(previous_animals), 0) ; TODO takes 1 more vm registers than 8.10 uword xx=32
; TODO expected result: 7 registers in 8.10, now takes 9 instead cx16.r0L = 3
if cx16.r0L in "derp" {
xx++
} }
xx = xx+(3*func(xx)+xx*2*cx16.r0L)
txt.print_uw(xx)
test_stack.test()
}
sub func(uword value) -> uword {
value ++
return value
}
} }

View File

@ -42,7 +42,8 @@ class RequestParser : Take {
quietAssembler = false, quietAssembler = false,
asmListfile = false, asmListfile = false,
experimentalCodegen = false, experimentalCodegen = false,
varsHigh = false varsHigh = false,
useRPN = false
) )
val compilationResult = compileProgram(args) val compilationResult = compileProgram(args)
return RsJson(Jsonding()) return RsJson(Jsonding())