block names are global (unscoped)

This commit is contained in:
Irmen de Jong 2019-03-25 23:31:02 +01:00
parent 7114d3193c
commit 62ceace941
6 changed files with 27 additions and 28 deletions

View File

@ -325,8 +325,8 @@ inline fun <reified T> findParentNode(node: Node): T? {
interface IStatement : Node {
fun process(processor: IAstProcessor) : IStatement
fun makeScopedName(name: String): List<String> {
// this is usually cached in a lazy property on the statement object itself
fun makeScopedName(name: String): String {
// this is usually cached in a lazy property on the statement object itself (label, subroutine, vardecl)
val scope = mutableListOf<String>()
var statementScope = this.parent
while(statementScope !is ParentSentinel && statementScope !is Module) {
@ -336,7 +336,7 @@ interface IStatement : Node {
statementScope = statementScope.parent
}
scope.add(name)
return scope
return scope.joinToString(".")
}
}
@ -507,7 +507,6 @@ class Block(override val name: String,
val isInLibrary: Boolean,
override val position: Position) : IStatement, INameScope {
override lateinit var parent: Node
val scopedname: String by lazy { makeScopedName(name).joinToString(".") }
override fun linkParents(parent: Node) {
this.parent = parent
@ -547,7 +546,7 @@ data class DirectiveArg(val str: String?, val name: String?, val int: Int?, over
data class Label(val name: String, override val position: Position) : IStatement {
override lateinit var parent: Node
val scopedname: String by lazy { makeScopedName(name).joinToString(".") }
val scopedname: String by lazy { makeScopedName(name) }
override fun linkParents(parent: Node) {
this.parent = parent
@ -685,7 +684,7 @@ class VarDecl(val type: VarDeclType,
override fun process(processor: IAstProcessor) = processor.process(this)
val scopedname: String by lazy { makeScopedName(name).joinToString(".") }
val scopedname: String by lazy { makeScopedName(name) }
override fun toString(): String {
return "VarDecl(name=$name, vartype=$type, datatype=$datatype, value=$value, pos=$position)"
@ -1625,7 +1624,7 @@ class Subroutine(override val name: String,
override var statements: MutableList<IStatement>,
override val position: Position) : IStatement, INameScope {
override lateinit var parent: Node
val scopedname: String by lazy { makeScopedName(name).joinToString(".") }
val scopedname: String by lazy { makeScopedName(name) }
override fun linkParents(parent: Node) {
this.parent = parent

View File

@ -62,12 +62,11 @@ private class AstIdentifiersChecker(val heap: HeapValues) : IAstProcessor {
}
override fun process(block: Block): IStatement {
val scopedName = block.scopedname
val existing = symbols[scopedName]
val existing = symbols[block.name]
if(existing!=null) {
nameError(block.name, block.position, existing)
} else {
symbols[scopedName] = block
symbols[block.name] = block
}
return super.process(block)
}
@ -91,6 +90,7 @@ private class AstIdentifiersChecker(val heap: HeapValues) : IAstProcessor {
// the builtin functions can't be redefined
checkResult.add(NameError("builtin function cannot be redefined", decl.position))
// TODO: check for name conflict only has to be done within the same scope, no need to get the full scoped name
val scopedName = decl.scopedname
val existing = symbols[scopedName]
if(existing!=null) {
@ -109,6 +109,7 @@ private class AstIdentifiersChecker(val heap: HeapValues) : IAstProcessor {
if (subroutine.parameters.any { it.name in BuiltinFunctions })
checkResult.add(NameError("builtin function name cannot be used as parameter", subroutine.position))
// TODO: check for name conflict only has to be done within the same scope, no need to get the full scoped name
val scopedName = subroutine.scopedname
val existing = symbols[scopedName]
if (existing != null) {
@ -152,6 +153,7 @@ private class AstIdentifiersChecker(val heap: HeapValues) : IAstProcessor {
// the builtin functions can't be redefined
checkResult.add(NameError("builtin function cannot be redefined", label.position))
} else {
// TODO: check for name conflict only has to be done within the same scope, no need to get the full scoped name
val scopedName = label.scopedname
val existing = symbols[scopedName]
if (existing != null) {

View File

@ -157,9 +157,9 @@ internal class Compiler(private val rootModule: Module,
}
override fun process(block: Block): IStatement {
prog.newBlock(block.scopedname, block.name, block.address, block.options())
prog.newBlock(block.name, block.address, block.options())
processVariables(block)
prog.label("block."+block.scopedname, false)
prog.label("block."+block.name, false)
prog.line(block.position)
translate(block.statements)
return super.process(block)

View File

@ -11,8 +11,7 @@ import java.nio.file.Path
class IntermediateProgram(val name: String, var loadAddress: Int, val heap: HeapValues, val importedFrom: Path) {
class ProgramBlock(val scopedname: String,
val shortname: String,
class ProgramBlock(val name: String,
var address: Int?,
val instructions: MutableList<Instruction> = mutableListOf(),
val variables: MutableMap<String, Value> = mutableMapOf(),
@ -447,8 +446,8 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
currentBlock.memoryPointers[name] = Pair(address, datatype)
}
fun newBlock(scopedname: String, shortname: String, address: Int?, options: Set<String>) {
currentBlock = ProgramBlock(scopedname, shortname, address, force_output="force_output" in options)
fun newBlock(name: String, address: Int?, options: Set<String>) {
currentBlock = ProgramBlock(name, address, force_output="force_output" in options)
blocks.add(currentBlock)
}
@ -472,7 +471,7 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
}
out.println("%end_heap")
for(blk in blocks) {
out.println("\n%block ${blk.scopedname} ${blk.address?.toString(16) ?: ""}")
out.println("\n%block ${blk.name} ${blk.address?.toString(16) ?: ""}")
out.println("%variables")
for(variable in blk.variables) {

View File

@ -44,8 +44,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
}.toMutableList()
val newConstants = block.memoryPointers.map { symname(it.key, block) to it.value }.toMap().toMutableMap()
val newblock = IntermediateProgram.ProgramBlock(
block.scopedname,
block.shortname,
block.name,
block.address,
newinstructions,
newvars,
@ -115,9 +114,9 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
blockLocal=true
scoped
}
scoped.startsWith("${block.shortname}.") -> {
scoped.startsWith("${block.name}.") -> { // TODO DOES THIS EVER OCCUR?
blockLocal = true
scoped.substring(block.shortname.length+1)
scoped.substring(block.name.length+1)
}
scoped.startsWith("block.") -> {
blockLocal = false
@ -199,7 +198,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
for(block in program.blocks) {
val initVarsLabel = block.instructions.firstOrNull { it is LabelInstr && it.name==initvarsSubName } as? LabelInstr
if(initVarsLabel!=null)
out(" jsr ${block.scopedname}.${initVarsLabel.name}")
out(" jsr ${block.name}.${initVarsLabel.name}")
}
out(" clc")
when(zeropage.exitProgramStrategy) {
@ -222,9 +221,9 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
private fun block2asm(blk: IntermediateProgram.ProgramBlock) {
block = blk
out("\n; ---- block: '${block.shortname}' ----")
out("\n; ---- block: '${block.name}' ----")
if(!blk.force_output)
out("${block.shortname}\t.proc\n")
out("${block.name}\t.proc\n")
if(block.address!=null) {
out(".cerror * > ${block.address?.toHex()}, 'block address overlaps by ', *-${block.address?.toHex()},' bytes'")
out("* = ${block.address?.toHex()}")
@ -232,7 +231,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
// deal with zeropage variables
for(variable in blk.variables) {
val sym = symname(blk.scopedname+"."+variable.key, null)
val sym = symname(blk.name+"."+variable.key, null)
val zpVar = program.allocatedZeropageVariables[sym]
if(zpVar==null) {
// This var is not on the ZP yet. Attempt to move it there (if it's not a float, those take up too much space)
@ -431,8 +430,8 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
return ""
val labelresult =
if(ins.name.startsWith("${block.shortname}."))
ins.name.substring(block.shortname.length+1)
if(ins.name.startsWith("${block.name}."))
ins.name.substring(block.name.length+1)
else
ins.name
return if(ins.asmProc) labelresult+"\t\t.proc" else labelresult

View File

@ -1,6 +1,6 @@
%zeropage basicsafe
; @todo fix this (issue #11 on github): it generates invalid asm due to improper label names
; @todo fix this loop labeling problem (issue #11 on github): it generates invalid asm due to improper label names
~ main {