From f83b9732ee4b69dd93b79affac8ce963d84c259d Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 1 Feb 2019 01:22:27 +0100 Subject: [PATCH] User defined blocks are sorted first, before library blocks. This prioritizes zero page allocation to user code (and makes reading the program easier) --- compiler/src/prog8/ast/AST.kt | 12 ++++---- compiler/src/prog8/ast/StmtReorderer.kt | 12 ++++++-- docs/source/todo.rst | 1 - examples/test.p8 | 38 +++++++++++-------------- prog8.iml | 1 + 5 files changed, 34 insertions(+), 30 deletions(-) diff --git a/compiler/src/prog8/ast/AST.kt b/compiler/src/prog8/ast/AST.kt index 83d69da8c..a1c42d703 100644 --- a/compiler/src/prog8/ast/AST.kt +++ b/compiler/src/prog8/ast/AST.kt @@ -506,11 +506,11 @@ private class GlobalNamespace(override val name: String, class Block(override val name: String, val address: Int?, override var statements: MutableList, + 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 statements.forEach {it.linkParents(this)} @@ -1754,7 +1754,7 @@ class RepeatLoop(var body: AnonymousScope, /***************** Antlr Extension methods to create AST ****************/ fun prog8Parser.ModuleContext.toAst(name: String, isLibrary: Boolean, importedFrom: Path) : Module = - Module(name, modulestatement().asSequence().map { it.toAst() }.toMutableList(), toPosition(), isLibrary, importedFrom) + Module(name, modulestatement().asSequence().map { it.toAst(isLibrary) }.toMutableList(), toPosition(), isLibrary, importedFrom) private fun ParserRuleContext.toPosition() : Position { @@ -1768,19 +1768,19 @@ private fun ParserRuleContext.toPosition() : Position { } -private fun prog8Parser.ModulestatementContext.toAst() : IStatement { +private fun prog8Parser.ModulestatementContext.toAst(isInLibrary: Boolean) : IStatement { val directive = directive()?.toAst() if(directive!=null) return directive - val block = block()?.toAst() + val block = block()?.toAst(isInLibrary) if(block!=null) return block throw FatalAstException(text) } -private fun prog8Parser.BlockContext.toAst() : IStatement = - Block(identifier().text, integerliteral()?.toAst()?.number?.toInt(), statement_block().toAst(), toPosition()) +private fun prog8Parser.BlockContext.toAst(isInLibrary: Boolean) : IStatement = + Block(identifier().text, integerliteral()?.toAst()?.number?.toInt(), statement_block().toAst(), isInLibrary, toPosition()) private fun prog8Parser.Statement_blockContext.toAst(): MutableList = diff --git a/compiler/src/prog8/ast/StmtReorderer.kt b/compiler/src/prog8/ast/StmtReorderer.kt index 8c6dd30fb..2f2445717 100644 --- a/compiler/src/prog8/ast/StmtReorderer.kt +++ b/compiler/src/prog8/ast/StmtReorderer.kt @@ -33,11 +33,21 @@ private class StatementReorderer(private val namespace: INameScope, private val val (blocks, other) = module.statements.partition { it is Block } module.statements = other.asSequence().plus(blocks.sortedBy { (it as Block).address ?: Int.MAX_VALUE }).toMutableList() + // make sure user-defined blocks come BEFORE library blocks, and move the "main" block to the top of everything + val nonLibraryBlocks = module.statements.withIndex() + .filter { it.value is Block && !(it.value as Block).isInLibrary } + .map { it.index to it.value } + .reversed() + for(blocks in nonLibraryBlocks) + module.statements.removeAt(blocks.first) + for(blocks in nonLibraryBlocks) + module.statements.add(0, blocks.second) val mainBlock = module.statements.single { it is Block && it.name=="main" } if((mainBlock as Block).address==null) { module.statements.remove(mainBlock) module.statements.add(0, mainBlock) } + val varDecls = module.statements.filterIsInstance() module.statements.removeAll(varDecls) module.statements.addAll(0, varDecls) @@ -46,8 +56,6 @@ private class StatementReorderer(private val namespace: INameScope, private val module.statements.removeAll(directives) module.statements.addAll(0, directives) - // TODO make sure user-defined blocks come BEFORE library blocks - sortConstantAssignments(module.statements) } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 2ea0f5705..d37c7dde0 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -31,7 +31,6 @@ Add more compiler optimizations to the existing ones. - on the final assembly source level - can the parameter passing to subroutines be optimized to avoid copying? -- make sure user-defined blocks come BEFORE library blocks (this helps zeropage variable allocations) - subroutines with 1 or 2 byte args (or 1 word arg) should be converted to asm calling convention with the args in A/Y register diff --git a/examples/test.p8 b/examples/test.p8 index 21a5f1a22..486ba0442 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -4,27 +4,23 @@ sub start() { - foo(1) - foo2(20) - bar(2,3) - baz(3333) - baz(-3333) + myblock2.foo() + myblock3.foo() } - - sub foo(ubyte arg) { - A=arg - } - - sub foo2(byte arg) { - A=33 - } - - sub bar(ubyte arg1, ubyte arg2) { - A=arg1 - } - - sub baz(word arg) { - A=lsb(arg) - } +} + +~ myblock2 { + + sub foo() { + A=99 + } +} + + +~ myblock3 { + + sub foo() { + A=99 + } } diff --git a/prog8.iml b/prog8.iml index e5e2d011e..c675202dc 100644 --- a/prog8.iml +++ b/prog8.iml @@ -11,6 +11,7 @@ +