mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
fix: for loop over array literal no longer crashes the compiler
This commit is contained in:
parent
b2876b0a03
commit
7a9e5afb93
@ -91,7 +91,8 @@ internal fun Program.checkIdentifiers(errors: IErrorReporter, program: Program,
|
||||
transforms.applyModifications()
|
||||
val lit2decl = LiteralsToAutoVars(this)
|
||||
lit2decl.visit(this)
|
||||
lit2decl.applyModifications()
|
||||
if(errors.noErrors())
|
||||
lit2decl.applyModifications()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
package prog8.compiler.astprocessing
|
||||
|
||||
import prog8.ast.IStatementContainer
|
||||
import prog8.ast.Node
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.base.DataType
|
||||
@ -28,26 +27,24 @@ internal class LiteralsToAutoVars(private val program: Program) : AstWalker() {
|
||||
override fun after(array: ArrayLiteralValue, parent: Node): Iterable<IAstModification> {
|
||||
val vardecl = array.parent as? VarDecl
|
||||
if(vardecl!=null) {
|
||||
// adjust the datatype of the array (to an educated guess)
|
||||
// adjust the datatype of the array (to an educated guess from the vardecl type)
|
||||
val arrayDt = array.type
|
||||
if(arrayDt isnot vardecl.datatype) {
|
||||
val cast = array.cast(vardecl.datatype)
|
||||
if (cast != null && cast !== array)
|
||||
if(cast!=null && cast !== array)
|
||||
return listOf(IAstModification.ReplaceNode(vardecl.value!!, cast, vardecl))
|
||||
}
|
||||
} else {
|
||||
val arrayDt = array.guessDatatype(program)
|
||||
if(arrayDt.isKnown) {
|
||||
// this array literal is part of an expression, turn it into an identifier reference
|
||||
// turn the array literal it into an identifier reference
|
||||
val litval2 = array.cast(arrayDt.getOr(DataType.UNDEFINED))
|
||||
if(litval2!=null) {
|
||||
if(array.parent !is IStatementContainer)
|
||||
return noModifications
|
||||
val vardecl2 = VarDecl.createAuto(litval2)
|
||||
val identifier = IdentifierReference(listOf(vardecl2.name), vardecl2.position)
|
||||
return listOf(
|
||||
IAstModification.ReplaceNode(array, identifier, parent),
|
||||
IAstModification.InsertFirst(vardecl2, array.parent as IStatementContainer)
|
||||
IAstModification.ReplaceNode(array, identifier, parent),
|
||||
IAstModification.InsertFirst(vardecl2, array.definingScope)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -301,4 +301,68 @@ class TestCompilerOnRanges: FunSpec({
|
||||
forloop.iterable shouldBe instanceOf<RangeExpr>()
|
||||
(forloop.iterable as RangeExpr).step shouldBe NumericLiteralValue(DataType.UBYTE, -2.0, Position.DUMMY)
|
||||
}
|
||||
|
||||
|
||||
test("for statement on all possible iterable expressions") {
|
||||
compileText(C64Target, false, """
|
||||
main {
|
||||
sub start() {
|
||||
ubyte xx
|
||||
str name = "irmen"
|
||||
ubyte[] values = [1,2,3,4,5,6,7]
|
||||
|
||||
for xx in name {
|
||||
xx++
|
||||
}
|
||||
|
||||
for xx in values {
|
||||
xx++
|
||||
}
|
||||
|
||||
for xx in 10 to 20 step 3 {
|
||||
xx++
|
||||
}
|
||||
|
||||
for xx in "abcdef" {
|
||||
xx++
|
||||
}
|
||||
|
||||
for xx in [2,4,6,8] {
|
||||
xx++
|
||||
}
|
||||
}
|
||||
}""").assertSuccess()
|
||||
}
|
||||
|
||||
// TODO enable this after this if-syntax is implemented
|
||||
xtest("if containment check on all possible iterable expressions") {
|
||||
compileText(C64Target, false, """
|
||||
main {
|
||||
sub start() {
|
||||
ubyte xx
|
||||
str name = "irmen"
|
||||
ubyte[] values = [1,2,3,4,5,6,7]
|
||||
|
||||
if xx in name {
|
||||
xx++
|
||||
}
|
||||
|
||||
if xx in values {
|
||||
xx++
|
||||
}
|
||||
|
||||
if xx in 10 to 20 step 3 {
|
||||
xx++
|
||||
}
|
||||
|
||||
if xx in "abcdef" {
|
||||
xx++
|
||||
}
|
||||
|
||||
if xx in [2,4,6,8] {
|
||||
xx++
|
||||
}
|
||||
}
|
||||
}""").assertSuccess()
|
||||
}
|
||||
})
|
||||
|
@ -6,6 +6,7 @@ For next compiler release (7.6)
|
||||
add "if X in [1,2,3] {...}" syntax , as an alternative to when X { 1,2,3-> {...} }
|
||||
if the array is not a literal, do a normal containment test instead in an array or string or range
|
||||
change "consider using when statement..." to "consider using if X in [..] or when statement..."
|
||||
also add to the docs!
|
||||
|
||||
|
||||
Blocked by an official Commander-x16 v39 release
|
||||
|
@ -5,10 +5,76 @@
|
||||
main {
|
||||
sub start() {
|
||||
ubyte @shared xx
|
||||
str name = "irmen"
|
||||
ubyte[] values = [1,2,3,4,5,6,7]
|
||||
|
||||
if xx<100 {
|
||||
foobar()
|
||||
for xx in name {
|
||||
txt.chrout(xx)
|
||||
txt.spc()
|
||||
}
|
||||
txt.nl()
|
||||
|
||||
for xx in values {
|
||||
txt.print_ub(xx)
|
||||
txt.spc()
|
||||
}
|
||||
txt.nl()
|
||||
|
||||
for xx in 10 to 20 step 3 {
|
||||
txt.print_ub(xx)
|
||||
txt.spc()
|
||||
}
|
||||
txt.nl()
|
||||
|
||||
for xx in "abcdef" {
|
||||
txt.print_ub(xx)
|
||||
txt.spc()
|
||||
}
|
||||
txt.nl()
|
||||
|
||||
for xx in [2,4,6,8] {
|
||||
txt.print_ub(xx)
|
||||
txt.spc()
|
||||
}
|
||||
txt.nl()
|
||||
|
||||
|
||||
; if xx in 100 { ; TODO error
|
||||
; xx++
|
||||
; }
|
||||
;
|
||||
; if xx in 'a' { ; TODO error
|
||||
; xx++
|
||||
; }
|
||||
;
|
||||
; if xx in "abc" { ; TODO containment test via when
|
||||
; xx++
|
||||
; }
|
||||
;
|
||||
; if xx in [1,2,3,4,5] { ; TODO containment test via when
|
||||
; xx++
|
||||
; }
|
||||
;
|
||||
; if xx in [1,2,3,4,5,6,7,8,9,10] { ; TODO containment test via loop?
|
||||
; xx++
|
||||
; }
|
||||
;
|
||||
; if xx in name { ; TODO containment test via loop
|
||||
; xx++
|
||||
; }
|
||||
;
|
||||
; if xx in values { ; TODO containment test via loop
|
||||
; xx++
|
||||
; }
|
||||
;
|
||||
; if xx in 10 to 20 step 2 { ; TODO
|
||||
;
|
||||
; }
|
||||
|
||||
; TODO const optimizing of the containment tests
|
||||
; TODO also with (u)word and floats
|
||||
|
||||
|
||||
|
||||
if xx==9 or xx==10 or xx==11 or xx==12 or xx==13 {
|
||||
txt.print("9 10 11\n")
|
||||
|
Loading…
x
Reference in New Issue
Block a user