mirror of
https://github.com/irmen/prog8.git
synced 2025-02-19 11:31:07 +00:00
simplify DirectiveArg
This commit is contained in:
parent
216825b98a
commit
75ddcda5f3
@ -367,10 +367,10 @@ internal fun determineCompilationOptions(program: Program, compTarget: ICompilat
|
||||
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)
|
||||
val outputTypeStr = outputDirective?.args?.single()?.name?.uppercase()
|
||||
val launcherTypeStr = launcherDirective?.args?.single()?.name?.uppercase()
|
||||
val outputTypeStr = outputDirective?.args?.single()?.string?.uppercase()
|
||||
val launcherTypeStr = launcherDirective?.args?.single()?.string?.uppercase()
|
||||
val zpoption: String? = (toplevelModule.statements.singleOrNull { it is Directive && it.directive == "%zeropage" }
|
||||
as? Directive)?.args?.single()?.name?.uppercase()
|
||||
as? Directive)?.args?.single()?.string?.uppercase()
|
||||
val allOptions = program.modules.flatMap { it.options() }.toSet()
|
||||
val floatsEnabled = "enable_floats" in allOptions
|
||||
var noSysInit = "no_sysinit" in allOptions
|
||||
|
@ -46,7 +46,7 @@ class ModuleImporter(private val program: Program,
|
||||
|
||||
fun importImplicitLibraryModule(name: String): Module? {
|
||||
val import = Directive("%import", listOf(
|
||||
DirectiveArg("", name, 42u, position = Position("<<<implicit-import>>>", 0, 0, 0))
|
||||
DirectiveArg(name, 42u, position = Position("<<<implicit-import>>>", 0, 0, 0))
|
||||
), Position("<<<implicit-import>>>", 0, 0, 0))
|
||||
return executeImportDirective(import, null)
|
||||
}
|
||||
@ -75,9 +75,7 @@ class ModuleImporter(private val program: Program,
|
||||
private fun executeImportDirective(import: Directive, importingModule: Module?): Module? {
|
||||
if(import.directive!="%import" || import.args.size!=1)
|
||||
throw SyntaxError("invalid import directive", import.position)
|
||||
if(!import.args[0].str.isNullOrEmpty() || import.args[0].name==null)
|
||||
throw SyntaxError("%import requires unquoted module name", import.position)
|
||||
val moduleName = import.args[0].name!!
|
||||
val moduleName = import.args[0].string!!
|
||||
if("$moduleName.p8" == import.position.file)
|
||||
throw SyntaxError("cannot import self", import.position)
|
||||
|
||||
|
@ -955,24 +955,24 @@ internal class AstChecker(private val program: Program,
|
||||
"%output" -> {
|
||||
if(directive.parent !is Module)
|
||||
err("this directive may only occur at module level")
|
||||
if(directive.args.size!=1 || directive.args[0].name !in OutputType.entries.map {it.name.lowercase()})
|
||||
if(directive.args.size!=1 || directive.args[0].string !in OutputType.entries.map {it.name.lowercase()})
|
||||
err("invalid output directive type")
|
||||
}
|
||||
"%launcher" -> {
|
||||
if(directive.parent !is Module)
|
||||
err("this directive may only occur at module level")
|
||||
if(directive.args.size!=1 || directive.args[0].name !in CbmPrgLauncherType.entries.map{it.name.lowercase()})
|
||||
if(directive.args.size!=1 || directive.args[0].string !in CbmPrgLauncherType.entries.map{it.name.lowercase()})
|
||||
err("invalid launcher directive type")
|
||||
}
|
||||
"%zeropage" -> {
|
||||
if(directive.parent !is Module)
|
||||
err("this directive may only occur at module level")
|
||||
if(directive.args.size!=1 ||
|
||||
directive.args[0].name != "basicsafe" &&
|
||||
directive.args[0].name != "floatsafe" &&
|
||||
directive.args[0].name != "kernalsafe" &&
|
||||
directive.args[0].name != "dontuse" &&
|
||||
directive.args[0].name != "full")
|
||||
directive.args[0].string != "basicsafe" &&
|
||||
directive.args[0].string != "floatsafe" &&
|
||||
directive.args[0].string != "kernalsafe" &&
|
||||
directive.args[0].string != "dontuse" &&
|
||||
directive.args[0].string != "full")
|
||||
err("invalid zp type, expected basicsafe, floatsafe, kernalsafe, dontuse, or full")
|
||||
}
|
||||
"%zpreserved", "%zpallowed" -> {
|
||||
@ -998,9 +998,9 @@ internal class AstChecker(private val program: Program,
|
||||
"%import" -> {
|
||||
if(directive.parent !is Module)
|
||||
err("this directive may only occur at module level")
|
||||
if(directive.args.size!=1 || directive.args[0].name==null)
|
||||
if(directive.args.size!=1 || directive.args[0].string==null)
|
||||
err("invalid import directive, expected module name argument")
|
||||
if(directive.args[0].name == (directive.parent as? Module)?.name)
|
||||
if(directive.args[0].string == (directive.parent as? Module)?.name)
|
||||
err("invalid import directive, cannot import itself")
|
||||
}
|
||||
"%breakpoint" -> {
|
||||
@ -1012,44 +1012,44 @@ internal class AstChecker(private val program: Program,
|
||||
"%asminclude" -> {
|
||||
if(directive.parent !is INameScope || directive.parent is Module)
|
||||
err("this directive can't be used here")
|
||||
if(directive.args.size!=1 || directive.args[0].str==null)
|
||||
if(directive.args.size!=1 || directive.args[0].string==null)
|
||||
err("invalid asminclude directive, expected argument: \"filename\"")
|
||||
checkFileExists(directive, directive.args[0].str!!)
|
||||
checkFileExists(directive, directive.args[0].string!!)
|
||||
}
|
||||
"%asmbinary" -> {
|
||||
if(directive.parent !is INameScope || directive.parent is Module)
|
||||
err("this directive can't be used here")
|
||||
val errormsg = "invalid asmbinary directive, expected arguments: \"filename\" [, offset [, length ] ]"
|
||||
if(directive.args.isEmpty()) err(errormsg)
|
||||
else if(directive.args[0].str==null) err(errormsg)
|
||||
else if(directive.args[0].string==null) err(errormsg)
|
||||
else if(directive.args.size>=2 && directive.args[1].int==null) err(errormsg)
|
||||
else if(directive.args.size==3 && directive.args[2].int==null) err(errormsg)
|
||||
else if(directive.args.size>3) err(errormsg)
|
||||
else checkFileExists(directive, directive.args[0].str!!)
|
||||
else checkFileExists(directive, directive.args[0].string!!)
|
||||
}
|
||||
"%option" -> {
|
||||
if(directive.parent !is Block && directive.parent !is Module)
|
||||
err("this directive may only occur in a block or at module level")
|
||||
if(directive.args.isEmpty())
|
||||
err("missing option directive argument(s)")
|
||||
else if(directive.args.map{it.name in arrayOf("enable_floats", "force_output", "no_sysinit", "merge", "verafxmuls", "no_symbol_prefixing", "ignore_unused")}.any { !it })
|
||||
else if(directive.args.map{it.string in arrayOf("enable_floats", "force_output", "no_sysinit", "merge", "verafxmuls", "no_symbol_prefixing", "ignore_unused")}.any { !it })
|
||||
err("invalid option directive argument(s)")
|
||||
if(directive.parent is Block) {
|
||||
if(directive.args.any {it.name !in arrayOf("force_output", "merge", "verafxmuls", "no_symbol_prefixing", "ignore_unused")})
|
||||
if(directive.args.any {it.string !in arrayOf("force_output", "merge", "verafxmuls", "no_symbol_prefixing", "ignore_unused")})
|
||||
err("using an option that is not valid for blocks")
|
||||
}
|
||||
if(directive.parent is Module) {
|
||||
if(directive.args.any {it.name !in arrayOf("enable_floats", "no_sysinit", "no_symbol_prefixing", "ignore_unused")})
|
||||
if(directive.args.any {it.string !in arrayOf("enable_floats", "no_sysinit", "no_symbol_prefixing", "ignore_unused")})
|
||||
err("using an option that is not valid for modules")
|
||||
}
|
||||
if(directive.args.any { it.name=="verafxmuls" } && compilerOptions.compTarget.name != Cx16Target.NAME)
|
||||
if(directive.args.any { it.string=="verafxmuls" } && compilerOptions.compTarget.name != Cx16Target.NAME)
|
||||
err("verafx option is only valid on cx16 target")
|
||||
}
|
||||
"%encoding" -> {
|
||||
if(directive.parent !is Module)
|
||||
err("this directive may only occur at module level")
|
||||
val allowedEncodings = Encoding.entries.map {it.prefix}
|
||||
if(directive.args.size!=1 || directive.args[0].name !in allowedEncodings)
|
||||
if(directive.args.size!=1 || directive.args[0].string !in allowedEncodings)
|
||||
err("invalid encoding directive, expected one of $allowedEncodings")
|
||||
}
|
||||
else -> throw SyntaxError("invalid directive ${directive.directive}", directive.position)
|
||||
|
@ -201,13 +201,13 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
|
||||
val directives = srcBlock.statements.filterIsInstance<Directive>()
|
||||
for (directive in directives.filter { it.directive == "%option" }) {
|
||||
for (arg in directive.args) {
|
||||
when (arg.name) {
|
||||
when (arg.string) {
|
||||
"no_symbol_prefixing" -> noSymbolPrefixing = true
|
||||
"ignore_unused" -> ignoreUnused = true
|
||||
"force_output" -> forceOutput = true
|
||||
"merge" -> { /* ignore this one */ }
|
||||
"verafxmuls" -> veraFxMuls = true
|
||||
else -> throw FatalAstException("weird directive option: ${arg.name}")
|
||||
else -> throw FatalAstException("weird directive option: ${arg.string}")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -253,7 +253,7 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
|
||||
PtAlign(align, directive.position)
|
||||
}
|
||||
"%asmbinary" -> {
|
||||
val filename = directive.args[0].str!!
|
||||
val filename = directive.args[0].string!!
|
||||
val offset: UInt? = if(directive.args.size>=2) directive.args[1].int!! else null
|
||||
val length: UInt? = if(directive.args.size>=3) directive.args[2].int!! else null
|
||||
val abspath = if(File(filename).isFile) {
|
||||
@ -268,7 +268,7 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
|
||||
throw FatalAstException("included file doesn't exist")
|
||||
}
|
||||
"%asminclude" -> {
|
||||
val result = loadAsmIncludeFile(directive.args[0].str!!, directive.definingModule.source)
|
||||
val result = loadAsmIncludeFile(directive.args[0].string!!, directive.definingModule.source)
|
||||
val assembly = result.getOrElse { throw it }
|
||||
PtInlineAssembly(assembly.trimEnd().trimStart('\r', '\n'), false, directive.position)
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
|
||||
override fun after(block: Block, parent: Node): Iterable<IAstModification> {
|
||||
val inheritOptions = block.definingModule.options() intersect setOf("no_symbol_prefixing", "ignore_unused") subtract block.options()
|
||||
if(inheritOptions.isNotEmpty()) {
|
||||
val directive = Directive("%option", inheritOptions.map{ DirectiveArg(null, it, null, block.position) }, block.position)
|
||||
val directive = Directive("%option", inheritOptions.map{ DirectiveArg(it, null, block.position) }, block.position)
|
||||
return listOf(IAstModification.InsertFirst(directive, block))
|
||||
}
|
||||
|
||||
|
@ -107,8 +107,7 @@ class AstToSourceTextConverter(val output: (text: String) -> Unit, val program:
|
||||
for(arg in directive.args) {
|
||||
when {
|
||||
arg.int!=null -> output(arg.int.toString())
|
||||
arg.name!=null -> output(arg.name)
|
||||
arg.str!=null -> output("\"${arg.str}\"")
|
||||
arg.string!=null -> output(arg.string)
|
||||
}
|
||||
if(arg!==directive.args.last())
|
||||
output(",")
|
||||
|
@ -328,7 +328,7 @@ open class Module(final override val statements: MutableList<Statement>,
|
||||
|
||||
override fun toString() = "Module(name=$name, pos=$position, lib=${isLibrary})"
|
||||
override fun referencesIdentifier(nameInSource: List<String>): Boolean = statements.any { it.referencesIdentifier(nameInSource) }
|
||||
fun options() = statements.filter { it is Directive && it.directive == "%option" }.flatMap { (it as Directive).args }.map {it.name!!}.toSet()
|
||||
fun options() = statements.filter { it is Directive && it.directive == "%option" }.flatMap { (it as Directive).args }.map {it.string!!}.toSet()
|
||||
|
||||
fun accept(visitor: IAstVisitor) = visitor.visit(this)
|
||||
fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
|
||||
@ -336,7 +336,7 @@ open class Module(final override val statements: MutableList<Statement>,
|
||||
val textEncoding: Encoding by lazy {
|
||||
val encoding = (statements.singleOrNull { it is Directive && it.directive == "%encoding" } as? Directive)
|
||||
if(encoding!=null)
|
||||
Encoding.entries.first { it.prefix==encoding.args[0].name }
|
||||
Encoding.entries.first { it.prefix==encoding.args[0].string }
|
||||
else
|
||||
program.encoding.defaultEncoding
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ class Program(val name: String,
|
||||
// insert a container module for all interned strings later
|
||||
val internedStringsModule = Module(mutableListOf(), Position.DUMMY, SourceCode.Generated(internedStringsModuleName))
|
||||
val block = Block(internedStringsModuleName, null, mutableListOf(), true, Position.DUMMY)
|
||||
val directive = Directive("%option", listOf(DirectiveArg(null,"no_symbol_prefixing", null, Position.DUMMY)), Position.DUMMY)
|
||||
val directive = Directive("%option", listOf(DirectiveArg("no_symbol_prefixing", null, Position.DUMMY)), Position.DUMMY)
|
||||
block.statements.add(directive)
|
||||
directive.linkParents(block)
|
||||
internedStringsModule.statements.add(block)
|
||||
|
@ -445,9 +445,13 @@ internal fun DirectiveContext.toAst() : Directive =
|
||||
|
||||
private fun DirectiveargContext.toAst() : DirectiveArg {
|
||||
val str = stringliteral()
|
||||
if(str?.encoding?.text!=null)
|
||||
throw SyntaxError("don't use a string encoding for directive arguments", toPosition())
|
||||
return DirectiveArg(str?.text?.substring(1, text.length-1), identifier()?.text, integerliteral()?.toAst()?.number?.toUInt(), toPosition())
|
||||
if(str!=null) {
|
||||
if (str.encoding?.text != null)
|
||||
throw SyntaxError("don't use a string encoding for directive arguments", toPosition())
|
||||
return DirectiveArg(str.text.substring(1, text.length-1), integerliteral()?.toAst()?.number?.toUInt(), toPosition())
|
||||
}
|
||||
|
||||
return DirectiveArg(identifier()?.text, integerliteral()?.toAst()?.number?.toUInt(), toPosition())
|
||||
}
|
||||
|
||||
private fun IntegerliteralContext.toAst(): NumericLiteralNode {
|
||||
|
@ -94,7 +94,7 @@ class Block(override val name: String,
|
||||
override fun toString() = "Block(name=$name, address=$address, ${statements.size} statements)"
|
||||
override fun referencesIdentifier(nameInSource: List<String>): Boolean = statements.any { it.referencesIdentifier(nameInSource) }
|
||||
|
||||
fun options() = statements.filter { it is Directive && it.directive == "%option" }.flatMap { (it as Directive).args }.map {it.name!!}.toSet()
|
||||
fun options() = statements.filter { it is Directive && it.directive == "%option" }.flatMap { (it as Directive).args }.map {it.string!!}.toSet()
|
||||
}
|
||||
|
||||
// note: a Directive is not strictly always Statement (in module scope, it's a Module Element rather)
|
||||
@ -132,14 +132,14 @@ data class Directive(val directive: String, val args: List<DirectiveArg>, overri
|
||||
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
|
||||
}
|
||||
|
||||
data class DirectiveArg(val str: String?, val name: String?, val int: UInt?, override val position: Position) : Node {
|
||||
data class DirectiveArg(val string: String?, val int: UInt?, override val position: Position) : Node {
|
||||
override lateinit var parent: Node
|
||||
|
||||
override fun linkParents(parent: Node) {
|
||||
this.parent = parent
|
||||
}
|
||||
override fun replaceChildNode(node: Node, replacement: Node) = throw FatalAstException("can't replace here")
|
||||
override fun copy() = DirectiveArg(str, name, int, position)
|
||||
override fun copy() = DirectiveArg(string, int, position)
|
||||
override fun referencesIdentifier(nameInSource: List<String>): Boolean = false
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ class CallGraph(private val program: Program) : IAstVisitor {
|
||||
override fun visit(directive: Directive) {
|
||||
val thisModule = directive.definingModule
|
||||
if (directive.directive == "%import") {
|
||||
val importedModule = program.modules.singleOrNull { it.name == directive.args[0].name } // the module may no longer exist at all due to optimizations
|
||||
val importedModule = program.modules.singleOrNull { it.name == directive.args[0].string } // the module may no longer exist at all due to optimizations
|
||||
if(importedModule!=null) {
|
||||
imports[thisModule] = imports.getValue(thisModule) + importedModule
|
||||
importedBy[importedModule] = importedBy.getValue(importedModule) + thisModule
|
||||
|
Loading…
x
Reference in New Issue
Block a user