add -plaintext and -ignorefootguns options

This commit is contained in:
Irmen de Jong 2024-12-03 18:55:55 +01:00
parent 8341f9c066
commit 1ebfff7c7b
10 changed files with 72 additions and 15 deletions

View File

@ -29,6 +29,7 @@ class CompilationOptions(val output: OutputType,
var slabsGolden: Boolean = false,
var splitWordArrays: Boolean = false,
var breakpointCpuInstruction: String? = null,
var ignoreFootguns: Boolean = false,
var outputDir: Path = Path(""),
var symbolDefs: Map<String, String> = emptyMap()
) {

View File

@ -7,6 +7,7 @@ import prog8.code.target.*
import prog8.code.target.virtual.VirtualMachineDefinition
import prog8.compiler.CompilationResult
import prog8.compiler.CompilerArguments
import prog8.compiler.ErrorReporter
import prog8.compiler.compileProgram
import java.io.File
import java.nio.file.FileSystems
@ -52,10 +53,12 @@ private fun compileMain(args: Array<String>): Boolean {
val startEmulator2 by cli.option(ArgType.Boolean, fullName = "emu2", description = "auto-start alternative emulator after successful compilation")
val experimentalCodegen by cli.option(ArgType.Boolean, fullName = "expericodegen", description = "use experimental/alternative codegen")
val float2bytes by cli.option(ArgType.String, fullName = "float2bytes", description = "convert floating point number to a list of bytes for the target system. NOTE: you need to supply a target option too, and also still have to supply a dummy module file name as well!")
val ignoreFootguns by cli.option(ArgType.Boolean, fullName = "ignorefootguns", description = "don't print warnings for 'footgun' issues: 'Yes I know I'm treading on mighty thin ice here'.")
val dontWriteAssembly by cli.option(ArgType.Boolean, fullName = "noasm", description="don't create assembly code")
val dontOptimize by cli.option(ArgType.Boolean, fullName = "noopt", description = "don't perform code optimizations")
val outputDir by cli.option(ArgType.String, fullName = "out", description = "directory for output files instead of current directory").default(".")
val printAst1 by cli.option(ArgType.Boolean, fullName = "printast1", description = "print out the compiler AST")
val plainText by cli.option(ArgType.Boolean, fullName = "plaintext", description = "output only plain text, no colors or fancy symbols")
val printAst2 by cli.option(ArgType.Boolean, fullName = "printast2", description = "print out the intermediate AST that is used for code generation")
val quietAssembler by cli.option(ArgType.Boolean, fullName = "quietasm", description = "don't print assembler output results")
val slabsGolden by cli.option(ArgType.Boolean, fullName = "slabsgolden", description = "put memory() slabs in 'golden ram' memory area instead of at the end of the program. On the cx16 target this is $0400-07ff. This is unavailable on other systems.")
@ -162,6 +165,7 @@ private fun compileMain(args: Array<String>): Boolean {
results.clear()
for(filepathRaw in moduleFiles) {
val filepath = pathFrom(filepathRaw).normalize()
val txtcolors = if(plainText==true) ErrorReporter.PlainText else ErrorReporter.AnsiColors
val compilerArgs = CompilerArguments(
filepath,
if(checkSource==true) false else dontOptimize != true,
@ -182,9 +186,11 @@ private fun compileMain(args: Array<String>): Boolean {
breakpointCpuInstruction,
printAst1 == true,
printAst2 == true,
ignoreFootguns == true,
processedSymbols,
srcdirs,
outputPath
outputPath,
errors = ErrorReporter(txtcolors)
)
val compilationResult = compileProgram(compilerArgs)
@ -242,6 +248,7 @@ private fun compileMain(args: Array<String>): Boolean {
val filepath = pathFrom(filepathRaw).normalize()
val compilationResult: CompilationResult
try {
val txtcolors = if(plainText==true) ErrorReporter.PlainText else ErrorReporter.AnsiColors
val compilerArgs = CompilerArguments(
filepath,
if(checkSource==true) false else dontOptimize != true,
@ -262,9 +269,11 @@ private fun compileMain(args: Array<String>): Boolean {
breakpointCpuInstruction,
printAst1 == true,
printAst2 == true,
ignoreFootguns == true,
processedSymbols,
srcdirs,
outputPath
outputPath,
errors = ErrorReporter(txtcolors)
)
val result = compileProgram(compilerArgs)

View File

@ -52,10 +52,11 @@ class CompilerArguments(val filepath: Path,
val breakpointCpuInstruction: String?,
val printAst1: Boolean,
val printAst2: Boolean,
val ignoreFootguns: Boolean,
val symbolDefs: Map<String, String>,
val sourceDirs: List<String> = emptyList(),
val outputDir: Path = Path(""),
val errors: IErrorReporter = ErrorReporter())
val errors: IErrorReporter = ErrorReporter(ErrorReporter.AnsiColors))
fun compileProgram(args: CompilerArguments): CompilationResult? {
@ -81,6 +82,7 @@ fun compileProgram(args: CompilerArguments): CompilationResult? {
dumpVariables = args.dumpVariables
dumpSymbols = args.dumpSymbols
breakpointCpuInstruction = args.breakpointCpuInstruction
ignoreFootguns = args.ignoreFootguns
varsHighBank = args.varsHighBank
varsGolden = args.varsGolden
slabsHighBank = args.slabsHighBank
@ -337,7 +339,7 @@ fun parseMainModule(filepath: Path,
return Triple(program, compilerOptions, importedFiles)
}
fun determineCompilationOptions(program: Program, compTarget: ICompilationTarget): CompilationOptions {
internal fun determineCompilationOptions(program: Program, compTarget: ICompilationTarget): CompilationOptions {
val toplevelModule = program.toplevelModule
val outputDirective = (toplevelModule.statements.singleOrNull { it is Directive && it.directive == "%output" } as? Directive)
val launcherDirective = (toplevelModule.statements.singleOrNull { it is Directive && it.directive == "%launcher" } as? Directive)

View File

@ -2,9 +2,9 @@ package prog8.compiler
import prog8.code.core.IErrorReporter
import prog8.code.core.Position
import java.io.PrintStream
internal class ErrorReporter: IErrorReporter {
internal class ErrorReporter(val colors: IConsoleColors): IErrorReporter {
private enum class MessageSeverity {
INFO,
WARNING,
@ -44,20 +44,27 @@ internal class ErrorReporter: IErrorReporter {
when(it.severity) {
MessageSeverity.ERROR -> {
System.out.flush()
printer.print("\u001b[91mERROR\u001B[0m ") // bright red
colors.error(printer)
printer.print("ERROR ")
colors.normal(printer)
numErrors++
}
MessageSeverity.WARNING -> {
printer.print("\u001b[93mWARN\u001B[0m ") // bright yellow
colors.warning(printer)
printer.print("WARN ")
colors.normal(printer)
numWarnings++
}
MessageSeverity.INFO -> {
printer.print("\u001b[92mINFO\u001B[0m ") // bright green
colors.info(printer)
printer.print("INFO ")
colors.normal(printer)
numInfos++
}
}
printer.println(msg)
alreadyReportedMessages.add(msg)
val filtered = colors.filtered(msg)
printer.println(filtered)
alreadyReportedMessages.add(filtered)
}
}
System.out.flush()
@ -69,4 +76,28 @@ internal class ErrorReporter: IErrorReporter {
override fun noErrors() = messages.none { it.severity==MessageSeverity.ERROR }
override fun noErrorForLine(position: Position) = !messages.any { it.position.line==position.line && it.severity!=MessageSeverity.INFO }
interface IConsoleColors {
fun error(printer: PrintStream)
fun warning(printer: PrintStream)
fun info(printer: PrintStream)
fun normal(printer: PrintStream)
fun filtered(msg: String): String
}
object AnsiColors: IConsoleColors {
override fun error(printer: PrintStream) = printer.print("\u001b[91m") // red
override fun warning(printer: PrintStream) = printer.print("\u001b[93m") // yellow
override fun info(printer: PrintStream) = printer.print("\u001b[92m") // green
override fun normal(printer: PrintStream) = printer.print("\u001B[0m")
override fun filtered(msg: String): String = msg
}
object PlainText: IConsoleColors {
override fun error(printer: PrintStream) {}
override fun warning(printer: PrintStream) {}
override fun info(printer: PrintStream) {}
override fun normal(printer: PrintStream) {}
override fun filtered(msg: String): String = msg.filter { !it.isSurrogate() }
}
}

View File

@ -516,7 +516,8 @@ internal class AstChecker(private val program: Program,
if (!subroutine.isAsmSubroutine && p.registerOrPair!=null) {
if (p.registerOrPair !in Cx16VirtualRegisters) errors.err("can only use R0-R15 as register param for normal subroutines", p.position)
else {
errors.warn("\uD83D\uDCA3 footgun: reusing R0-R15 as parameters risks overwriting due to clobbering or no callstack", subroutine.position)
if(!compilerOptions.ignoreFootguns)
errors.warn("\uD83D\uDCA3 footgun: reusing R0-R15 as parameters risks overwriting due to clobbering or no callstack", subroutine.position)
if(p.type !in WordDatatypes && p.type !in ByteDatatypesWithBoolean) {
errors.err("can only use register param when type is boolean, byte or word", p.position)
}
@ -929,8 +930,10 @@ internal class AstChecker(private val program: Program,
if(decl.datatype==DataType.STR)
errors.err("string variables cannot be @dirty", decl.position)
else {
if(decl.value==null)
errors.warn("\uD83D\uDCA3 footgun: dirty variable, initial value will be undefined", decl.position)
if(decl.value==null) {
if(!compilerOptions.ignoreFootguns)
errors.warn("\uD83D\uDCA3 footgun: dirty variable, initial value will be undefined", decl.position)
}
else
errors.err("dirty variable can't have initialization value", decl.position)
}

View File

@ -43,6 +43,7 @@ private fun compileTheThing(filepath: Path, optimize: Boolean, target: ICompilat
breakpointCpuInstruction = null,
printAst1 = false,
printAst2 = false,
ignoreFootguns = false,
symbolDefs = emptyMap(),
outputDir = outputDir
)

View File

@ -41,6 +41,7 @@ class TestCompilerOptionSourcedirs: FunSpec({
breakpointCpuInstruction = null,
printAst1 = false,
printAst2 = false,
ignoreFootguns = false,
symbolDefs = emptyMap(),
sourceDirs,
outputDir

View File

@ -43,6 +43,7 @@ internal fun compileFile(
breakpointCpuInstruction = null,
printAst1 = false,
printAst2 = false,
ignoreFootguns = false,
)
return compileProgram(args)
}

View File

@ -176,6 +176,12 @@ One or more .p8 module files
NOTE: you need to supply a target option too, and also still have to supply a dummy module file name as well!
Also see -bytes2float
``-ignorefootguns``
Don't print warnings for 'footgun' issues.
Footgun issues are certain things you can do in Prog8 that may make your program blow up unexpectedly,
for instance uncareful use of dirty variables, or reusing the R0-R15 registers for subroutine parameters.
With this option you're basically saying: "Yes, I know I am treading on mighty thin ice here, but I don't want to be reminded about that".
``-noasm``
Do not create assembly code and output program.
Useful for debugging or doing quick syntax checks.
@ -187,6 +193,9 @@ One or more .p8 module files
``-out <directory>``
sets directory location for output files instead of current directory
``-plaintext``
Prints output messages in plain text: no colors or fancy symbols.
``-printast1``
Prints the "compiler AST" (the internal representation of the program) after all processing steps.

View File

@ -1,7 +1,6 @@
TODO
====
add a -plain option to turn off text output coloring and unicode symbols in error messages (footguns)
make a compiler switch to disable footgun warnings -ignorefootguns
update zsmkit to newest version that includes the on_deck routines when stabilized