Skip to content

Commit

Permalink
fix chained assignment and multi-vardecl RHS evaluation
Browse files Browse the repository at this point in the history
  • Loading branch information
irmen committed Dec 10, 2023
1 parent 2668bf8 commit e98e951
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 52 deletions.
14 changes: 7 additions & 7 deletions compiler/src/prog8/buildversion/BuildVersion.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ package prog8.buildversion
*/
const val MAVEN_GROUP = "prog8"
const val MAVEN_NAME = "compiler"
const val VERSION = "9.7-SNAPSHOT"
const val GIT_REVISION = 4212
const val GIT_SHA = "f81061dd42403294e7cb5ebd3c0ed57d6c57c3d5"
const val GIT_DATE = "2023-11-18T00:03:34Z"
const val GIT_BRANCH = "continue-stmt"
const val BUILD_DATE = "2023-11-19T16:19:02Z"
const val BUILD_UNIX_TIME = 1700410742198L
const val VERSION = "9.7"
const val GIT_REVISION = 4286
const val GIT_SHA = "cfc9c15f1e9fe96940e170fb14ad3a957109977c"
const val GIT_DATE = "2023-12-10T15:22:00Z"
const val GIT_BRANCH = "master"
const val BUILD_DATE = "2023-12-10T15:44:19Z"
const val BUILD_UNIX_TIME = 1702223059842L
const val DIRTY = 1
20 changes: 16 additions & 4 deletions compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -294,10 +294,22 @@ _after:
val assigns = mutableListOf<Statement>(assign)
var lastChained: ChainedAssignment = chainedAssignment
var pc: ChainedAssignment? = chainedAssignment
while(pc!=null) {
lastChained = pc
assigns.add(0, Assignment(pc.target.copy(), assign.value.copy(), assign.origin, pc.position))
pc = pc.parent as? ChainedAssignment

if(assign.value.isSimple) {
// simply copy the RHS value to each component's assignment
while (pc != null) {
lastChained = pc
assigns.add(Assignment(pc.target.copy(), assign.value.copy(), assign.origin, pc.position))
pc = pc.parent as? ChainedAssignment
}
} else if(pc!=null) {
// need to evaluate RHS once and reuse that in each component's assignment
val firstComponentAsValue = assign.target.toExpression()
while (pc != null) {
lastChained = pc
assigns.add(Assignment(pc.target.copy(), firstComponentAsValue.copy(), assign.origin, pc.position))
pc = pc.parent as? ChainedAssignment
}
}
return listOf(IAstModification.ReplaceNode(lastChained,
AnonymousScope(assigns, chainedAssignment.position), lastChained.parent))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ internal class LiteralsToAutoVars(private val program: Program,
if(errors.noErrors()) {
// desugar into individual vardecl per name.
return decl.desugarMultiDecl().map {
IAstModification.InsertAfter(decl, it, parent as IStatementContainer)
IAstModification.InsertBefore(decl, it, parent as IStatementContainer)
} + IAstModification.Remove(decl, parent as IStatementContainer)
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/ast/TestVariousCompilerAst.kt
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ main {
val vars = st.filterIsInstance<VarDecl>()
vars.size shouldBe 7
vars.all { it.names.size<=1 } shouldBe true
vars.map { it.name } shouldBe listOf("s","r","q","z","y","x","w")
vars.map { it.name }.toSet() shouldBe setOf("s","r","q","z","y","x","w")
val forloop = st.single { it is ForLoop } as ForLoop
forloop.body.statements[0] shouldBe instanceOf<Assignment>()
forloop.body.statements[1] shouldBe instanceOf<Assignment>()
Expand Down
29 changes: 25 additions & 4 deletions compilerAst/src/prog8/ast/statements/AstStatements.kt
Original file line number Diff line number Diff line change
Expand Up @@ -317,13 +317,34 @@ class VarDecl(val type: VarDeclType,
this.arraysize?.referencesIdentifier(nameInSource)==true

fun desugarMultiDecl(): List<VarDecl> {
return names.map {
val copy = VarDecl(type, origin, declaredDatatype, zeropage, arraysize?.copy(), it, emptyList(), value?.copy(),
if(value?.isSimple==true) {
// just copy the initialization value to a separata vardecl for each component
return names.map {
val copy = VarDecl(type, origin, declaredDatatype, zeropage, arraysize?.copy(), it, emptyList(), value?.copy(),
isArray, sharedWithAsm, splitArray, position)
copy.allowInitializeWithZero = this.allowInitializeWithZero
copy
}
} else {
// evaluate the value once in the vardecl for the first component, and set the other components to the first
val first = VarDecl(type, origin, declaredDatatype, zeropage, arraysize?.copy(), names[0], emptyList(), value?.copy(),
isArray, sharedWithAsm, splitArray, position)
copy.allowInitializeWithZero = this.allowInitializeWithZero
copy
first.allowInitializeWithZero = this.allowInitializeWithZero
val firstVar = firstVarAsValue(first)
return listOf(first) + names.drop(1 ).map {
val copy = VarDecl(type, origin, declaredDatatype, zeropage, arraysize?.copy(), it, emptyList(), firstVar.copy(),
isArray, sharedWithAsm, splitArray, position)
copy.allowInitializeWithZero = this.allowInitializeWithZero
copy
}
}
}

private fun firstVarAsValue(first: VarDecl): Expression {
if(first.isArray || first.type!=VarDeclType.VAR)
throw FatalAstException("invalid multi decl type $first")
return IdentifierReference(listOf(first.name), first.position)
}
}

class ArrayIndex(var indexExpr: Expression,
Expand Down
50 changes: 15 additions & 35 deletions examples/test.p8
Original file line number Diff line number Diff line change
@@ -1,44 +1,24 @@
%import textio
%import string
%import math
%zeropage basicsafe

main {
sub start() {
cx16.set_chrin_keyhandler(0, &keystroke_handler)
cbm.CHRIN()
}
ubyte x,y,z = math.rnd()

sub keystroke_handler() -> ubyte {
%asm {{
sta cx16.r0L
}}
uword cmdxx = grab_cmdline()
if_cs {
; first entry, decide if we want to override
if cx16.r0L==9 {
; intercept TAB
sys.clear_carry()
return 0
}
sys.set_carry()
return 0
} else {
if cx16.r0L==9 {
%asm {{
brk ; BOOM
}}
uword cmd = grab_cmdline()
if cmd and cmd[0] {
;cx16.r5++
}
return '!'
}
return 0 ; eat all other characters
}
txt.print_ub(x)
txt.nl()
txt.print_ub(y)
txt.nl()
txt.print_ub(z)
txt.nl()

sub grab_cmdline() -> uword {
cx16.r9++
return $5000
}
x=y=z=math.rnd()
txt.print_ub(x)
txt.nl()
txt.print_ub(y)
txt.nl()
txt.print_ub(z)
txt.nl()
}
}

0 comments on commit e98e951

Please sign in to comment.