main block element order now remains the same as in source

This commit is contained in:
Irmen de Jong 2022-11-15 18:51:52 +01:00
parent df1793efbf
commit 922033c1b2
8 changed files with 40 additions and 43 deletions

View File

@ -202,16 +202,10 @@ internal class ProgramAndVarsGen(
asmsubs2asm(block.statements)
asmgen.out("")
asmgen.out("; subroutines in this block")
// First translate regular statements, and then put the subroutines at the end.
// (regular statements = everything except the initialization assignments;
// these will be part of the prog8_init_vars init routine generated below)
val initializers = blockVariableInitializers.getValue(block)
val statements = block.statements.filterNot { it in initializers }
val (subroutine, stmts) = statements.partition { it is Subroutine }
stmts.forEach { asmgen.translate(it) }
subroutine.forEach { asmgen.translate(it) }
val notInitializers = block.statements.filterNot { it in initializers }
notInitializers.forEach { asmgen.translate(it) }
if(!options.dontReinitGlobals) {
// generate subroutine to initialize block-level (global) variables

View File

@ -1122,7 +1122,7 @@ class IRCodeGen(
irBlock += IRInlineBinaryChunk(null, readBinaryData(child), null)
}
is PtLabel -> {
TODO("allow label inside block scope ${child.name}")
irBlock += IRCodeChunk(child.name, null)
}
else -> TODO("weird child node $child")
}

View File

@ -382,7 +382,7 @@ private fun postprocessAst(program: Program, errors: IErrorReporter, compilerOpt
callGraph.checkRecursiveCalls(errors)
program.verifyFunctionArgTypes(errors)
errors.report()
program.moveMainAndStartToFirst()
program.moveMainBlockAsFirst()
program.checkValid(errors, compilerOptions) // check if final tree is still valid
errors.report()
}

View File

@ -129,35 +129,19 @@ internal fun Program.variousCleanups(errors: IErrorReporter, options: Compilatio
}
}
internal fun Program.moveMainAndStartToFirst() {
internal fun Program.moveMainBlockAsFirst() {
// The module containing the program entrypoint is moved to the first in the sequence.
// the "main" block containing the entrypoint is moved to the top in there,
// and finally the entrypoint subroutine "start" itself is moved to the top in that block.
// the "main" block containing the entrypoint is moved to the top in there.
// sortModules()
val directives = modules[0].statements.filterIsInstance<Directive>()
val start = this.entrypoint
val mod = start.definingModule
val block = start.definingBlock
moveModuleToFront(mod)
mod.remove(block)
var afterDirective = mod.statements.indexOfFirst { it !is Directive }
val module = this.entrypoint.definingModule
val block = this.entrypoint.definingBlock
moveModuleToFront(module)
module.remove(block)
val afterDirective = module.statements.indexOfFirst { it !is Directive }
if(afterDirective<0)
mod.statements.add(block)
module.statements.add(block)
else
mod.statements.add(afterDirective, block)
block.remove(start)
afterDirective = block.statements.indexOfFirst { it !is Directive }
if(afterDirective<0)
block.statements.add(start)
else
block.statements.add(afterDirective, start)
// overwrite the directives in the module containing the entrypoint
for(directive in directives) {
modules[0].statements.removeAll { it is Directive && it.directive == directive.directive }
modules[0].statements.add(0, directive)
}
module.statements.add(afterDirective, block)
}
internal fun IdentifierReference.isSubroutineParameter(program: Program): Boolean {

View File

@ -37,11 +37,6 @@ internal class BeforeAsmAstChanger(val program: Program,
}
override fun before(block: Block, parent: Node): Iterable<IAstModification> {
// move all subroutines to the bottom of the block
val subs = block.statements.filterIsInstance<Subroutine>()
block.statements.removeAll(subs)
block.statements.addAll(subs)
// adjust global variables initialization
if(options.dontReinitGlobals) {
block.statements.asSequence().filterIsInstance<VarDecl>().forEach {

View File

@ -3,6 +3,7 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- make it so that uword xx = <byte constant> <op> expr is treated as <word constant> <op> <expr> instead (or inverse order)
- ir/vm: allow label in block scope
- regression test the various projects
- 6502 codegen: make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as ``p8v_``? Or not worth it (most 3 letter opcodes as variables are nonsensical anyway)

View File

@ -1,8 +1,25 @@
%import textio
%zeropage basicsafe
main {
alsostart:
sub start() {
uword xx = 100
uword yy = xx / 256 ; TODO hangs in optimizer for 6502
yy++
internalstart:
txt.print_uwhex(start, true)
txt.nl()
txt.print_uwhex(alsostart, true)
txt.nl()
txt.print_uwhex(internalstart, true)
txt.nl()
txt.print_uwhex(startend, true)
txt.nl()
txt.print_uwhex(internalend, true)
txt.nl()
internalend:
}
startend:
}

View File

@ -222,6 +222,11 @@ class IRBlock(
operator fun plusAssign(sub: IRAsmSubroutine) { asmSubroutines += sub }
operator fun plusAssign(asm: IRInlineAsmChunk) { inlineAssemblies += asm }
operator fun plusAssign(binary: IRInlineBinaryChunk) { inlineBinaries += binary }
operator fun plusAssign(irCodeChunk: IRCodeChunk) {
// this is for a separate label in the block scope. (random code statements are not allowed)
require(irCodeChunk.isEmpty() && irCodeChunk.label!=null)
TODO("allow labels in block scope, ${irCodeChunk.label}")
}
fun isEmpty(): Boolean {
val noAsm = inlineAssemblies.isEmpty() || inlineAssemblies.all { it.isEmpty() }
@ -230,6 +235,7 @@ class IRBlock(
val noBins = inlineBinaries.isEmpty() || inlineBinaries.all { it.isEmpty() }
return noAsm && noSubs && noAsmSubs && noBins
}
}
class IRSubroutine(val name: String,