* refactor RangeExpr, step 1: remove IStringEncoding as ctor arg and instead put it as arg to the two methods that actually depend on it: toConstantIntegerRange and size (as *it* calls the former)

This commit is contained in:
meisl 2021-07-17 20:45:17 +02:00
parent 3f6f25e06f
commit 48d3abc1fe
8 changed files with 23 additions and 30 deletions

View File

@ -19,7 +19,7 @@ internal class ForLoopsAsmGen(private val program: Program, private val asmgen:
throw AssemblyError("unknown dt") throw AssemblyError("unknown dt")
when(stmt.iterable) { when(stmt.iterable) {
is RangeExpr -> { is RangeExpr -> {
val range = (stmt.iterable as RangeExpr).toConstantIntegerRange() val range = (stmt.iterable as RangeExpr).toConstantIntegerRange(asmgen.options.compTarget)
if(range==null) { if(range==null) {
translateForOverNonconstRange(stmt, iterableDt.typeOrElse(DataType.UNDEFINED), stmt.iterable as RangeExpr) translateForOverNonconstRange(stmt, iterableDt.typeOrElse(DataType.UNDEFINED), stmt.iterable as RangeExpr)
} else { } else {

View File

@ -223,7 +223,7 @@ internal class ConstantFoldingOptimizer(private val program: Program, private va
range.step range.step
} }
return RangeExpr(fromCast.valueOrZero(), toCast.valueOrZero(), newStep, compTarget, range.position) return RangeExpr(fromCast.valueOrZero(), toCast.valueOrZero(), newStep, range.position)
} }
// adjust the datatype of a range expression in for loops to the loop variable. // adjust the datatype of a range expression in for loops to the loop variable.

View File

@ -129,9 +129,9 @@ internal class ConstantIdentifierReplacer(private val program: Program, private
if(rangeExpr!=null) { if(rangeExpr!=null) {
// convert the initializer range expression to an actual array // convert the initializer range expression to an actual array
val declArraySize = decl.arraysize?.constIndex() val declArraySize = decl.arraysize?.constIndex()
if(declArraySize!=null && declArraySize!=rangeExpr.size()) if(declArraySize!=null && declArraySize!=rangeExpr.size(compTarget))
errors.err("range expression size doesn't match declared array size", decl.value?.position!!) errors.err("range expression size doesn't match declared array size", decl.value?.position!!)
val constRange = rangeExpr.toConstantIntegerRange() val constRange = rangeExpr.toConstantIntegerRange(compTarget)
if(constRange!=null) { if(constRange!=null) {
val eltType = rangeExpr.inferType(program).typeOrElse(DataType.UBYTE) val eltType = rangeExpr.inferType(program).typeOrElse(DataType.UBYTE)
val newValue = if(eltType in ByteDatatypes) { val newValue = if(eltType in ByteDatatypes) {
@ -184,9 +184,9 @@ internal class ConstantIdentifierReplacer(private val program: Program, private
if(rangeExpr!=null) { if(rangeExpr!=null) {
// convert the initializer range expression to an actual array of floats // convert the initializer range expression to an actual array of floats
val declArraySize = decl.arraysize?.constIndex() val declArraySize = decl.arraysize?.constIndex()
if(declArraySize!=null && declArraySize!=rangeExpr.size()) if(declArraySize!=null && declArraySize!=rangeExpr.size(compTarget))
errors.err("range expression size doesn't match declared array size", decl.value?.position!!) errors.err("range expression size doesn't match declared array size", decl.value?.position!!)
val constRange = rangeExpr.toConstantIntegerRange() val constRange = rangeExpr.toConstantIntegerRange(compTarget)
if(constRange!=null) { if(constRange!=null) {
val newValue = ArrayLiteralValue(InferredTypes.InferredType.known(DataType.ARRAY_F), val newValue = ArrayLiteralValue(InferredTypes.InferredType.known(DataType.ARRAY_F),
constRange.map { NumericLiteralValue(DataType.FLOAT, it.toDouble(), decl.value!!.position) }.toTypedArray(), constRange.map { NumericLiteralValue(DataType.FLOAT, it.toDouble(), decl.value!!.position) }.toTypedArray(),

View File

@ -162,7 +162,7 @@ internal class StatementOptimizer(private val program: Program,
val range = forLoop.iterable as? RangeExpr val range = forLoop.iterable as? RangeExpr
if(range!=null) { if(range!=null) {
if(range.size()==1) { if (range.size(compTarget) == 1) {
// for loop over a (constant) range of just a single value-- optimize the loop away // for loop over a (constant) range of just a single value-- optimize the loop away
// loopvar/reg = range value , follow by block // loopvar/reg = range value , follow by block
val scope = AnonymousScope(mutableListOf(), forLoop.position) val scope = AnonymousScope(mutableListOf(), forLoop.position)

View File

@ -16,7 +16,6 @@ import prog8.ast.statements.Subroutine
import prog8.ast.statements.VarDecl import prog8.ast.statements.VarDecl
import prog8.compiler.target.C64Target import prog8.compiler.target.C64Target
import prog8.compiler.target.Cx16Target import prog8.compiler.target.Cx16Target
import prog8.optimizer.ConstantIdentifierReplacer
/** /**
@ -146,7 +145,7 @@ class TestCompilerOnRanges {
@Test @Test
fun testForLoopWithRange_char_to_char() { fun testForLoopWithRange_char_to_char() {
val platform = Cx16Target val platform = Cx16Target
val result = compileText(platform, true, """ val result = compileText(platform, optimize = true, """
main { main {
sub start() { sub start() {
ubyte i ubyte i
@ -168,15 +167,16 @@ class TestCompilerOnRanges {
val expectedEnd = platform.encodeString("f", false)[0].toInt() val expectedEnd = platform.encodeString("f", false)[0].toInt()
val expectedStr = "$expectedStart .. $expectedEnd" val expectedStr = "$expectedStart .. $expectedEnd"
val intProgression = rangeExpr.toConstantIntegerRange() val intProgression = rangeExpr.toConstantIntegerRange(platform)
val actualStr = "${intProgression?.first} .. ${intProgression?.last}" val actualStr = "${intProgression?.first} .. ${intProgression?.last}"
assertEquals(expectedStr, actualStr,".first .. .last") assertEquals(expectedStr, actualStr,".first .. .last")
assertEquals(expectedEnd - expectedStart + 1, rangeExpr.size(), "rangeExpr.size()") assertEquals(expectedEnd - expectedStart + 1, rangeExpr.size(platform), "rangeExpr.size()")
} }
@Test @Test
fun testForLoopWithRange_bool_to_bool() { fun testForLoopWithRange_bool_to_bool() {
val result = compileText(Cx16Target, true, """ val platform = Cx16Target
val result = compileText(platform, optimize = true, """
main { main {
sub start() { sub start() {
ubyte i ubyte i
@ -194,15 +194,16 @@ class TestCompilerOnRanges {
.map { it.iterable } .map { it.iterable }
.filterIsInstance<RangeExpr>()[0] .filterIsInstance<RangeExpr>()[0]
assertEquals(2, rangeExpr.size()) assertEquals(2, rangeExpr.size(platform))
val intProgression = rangeExpr.toConstantIntegerRange() val intProgression = rangeExpr.toConstantIntegerRange(platform)
assertEquals(0, intProgression?.first) assertEquals(0, intProgression?.first)
assertEquals(1, intProgression?.last) assertEquals(1, intProgression?.last)
} }
@Test @Test
fun testForLoopWithRange_ubyte_to_ubyte() { fun testForLoopWithRange_ubyte_to_ubyte() {
val result = compileText(Cx16Target, true, """ val platform = Cx16Target
val result = compileText(platform, optimize = true, """
main { main {
sub start() { sub start() {
ubyte i ubyte i
@ -220,8 +221,8 @@ class TestCompilerOnRanges {
.map { it.iterable } .map { it.iterable }
.filterIsInstance<RangeExpr>()[0] .filterIsInstance<RangeExpr>()[0]
assertEquals(9, rangeExpr.size()) assertEquals(9, rangeExpr.size(platform))
val intProgression = rangeExpr.toConstantIntegerRange() val intProgression = rangeExpr.toConstantIntegerRange(platform)
assertEquals(1, intProgression?.first) assertEquals(1, intProgression?.first)
assertEquals(9, intProgression?.last) assertEquals(9, intProgression?.last)
} }

View File

@ -6,9 +6,6 @@ import prog8.ast.statements.*
import prog8.ast.walk.AstWalker import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstVisitor import prog8.ast.walk.IAstVisitor
import prog8.parser.SourceCode import prog8.parser.SourceCode
import java.nio.file.Path
import java.nio.file.Paths
import kotlin.io.path.name
import kotlin.math.abs import kotlin.math.abs
const val internedStringsModuleName = "prog8_interned_strings" const val internedStringsModuleName = "prog8_interned_strings"

View File

@ -1,6 +1,5 @@
package prog8.ast.antlr package prog8.ast.antlr
import org.antlr.v4.runtime.IntStream
import org.antlr.v4.runtime.ParserRuleContext import org.antlr.v4.runtime.ParserRuleContext
import org.antlr.v4.runtime.tree.TerminalNode import org.antlr.v4.runtime.tree.TerminalNode
import prog8.ast.IStringEncoding import prog8.ast.IStringEncoding
@ -10,9 +9,6 @@ import prog8.ast.expressions.*
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.parser.Prog8ANTLRParser import prog8.parser.Prog8ANTLRParser
import prog8.parser.SourceCode import prog8.parser.SourceCode
import java.io.CharConversionException
import java.io.File
import java.nio.file.Path
/***************** Antlr Extension methods to create AST ****************/ /***************** Antlr Extension methods to create AST ****************/
@ -462,7 +458,7 @@ private fun Prog8ANTLRParser.ExpressionContext.toAst(encoding: IStringEncoding)
if (rangefrom!=null && rangeto!=null) { if (rangefrom!=null && rangeto!=null) {
val defaultstep = if(rto.text == "to") 1 else -1 val defaultstep = if(rto.text == "to") 1 else -1
val step = rangestep?.toAst(encoding) ?: NumericLiteralValue(DataType.UBYTE, defaultstep, toPosition()) val step = rangestep?.toAst(encoding) ?: NumericLiteralValue(DataType.UBYTE, defaultstep, toPosition())
return RangeExpr(rangefrom.toAst(encoding), rangeto.toAst(encoding), step, encoding, toPosition()) return RangeExpr(rangefrom.toAst(encoding), rangeto.toAst(encoding), step, toPosition())
} }
if(childCount==3 && children[0].text=="(" && children[2].text==")") if(childCount==3 && children[0].text=="(" && children[2].text==")")
@ -581,7 +577,7 @@ private fun Prog8ANTLRParser.UntilloopContext.toAst(encoding: IStringEncoding):
private fun Prog8ANTLRParser.WhenstmtContext.toAst(encoding: IStringEncoding): WhenStatement { private fun Prog8ANTLRParser.WhenstmtContext.toAst(encoding: IStringEncoding): WhenStatement {
val condition = expression().toAst(encoding) val condition = expression().toAst(encoding)
val choices = this.when_choice()?.map { it.toAst(encoding) }?.toMutableList() ?: mutableListOf() val choices = this.when_choice()?.map { it.toAst(encoding) }?.toMutableList() ?: mutableListOf<WhenChoice>()
return WhenStatement(condition, choices, toPosition()) return WhenStatement(condition, choices, toPosition())
} }

View File

@ -667,7 +667,6 @@ class ArrayLiteralValue(val type: InferredTypes.InferredType, // inferred be
class RangeExpr(var from: Expression, class RangeExpr(var from: Expression,
var to: Expression, var to: Expression,
var step: Expression, var step: Expression,
private val encoding: IStringEncoding,
override val position: Position) : Expression() { override val position: Position) : Expression() {
override lateinit var parent: Node override lateinit var parent: Node
@ -720,15 +719,15 @@ class RangeExpr(var from: Expression,
return "RangeExpr(from $from, to $to, step $step, pos=$position)" return "RangeExpr(from $from, to $to, step $step, pos=$position)"
} }
fun size(): Int? { fun size(encoding: IStringEncoding): Int? {
val fromLv = (from as? NumericLiteralValue) val fromLv = (from as? NumericLiteralValue)
val toLv = (to as? NumericLiteralValue) val toLv = (to as? NumericLiteralValue)
if(fromLv==null || toLv==null) if(fromLv==null || toLv==null)
return null return null
return toConstantIntegerRange()?.count() return toConstantIntegerRange(encoding)?.count()
} }
fun toConstantIntegerRange(): IntProgression? { fun toConstantIntegerRange(encoding: IStringEncoding): IntProgression? {
val fromVal: Int val fromVal: Int
val toVal: Int val toVal: Int
val fromString = from as? StringLiteralValue val fromString = from as? StringLiteralValue