diff --git a/README.md b/README.md index 6fd5614d1..05af920b6 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,8 @@ What does Prog8 provide? - small program boilerplate/compilersupport overhead - programs can be run multiple times without reloading because of automatic variable (re)initializations. - conditional branches -- 'when' statement to provide a concise jump table alternative to if/elseif chains +- ``when`` statement to provide a concise jump table alternative to if/elseif chains +- ``in`` expression for concise and efficient multi-value/containment check - many built-in functions such as ``sin``, ``cos``, ``rnd``, ``abs``, ``min``, ``max``, ``sqrt``, ``msb``, ``rol``, ``ror``, ``swap``, ``sort`` and ``reverse`` - various powerful built-in libraries to do I/O, number conversions, graphics and more - convenience abstractions for low level aspects such as ZeroPage handling, program startup, explicit memory addresses diff --git a/codeGeneration/src/prog8/codegen/target/c64/C64MachineDefinition.kt b/codeGeneration/src/prog8/codegen/target/c64/C64MachineDefinition.kt index 26d50ee09..e23ee30ce 100644 --- a/codeGeneration/src/prog8/codegen/target/c64/C64MachineDefinition.kt +++ b/codeGeneration/src/prog8/codegen/target/c64/C64MachineDefinition.kt @@ -2,7 +2,7 @@ package prog8.codegen.target.c64 import prog8.ast.base.DataType import prog8.codegen.target.cbm.Mflpt5 -import prog8.codegen.target.cbm.viceMonListPostfix +import prog8.codegen.target.cbm.viceMonListName import prog8.compilerinterface.* import java.io.IOException import java.nio.file.Path @@ -42,7 +42,8 @@ class C64MachineDefinition: IMachineDefinition { for(emulator in listOf("x64sc", "x64")) { println("\nStarting C-64 emulator $emulator...") - val cmdline = listOf(emulator, "-silent", "-moncommands", "${programNameWithPath}.$viceMonListPostfix", + val viceMonlist = viceMonListName(programNameWithPath.toString()) + val cmdline = listOf(emulator, "-silent", "-moncommands", viceMonlist, "-autostartprgmode", "1", "-autostart-warp", "-autostart", "${programNameWithPath}.prg") val processb = ProcessBuilder(cmdline).inheritIO() val process: Process diff --git a/codeGeneration/src/prog8/codegen/target/cbm/AssemblyProgram.kt b/codeGeneration/src/prog8/codegen/target/cbm/AssemblyProgram.kt index 4d15f2e77..e3c3c438c 100644 --- a/codeGeneration/src/prog8/codegen/target/cbm/AssemblyProgram.kt +++ b/codeGeneration/src/prog8/codegen/target/cbm/AssemblyProgram.kt @@ -14,7 +14,7 @@ import kotlin.io.path.Path import kotlin.io.path.isRegularFile -internal const val viceMonListPostfix = "vice-mon-list" +internal fun viceMonListName(baseFilename: String) = "$baseFilename.vice-mon-list" class AssemblyProgram( override val valid: Boolean, @@ -25,17 +25,22 @@ class AssemblyProgram( private val assemblyFile = outputDir.resolve("$name.asm") private val prgFile = outputDir.resolve("$name.prg") private val binFile = outputDir.resolve("$name.bin") - private val viceMonListFile = outputDir.resolve("$name.$viceMonListPostfix") + private val viceMonListFile = outputDir.resolve(viceMonListName(name)) + private val listFile = outputDir.resolve("$name.list") - override fun assemble(quiet: Boolean, options: CompilationOptions): Int { + override fun assemble(options: CompilationOptions): Int { // add "-Wlong-branch" to see warnings about conversion of branch instructions to jumps (default = do this silently) val command = mutableListOf("64tass", "--ascii", "--case-sensitive", "--long-branch", "-Wall", "-Wno-strict-bool", "-Wno-shadow", // "-Werror", - "--dump-labels", "--vice-labels", "-l", viceMonListFile.toString(), "--no-monitor") + "--dump-labels", "--vice-labels", "--labels=$viceMonListFile", "--no-monitor" + ) - if(quiet) + if(options.asmQuiet) command.add("--quiet") + if(options.asmListfile) + command.add("--list=$listFile") + val outFile = when (options.output) { OutputType.PRG -> { command.add("--cbm-prg") diff --git a/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt b/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt index a7a2c8eb5..5a3e8c7a6 100644 --- a/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt +++ b/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt @@ -574,6 +574,26 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, asmgen.assignExpressionToRegister(value, RegisterOrPair.A) asmgen.out(" eor $name | sta $name") } + "==" -> { + asmgen.assignExpressionToRegister(value, RegisterOrPair.A) + asmgen.out(""" + cmp $name + beq + + lda #0 + beq ++ ++ lda #1 ++ sta $name""") + } + "!=" -> { + asmgen.assignExpressionToRegister(value, RegisterOrPair.A) + asmgen.out(""" + cmp $name + beq + + lda #1 + bne ++ ++ lda #0 ++ sta $name""") + } else -> throw AssemblyError("invalid operator for in-place modification $operator") } } @@ -631,6 +651,26 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, "&", "and" -> asmgen.out(" lda $name | and $otherName | sta $name") "|", "or" -> asmgen.out(" lda $name | ora $otherName | sta $name") "^", "xor" -> asmgen.out(" lda $name | eor $otherName | sta $name") + "==" -> { + asmgen.out(""" + lda $otherName + cmp $name + beq + + lda #0 + bne ++ ++ lda #1 ++ sta $name""") + } + "!=" -> { + asmgen.out(""" + lda $otherName + cmp $name + beq + + lda #1 + bne ++ ++ lda #0 ++ sta $name""") + } else -> throw AssemblyError("invalid operator for in-place modification $operator") } } @@ -702,6 +742,26 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, "&", "and" -> asmgen.out(" lda $name | and #$value | sta $name") "|", "or" -> asmgen.out(" lda $name | ora #$value | sta $name") "^", "xor" -> asmgen.out(" lda $name | eor #$value | sta $name") + "==" -> { + asmgen.out(""" + lda #$value + cmp $name + beq + + lda #0 + bne ++ ++ lda #1 ++ sta $name""") + } + "!=" -> { + asmgen.out(""" + lda #$value + cmp $name + beq + + lda #1 + bne ++ ++ lda #0 ++ sta $name""") + } else -> throw AssemblyError("invalid operator for in-place modification $operator") } } diff --git a/codeGeneration/src/prog8/codegen/target/cx16/CX16MachineDefinition.kt b/codeGeneration/src/prog8/codegen/target/cx16/CX16MachineDefinition.kt index 0144895e2..c2c514cc1 100644 --- a/codeGeneration/src/prog8/codegen/target/cx16/CX16MachineDefinition.kt +++ b/codeGeneration/src/prog8/codegen/target/cx16/CX16MachineDefinition.kt @@ -2,7 +2,7 @@ package prog8.codegen.target.cx16 import prog8.ast.base.DataType import prog8.codegen.target.cbm.Mflpt5 -import prog8.codegen.target.cbm.viceMonListPostfix +import prog8.codegen.target.cbm.viceMonListName import prog8.compilerinterface.* import java.io.IOException import java.nio.file.Path @@ -44,7 +44,7 @@ class CX16MachineDefinition: IMachineDefinition { } 2 -> { emulatorName = "box16" - extraArgs = listOf("-sym", "${programNameWithPath}.$viceMonListPostfix") + extraArgs = listOf("-sym", viceMonListName(programNameWithPath.toString())) } else -> { System.err.println("Cx16 target only supports x16emu and box16 emulators.") diff --git a/codeOptimizers/src/prog8/optimizer/BinExprSplitter.kt b/codeOptimizers/src/prog8/optimizer/BinExprSplitter.kt index 84d9a2f27..cbf5594b2 100644 --- a/codeOptimizers/src/prog8/optimizer/BinExprSplitter.kt +++ b/codeOptimizers/src/prog8/optimizer/BinExprSplitter.kt @@ -45,7 +45,7 @@ X = BinExpr X = LeftExpr */ - if(binExpr.operator in AugmentAssignmentOperators && isSimpleTarget(assignment.target)) { + if(binExpr.operator in AugmentAssignmentOperators + listOf("==", "!=") && isSimpleTarget(assignment.target)) { if(assignment.target isSameAs binExpr.right) return noModifications if(assignment.target isSameAs binExpr.left) { @@ -73,6 +73,15 @@ X = BinExpr X = LeftExpr // ) } + if(binExpr.operator == "==" || binExpr.operator == "!=") { + // don't split if the operand(s) don't fit the type of the resulting variable + val targetDt = assignment.target.inferType(program) + val leftDt = binExpr.left.inferType(program) + val rightDt = binExpr.right.inferType(program) + if(leftDt isNotAssignableTo targetDt || rightDt isNotAssignableTo targetDt) + return noModifications + } + if(binExpr.right.isSimple) { val firstAssign = Assignment(assignment.target.copy(), binExpr.left, binExpr.left.position) val targetExpr = assignment.target.toExpression() diff --git a/compiler/src/prog8/CompilerMain.kt b/compiler/src/prog8/CompilerMain.kt index 4e0571033..d26729487 100644 --- a/compiler/src/prog8/CompilerMain.kt +++ b/compiler/src/prog8/CompilerMain.kt @@ -41,6 +41,7 @@ private fun compileMain(args: Array): Boolean { val watchMode by cli.option(ArgType.Boolean, fullName = "watch", description = "continuous compilation mode (watches for file changes), greatly increases compilation speed") val slowCodegenWarnings by cli.option(ArgType.Boolean, fullName = "slowwarn", description="show debug warnings about slow/problematic assembly code generation") val quietAssembler by cli.option(ArgType.Boolean, fullName = "quietasm", description = "don't print assembler output results") + val asmListfile by cli.option(ArgType.Boolean, fullName = "asmlist", description = "make the assembler produce a listing file as well") val compilationTarget by cli.option(ArgType.String, fullName = "target", description = "target output of the compiler (one of '${C64Target.name}', '${C128Target.name}', '${Cx16Target.name}')").default(C64Target.name) val sourceDirs by cli.option(ArgType.String, fullName="srcdirs", description = "list of extra paths, separated with ${File.pathSeparator}, to search in for imported modules").multiple().delimiter(File.pathSeparator) val moduleFiles by cli.argument(ArgType.String, fullName = "modules", description = "main module file(s) to compile").multiple(999) @@ -89,6 +90,7 @@ private fun compileMain(args: Array): Boolean { dontWriteAssembly != true, slowCodegenWarnings == true, quietAssembler == true, + asmListfile == true, compilationTarget, srcdirs, outputPath @@ -137,6 +139,7 @@ private fun compileMain(args: Array): Boolean { dontWriteAssembly != true, slowCodegenWarnings == true, quietAssembler == true, + asmListfile == true, compilationTarget, srcdirs, outputPath diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 21e2af8a9..7986cd900 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -35,6 +35,7 @@ class CompilerArguments(val filepath: Path, val writeAssembly: Boolean, val slowCodegenWarnings: Boolean, val quietAssembler: Boolean, + val asmListfile: Boolean, val compilationTarget: String, val sourceDirs: List = emptyList(), val outputDir: Path = Path(""), @@ -61,14 +62,19 @@ fun compileProgram(args: CompilerArguments): CompilationResult { // import main module and everything it needs val (programresult, compilationOptions, imported) = parseImports(args.filepath, args.errors, compTarget, args.sourceDirs) with(compilationOptions) { - this.slowCodegenWarnings = args.slowCodegenWarnings - this.optimize = args.optimize - this.optimizeFloatExpressions = optimizeFloatExpr + slowCodegenWarnings = args.slowCodegenWarnings + optimize = args.optimize + optimizeFloatExpressions = optimizeFloatExpr + asmQuiet = args.quietAssembler + asmListfile = args.asmListfile } program = programresult importedFiles = imported processAst(program, args.errors, compilationOptions) - if (compilationOptions.optimize) + if (compilationOptions.optimize) { +// println("*********** AST RIGHT BEFORE OPTIMIZING *************") +// printProgram(program) + optimizeAst( program, compilationOptions, @@ -76,13 +82,14 @@ fun compileProgram(args: CompilerArguments): CompilationResult { BuiltinFunctionsFacade(BuiltinFunctions), compTarget ) + } postprocessAst(program, args.errors, compilationOptions) // println("*********** AST BEFORE ASSEMBLYGEN *************") // printProgram(program) if (args.writeAssembly) { - when (val result = writeAssembly(program, args.errors, args.outputDir, args.quietAssembler, compilationOptions)) { + when (val result = writeAssembly(program, args.errors, args.outputDir, compilationOptions)) { is WriteAssemblyResult.Ok -> programName = result.filename is WriteAssemblyResult.Fail -> { System.err.println(result.error) @@ -324,7 +331,6 @@ private sealed class WriteAssemblyResult { private fun writeAssembly(program: Program, errors: IErrorReporter, outputDir: Path, - quietAssembler: Boolean, compilerOptions: CompilationOptions ): WriteAssemblyResult { // asm generation directly from the Ast @@ -344,7 +350,7 @@ private fun writeAssembly(program: Program, errors.report() return if(assembly.valid && errors.noErrors()) { - val assemblerReturnStatus = assembly.assemble(quietAssembler, compilerOptions) + val assemblerReturnStatus = assembly.assemble(compilerOptions) if(assemblerReturnStatus!=0) WriteAssemblyResult.Fail("assembler step failed with return code $assemblerReturnStatus") else { diff --git a/compiler/src/prog8/compiler/astprocessing/ParentNodeChecker.kt b/compiler/src/prog8/compiler/astprocessing/ParentNodeChecker.kt index c28d414fb..25e9febe0 100644 --- a/compiler/src/prog8/compiler/astprocessing/ParentNodeChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/ParentNodeChecker.kt @@ -209,9 +209,9 @@ internal class ParentNodeChecker: AstWalker() { return noModifications } - override fun before(`when`: When, parent: Node): Iterable { - if(`when`.parent!==parent) - throw FatalAstException("parent node mismatch at $`when`") + override fun before(whenStmt: When, parent: Node): Iterable { + if(whenStmt.parent!==parent) + throw FatalAstException("parent node mismatch at $whenStmt") return noModifications } diff --git a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt index be706c5f1..36a7ef0ee 100644 --- a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt +++ b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt @@ -262,19 +262,19 @@ internal class StatementReorderer(val program: Program, return noModifications } - override fun after(`when`: When, parent: Node): Iterable { - val lastChoiceValues = `when`.choices.lastOrNull()?.values + override fun after(whenStmt: When, parent: Node): Iterable { + val lastChoiceValues = whenStmt.choices.lastOrNull()?.values if(lastChoiceValues?.isNotEmpty()==true) { - val elseChoice = `when`.choices.indexOfFirst { it.values==null || it.values?.isEmpty()==true } + val elseChoice = whenStmt.choices.indexOfFirst { it.values==null || it.values?.isEmpty()==true } if(elseChoice>=0) - errors.err("else choice must be the last one", `when`.choices[elseChoice].position) + errors.err("else choice must be the last one", whenStmt.choices[elseChoice].position) } - val choices = `when`.choiceValues(program).sortedBy { + val choices = whenStmt.choiceValues(program).sortedBy { it.first?.first() ?: Int.MAX_VALUE } - `when`.choices.clear() - choices.mapTo(`when`.choices) { it.second } + whenStmt.choices.clear() + choices.mapTo(whenStmt.choices) { it.second } return noModifications } @@ -448,8 +448,6 @@ internal class StatementReorderer(val program: Program, return noModifications } else { // clobber risk; evaluate the arguments on the CPU stack first (in reverse order)... - if (options.slowCodegenWarnings) - errors.warn("slow argument passing used to avoid register clobbering", call.position) val argOrder = options.compTarget.asmsubArgsEvalOrder(function) val scope = AnonymousScope(mutableListOf(), call.position) if(function.shouldSaveX()) { diff --git a/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt b/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt index eefc53c8e..1b44a3abf 100644 --- a/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt +++ b/compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt @@ -99,7 +99,8 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter) val rightBinExpr = expr.right as? BinaryExpression if(leftBinExpr!=null && leftBinExpr.operator=="==" && rightBinExpr!=null && rightBinExpr.operator=="==") { if(leftBinExpr.right is NumericLiteralValue && rightBinExpr.right is NumericLiteralValue) { - errors.warn("consider using 'in' or 'when' to test for multiple values", expr.position) + if(leftBinExpr.left isSameAs rightBinExpr.left) + errors.warn("consider using 'in' or 'when' to test for multiple values", expr.position) } } } diff --git a/compiler/test/TestCompilerOnExamples.kt b/compiler/test/TestCompilerOnExamples.kt index 53649587e..3c5b1f66b 100644 --- a/compiler/test/TestCompilerOnExamples.kt +++ b/compiler/test/TestCompilerOnExamples.kt @@ -30,6 +30,7 @@ private fun compileTheThing(filepath: Path, optimize: Boolean, target: ICompilat writeAssembly = true, slowCodegenWarnings = false, quietAssembler = true, + asmListfile = false, compilationTarget = target.name, outputDir = outputDir ) diff --git a/compiler/test/TestCompilerOptionLibdirs.kt b/compiler/test/TestCompilerOptionLibdirs.kt index ff4647bbb..22dcba967 100644 --- a/compiler/test/TestCompilerOptionLibdirs.kt +++ b/compiler/test/TestCompilerOptionLibdirs.kt @@ -44,6 +44,7 @@ class TestCompilerOptionSourcedirs: FunSpec({ writeAssembly = true, slowCodegenWarnings = false, quietAssembler = true, + asmListfile = false, compilationTarget = Cx16Target.name, sourceDirs, outputDir diff --git a/compiler/test/helpers/compileXyz.kt b/compiler/test/helpers/compileXyz.kt index 6c23f261b..37fd2abf9 100644 --- a/compiler/test/helpers/compileXyz.kt +++ b/compiler/test/helpers/compileXyz.kt @@ -51,6 +51,7 @@ internal fun compileFile( writeAssembly = writeAssembly, slowCodegenWarnings = false, quietAssembler = true, + asmListfile = false, platform.name, outputDir = outputDir, errors = errors ?: ErrorReporterForTests() diff --git a/compilerAst/src/prog8/ast/AstToSourceTextConverter.kt b/compilerAst/src/prog8/ast/AstToSourceTextConverter.kt index f01cdad73..f308556ff 100644 --- a/compilerAst/src/prog8/ast/AstToSourceTextConverter.kt +++ b/compilerAst/src/prog8/ast/AstToSourceTextConverter.kt @@ -428,12 +428,12 @@ class AstToSourceTextConverter(val output: (text: String) -> Unit, val program: outputlni("}}") } - override fun visit(`when`: When) { + override fun visit(whenStmt: When) { output("when ") - `when`.condition.accept(this) + whenStmt.condition.accept(this) outputln(" {") scopelevel++ - `when`.choices.forEach { it.accept(this) } + whenStmt.choices.forEach { it.accept(this) } scopelevel-- outputlni("}") } diff --git a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt index 9fc48e13d..f9598ec0d 100644 --- a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt +++ b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt @@ -1055,7 +1055,7 @@ class ContainmentCheck(var element: Expression, override fun referencesIdentifier(nameInSource: List): Boolean { if(element is IdentifierReference) return element.referencesIdentifier(nameInSource) - return iterable?.referencesIdentifier(nameInSource) ?: false + return iterable.referencesIdentifier(nameInSource) } override fun inferType(program: Program) = InferredTypes.knownFor(DataType.UBYTE) diff --git a/compilerAst/src/prog8/ast/walk/IAstVisitor.kt b/compilerAst/src/prog8/ast/walk/IAstVisitor.kt index 8ea30bfec..2f847865b 100644 --- a/compilerAst/src/prog8/ast/walk/IAstVisitor.kt +++ b/compilerAst/src/prog8/ast/walk/IAstVisitor.kt @@ -28,7 +28,7 @@ interface IAstVisitor { fun visit(containment: ContainmentCheck) { containment.element.accept(this) - containment.iterable?.accept(this) + containment.iterable.accept(this) } fun visit(block: Block) { @@ -172,9 +172,9 @@ interface IAstVisitor { fun visit(nop: Nop) { } - fun visit(`when`: When) { - `when`.condition.accept(this) - `when`.choices.forEach { it.accept(this) } + fun visit(whenStmt: When) { + whenStmt.condition.accept(this) + whenStmt.choices.forEach { it.accept(this) } } fun visit(whenChoice: WhenChoice) { diff --git a/compilerInterfaces/src/prog8/compilerinterface/CompilationOptions.kt b/compilerInterfaces/src/prog8/compilerinterface/CompilationOptions.kt index 67e75dc61..c8ea565f2 100644 --- a/compilerInterfaces/src/prog8/compilerinterface/CompilationOptions.kt +++ b/compilerInterfaces/src/prog8/compilerinterface/CompilationOptions.kt @@ -28,5 +28,7 @@ class CompilationOptions(val output: OutputType, // these are set based on command line arguments: var slowCodegenWarnings: Boolean = false, var optimize: Boolean = false, - var optimizeFloatExpressions: Boolean = false + var optimizeFloatExpressions: Boolean = false, + var asmQuiet: Boolean = false, + var asmListfile: Boolean = false ) diff --git a/compilerInterfaces/src/prog8/compilerinterface/IAssemblyGenerator.kt b/compilerInterfaces/src/prog8/compilerinterface/IAssemblyGenerator.kt index 4cf4e4c69..934485fec 100644 --- a/compilerInterfaces/src/prog8/compilerinterface/IAssemblyGenerator.kt +++ b/compilerInterfaces/src/prog8/compilerinterface/IAssemblyGenerator.kt @@ -11,5 +11,5 @@ const val subroutineFloatEvalResultVar2 = "_prog8_float_eval_result2" interface IAssemblyProgram { val valid: Boolean val name: String - fun assemble(quiet: Boolean, options: CompilationOptions): Int + fun assemble(options: CompilationOptions): Int } diff --git a/docs/source/building.rst b/docs/source/building.rst index 528184b33..9145df64d 100644 --- a/docs/source/building.rst +++ b/docs/source/building.rst @@ -144,6 +144,9 @@ One or more .p8 module files ``-quietasm`` Don't print assembler output results. +``-asmlist`` + Generate an assembler listing file as well. + Module source code files ------------------------ diff --git a/docs/source/index.rst b/docs/source/index.rst index 11b29bb70..0b6bbfbf6 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -54,6 +54,9 @@ Language features - Subroutines with parameters and return values - Complex nested expressions are possible - Variables are allocated statically +- Conditional branches to map directly on processor branch instructions +- ``when`` statement to avoid if-else chains +- ``in`` expression for concise and efficient multi-value/containment test - Nested subroutines can access variables from outer scopes to avoids the overhead to pass everything via parameters - Variable data types include signed and unsigned bytes and words, arrays, strings. - Floating point math also supported if the target system provides floating point library routines (C64 and Cx16 both do). diff --git a/docs/source/todo.rst b/docs/source/todo.rst index a735c6c0d..3bb0f63e9 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -5,6 +5,7 @@ For next compiler release (7.6) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... + Blocked by an official Commander-x16 v39 release ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - simplify cx16.joystick_get2() once this cx16 rom issue is resolved: https://github.com/commanderx16/x16-rom/issues/203 @@ -13,10 +14,10 @@ Blocked by an official Commander-x16 v39 release Future ^^^^^^ +- make some sort of "porting guide" with things required to support a new target platform - make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as ``v_`` then we can get rid of the instruction lists in the machinedefinitions as well? - fix the asm-labels problem (github issue #62) -- make (an option) to let 64tass produce a listing file as well as output. - simplifyConditionalExpression() should not split expression if it still results in stack-based evaluation - simplifyConditionalExpression() sometimes introduces needless assignment to r9 tempvar - get rid of all TODO's in the code @@ -41,7 +42,6 @@ Future More code optimization ideas ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - automatically convert if statements that test for multiple values (if X==1 or X==2..) to if X in [1,2,..] statements, instead of just a warning -- - byte typed expressions should be evaluated in the accumulator where possible, without (temp)var for instance value = otherbyte >> 1 --> lda otherbite ; lsr a; sta value - rewrite expression tree evaluation such that it doesn't use an eval stack but flatten the tree into linear code that uses a fixed number of predetermined value 'variables' diff --git a/examples/cx16/bobs.p8 b/examples/cx16/bobs.p8 index d15ed0f79..404fb6657 100644 --- a/examples/cx16/bobs.p8 +++ b/examples/cx16/bobs.p8 @@ -8,7 +8,7 @@ main { sub start() { - cx16.screen_set_mode(0) + void cx16.screen_set_mode(0) txt.print("\n\n how many sprites does\n the commander x16 have?\n") sys.wait(120) txt.print("\n\n the manual says: '128'.\n") diff --git a/examples/cx16/rasterbars.p8 b/examples/cx16/rasterbars.p8 index 94b2bf4b2..2ecb31bfc 100644 --- a/examples/cx16/rasterbars.p8 +++ b/examples/cx16/rasterbars.p8 @@ -8,7 +8,7 @@ main { sub start() { - cx16.screen_set_mode(0) + void cx16.screen_set_mode(0) txt.plot(14,14) txt.print("raster bars!") diff --git a/examples/textelite.p8 b/examples/textelite.p8 index c0371bb0a..669c7ee6b 100644 --- a/examples/textelite.p8 +++ b/examples/textelite.p8 @@ -870,7 +870,7 @@ planet { ubyte ni for ni in 1 to len(name) { ubyte cc = name[ni] - if cc=='e' or cc=='o' or cc==0 + if cc in ['e', 'o', 0] break else { @(result_ptr) = cc diff --git a/httpCompilerService/src/prog8/http/TestHttp.kt b/httpCompilerService/src/prog8/http/TestHttp.kt index 863df7672..e0e28ae95 100644 --- a/httpCompilerService/src/prog8/http/TestHttp.kt +++ b/httpCompilerService/src/prog8/http/TestHttp.kt @@ -37,7 +37,8 @@ class RequestParser : Take { writeAssembly = true, slowCodegenWarnings = true, compilationTarget = "c64", - quietAssembler = false + quietAssembler = false, + asmListfile = false ) val compilationResult = compileProgram(args) return RsJson(Jsonding())