mirror of
https://github.com/irmen/prog8.git
synced 2024-09-10 09:54:32 +00:00
improve the way %option merge works, you can now merge your own code with library code for instance.
This commit is contained in:
parent
ad14c88fde
commit
42db3085df
@ -110,14 +110,18 @@ class ModuleImporter(private val program: Program,
|
|||||||
// their content has to be merged into already existing other block with the same name.
|
// their content has to be merged into already existing other block with the same name.
|
||||||
val blocks = importedModule.statements.filterIsInstance<Block>()
|
val blocks = importedModule.statements.filterIsInstance<Block>()
|
||||||
for(block in blocks) {
|
for(block in blocks) {
|
||||||
if("merge" in block.options()) {
|
val blockHasMergeOption = "merge" in block.options()
|
||||||
val existingBlock = program.allBlocks.firstOrNull { it.name==block.name && it !== block}
|
val existingBlock = program.allBlocks.firstOrNull { it.name==block.name && it !== block}
|
||||||
if(existingBlock!=null) {
|
if(existingBlock!=null) {
|
||||||
|
val existingBlockHasMergeOption = "merge" in existingBlock.options()
|
||||||
|
if (blockHasMergeOption || existingBlockHasMergeOption) {
|
||||||
|
// transplant the contents
|
||||||
existingBlock.statements.addAll(block.statements.filter { it !is Directive })
|
existingBlock.statements.addAll(block.statements.filter { it !is Directive })
|
||||||
importedModule.statements.remove(block)
|
importedModule.statements.remove(block)
|
||||||
} else {
|
|
||||||
val merges = block.statements.filter { it is Directive && it.directive=="%option" && it.args.any { a->a.name=="merge" } }
|
if(blockHasMergeOption && !existingBlockHasMergeOption) {
|
||||||
block.statements.removeAll(merges.toSet())
|
existingBlock.statements.add(0, Directive("%option", listOf(DirectiveArg(null, "merge", null, block.position)), block.position))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,10 +33,13 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter,
|
|||||||
override fun visit(block: Block) {
|
override fun visit(block: Block) {
|
||||||
val existing = blocks[block.name]
|
val existing = blocks[block.name]
|
||||||
if(existing!=null) {
|
if(existing!=null) {
|
||||||
if(block.isInLibrary)
|
// we allow duplicates if at least one of them has %option merge
|
||||||
nameError(existing.name, existing.position, block)
|
if("merge" !in existing.options() + block.options()) {
|
||||||
else
|
if (block.isInLibrary)
|
||||||
nameError(block.name, block.position, existing)
|
nameError(existing.name, existing.position, block)
|
||||||
|
else
|
||||||
|
nameError(block.name, block.position, existing)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
blocks[block.name] = block
|
blocks[block.name] = block
|
||||||
|
@ -3,10 +3,12 @@ package prog8tests
|
|||||||
import io.kotest.assertions.withClue
|
import io.kotest.assertions.withClue
|
||||||
import io.kotest.core.spec.style.FunSpec
|
import io.kotest.core.spec.style.FunSpec
|
||||||
import io.kotest.matchers.shouldBe
|
import io.kotest.matchers.shouldBe
|
||||||
|
import io.kotest.matchers.shouldNotBe
|
||||||
import io.kotest.matchers.string.shouldStartWith
|
import io.kotest.matchers.string.shouldStartWith
|
||||||
import prog8.code.core.ZeropageType
|
import prog8.code.core.ZeropageType
|
||||||
import prog8.code.core.internedStringsModuleName
|
import prog8.code.core.internedStringsModuleName
|
||||||
import prog8.code.target.C64Target
|
import prog8.code.target.C64Target
|
||||||
|
import prog8.code.target.VMTarget
|
||||||
import prog8.compiler.determineCompilationOptions
|
import prog8.compiler.determineCompilationOptions
|
||||||
import prog8.compiler.parseMainModule
|
import prog8.compiler.parseMainModule
|
||||||
import prog8tests.helpers.ErrorReporterForTests
|
import prog8tests.helpers.ErrorReporterForTests
|
||||||
@ -108,4 +110,29 @@ main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test("merge option works on library modules") {
|
||||||
|
val src="""
|
||||||
|
%zeropage basicsafe
|
||||||
|
%import textio
|
||||||
|
|
||||||
|
txt {
|
||||||
|
%option merge
|
||||||
|
sub println(uword string) {
|
||||||
|
txt.print(string)
|
||||||
|
txt.nl()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
sub start() {
|
||||||
|
txt.lowercase()
|
||||||
|
txt.println("Hello, world1")
|
||||||
|
txt.println("Hello, world2")
|
||||||
|
txt.println("Hello, world3")
|
||||||
|
}
|
||||||
|
}"""
|
||||||
|
compileText(VMTarget(), optimize = false, src) shouldNotBe null
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
@ -143,7 +143,7 @@ Directives
|
|||||||
Warning: if you use this to align array variables in the block, these have to be initialized with a value to make them stay in the block and get aligned properly. Otherwise they'll end up at a random spot in the BSS section and the alignment doesn't apply there.
|
Warning: if you use this to align array variables in the block, these have to be initialized with a value to make them stay in the block and get aligned properly. Otherwise they'll end up at a random spot in the BSS section and the alignment doesn't apply there.
|
||||||
- ``align_page`` (in a block) will make the assembler align the start address of this block on a page boundary in memory (so, the LSB of the address is 0).
|
- ``align_page`` (in a block) will make the assembler align the start address of this block on a page boundary in memory (so, the LSB of the address is 0).
|
||||||
Warning: if you use this to align array variables in the block, these have to be initialized with a value to make them stay in the block and get aligned properly. Otherwise they'll end up at a random spot in the BSS section and the alignment doesn't apply there.
|
Warning: if you use this to align array variables in the block, these have to be initialized with a value to make them stay in the block and get aligned properly. Otherwise they'll end up at a random spot in the BSS section and the alignment doesn't apply there.
|
||||||
- ``merge`` (in a block) will merge this block's contents into an already existing block with the same name. Useful in library scenarios.
|
- ``merge`` (in a block) will merge this block's contents into an already existing block with the same name. Useful in library scenarios. Can result in a bunch of unused symbol warnings, this depends on the import order.
|
||||||
- ``splitarrays`` (block or module) makes all word-arrays in this scope lsb/msb split arrays (as if they all have the @split tag). See Arrays.
|
- ``splitarrays`` (block or module) makes all word-arrays in this scope lsb/msb split arrays (as if they all have the @split tag). See Arrays.
|
||||||
- ``no_symbol_prefixing`` (block) makes the compiler *not* use symbol-prefixing when translating prog8 code into assembly.
|
- ``no_symbol_prefixing`` (block) makes the compiler *not* use symbol-prefixing when translating prog8 code into assembly.
|
||||||
Only use this if you know what you're doing because it could result in invalid assembly code being generated.
|
Only use this if you know what you're doing because it could result in invalid assembly code being generated.
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
- improve the working of %option merge: should be able to merge your own stuff into say textio. , and improve the docs about it too.
|
|
||||||
|
|
||||||
- [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 ....
|
- [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 ....
|
||||||
- [on branch: ir-less-branch-opcodes] IR: reduce the number of branch instructions such as BEQ, BEQR, etc (gradually), replace with CMP(I) + status branch instruction
|
- [on branch: ir-less-branch-opcodes] IR: reduce the number of branch instructions such as BEQ, BEQR, etc (gradually), replace with CMP(I) + status branch instruction
|
||||||
- IR: reduce amount of CMP/CMPI after instructions that set the status bits correctly (LOADs? INC? Bitwise operations, etc), but only after setting the status bits is verified!
|
- IR: reduce amount of CMP/CMPI after instructions that set the status bits correctly (LOADs? INC? Bitwise operations, etc), but only after setting the status bits is verified!
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
%import textio
|
||||||
|
|
||||||
|
txt {
|
||||||
|
%option merge
|
||||||
|
sub println(uword string) {
|
||||||
|
txt.print(string)
|
||||||
|
txt.nl()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
str name = "thing"
|
txt.lowercase()
|
||||||
modify(name)
|
txt.println("Hello, world1")
|
||||||
|
txt.println("Hello, world2")
|
||||||
sub modify(str arg) {
|
txt.println("Hello, world3")
|
||||||
ubyte n=1
|
|
||||||
uword pointervar
|
|
||||||
arg[n+1] = arg[1]
|
|
||||||
pointervar[n+1] = pointervar[1]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user