alias test program, replace alias chains

This commit is contained in:
Irmen de Jong
2026-02-06 22:57:23 +01:00
parent 3b16d08246
commit 709ced1bca
5 changed files with 235 additions and 52 deletions

View File

@@ -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) {

View File

@@ -341,11 +341,48 @@ class AstPreprocessor(val program: Program,
return noModifications
}
override fun after(alias: Alias, parent: Node): Iterable<IAstModification> {
override fun before(alias: Alias, parent: Node): Iterable<IAstModification> {
// 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
}

View File

@@ -126,16 +126,6 @@ internal class LiteralsToAutoVarsAndRecombineIdentifiers(private val program: Pr
return noModifications
}
override fun after(alias: Alias, parent: Node): Iterable<IAstModification> {
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<IAstModification> {
val target = identifier.targetStatement()

View File

@@ -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++
}

View File

@@ -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
}