From 709ced1bca4962f2b131ef06fdd2b730be871fdf Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 6 Feb 2026 22:57:23 +0100 Subject: [PATCH] alias test program, replace alias chains --- .../astprocessing/AstIdentifiersChecker.kt | 3 - .../compiler/astprocessing/AstPreprocessor.kt | 43 +++- ...teralsToAutoVarsAndRecombineIdentifiers.kt | 10 - compiler/test/TestPointers.kt | 4 +- examples/test.p8 | 227 +++++++++++++++--- 5 files changed, 235 insertions(+), 52 deletions(-) diff --git a/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt index aa36f66d1..4b7d949f7 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstIdentifiersChecker.kt @@ -44,9 +44,6 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter, override fun visit(alias: Alias) { if(alias.target.targetStatement(program.builtinFunctions)==null) errors.err("undefined symbol: ${alias.target.nameInSource.joinToString(".") }", alias.target.position) - - if(alias.alias == alias.target.nameInSource.first()) - errors.err("alias references itself", alias.position) } override fun visit(block: Block) { diff --git a/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt b/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt index 8ff8c2d2e..2559bcd9b 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt @@ -341,11 +341,48 @@ class AstPreprocessor(val program: Program, return noModifications } - override fun after(alias: Alias, parent: Node): Iterable { + override fun before(alias: Alias, parent: Node): Iterable { + // shortcut aliases that point to aliases (remove alias chains) val tgt = alias.target.targetStatement(program.builtinFunctions) - if(tgt is Block) { - errors.err("cannot alias blocks", alias.target.position) + + if(tgt!=null) { + if(alias.alias == alias.target.nameInSource.first()) { + errors.err("alias loop", alias.position) + } else if(tgt is Block) { + errors.err("cannot alias blocks", alias.target.position) // TODO remove this check? move it to AstChecker? + } else if(tgt is Alias) { + var chainedAlias = alias + var chainedTargetName = alias.target + var maxhops = 100 + while(true) { + val tgt2 = chainedAlias.target.targetStatement(program.builtinFunctions) + if (tgt2 is Alias) { + chainedAlias = tgt2 + chainedTargetName = tgt2.target + } + else { + val tgt2 = chainedTargetName.targetStatement(program.builtinFunctions) as? INamedStatement + val replacement = if(tgt2!=null) { + if(tgt2.scopedName != chainedTargetName.nameInSource) { + val scopedTarget = IdentifierReference(tgt2.scopedName, alias.position) + Alias(alias.alias, scopedTarget, alias.position) + } else { + Alias(alias.alias, chainedTargetName, alias.position) + } + } else { + Alias(alias.alias, chainedTargetName, alias.position) + } + return listOf(IAstModification.ReplaceNode(alias, replacement, parent)) + } + maxhops-- + if(maxhops==0) { + errors.err("alias loop", alias.position) + break + } + } + } } + return noModifications } diff --git a/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVarsAndRecombineIdentifiers.kt b/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVarsAndRecombineIdentifiers.kt index 6a8777c28..f5d93c5d9 100644 --- a/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVarsAndRecombineIdentifiers.kt +++ b/compiler/src/prog8/compiler/astprocessing/LiteralsToAutoVarsAndRecombineIdentifiers.kt @@ -126,16 +126,6 @@ internal class LiteralsToAutoVarsAndRecombineIdentifiers(private val program: Pr return noModifications } - override fun after(alias: Alias, parent: Node): Iterable { - val target = alias.target.targetStatement() - if(target is Alias) { - // shortcut the alias that refers to another alias - val newAlias = Alias(alias.alias, target.target, alias.position) - return listOf(IAstModification.ReplaceNode(alias, newAlias, parent)) - } - return noModifications - } - override fun after(identifier: IdentifierReference, parent: Node): Iterable { val target = identifier.targetStatement() diff --git a/compiler/test/TestPointers.kt b/compiler/test/TestPointers.kt index b0a5bf2dc..8e2da79eb 100644 --- a/compiler/test/TestPointers.kt +++ b/compiler/test/TestPointers.kt @@ -2432,7 +2432,7 @@ main { sub alias1() { alias TheNode = structdefs.Node - ^^TheNode node = 20000 + ^^TheNode @shared node = 20000 node.value = 100 } @@ -2444,7 +2444,7 @@ main { sub alias3() { alias TheNode = structdefs.Node - ^^TheNode node = 20000 + ^^TheNode @shared node = 20000 node++ } diff --git a/examples/test.p8 b/examples/test.p8 index 7894001eb..300c36641 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,44 +1,203 @@ -%import textio %zeropage basicsafe -%option no_sysinit main { + alias print = mytxt.print + alias width = mytxt.DEFAULT_WIDTH + alias textOverlay_top = mytxt.overlayTop + alias textOverlay_bot = mytxt.overlayBot + sub start() { - uword @shared derp=2000 - derp[1000] = %00111100 - derp[1001] = %01111110 + address_of_alias() + alias1() + alias2() + alias3() + alias4() + alias5() + alias6() + player.test() + alias_scopes() + alias_loop_error() + alias_error() + aliased_func_error() + } - ror(@(3000)) - txt.print_ubbin(derp[1000], true) - txt.spc() - sys.clear_carry() - rol(@(3000)) - txt.print_ubbin(derp[1000], true) - txt.nl() + sub address_of_alias() { + ubyte @shared index = 3 + ubyte[10] array + alias curframe = array - ror(derp[1000]) - txt.print_ubbin(derp[1000], true) - txt.spc() - sys.clear_carry() - rol(derp[1000]) - txt.print_ubbin(derp[1000], true) - txt.nl() + cx16.r0 = &curframe + cx16.r1 = &curframe[3] + cx16.r2 = &curframe + 3 + cx16.r3 = &curframe[index] + cx16.r4 = &curframe + index + } - ror(@(derp +1000)) - txt.print_ubbin(derp[1000], true) - txt.spc() - sys.clear_carry() - rol(@(derp +1000)) - txt.print_ubbin(derp[1000], true) - txt.nl() + sub alias1() { + alias TheNode = structdefs.Node + ^^TheNode @shared node = 20000 + node.value = 100 + } - ^^uword a = derp+1000 - ror(a^^) - txt.print_uwbin(a^^, true) - txt.nl() - sys.clear_carry() - rol(a^^) - txt.print_uwbin(a^^, true) - txt.nl() + sub alias2() { + ^^structdefs.Node node = 20000 + alias thing = node + thing.value=200 + } + + sub alias3() { + alias TheNode = structdefs.Node + ^^TheNode @shared node = 20000 + node++ + } + + sub alias4() { + alias currentElement = structdefs.element + currentElement = 20000 + + ; all 3 should be the same: + structdefs.element.value = 42 + currentElement.value = 42 + currentElement^^.value = 42 + + ; all 3 should be the same: + structdefs.element.value2 = 4242 + currentElement.value2 = 4242 + currentElement^^.value2 = 4242 + + cx16.r0 = currentElement^^.value2 + cx16.r1 = currentElement.value2 + } + + sub alias5() { + alias nid = structdefs.element.value + nid++ + } + + sub alias6() { + alias print2 = mytxt.print + alias width2 = mytxt.DEFAULT_WIDTH + print("one") + print2("two") + mytxt.print_ub(width) + mytxt.print_ub(width2) + + ; chained aliases + alias chained = print2 + chained("chained") + + ; multi vardecls + textOverlay_bot++ + textOverlay_top++ + } + + sub alias_scopes() { + alias mything = other.thing + alias myvariable = other.variable + + mything() + myvariable ++ + + other.thing2() + other.variable2 ++ + + alias nid = structdefs.element.value + nid++ + } + + sub alias_loop_error() { + alias vv = vv + alias xx = xx.yy + alias zz = mm + alias mm = zz + } + + alias print = mytxt.print2222 + alias width = mytxt.DEFAULT_WIDTH + + sub alias_error() { + alias print2 = mytxt.print + alias width2 = mytxt.DEFAULT_WIDTH_XXX + print("one") + print2("two") + mytxt.print_ub(width) + mytxt.print_ub(width2) + } + + sub aliased_func_error() { + alias func1 = actualfunc + alias func2 = mkword + alias func3 = func1 + alias func4 = func2 + + ; all wrong: + func1(1,2) + func1() + func2(1,2,3,4) + func2() + func3() + func4() + + ; all ok: + func1(1) + cx16.r0 = func2(1,2) + func3(1) + cx16.r0 = func4(1,2) + + sub actualfunc(ubyte a) { + a++ + } } } + + + +cx16 { + %option merge + &^^word pword4 = &cx16.r4 +} + +player { + alias sxPtr = cx16.pword4 + &^^word zxPtr = &cx16.r6 + + sub test() { + sxPtr^^ = -99 ; aliased assignment + if (zxPtr^^ - sxPtr^^) in -13 to 13 { ; aliased expression + cx16.r0++ + } + } +} + + +mytxt { + uword overlayTop, overlayBot + + const ubyte DEFAULT_WIDTH = 80 + sub print_ub(ubyte value) { + ; nothing + } + sub print(str msg) { + ; nothing + } +} + +structdefs { + struct Node { + ubyte value + uword value2 + } + + ^^Node @shared element +} + +other { + sub thing() { + cx16.r0++ + } + + ubyte @shared variable + + alias thing2 = thing + alias variable2 = variable +}