From b7d8f026f4ebefb714939e26a5eeba42d9360505 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 13 Oct 2018 18:15:09 +0200 Subject: [PATCH] refactor --- compiler/src/prog8/CompilerMain.kt | 11 +- compiler/src/prog8/compiler/Compiler.kt | 7 +- .../compiler/intermediate/Instruction.kt | 39 ++ .../{ => intermediate}/IntermediateProgram.kt | 5 +- .../src/prog8/compiler/intermediate/Opcode.kt | 241 +++++++++++++ .../intermediate}/Value.kt | 7 +- .../src/prog8/compiler/target/c64/AsmGen.kt | 15 + .../compiler/target/c64/AssemblyProgram.kt | 57 +++ .../src/prog8/compiler/target/c64/Charset.kt | 37 -- .../prog8/compiler/target/c64/Commodore64.kt | 90 ++--- compiler/src/prog8/stackvm/Program.kt | 1 + compiler/src/prog8/stackvm/StackVm.kt | 338 ++---------------- compiler/test/StackVMOpcodeTests.kt | 23 +- compiler/test/UnitTests.kt | 2 +- compiler/test/ValueOperationsTests.kt | 2 +- 15 files changed, 450 insertions(+), 425 deletions(-) create mode 100644 compiler/src/prog8/compiler/intermediate/Instruction.kt rename compiler/src/prog8/compiler/{ => intermediate}/IntermediateProgram.kt (99%) create mode 100644 compiler/src/prog8/compiler/intermediate/Opcode.kt rename compiler/src/prog8/{stackvm => compiler/intermediate}/Value.kt (99%) create mode 100644 compiler/src/prog8/compiler/target/c64/AsmGen.kt create mode 100644 compiler/src/prog8/compiler/target/c64/AssemblyProgram.kt delete mode 100644 compiler/src/prog8/compiler/target/c64/Charset.kt diff --git a/compiler/src/prog8/CompilerMain.kt b/compiler/src/prog8/CompilerMain.kt index 8be3754c1..da5744083 100644 --- a/compiler/src/prog8/CompilerMain.kt +++ b/compiler/src/prog8/CompilerMain.kt @@ -2,6 +2,7 @@ package prog8 import prog8.ast.* import prog8.compiler.* +import prog8.compiler.target.c64.AsmGen import prog8.optimizing.constantFold import prog8.optimizing.optimizeStatements import prog8.optimizing.simplifyExpressions @@ -103,15 +104,13 @@ fun main(args: Array) { stackvmFile.close() println("StackVM program code written to '$stackVmFilename'") -// val assembly = stackvmProg.compileToAssembly() -// -// assembly.assemble(compilerOptions, "input", "output") -// val monitorfile = assembly.generateBreakpointList() + val assembly = AsmGen(compilerOptions).compileToAssembly(intermediate) + assembly.assemble(compilerOptions) val endTime = System.currentTimeMillis() - println("\nTotal compilation time: ${(endTime-startTime)/1000.0} sec.") + println("\nTotal compilation+assemble time: ${(endTime-startTime)/1000.0} sec.") -// // start the vice emulator +// // todo start the vice emulator // val program = "foo" // val cmdline = listOf("x64", "-moncommands", monitorfile, // "-autostartprgmode", "1", "-autostart-warp", "-autostart", program) diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index a3f230de8..0a9142439 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -1,6 +1,9 @@ package prog8.compiler import prog8.ast.* +import prog8.compiler.intermediate.IntermediateProgram +import prog8.compiler.intermediate.Opcode +import prog8.compiler.intermediate.Value import prog8.stackvm.* import java.util.* import kotlin.math.abs @@ -1394,7 +1397,7 @@ private class StatementTranslator(private val prog: IntermediateProgram, continueStmtLabelStack.push(continueLabel) breakStmtLabelStack.push(breakLabel) - val zero = Value(if(numElements<=255) DataType.UBYTE else DataType.UWORD, 0) + val zero = Value(if (numElements <= 255) DataType.UBYTE else DataType.UWORD, 0) prog.instr(opcodePush(zero.type), zero) prog.instr(opcodePopvar(zero.type), callLabel = indexVar) prog.label(loopLabel) @@ -1473,7 +1476,7 @@ private class StatementTranslator(private val prog: IntermediateProgram, } // TODO: optimize edge cases if last value = 255 or 0 (for bytes) etc. to avoid PUSH_BYTE / SUB opcodes and make use of the wrapping around of the value. - prog.instr(opcodePush(varDt), Value(varDt, range.last+range.step)) + prog.instr(opcodePush(varDt), Value(varDt, range.last + range.step)) prog.instr(opcodePushvar(varDt), callLabel = varname) prog.instr(opcodeSub(varDt)) prog.instr(Opcode.BNZ, callLabel = loopLabel) diff --git a/compiler/src/prog8/compiler/intermediate/Instruction.kt b/compiler/src/prog8/compiler/intermediate/Instruction.kt new file mode 100644 index 000000000..07787023b --- /dev/null +++ b/compiler/src/prog8/compiler/intermediate/Instruction.kt @@ -0,0 +1,39 @@ +package prog8.compiler.intermediate + +import prog8.stackvm.Syscall + +open class Instruction(val opcode: Opcode, + val arg: Value? = null, + val callLabel: String? = null, + val callLabel2: String? = null) +{ + lateinit var next: Instruction + var nextAlt: Instruction? = null + + override fun toString(): String { + val argStr = arg?.toString() ?: "" + val result = + when { + opcode== Opcode.LINE -> "_line $callLabel" + opcode== Opcode.SYSCALL -> { + val syscall = Syscall.values().find { it.callNr==arg!!.numericValue() } + "syscall $syscall" + } + opcode in opcodesWithVarArgument -> { + // opcodes that manipulate a variable + "${opcode.toString().toLowerCase()} ${callLabel?:""} ${callLabel2?:""}".trimEnd() + } + callLabel==null -> "${opcode.toString().toLowerCase()} $argStr" + else -> "${opcode.toString().toLowerCase()} $callLabel $argStr" + } + .trimEnd() + + return " $result" + } +} + +class LabelInstr(val name: String) : Instruction(opcode = Opcode.NOP) { + override fun toString(): String { + return "\n$name:" + } +} diff --git a/compiler/src/prog8/compiler/IntermediateProgram.kt b/compiler/src/prog8/compiler/intermediate/IntermediateProgram.kt similarity index 99% rename from compiler/src/prog8/compiler/IntermediateProgram.kt rename to compiler/src/prog8/compiler/intermediate/IntermediateProgram.kt index 8adecabca..fe47e89de 100644 --- a/compiler/src/prog8/compiler/IntermediateProgram.kt +++ b/compiler/src/prog8/compiler/intermediate/IntermediateProgram.kt @@ -1,10 +1,11 @@ -package prog8.compiler +package prog8.compiler.intermediate import prog8.ast.DataType import prog8.ast.LiteralValue import prog8.ast.Position import prog8.ast.VarDecl -import prog8.stackvm.* +import prog8.compiler.CompilerException +import prog8.compiler.HeapValues import java.io.PrintStream diff --git a/compiler/src/prog8/compiler/intermediate/Opcode.kt b/compiler/src/prog8/compiler/intermediate/Opcode.kt new file mode 100644 index 000000000..c6c106052 --- /dev/null +++ b/compiler/src/prog8/compiler/intermediate/Opcode.kt @@ -0,0 +1,241 @@ +package prog8.compiler.intermediate + +enum class Opcode { + + // pushing values on the (evaluation) stack + PUSH_BYTE, // push byte value + PUSH_WORD, // push word value (or 'address' of string / array / matrix) + PUSH_FLOAT, // push float value + PUSH_MEM_B, // push byte value from memory to stack + PUSH_MEM_UB, // push byte value from memory to stack + PUSH_MEM_W, // push word value from memory to stack + PUSH_MEM_UW, // push word value from memory to stack + PUSH_MEM_FLOAT, // push float value from memory to stack + PUSH_VAR_BYTE, // push byte variable (ubyte, byte) + PUSH_VAR_WORD, // push word variable (uword, word) + PUSH_VAR_FLOAT, // push float variable + + // popping values off the (evaluation) stack, possibly storing them in another location + DISCARD_BYTE, // discard top byte value + DISCARD_WORD, // discard top word value + DISCARD_FLOAT, // discard top float value + POP_MEM_B, // pop byte value into destination memory address + POP_MEM_UB, // pop byte value into destination memory address + POP_MEM_W, // pop word value into destination memory address + POP_MEM_UW, // pop word value into destination memory address + POP_MEM_FLOAT, // pop float value into destination memory address + POP_VAR_BYTE, // pop byte value into variable (byte, ubyte) + POP_VAR_WORD, // pop word value into variable (word, uword) + POP_VAR_FLOAT, // pop float value into variable + + // optimized copying of one var to another (replaces push+pop) + COPY_VAR_BYTE, + COPY_VAR_WORD, + COPY_VAR_FLOAT, + + // numeric arithmetic + ADD_UB, + ADD_B, + ADD_UW, + ADD_W, + ADD_F, + SUB_UB, + SUB_B, + SUB_UW, + SUB_W, + SUB_F, + MUL_UB, + MUL_B, + MUL_UW, + MUL_W, + MUL_F, + DIV_UB, + DIV_B, + DIV_UW, + DIV_W, + DIV_F, + FLOORDIV_UB, + FLOORDIV_B, + FLOORDIV_UW, + FLOORDIV_W, + FLOORDIV_F, + REMAINDER_UB, + REMAINDER_B, + REMAINDER_UW, + REMAINDER_W, + REMAINDER_F, + POW_UB, + POW_B, + POW_UW, + POW_W, + POW_F, + NEG_B, + NEG_W, + NEG_F, + + // bit shifts and bitwise arithmetic + SHL_BYTE, + SHL_WORD, + SHL_MEM_BYTE, + SHL_MEM_WORD, + SHL_VAR_BYTE, + SHL_VAR_WORD, + SHR_BYTE, + SHR_WORD, + SHR_MEM_BYTE, + SHR_MEM_WORD, + SHR_VAR_BYTE, + SHR_VAR_WORD, + ROL_BYTE, + ROL_WORD, + ROL_MEM_BYTE, + ROL_MEM_WORD, + ROL_VAR_BYTE, + ROL_VAR_WORD, + ROR_BYTE, + ROR_WORD, + ROR_MEM_BYTE, + ROR_MEM_WORD, + ROR_VAR_BYTE, + ROR_VAR_WORD, + ROL2_BYTE, + ROL2_WORD, + ROL2_MEM_BYTE, + ROL2_MEM_WORD, + ROL2_VAR_BYTE, + ROL2_VAR_WORD, + ROR2_BYTE, + ROR2_WORD, + ROR2_MEM_BYTE, + ROR2_MEM_WORD, + ROR2_VAR_BYTE, + ROR2_VAR_WORD, + BITAND_BYTE, + BITAND_WORD, + BITOR_BYTE, + BITOR_WORD, + BITXOR_BYTE, + BITXOR_WORD, + INV_BYTE, + INV_WORD, + + // numeric type conversions + LSB, + MSB, + B2UB, + UB2B, + B2WORD, // convert a byte into a word where it is the lower eight bits $ssxx with sign extension + UB2UWORD, // convert a byte into a word where it is the lower eight bits $00xx + MSB2WORD, // convert a byte into a word where it is the upper eight bits $xx00 + B2FLOAT, // convert byte into floating point + UB2FLOAT, // convert unsigned byte into floating point + W2FLOAT, // convert word into floating point + UW2FLOAT, // convert unsigned word into floating point + + // logical operations + AND_BYTE, + AND_WORD, + OR_BYTE, + OR_WORD, + XOR_BYTE, + XOR_WORD, + NOT_BYTE, + NOT_WORD, + + // increment, decrement + INC_B, + INC_UB, + INC_W, + INC_UW, + INC_F, + INC_VAR_B, + INC_VAR_UB, + INC_VAR_W, + INC_VAR_UW, + INC_VAR_F, + DEC_B, + DEC_UB, + DEC_W, + DEC_UW, + DEC_F, + DEC_VAR_B, + DEC_VAR_UB, + DEC_VAR_W, + DEC_VAR_UW, + DEC_VAR_F, + + // comparisons + LESS_B, + LESS_UB, + LESS_W, + LESS_UW, + LESS_F, + GREATER_B, + GREATER_UB, + GREATER_W, + GREATER_UW, + GREATER_F, + LESSEQ_B, + LESSEQ_UB, + LESSEQ_W, + LESSEQ_UW, + LESSEQ_F, + GREATEREQ_B, + GREATEREQ_UB, + GREATEREQ_W, + GREATEREQ_UW, + GREATEREQ_F, + EQUAL_BYTE, + EQUAL_WORD, + EQUAL_F, + NOTEQUAL_BYTE, + NOTEQUAL_WORD, + NOTEQUAL_F, + + // array access + READ_INDEXED_VAR_BYTE, + READ_INDEXED_VAR_WORD, + READ_INDEXED_VAR_FLOAT, + WRITE_INDEXED_VAR_BYTE, + WRITE_INDEXED_VAR_WORD, + WRITE_INDEXED_VAR_FLOAT, + + // branching + JUMP, + BCS, + BCC, + BZ, // branch if value on top of stack is zero + BNZ, // branch if value on top of stack is not zero + BNEG, // branch if value on top of stack < 0 + BPOS, // branch if value on top of stack >= 0 + // BVS, // status flag V (overflow) not implemented + // BVC, // status flag V (overflow) not implemented + + // subroutine calling + CALL, + RETURN, + SYSCALL, + + // misc + SEC, // set carry status flag NOTE: is mostly fake, carry flag is not affected by any numeric operations + CLC, // clear carry status flag NOTE: is mostly fake, carry flag is not affected by any numeric operations + SEI, // set irq-disable status flag + CLI, // clear irq-disable status flag + NOP, // do nothing + BREAKPOINT, // breakpoint + TERMINATE, // end the program + LINE // track source file line number +} + +val opcodesWithVarArgument = setOf( + Opcode.INC_VAR_B, Opcode.INC_VAR_W, Opcode.DEC_VAR_B, Opcode.DEC_VAR_W, + Opcode.INC_VAR_UB, Opcode.INC_VAR_UW, Opcode.DEC_VAR_UB, Opcode.DEC_VAR_UW, + Opcode.SHR_VAR_BYTE, Opcode.SHR_VAR_WORD, Opcode.SHL_VAR_BYTE, Opcode.SHL_VAR_WORD, + Opcode.ROL_VAR_BYTE, Opcode.ROL_VAR_WORD, Opcode.ROR_VAR_BYTE, Opcode.ROR_VAR_WORD, + Opcode.ROL2_VAR_BYTE, Opcode.ROL2_VAR_WORD, Opcode.ROR2_VAR_BYTE, Opcode.ROR2_VAR_WORD, + Opcode.POP_VAR_BYTE, Opcode.POP_VAR_WORD, Opcode.POP_VAR_FLOAT, + Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_WORD, Opcode.PUSH_VAR_FLOAT, + Opcode.COPY_VAR_BYTE, Opcode.COPY_VAR_WORD, Opcode.COPY_VAR_FLOAT, + Opcode.READ_INDEXED_VAR_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.READ_INDEXED_VAR_FLOAT, + Opcode.WRITE_INDEXED_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD, Opcode.WRITE_INDEXED_VAR_FLOAT +) diff --git a/compiler/src/prog8/stackvm/Value.kt b/compiler/src/prog8/compiler/intermediate/Value.kt similarity index 99% rename from compiler/src/prog8/stackvm/Value.kt rename to compiler/src/prog8/compiler/intermediate/Value.kt index 763b98189..0c3d67cbf 100644 --- a/compiler/src/prog8/stackvm/Value.kt +++ b/compiler/src/prog8/compiler/intermediate/Value.kt @@ -1,8 +1,9 @@ -package prog8.stackvm +package prog8.compiler.intermediate import prog8.ast.DataType import prog8.ast.IterableDatatypes import prog8.ast.NumericDatatypes +import prog8.stackvm.VmExecutionException import kotlin.math.abs import kotlin.math.floor import kotlin.math.pow @@ -123,9 +124,9 @@ class Value(val type: DataType, numericvalueOrHeapId: Number) { // storing a negative number in an unsigned one is done by storing the 2's complement instead val number = abs(result.toDouble().toInt()) if(leftDt==DataType.UBYTE) - Value(DataType.UBYTE, (number xor 255) +1) + Value(DataType.UBYTE, (number xor 255) + 1) else - Value(DataType.UBYTE, (number xor 65535) +1) + Value(DataType.UBYTE, (number xor 65535) + 1) } DataType.BYTE -> Value(DataType.BYTE, result.toInt()) DataType.WORD -> Value(DataType.WORD, result.toInt()) diff --git a/compiler/src/prog8/compiler/target/c64/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/AsmGen.kt new file mode 100644 index 000000000..d95d5d6a1 --- /dev/null +++ b/compiler/src/prog8/compiler/target/c64/AsmGen.kt @@ -0,0 +1,15 @@ +package prog8.compiler.target.c64 + +import prog8.compiler.CompilationOptions +import prog8.compiler.intermediate.IntermediateProgram + + +class AsmGen(val options: CompilationOptions) { + fun compileToAssembly(program: IntermediateProgram): AssemblyProgram { + println("\nGenerating assembly code from intermediate code... ") + // todo generate 6502 assembly + return AssemblyProgram(program.name) + } +} + + diff --git a/compiler/src/prog8/compiler/target/c64/AssemblyProgram.kt b/compiler/src/prog8/compiler/target/c64/AssemblyProgram.kt new file mode 100644 index 000000000..60d20e06b --- /dev/null +++ b/compiler/src/prog8/compiler/target/c64/AssemblyProgram.kt @@ -0,0 +1,57 @@ +package prog8.compiler.target.c64 + +import prog8.compiler.CompilationOptions +import prog8.compiler.OutputType +import java.io.File +import kotlin.system.exitProcess + +class AssemblyProgram(val name: String) { + private val assemblyFile = "$name.asm" + private val viceMonListFile = "$name.vice-mon-list" + + fun assemble(options: CompilationOptions) { + println("Generating machine code program...") + + val command = mutableListOf("64tass", "--ascii", "--case-sensitive", "-Wall", "-Wno-strict-bool", + "--dump-labels", "--vice-labels", "-l", viceMonListFile, "--no-monitor") + + val outFile = when(options.output) { + OutputType.PRG -> { + command.add("--cbm-prg") + println("\nCreating C-64 prg.") + "$name.prg" + } + OutputType.RAW -> { + command.add("--nostart") + println("\nCreating raw binary.") + "$name.bin" + } + } + command.addAll(listOf("--output", outFile, assemblyFile)) + + val proc = ProcessBuilder(command).inheritIO().start() + val result = proc.waitFor() + if(result!=0) { + System.err.println("assembler failed with returncode $result") + exitProcess(result) + } + + generateBreakpointList() + } + + private fun generateBreakpointList() { + // builds list of breakpoints, appends to monitor list file + val breakpoints = mutableListOf() + val pattern = Regex("""al (\w+) \S+_prog8_breakpoint_\d+.?""") // todo what's with the _prog8_breakpoint_? how to find breakpoint? + for(line in File(viceMonListFile).readLines()) { + val match = pattern.matchEntire(line) + if(match!=null) + breakpoints.add("break \$" + match.groupValues[0]) // todo check + } + val num = breakpoints.size + breakpoints.add(0, "; vice monitor breakpoint list now follows") + breakpoints.add(1, "; $num breakpoints have been defined") + breakpoints.add(2, "del") + File(viceMonListFile).appendText(breakpoints.joinToString("\n")) + } +} \ No newline at end of file diff --git a/compiler/src/prog8/compiler/target/c64/Charset.kt b/compiler/src/prog8/compiler/target/c64/Charset.kt deleted file mode 100644 index 2fbdfe541..000000000 --- a/compiler/src/prog8/compiler/target/c64/Charset.kt +++ /dev/null @@ -1,37 +0,0 @@ -package prog8.compiler.target.c64 - -import java.awt.Color -import java.awt.image.BufferedImage -import javax.imageio.ImageIO - -object Charset { - private val normalImg = ImageIO.read(javaClass.getResource("/charset/c64/charset-normal.png")) - private val shiftedImg = ImageIO.read(javaClass.getResource("/charset/c64/charset-shifted.png")) - - private fun scanChars(img: BufferedImage): Array { - - val transparent = BufferedImage(img.width, img.height, BufferedImage.TYPE_INT_ARGB) - transparent.createGraphics().drawImage(img, 0, 0, null) - - val black = Color(0,0,0).rgb - val nopixel = Color(0,0,0,0).rgb - for(y in 0 until transparent.height) { - for(x in 0 until transparent.width) { - val col = transparent.getRGB(x, y) - if(col==black) - transparent.setRGB(x, y, nopixel) - } - } - - val numColumns = transparent.width / 8 - val charImages = (0..255).map { - val charX = it % numColumns - val charY = it/ numColumns - transparent.getSubimage(charX*8, charY*8, 8, 8) - } - return charImages.toTypedArray() - } - - val normalChars = scanChars(normalImg) - val shiftedChars = scanChars(shiftedImg) -} diff --git a/compiler/src/prog8/compiler/target/c64/Commodore64.kt b/compiler/src/prog8/compiler/target/c64/Commodore64.kt index dcc085651..aeedbf413 100644 --- a/compiler/src/prog8/compiler/target/c64/Commodore64.kt +++ b/compiler/src/prog8/compiler/target/c64/Commodore64.kt @@ -1,10 +1,11 @@ package prog8.compiler.target.c64 import prog8.compiler.* -import prog8.stackvm.Program +import java.awt.Color +import java.awt.image.BufferedImage +import javax.imageio.ImageIO import kotlin.math.absoluteValue import kotlin.math.pow -import kotlin.system.exitProcess // 5-byte cbm MFLPT format limitations: @@ -12,7 +13,6 @@ const val FLOAT_MAX_POSITIVE = 1.7014118345e+38 const val FLOAT_MAX_NEGATIVE = -1.7014118345e+38 - class C64Zeropage(options: CompilationOptions) : Zeropage(options) { companion object { @@ -113,60 +113,34 @@ data class Mflpt5(val b0: Short, val b1: Short, val b2: Short, val b3: Short, va } } +object Charset { + private val normalImg = ImageIO.read(javaClass.getResource("/charset/c64/charset-normal.png")) + private val shiftedImg = ImageIO.read(javaClass.getResource("/charset/c64/charset-shifted.png")) -fun compileToAssembly(program: Program): AssemblyResult { - println("\nGenerating assembly code from stackvmProg code... ") - // todo generate 6502 assembly - return AssemblyResult(program.name) + private fun scanChars(img: BufferedImage): Array { + + val transparent = BufferedImage(img.width, img.height, BufferedImage.TYPE_INT_ARGB) + transparent.createGraphics().drawImage(img, 0, 0, null) + + val black = Color(0,0,0).rgb + val nopixel = Color(0,0,0,0).rgb + for(y in 0 until transparent.height) { + for(x in 0 until transparent.width) { + val col = transparent.getRGB(x, y) + if(col==black) + transparent.setRGB(x, y, nopixel) + } + } + + val numColumns = transparent.width / 8 + val charImages = (0..255).map { + val charX = it % numColumns + val charY = it/ numColumns + transparent.getSubimage(charX*8, charY*8, 8, 8) + } + return charImages.toTypedArray() + } + + val normalChars = scanChars(normalImg) + val shiftedChars = scanChars(shiftedImg) } - - -class AssemblyResult(val name: String) { - fun assemble(options: CompilationOptions, inputfilename: String, outputfilename: String) { - println("\nGenerating machine code program...") - - val command = mutableListOf("64tass", "--ascii", "--case-sensitive", "-Wall", "-Wno-strict-bool", - "--dump-labels", "--vice-labels", "-l", "$outputfilename.vice-mon-list", - "--no-monitor", "--output", outputfilename, inputfilename) - - when(options.output) { - OutputType.PRG -> { - command.add("--cbm-prg") - println("\nCreating C-64 prg.") - } - OutputType.RAW -> { - command.add("--nostart") - println("\nCreating raw binary.") - } - } - - val proc = ProcessBuilder(command).inheritIO().start() - val result = proc.waitFor() - if(result!=0) { - System.err.println("assembler failed with returncode $result") - exitProcess(result) - } - } - - fun generateBreakpointList(): String { - // todo build breakpoint list -/* - def generate_breakpoint_list(self, program_filename: str) -> str: - breakpoints = [] - vice_mon_file = program_filename + ".vice-mon-list" - with open(vice_mon_file, "rU") as f: - for line in f: - match = re.fullmatch(r"al (?P
\w+) \S+_prog8_breakpoint_\d+.?", line, re.DOTALL) - if match: - breakpoints.append("$" + match.group("address")) - with open(vice_mon_file, "at") as f: - print("; vice monitor breakpoint list now follows", file=f) - print("; {:d} breakpoints have been defined here".format(len(breakpoints)), file=f) - print("del", file=f) - for b in breakpoints: - print("break", b, file=f) - return vice_mon_file - */ - return "monitorfile.txt" - } -} \ No newline at end of file diff --git a/compiler/src/prog8/stackvm/Program.kt b/compiler/src/prog8/stackvm/Program.kt index 940afd319..14d28640b 100644 --- a/compiler/src/prog8/stackvm/Program.kt +++ b/compiler/src/prog8/stackvm/Program.kt @@ -2,6 +2,7 @@ package prog8.stackvm import prog8.ast.DataType import prog8.compiler.HeapValues +import prog8.compiler.intermediate.* import prog8.compiler.unescape import java.io.File import java.util.* diff --git a/compiler/src/prog8/stackvm/StackVm.kt b/compiler/src/prog8/stackvm/StackVm.kt index caef40e4f..41d7e4a9a 100644 --- a/compiler/src/prog8/stackvm/StackVm.kt +++ b/compiler/src/prog8/stackvm/StackVm.kt @@ -4,251 +4,15 @@ import prog8.ast.DataType import prog8.ast.IterableDatatypes import prog8.ast.NumericDatatypes import prog8.compiler.HeapValues +import prog8.compiler.intermediate.Instruction +import prog8.compiler.intermediate.Opcode +import prog8.compiler.intermediate.Value import prog8.compiler.target.c64.Petscii import java.io.File import java.io.PrintStream import java.util.* import kotlin.math.* -enum class Opcode { - - // pushing values on the (evaluation) stack - PUSH_BYTE, // push byte value - PUSH_WORD, // push word value (or 'address' of string / array / matrix) - PUSH_FLOAT, // push float value - PUSH_MEM_B, // push byte value from memory to stack - PUSH_MEM_UB, // push byte value from memory to stack - PUSH_MEM_W, // push word value from memory to stack - PUSH_MEM_UW, // push word value from memory to stack - PUSH_MEM_FLOAT, // push float value from memory to stack - PUSH_VAR_BYTE, // push byte variable (ubyte, byte) - PUSH_VAR_WORD, // push word variable (uword, word) - PUSH_VAR_FLOAT, // push float variable - - // popping values off the (evaluation) stack, possibly storing them in another location - DISCARD_BYTE, // discard top byte value - DISCARD_WORD, // discard top word value - DISCARD_FLOAT, // discard top float value - POP_MEM_B, // pop byte value into destination memory address - POP_MEM_UB, // pop byte value into destination memory address - POP_MEM_W, // pop word value into destination memory address - POP_MEM_UW, // pop word value into destination memory address - POP_MEM_FLOAT, // pop float value into destination memory address - POP_VAR_BYTE, // pop byte value into variable (byte, ubyte) - POP_VAR_WORD, // pop word value into variable (word, uword) - POP_VAR_FLOAT, // pop float value into variable - - // optimized copying of one var to another (replaces push+pop) - COPY_VAR_BYTE, - COPY_VAR_WORD, - COPY_VAR_FLOAT, - - // numeric arithmetic - ADD_UB, - ADD_B, - ADD_UW, - ADD_W, - ADD_F, - SUB_UB, - SUB_B, - SUB_UW, - SUB_W, - SUB_F, - MUL_UB, - MUL_B, - MUL_UW, - MUL_W, - MUL_F, - DIV_UB, - DIV_B, - DIV_UW, - DIV_W, - DIV_F, - FLOORDIV_UB, - FLOORDIV_B, - FLOORDIV_UW, - FLOORDIV_W, - FLOORDIV_F, - REMAINDER_UB, - REMAINDER_B, - REMAINDER_UW, - REMAINDER_W, - REMAINDER_F, - POW_UB, - POW_B, - POW_UW, - POW_W, - POW_F, - NEG_B, - NEG_W, - NEG_F, - - // bit shifts and bitwise arithmetic - SHL_BYTE, - SHL_WORD, - SHL_MEM_BYTE, - SHL_MEM_WORD, - SHL_VAR_BYTE, - SHL_VAR_WORD, - SHR_BYTE, - SHR_WORD, - SHR_MEM_BYTE, - SHR_MEM_WORD, - SHR_VAR_BYTE, - SHR_VAR_WORD, - ROL_BYTE, - ROL_WORD, - ROL_MEM_BYTE, - ROL_MEM_WORD, - ROL_VAR_BYTE, - ROL_VAR_WORD, - ROR_BYTE, - ROR_WORD, - ROR_MEM_BYTE, - ROR_MEM_WORD, - ROR_VAR_BYTE, - ROR_VAR_WORD, - ROL2_BYTE, - ROL2_WORD, - ROL2_MEM_BYTE, - ROL2_MEM_WORD, - ROL2_VAR_BYTE, - ROL2_VAR_WORD, - ROR2_BYTE, - ROR2_WORD, - ROR2_MEM_BYTE, - ROR2_MEM_WORD, - ROR2_VAR_BYTE, - ROR2_VAR_WORD, - BITAND_BYTE, - BITAND_WORD, - BITOR_BYTE, - BITOR_WORD, - BITXOR_BYTE, - BITXOR_WORD, - INV_BYTE, - INV_WORD, - - // numeric type conversions - LSB, - MSB, - B2UB, - UB2B, - B2WORD, // convert a byte into a word where it is the lower eight bits $ssxx with sign extension - UB2UWORD, // convert a byte into a word where it is the lower eight bits $00xx - MSB2WORD, // convert a byte into a word where it is the upper eight bits $xx00 - B2FLOAT, // convert byte into floating point - UB2FLOAT, // convert unsigned byte into floating point - W2FLOAT, // convert word into floating point - UW2FLOAT, // convert unsigned word into floating point - - // logical operations - AND_BYTE, - AND_WORD, - OR_BYTE, - OR_WORD, - XOR_BYTE, - XOR_WORD, - NOT_BYTE, - NOT_WORD, - - // increment, decrement - INC_B, - INC_UB, - INC_W, - INC_UW, - INC_F, - INC_VAR_B, - INC_VAR_UB, - INC_VAR_W, - INC_VAR_UW, - INC_VAR_F, - DEC_B, - DEC_UB, - DEC_W, - DEC_UW, - DEC_F, - DEC_VAR_B, - DEC_VAR_UB, - DEC_VAR_W, - DEC_VAR_UW, - DEC_VAR_F, - - // comparisons - LESS_B, - LESS_UB, - LESS_W, - LESS_UW, - LESS_F, - GREATER_B, - GREATER_UB, - GREATER_W, - GREATER_UW, - GREATER_F, - LESSEQ_B, - LESSEQ_UB, - LESSEQ_W, - LESSEQ_UW, - LESSEQ_F, - GREATEREQ_B, - GREATEREQ_UB, - GREATEREQ_W, - GREATEREQ_UW, - GREATEREQ_F, - EQUAL_BYTE, - EQUAL_WORD, - EQUAL_F, - NOTEQUAL_BYTE, - NOTEQUAL_WORD, - NOTEQUAL_F, - - // array access - READ_INDEXED_VAR_BYTE, - READ_INDEXED_VAR_WORD, - READ_INDEXED_VAR_FLOAT, - WRITE_INDEXED_VAR_BYTE, - WRITE_INDEXED_VAR_WORD, - WRITE_INDEXED_VAR_FLOAT, - - // branching - JUMP, - BCS, - BCC, - BZ, // branch if value on top of stack is zero - BNZ, // branch if value on top of stack is not zero - BNEG, // branch if value on top of stack < 0 - BPOS, // branch if value on top of stack >= 0 - // BVS, // status flag V (overflow) not implemented - // BVC, // status flag V (overflow) not implemented - - // subroutine calling - CALL, - RETURN, - SYSCALL, - - // misc - SEC, // set carry status flag NOTE: is mostly fake, carry flag is not affected by any numeric operations - CLC, // clear carry status flag NOTE: is mostly fake, carry flag is not affected by any numeric operations - SEI, // set irq-disable status flag - CLI, // clear irq-disable status flag - NOP, // do nothing - BREAKPOINT, // breakpoint - TERMINATE, // end the program - LINE // track source file line number -} - -val opcodesWithVarArgument = setOf( - Opcode.INC_VAR_B, Opcode.INC_VAR_W, Opcode.DEC_VAR_B, Opcode.DEC_VAR_W, - Opcode.INC_VAR_UB, Opcode.INC_VAR_UW, Opcode.DEC_VAR_UB, Opcode.DEC_VAR_UW, - Opcode.SHR_VAR_BYTE, Opcode.SHR_VAR_WORD, Opcode.SHL_VAR_BYTE, Opcode.SHL_VAR_WORD, - Opcode.ROL_VAR_BYTE, Opcode.ROL_VAR_WORD, Opcode.ROR_VAR_BYTE, Opcode.ROR_VAR_WORD, - Opcode.ROL2_VAR_BYTE, Opcode.ROL2_VAR_WORD, Opcode.ROR2_VAR_BYTE, Opcode.ROR2_VAR_WORD, - Opcode.POP_VAR_BYTE, Opcode.POP_VAR_WORD, Opcode.POP_VAR_FLOAT, - Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_WORD, Opcode.PUSH_VAR_FLOAT, - Opcode.COPY_VAR_BYTE, Opcode.COPY_VAR_WORD, Opcode.COPY_VAR_FLOAT, - Opcode.READ_INDEXED_VAR_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.READ_INDEXED_VAR_FLOAT, - Opcode.WRITE_INDEXED_VAR_BYTE, Opcode.WRITE_INDEXED_VAR_WORD, Opcode.WRITE_INDEXED_VAR_FLOAT - ) enum class Syscall(val callNr: Short) { WRITE_MEMCHR(10), // print a single char from the memory address popped from stack @@ -301,42 +65,6 @@ enum class Syscall(val callNr: Short) { } -open class Instruction(val opcode: Opcode, - val arg: Value? = null, - val callLabel: String? = null, - val callLabel2: String? = null) -{ - lateinit var next: Instruction - var nextAlt: Instruction? = null - - override fun toString(): String { - val argStr = arg?.toString() ?: "" - val result = - when { - opcode==Opcode.LINE -> "_line $callLabel" - opcode==Opcode.SYSCALL -> { - val syscall = Syscall.values().find { it.callNr==arg!!.numericValue() } - "syscall $syscall" - } - opcode in opcodesWithVarArgument -> { - // opcodes that manipulate a variable - "${opcode.toString().toLowerCase()} ${callLabel?:""} ${callLabel2?:""}".trimEnd() - } - callLabel==null -> "${opcode.toString().toLowerCase()} $argStr" - else -> "${opcode.toString().toLowerCase()} $callLabel $argStr" - } - .trimEnd() - - return " $result" - } -} - -class LabelInstr(val name: String) : Instruction(opcode = Opcode.NOP) { - override fun toString(): String { - return "\n$name:" - } -} - class VmExecutionException(msg: String?) : Exception(msg) class VmTerminationException(msg: String?) : Exception(msg) @@ -1307,157 +1035,157 @@ class StackVm(private var traceOutputFile: String?) { val (top, second) = evalstack.pop2() checkDt(top, DataType.UBYTE) checkDt(second, DataType.UBYTE) - evalstack.push(Value(DataType.UBYTE, if(second < top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second < top) 1 else 0)) } Opcode.LESS_B -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.BYTE) checkDt(second, DataType.BYTE) - evalstack.push(Value(DataType.UBYTE, if(second < top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second < top) 1 else 0)) } Opcode.LESS_UW -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.UWORD) checkDt(second, DataType.UWORD) - evalstack.push(Value(DataType.UBYTE, if(second < top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second < top) 1 else 0)) } Opcode.LESS_W -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.WORD) checkDt(second, DataType.WORD) - evalstack.push(Value(DataType.UBYTE, if(second < top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second < top) 1 else 0)) } Opcode.LESS_F -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.FLOAT) checkDt(second, DataType.FLOAT) - evalstack.push(Value(DataType.UBYTE, if(second < top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second < top) 1 else 0)) } Opcode.GREATER_UB -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.UBYTE) checkDt(second, DataType.UBYTE) - evalstack.push(Value(DataType.UBYTE, if(second > top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second > top) 1 else 0)) } Opcode.GREATER_B -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.BYTE) checkDt(second, DataType.BYTE) - evalstack.push(Value(DataType.UBYTE, if(second > top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second > top) 1 else 0)) } Opcode.GREATER_UW -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.UWORD) checkDt(second, DataType.UWORD) - evalstack.push(Value(DataType.UBYTE, if(second > top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second > top) 1 else 0)) } Opcode.GREATER_W -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.WORD) checkDt(second, DataType.WORD) - evalstack.push(Value(DataType.UBYTE, if(second > top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second > top) 1 else 0)) } Opcode.GREATER_F -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.FLOAT) checkDt(second, DataType.FLOAT) - evalstack.push(Value(DataType.UBYTE, if(second > top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second > top) 1 else 0)) } Opcode.LESSEQ_UB -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.UBYTE) checkDt(second, DataType.UBYTE) - evalstack.push(Value(DataType.UBYTE, if(second <= top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second <= top) 1 else 0)) } Opcode.LESSEQ_B -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.BYTE) checkDt(second, DataType.BYTE) - evalstack.push(Value(DataType.UBYTE, if(second <= top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second <= top) 1 else 0)) } Opcode.LESSEQ_UW -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.UWORD) checkDt(second, DataType.UWORD) - evalstack.push(Value(DataType.UBYTE, if(second <= top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second <= top) 1 else 0)) } Opcode.LESSEQ_W -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.WORD) checkDt(second, DataType.WORD) - evalstack.push(Value(DataType.UBYTE, if(second <= top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second <= top) 1 else 0)) } Opcode.LESSEQ_F -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.FLOAT) checkDt(second, DataType.FLOAT) - evalstack.push(Value(DataType.UBYTE, if(second <= top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second <= top) 1 else 0)) } Opcode.GREATEREQ_UB -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.UBYTE) checkDt(second, DataType.UBYTE) - evalstack.push(Value(DataType.UBYTE, if(second >= top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second >= top) 1 else 0)) } Opcode.GREATEREQ_B -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.BYTE) checkDt(second, DataType.BYTE) - evalstack.push(Value(DataType.UBYTE, if(second >= top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second >= top) 1 else 0)) } Opcode.GREATEREQ_UW -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.UWORD) checkDt(second, DataType.UWORD) - evalstack.push(Value(DataType.UBYTE, if(second >= top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second >= top) 1 else 0)) } Opcode.GREATEREQ_W -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.WORD) checkDt(second, DataType.WORD) - evalstack.push(Value(DataType.UBYTE, if(second >= top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second >= top) 1 else 0)) } Opcode.GREATEREQ_F -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.FLOAT) checkDt(second, DataType.FLOAT) - evalstack.push(Value(DataType.UBYTE, if(second >= top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second >= top) 1 else 0)) } Opcode.EQUAL_BYTE -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.UBYTE) checkDt(second, DataType.UBYTE) - evalstack.push(Value(DataType.UBYTE, if(second == top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second == top) 1 else 0)) } Opcode.EQUAL_WORD -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.UWORD) checkDt(second, DataType.UWORD) - evalstack.push(Value(DataType.UBYTE, if(second == top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second == top) 1 else 0)) } Opcode.EQUAL_F -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.FLOAT) checkDt(second, DataType.FLOAT) - evalstack.push(Value(DataType.UBYTE, if(second == top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second == top) 1 else 0)) } Opcode.NOTEQUAL_BYTE -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.UBYTE) checkDt(second, DataType.UBYTE) - evalstack.push(Value(DataType.UBYTE, if(second != top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second != top) 1 else 0)) } Opcode.NOTEQUAL_WORD -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.UWORD) checkDt(second, DataType.UWORD) - evalstack.push(Value(DataType.UBYTE, if(second != top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second != top) 1 else 0)) } Opcode.NOTEQUAL_F -> { val (top, second) = evalstack.pop2() checkDt(top, DataType.FLOAT) checkDt(second, DataType.FLOAT) - evalstack.push(Value(DataType.UBYTE, if(second != top) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (second != top) 1 else 0)) } Opcode.B2UB -> { val byte = evalstack.pop() @@ -1793,7 +1521,7 @@ class StackVm(private var traceOutputFile: String?) { if (value.str != null) evalstack.push(Value(DataType.UBYTE, if (Petscii.encodePetscii(value.str, true).any { c -> c != 0.toShort() }) 1 else 0)) else - evalstack.push(Value(DataType.UBYTE, if (value.array!!.any{ v->v!=0}) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (value.array!!.any { v -> v != 0 }) 1 else 0)) } Syscall.FUNC_ALL -> { val iterable = evalstack.pop() @@ -1801,7 +1529,7 @@ class StackVm(private var traceOutputFile: String?) { if (value.str != null) evalstack.push(Value(DataType.UBYTE, if (Petscii.encodePetscii(value.str, true).all { c -> c != 0.toShort() }) 1 else 0)) else - evalstack.push(Value(DataType.UBYTE, if (value.array!!.all{ v->v!=0}) 1 else 0)) + evalstack.push(Value(DataType.UBYTE, if (value.array!!.all { v -> v != 0 }) 1 else 0)) } Syscall.FUNC_STR2BYTE -> { val strvar = evalstack.pop() @@ -1845,7 +1573,7 @@ class StackVm(private var traceOutputFile: String?) { if(value.integerValue() <= 32767) Value(DataType.WORD, value.integerValue()) else - Value(DataType.WORD, -((value.integerValue() xor 65535)+1)) + Value(DataType.WORD, -((value.integerValue() xor 65535) + 1)) evalstack.push(v2) } DataType.WORD -> evalstack.push(value) @@ -1863,7 +1591,7 @@ class StackVm(private var traceOutputFile: String?) { if(value.integerValue()>=0) Value(DataType.UWORD, value.integerValue()) else - Value(DataType.UWORD, (abs(value.integerValue()) xor 65535)+1) + Value(DataType.UWORD, (abs(value.integerValue()) xor 65535) + 1) evalstack.push(v2) } else -> {} diff --git a/compiler/test/StackVMOpcodeTests.kt b/compiler/test/StackVMOpcodeTests.kt index ce03de7b4..9bce56d1a 100644 --- a/compiler/test/StackVMOpcodeTests.kt +++ b/compiler/test/StackVMOpcodeTests.kt @@ -6,6 +6,9 @@ import org.junit.jupiter.api.Test import org.junit.jupiter.api.TestInstance import prog8.ast.DataType import prog8.compiler.HeapValues +import prog8.compiler.intermediate.Instruction +import prog8.compiler.intermediate.Opcode +import prog8.compiler.intermediate.Value import prog8.stackvm.* import kotlin.test.* @@ -317,7 +320,7 @@ class TestStackVmOpcodes { @Test fun testSub() { testBinaryOperator(Value(DataType.UBYTE, 250), Opcode.SUB_UB, Value(DataType.UBYTE, 70), Value(DataType.UBYTE, 180)) - testBinaryOperator(Value(DataType.UWORD, 4000), Opcode.SUB_UW, Value(DataType.UWORD, 123), Value(DataType.UWORD, 4000-123)) + testBinaryOperator(Value(DataType.UWORD, 4000), Opcode.SUB_UW, Value(DataType.UWORD, 123), Value(DataType.UWORD, 4000 - 123)) testBinaryOperator(Value(DataType.FLOAT, 123.44), Opcode.SUB_F, Value(DataType.FLOAT, 23.44), Value(DataType.FLOAT, 100.0)) assertFailsWith { testBinaryOperator(Value(DataType.UWORD, 4000 - 40), Opcode.SUB_UW, Value(DataType.FLOAT, 42.25), Value(DataType.FLOAT, 42.25 - (4000 - 40))) @@ -327,7 +330,7 @@ class TestStackVmOpcodes { @Test fun testMul() { testBinaryOperator(Value(DataType.UBYTE, 41), Opcode.MUL_UB, Value(DataType.UBYTE, 4), Value(DataType.UBYTE, 164)) - testBinaryOperator(Value(DataType.UWORD, 401), Opcode.MUL_UW, Value(DataType.UWORD, 4), Value(DataType.UWORD, 401*4)) + testBinaryOperator(Value(DataType.UWORD, 401), Opcode.MUL_UW, Value(DataType.UWORD, 4), Value(DataType.UWORD, 401 * 4)) testBinaryOperator(Value(DataType.FLOAT, 40.1), Opcode.MUL_F, Value(DataType.FLOAT, 2.4), Value(DataType.FLOAT, 96.24)) assertFailsWith { testBinaryOperator(Value(DataType.UWORD, 401 * 4), Opcode.MUL_UW, Value(DataType.FLOAT, 42.2533), Value(DataType.FLOAT, 42.2533 * (401 * 4))) @@ -338,7 +341,7 @@ class TestStackVmOpcodes { fun testDiv() { testBinaryOperator(Value(DataType.UBYTE, 250), Opcode.DIV_UB, Value(DataType.UBYTE, 12), Value(DataType.UBYTE, 20)) testBinaryOperator(Value(DataType.UWORD, 3999), Opcode.DIV_UW, Value(DataType.UWORD, 40), Value(DataType.UWORD, 99)) - testBinaryOperator(Value(DataType.FLOAT, 42.25), Opcode.DIV_F, Value(DataType.FLOAT, 99.0), Value(DataType.FLOAT, 42.25/99.0)) + testBinaryOperator(Value(DataType.FLOAT, 42.25), Opcode.DIV_F, Value(DataType.FLOAT, 99.0), Value(DataType.FLOAT, 42.25 / 99.0)) assertFailsWith { testBinaryOperator(Value(DataType.UWORD, 3333), Opcode.DIV_UW, Value(DataType.FLOAT, 2.22), Value(DataType.FLOAT, 3333 / 2.22)) } @@ -643,12 +646,12 @@ class TestStackVmOpcodes { @Test fun testIncVar() { val ins = mutableListOf( - Instruction(Opcode.INC_VAR_UW, callLabel ="var1"), - Instruction(Opcode.INC_VAR_UB, callLabel ="var2"), - Instruction(Opcode.INC_VAR_F, callLabel ="var3"), - Instruction(Opcode.INC_VAR_UW, callLabel ="var1"), - Instruction(Opcode.INC_VAR_UB, callLabel ="var2"), - Instruction(Opcode.INC_VAR_F, callLabel ="var3") + Instruction(Opcode.INC_VAR_UW, callLabel = "var1"), + Instruction(Opcode.INC_VAR_UB, callLabel = "var2"), + Instruction(Opcode.INC_VAR_F, callLabel = "var3"), + Instruction(Opcode.INC_VAR_UW, callLabel = "var1"), + Instruction(Opcode.INC_VAR_UB, callLabel = "var2"), + Instruction(Opcode.INC_VAR_F, callLabel = "var3") ) val vars = mapOf("var1" to Value(DataType.UWORD, 65534), "var2" to Value(DataType.UBYTE, 254), @@ -675,7 +678,7 @@ class TestStackVmOpcodes { Instruction(Opcode.DEC_VAR_UB, callLabel = "var2"), Instruction(Opcode.DEC_VAR_F, callLabel = "var3") ) - val vars = mapOf("var1" to Value(DataType.UWORD,1), + val vars = mapOf("var1" to Value(DataType.UWORD, 1), "var2" to Value(DataType.UBYTE, 1), "var3" to Value(DataType.FLOAT, 1.5) ) diff --git a/compiler/test/UnitTests.kt b/compiler/test/UnitTests.kt index c120a807a..fe0ccd8b5 100644 --- a/compiler/test/UnitTests.kt +++ b/compiler/test/UnitTests.kt @@ -8,7 +8,7 @@ import org.junit.jupiter.api.TestInstance import prog8.ast.* import prog8.compiler.* import prog8.compiler.target.c64.* -import prog8.stackvm.Value +import prog8.compiler.intermediate.Value import kotlin.test.assertEquals import kotlin.test.assertFailsWith import kotlin.test.assertFalse diff --git a/compiler/test/ValueOperationsTests.kt b/compiler/test/ValueOperationsTests.kt index 2698bc60c..ea2d0a73e 100644 --- a/compiler/test/ValueOperationsTests.kt +++ b/compiler/test/ValueOperationsTests.kt @@ -6,7 +6,7 @@ import prog8.ast.DataType import prog8.ast.ExpressionError import prog8.ast.LiteralValue import prog8.ast.Position -import prog8.stackvm.Value +import prog8.compiler.intermediate.Value import prog8.stackvm.VmExecutionException import kotlin.test.*