diff --git a/codeCore/src/prog8/code/core/CompilationOptions.kt b/codeCore/src/prog8/code/core/CompilationOptions.kt index 0f288d8d2..4e761584e 100644 --- a/codeCore/src/prog8/code/core/CompilationOptions.kt +++ b/codeCore/src/prog8/code/core/CompilationOptions.kt @@ -20,5 +20,6 @@ class CompilationOptions(val output: OutputType, var asmQuiet: Boolean = false, var asmListfile: Boolean = false, var experimentalCodegen: Boolean = false, - var outputDir: Path = Path("") + var outputDir: Path = Path(""), + var symbolDefs: Map = emptyMap() ) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt index 3af893a74..dba2abc0d 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt @@ -73,6 +73,13 @@ internal class ProgramAndVarsGen( asmgen.out("P8ESTACK_LO = ${compTarget.machine.ESTACK_LO.toHex()}") asmgen.out("P8ESTACK_HI = ${compTarget.machine.ESTACK_HI.toHex()}") + if(options.symbolDefs.isNotEmpty()) { + asmgen.out("; -- user supplied symbols on the command line") + for((name, value) in options.symbolDefs) { + asmgen.out("$name = $value") + } + } + when(options.output) { OutputType.RAW -> { asmgen.out("; ---- raw assembler program ----") diff --git a/codeGenExperimental/src/prog8/codegen/experimental/AstToXmlConverter.kt b/codeGenExperimental/src/prog8/codegen/experimental/AstToXmlConverter.kt index 9f3bad30d..0269e885e 100644 --- a/codeGenExperimental/src/prog8/codegen/experimental/AstToXmlConverter.kt +++ b/codeGenExperimental/src/prog8/codegen/experimental/AstToXmlConverter.kt @@ -144,6 +144,15 @@ class AstToXmlConverter(internal val program: PtProgram, xml.endElt() } } + if(options.symbolDefs.isNotEmpty()) { + xml.startChildren() + options.symbolDefs.forEach { name, value -> + xml.elt("symboldef") + xml.attr("name", name) + xml.attr("value", value) + xml.endElt() + } + } xml.endElt() } diff --git a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt index 1524c6640..e8a7dcffb 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt @@ -58,6 +58,9 @@ class CodeGen(internal val program: PtProgram, } } + if(options.symbolDefs.isNotEmpty()) + throw AssemblyError("virtual target doesn't support symbols defined on the commandline") + for (block in program.allBlocks()) { vmprog.addBlock(translate(block)) } diff --git a/compiler/src/prog8/CompilerMain.kt b/compiler/src/prog8/CompilerMain.kt index bb8453b80..f0de75ba2 100644 --- a/compiler/src/prog8/CompilerMain.kt +++ b/compiler/src/prog8/CompilerMain.kt @@ -46,10 +46,10 @@ private fun compileMain(args: Array): Boolean { 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 experimentalCodegen by cli.option(ArgType.Boolean, fullName = "expericodegen", description = "use experimental/alternative codegen") - val compilationTarget by cli.option(ArgType.String, fullName = "target", description = "target output of the compiler (one of '${C64Target.NAME}', '${C128Target.NAME}', '${Cx16Target.NAME}', '${AtariTarget.NAME}', '${VMTarget.NAME}')") - .default(C64Target.NAME) + val compilationTarget by cli.option(ArgType.String, fullName = "target", description = "target output of the compiler (one of '${C64Target.NAME}', '${C128Target.NAME}', '${Cx16Target.NAME}', '${AtariTarget.NAME}', '${VMTarget.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 startVm by cli.option(ArgType.Boolean, fullName = "vm", description = "load and run a p8-virt listing in the VM instead") + val symbolDefs by cli.option(ArgType.String, fullName = "D", description = "define assembly symbol(s) like -D SYMBOL=VALUE").multiple() val moduleFiles by cli.argument(ArgType.String, fullName = "modules", description = "main module file(s) to compile").multiple(999) try { @@ -84,6 +84,8 @@ private fun compileMain(args: Array): Boolean { return runVm(moduleFiles.first()) } + val processedSymbols = processSymbolDefs(symbolDefs) ?: return false + if(watchMode==true) { val watchservice = FileSystems.getDefault().newWatchService() val allImportedFiles = mutableSetOf() @@ -104,6 +106,7 @@ private fun compileMain(args: Array): Boolean { asmListfile == true, experimentalCodegen == true, compilationTarget, + processedSymbols, srcdirs, outputPath ) @@ -156,6 +159,7 @@ private fun compileMain(args: Array): Boolean { asmListfile == true, experimentalCodegen == true, compilationTarget, + processedSymbols, srcdirs, outputPath ) @@ -193,6 +197,21 @@ private fun compileMain(args: Array): Boolean { return true } +private fun processSymbolDefs(symbolDefs: List): Map? { + val result = mutableMapOf() + val defPattern = """(.+)\s*=\s*(.+)""".toRegex() + for(def in symbolDefs) { + val match = defPattern.matchEntire(def.trim()) + if(match==null) { + System.err.println("invalid symbol definition (expected NAME=VALUE): $def") + return null + } + val (_, name, value) = match.groupValues + result[name.trim()] = value.trim() + } + return result +} + fun runVm(listingFilename: String): Boolean { val name = if(listingFilename.endsWith(".p8virt")) diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index dcdb86e0d..ab09ca216 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -38,6 +38,7 @@ class CompilerArguments(val filepath: Path, val asmListfile: Boolean, val experimentalCodegen: Boolean, val compilationTarget: String, + val symbolDefs: Map, val sourceDirs: List = emptyList(), val outputDir: Path = Path(""), val errors: IErrorReporter = ErrorReporter()) @@ -78,6 +79,7 @@ fun compileProgram(args: CompilerArguments): CompilationResult? { asmListfile = args.asmListfile experimentalCodegen = args.experimentalCodegen outputDir = args.outputDir.normalize() + symbolDefs = args.symbolDefs } program = programresult importedFiles = imported diff --git a/compiler/test/TestCompilerOnExamples.kt b/compiler/test/TestCompilerOnExamples.kt index 2f7381612..7ad828452 100644 --- a/compiler/test/TestCompilerOnExamples.kt +++ b/compiler/test/TestCompilerOnExamples.kt @@ -37,6 +37,7 @@ private fun compileTheThing(filepath: Path, optimize: Boolean, target: ICompilat asmListfile = false, experimentalCodegen = false, compilationTarget = target.name, + symbolDefs = emptyMap(), outputDir = outputDir ) return compileProgram(args) diff --git a/compiler/test/TestCompilerOptionLibdirs.kt b/compiler/test/TestCompilerOptionLibdirs.kt index 35325912d..c57008ee2 100644 --- a/compiler/test/TestCompilerOptionLibdirs.kt +++ b/compiler/test/TestCompilerOptionLibdirs.kt @@ -51,6 +51,7 @@ class TestCompilerOptionSourcedirs: FunSpec({ asmListfile = false, experimentalCodegen = false, compilationTarget = Cx16Target.NAME, + symbolDefs = emptyMap(), sourceDirs, outputDir ) diff --git a/compiler/test/helpers/compileXyz.kt b/compiler/test/helpers/compileXyz.kt index c2bb6efd1..28e97a326 100644 --- a/compiler/test/helpers/compileXyz.kt +++ b/compiler/test/helpers/compileXyz.kt @@ -37,6 +37,7 @@ internal fun compileFile( asmListfile = false, experimentalCodegen = false, platform.name, + symbolDefs = emptyMap(), outputDir = outputDir, errors = errors ?: ErrorReporterForTests() ) diff --git a/httpCompilerService/src/prog8/http/TestHttp.kt b/httpCompilerService/src/prog8/http/TestHttp.kt index 033b9f83a..da711f333 100644 --- a/httpCompilerService/src/prog8/http/TestHttp.kt +++ b/httpCompilerService/src/prog8/http/TestHttp.kt @@ -38,6 +38,7 @@ class RequestParser : Take { writeAssembly = true, slowCodegenWarnings = true, compilationTarget = "c64", + symbolDefs = emptyMap(), quietAssembler = false, asmListfile = false, experimentalCodegen = false