Skip to content

Commit

Permalink
fix rangeexpression value type casting
Browse files Browse the repository at this point in the history
  • Loading branch information
irmen committed Feb 11, 2025
1 parent 17334a1 commit 9e79722
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
val constElt = srcCheck.element.constValue(program)?.number
val step = range.step.constValue(program)?.number
if(constElt!=null && constRange!=null) {
return PtNumber(BaseDataType.UBYTE, if(constRange.first<=constElt && constElt<=constRange.last) 1.0 else 0.0, srcCheck.position)
return PtBool(constRange.first<=constElt && constElt<=constRange.last, srcCheck.position)
}
else if(step==1.0) {
// x in low to high --> low <=x and x <= high
Expand All @@ -707,7 +707,7 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
return desugar(range)
} else {
errors.err("cannot use step size different than 1 or -1 in a non constant range containment check", srcCheck.position)
return PtNumber(BaseDataType.BYTE, 0.0, Position.DUMMY)
return PtBool(false, srcCheck.position)
}
}
else -> throw FatalAstException("iterable in containmentcheck must always be an identifier (referencing string or array) or a range expression $srcCheck")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
if(fromConst!=null) {
val cast = fromConst.cast(varDt.base, true)
if(cast.isValid)
modifications += IAstModification.ReplaceNode(range.to, cast.valueOrZero(), range)
modifications += IAstModification.ReplaceNode(range.from, cast.valueOrZero(), range)
else
errors.err("incompatible range value type", range.from.position)
} else {
Expand Down
48 changes: 48 additions & 0 deletions compiler/test/TestCompilerOnRanges.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ import prog8.ast.expressions.NumericLiteral
import prog8.ast.expressions.RangeExpression
import prog8.ast.statements.ForLoop
import prog8.ast.statements.VarDecl
import prog8.code.ast.PtBinaryExpression
import prog8.code.ast.PtBool
import prog8.code.ast.PtIdentifier
import prog8.code.ast.PtIfElse
import prog8.code.ast.PtNumber
import prog8.code.core.BaseDataType
import prog8.code.core.DataType
import prog8.code.core.Encoding
Expand Down Expand Up @@ -450,4 +455,47 @@ main {
}"""
compileText(Cx16Target(), true, src) shouldNotBe null
}

test("constant containmentcheck simplification") {
val src="""
main {
sub start() {
const word wc = 0
if wc in 252 to 272
return
}
}"""

val result = compileText(Cx16Target(), false, src)
val st = result!!.codegenAst!!.entrypoint()!!.children
st.size shouldBe 3
((st[1] as PtIfElse).condition as PtBool).value shouldBe false
}

test("containmentcheck type casting") {
val src="""
main {
sub start() {
word @shared ww
if ww in 325 to 477
return
}
}"""

val result = compileText(Cx16Target(), false, src)
val st = result!!.codegenAst!!.entrypoint()!!.children
st.size shouldBe 4
val cond = (st[2] as PtIfElse).condition as PtBinaryExpression
cond.operator shouldBe "and"
val left = cond.left as PtBinaryExpression
val right = cond.right as PtBinaryExpression
left.operator shouldBe "<="
(left.left as PtNumber).type shouldBe DataType.forDt(BaseDataType.WORD)
(left.left as PtNumber).number shouldBe 325.0
left.right shouldBe instanceOf<PtIdentifier>()
right.operator shouldBe "<="
(right.right as PtNumber).type shouldBe DataType.forDt(BaseDataType.WORD)
(right.right as PtNumber).number shouldBe 477.0
right.left shouldBe instanceOf<PtIdentifier>()
}
})
1 change: 0 additions & 1 deletion compiler/test/codegeneration/TestAsmGenSymbols.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import prog8.ast.Module
import prog8.ast.Program
import prog8.ast.expressions.AddressOf
import prog8.ast.expressions.IdentifierReference
import prog8.ast.expressions.NumericLiteral
import prog8.ast.statements.*
import prog8.code.SymbolTableMaker
import prog8.code.ast.PtAddressOf
Expand Down
2 changes: 2 additions & 0 deletions docs/source/todo.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ TODO

- Make neo and atari targets external via configs? They are very bare bones atm so easier to contribute to if they're configurable externally? What about the pet32 target

- add Adiee5's NES target and example to the docs somewhere https://github.com/adiee5/prog8-nes-target

- add paypal donation button as well?
- announce prog8 on the 6502.org site?

Expand Down
6 changes: 3 additions & 3 deletions intermediate/src/prog8/intermediate/IRFileReader.kt
Original file line number Diff line number Diff line change
Expand Up @@ -170,14 +170,14 @@ class IRFileReader {
val arrayspec = match.groups["arrayspec"]?.value ?: ""
val name = match.groups["name"]!!.value
val zpwish = match.groups["zp"]!!.value
val split = match.groups["split"]?.value ?: ""
match.groups["split"]?.value ?: ""
val alignment = match.groups["align"]?.value ?: ""
if('.' !in name)
throw IRParseException("unscoped name: $name")
val arraysize = if(arrayspec.isNotBlank()) arrayspec.substring(1, arrayspec.length-1).toInt() else null
val dt = parseDatatype(type, arraysize!=null)
val zp = if(zpwish.isBlank()) ZeropageWish.DONTCARE else ZeropageWish.valueOf(zpwish)
val isSplit = if(split.isBlank()) false else split.toBoolean()
// val isSplit = if(split.isBlank()) false else split.toBoolean()
val align = if(alignment.isBlank()) 0u else alignment.toUInt()
val newVar = StStaticVariable(name, dt, null, null, arraysize, zp, align.toInt(), null)
variables.add(newVar)
Expand Down Expand Up @@ -242,7 +242,7 @@ class IRFileReader {
val arraysize = if(arrayspec.isNotBlank()) arrayspec.substring(1, arrayspec.length-1).toInt() else null
val dt = parseDatatype(type, arraysize!=null)
val zp = if(zpwish.isBlank()) ZeropageWish.DONTCARE else ZeropageWish.valueOf(zpwish)
val isSplit = if(split.isBlank()) false else split.toBoolean()
if(split.isBlank()) false else split.toBoolean()
val align = if(alignment.isBlank()) 0u else alignment.toUInt()
var initNumeric: Double? = null
var initArray: StArray? = null
Expand Down

0 comments on commit 9e79722

Please sign in to comment.