fix subroutine inlining symbol scope error

This commit is contained in:
Irmen de Jong 2024-06-29 17:47:13 +02:00
parent ead8aa7800
commit ddf990296b
6 changed files with 23 additions and 21 deletions

View File

@ -51,9 +51,9 @@ GNU GPL 3.0 (see file LICENSE), with exception for generated code:
What does Prog8 provide? What does Prog8 provide?
------------------------ ------------------------
- can produce smaller and faster running programs than equivalent C code compiled with CC65 or even LLVM-MOS
- all advantages of a higher level language over having to write assembly code manually - all advantages of a higher level language over having to write assembly code manually
- programs run very fast because compilation to native machine code - programs run very fast because compilation to native machine code
- code often is smaller and faster than equivalent C code compiled with CC65 or even LLVM-MOS
- modularity, symbol scoping, subroutines - modularity, symbol scoping, subroutines
- various data types other than just bytes (16-bit words, floats, strings) - various data types other than just bytes (16-bit words, floats, strings)
- floating point math is supported if the target system provides floating point library routines (C64 and Cx16 both do) - floating point math is supported if the target system provides floating point library routines (C64 and Cx16 both do)

View File

@ -104,7 +104,7 @@ class ExpressionSimplifier(private val program: Program, private val options: Co
val leftIDt = expr.left.inferType(program) val leftIDt = expr.left.inferType(program)
val rightIDt = expr.right.inferType(program) val rightIDt = expr.right.inferType(program)
if (!leftIDt.isKnown || !rightIDt.isKnown) if (!leftIDt.isKnown || !rightIDt.isKnown)
throw FatalAstException("can't determine datatype of both expression operands $expr") return noModifications
// X + (-A) --> X - A // X + (-A) --> X - A
if (expr.operator == "+" && (expr.right as? PrefixExpression)?.operator == "-") { if (expr.operator == "+" && (expr.right as? PrefixExpression)?.operator == "-") {

View File

@ -147,6 +147,7 @@ class Inliner(private val program: Program, private val options: CompilationOpti
} }
private fun makeFullyScoped(call: FunctionCallStatement) { private fun makeFullyScoped(call: FunctionCallStatement) {
makeFullyScoped(call.target)
call.target.targetSubroutine(program)?.let { sub -> call.target.targetSubroutine(program)?.let { sub ->
val scopedName = IdentifierReference(sub.scopedName, call.target.position) val scopedName = IdentifierReference(sub.scopedName, call.target.position)
val scopedArgs = makeScopedArgs(call.args) val scopedArgs = makeScopedArgs(call.args)
@ -169,6 +170,7 @@ class Inliner(private val program: Program, private val options: CompilationOpti
} }
private fun makeFullyScoped(call: FunctionCallExpression) { private fun makeFullyScoped(call: FunctionCallExpression) {
makeFullyScoped(call.target)
call.target.targetSubroutine(program)?.let { sub -> call.target.targetSubroutine(program)?.let { sub ->
val scopedName = IdentifierReference(sub.scopedName, call.target.position) val scopedName = IdentifierReference(sub.scopedName, call.target.position)
val scopedArgs = makeScopedArgs(call.args) val scopedArgs = makeScopedArgs(call.args)

View File

@ -1060,23 +1060,25 @@ main {
compileText(C64Target(), true, src, writeAssembly = true) shouldNotBe null compileText(C64Target(), true, src, writeAssembly = true) shouldNotBe null
} }
xtest("optimizing inlined functions must reference proper scopes") { test("optimizing inlined functions must reference proper scopes") {
val src=""" val src="""
main { main {
sub start() { sub start() {
other.sub1() void other.sub1()
cx16.r0L = other.sub1()+other.sub1()
} }
} }
other { other {
sub sub2() { sub sub2() -> ubyte{
cx16.r0++ cx16.r0++
cx16.r1++ cx16.r1++
return cx16.r0L
} }
sub sub1() { sub sub1() -> ubyte {
sub2() return sub2()
} }
}""" }"""

View File

@ -70,9 +70,9 @@ Features
-------- --------
- it is a cross-compiler running on modern machines (Linux, MacOS, Windows, ...) - it is a cross-compiler running on modern machines (Linux, MacOS, Windows, ...)
- can produce smaller and faster running programs than equivalent C code compiled with CC65 or even LLVM-MOS
- the compiled programs run very fast, because compilation to highly efficient native machine code. - the compiled programs run very fast, because compilation to highly efficient native machine code.
- Provides a convenient and fast edit/compile/run cycle by being able to directly launch - code often is smaller and faster than equivalent C code compiled with CC65 or even LLVM-MOS
- provides a convenient and fast edit/compile/run cycle by being able to directly launch
the compiled program in an emulator and provide debugging information to this emulator. the compiled program in an emulator and provide debugging information to this emulator.
- the language looks like a mix of Python and C so should be quite easy to learn - the language looks like a mix of Python and C so should be quite easy to learn
- Modular programming, scoping via modules, code blocks, and subroutines. No need for forward declarations. - Modular programming, scoping via modules, code blocks, and subroutines. No need for forward declarations.

View File

@ -1,11 +1,9 @@
TODO TODO
==== ====
optimizer bug, see "optimizing inlined functions must reference proper scopes" unittest (skipped for now)
causes compiler error for virtual: just calling txt.cls() gives compile error undefined symbol clear_screen
https://github.com/irmen/prog8/issues/136 (string.find register order issue) https://github.com/irmen/prog8/issues/136 (string.find register order issue)
other issues on github.
optimize signed byte/word division by powers of 2 (and shift right?), it's now using divmod routine. (also % ?) optimize signed byte/word division by powers of 2 (and shift right?), it's now using divmod routine. (also % ?)
see inplacemodificationByteVariableWithLiteralval() and inplacemodificationSomeWordWithLiteralval() see inplacemodificationByteVariableWithLiteralval() and inplacemodificationSomeWordWithLiteralval()