diff --git a/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt b/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt index b420be300..3eb3760a6 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt @@ -5,8 +5,7 @@ import prog8.ast.Node import prog8.ast.Program import prog8.ast.base.DataType import prog8.ast.base.FatalAstException -import prog8.ast.expressions.CharLiteral -import prog8.ast.expressions.NumericLiteralValue +import prog8.ast.expressions.* import prog8.ast.statements.Directive import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstModification @@ -14,6 +13,53 @@ import prog8.compiler.BeforeAsmGenerationAstChanger import prog8.compiler.CompilationOptions import prog8.compiler.IErrorReporter import prog8.compiler.target.ICompilationTarget +import kotlin.math.abs + + +fun RangeExpr.size(encoding: IStringEncoding): Int? { + val fromLv = (from as? NumericLiteralValue) + val toLv = (to as? NumericLiteralValue) + if(fromLv==null || toLv==null) + return null + return toConstantIntegerRange(encoding)?.count() +} + +fun RangeExpr.toConstantIntegerRange(encoding: IStringEncoding): IntProgression? { + val fromVal: Int + val toVal: Int + val fromString = from as? StringLiteralValue + val toString = to as? StringLiteralValue + if(fromString!=null && toString!=null ) { + // string range -> int range over character values + fromVal = encoding.encodeString(fromString.value, fromString.altEncoding)[0].toInt() + toVal = encoding.encodeString(toString.value, fromString.altEncoding)[0].toInt() + } else { + val fromLv = from as? NumericLiteralValue + val toLv = to as? NumericLiteralValue + if(fromLv==null || toLv==null) + return null // non-constant range + // integer range + fromVal = fromLv.number.toInt() + toVal = toLv.number.toInt() + } + val stepVal = (step as? NumericLiteralValue)?.number?.toInt() ?: 1 + return makeRange(fromVal, toVal, stepVal) +} + +private fun makeRange(fromVal: Int, toVal: Int, stepVal: Int): IntProgression { + return when { + fromVal <= toVal -> when { + stepVal <= 0 -> IntRange.EMPTY + stepVal == 1 -> fromVal..toVal + else -> fromVal..toVal step stepVal + } + else -> when { + stepVal >= 0 -> IntRange.EMPTY + stepVal == -1 -> fromVal downTo toVal + else -> fromVal downTo toVal step abs(stepVal) + } + } +} internal fun Program.checkValid(compilerOptions: CompilationOptions, errors: IErrorReporter, compTarget: ICompilationTarget) { diff --git a/compiler/src/prog8/compiler/target/cpu6502/codegen/ForLoopsAsmGen.kt b/compiler/src/prog8/compiler/target/cpu6502/codegen/ForLoopsAsmGen.kt index 1aa1a8bff..226c4e7b8 100644 --- a/compiler/src/prog8/compiler/target/cpu6502/codegen/ForLoopsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/cpu6502/codegen/ForLoopsAsmGen.kt @@ -9,6 +9,7 @@ import prog8.ast.expressions.RangeExpr import prog8.ast.statements.ForLoop import prog8.ast.toHex import prog8.compiler.AssemblyError +import prog8.compiler.astprocessing.toConstantIntegerRange import kotlin.math.absoluteValue internal class ForLoopsAsmGen(private val program: Program, private val asmgen: AsmGen) { diff --git a/compiler/src/prog8/optimizer/ConstantIdentifierReplacer.kt b/compiler/src/prog8/optimizer/ConstantIdentifierReplacer.kt index f45bfd4a1..cfab08140 100644 --- a/compiler/src/prog8/optimizer/ConstantIdentifierReplacer.kt +++ b/compiler/src/prog8/optimizer/ConstantIdentifierReplacer.kt @@ -9,6 +9,8 @@ import prog8.ast.statements.* import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstModification import prog8.compiler.IErrorReporter +import prog8.compiler.astprocessing.size +import prog8.compiler.astprocessing.toConstantIntegerRange import prog8.compiler.target.ICompilationTarget // Fix up the literal value's type to match that of the vardecl diff --git a/compiler/src/prog8/optimizer/StatementOptimizer.kt b/compiler/src/prog8/optimizer/StatementOptimizer.kt index af7455e22..5688cb8cf 100644 --- a/compiler/src/prog8/optimizer/StatementOptimizer.kt +++ b/compiler/src/prog8/optimizer/StatementOptimizer.kt @@ -11,6 +11,7 @@ import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstModification import prog8.ast.walk.IAstVisitor import prog8.compiler.IErrorReporter +import prog8.compiler.astprocessing.size import prog8.compiler.target.ICompilationTarget import kotlin.math.floor diff --git a/compiler/test/TestCompilerOnRanges.kt b/compiler/test/TestCompilerOnRanges.kt index 18e7bd16f..c6c36cc78 100644 --- a/compiler/test/TestCompilerOnRanges.kt +++ b/compiler/test/TestCompilerOnRanges.kt @@ -14,6 +14,8 @@ import prog8.ast.expressions.* import prog8.ast.statements.ForLoop import prog8.ast.statements.Subroutine import prog8.ast.statements.VarDecl +import prog8.compiler.astprocessing.size +import prog8.compiler.astprocessing.toConstantIntegerRange import prog8.compiler.target.C64Target import prog8.compiler.target.Cx16Target diff --git a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt index 48205ff30..de7994e4c 100644 --- a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt +++ b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt @@ -7,7 +7,6 @@ import prog8.ast.statements.* import prog8.ast.walk.AstWalker import prog8.ast.walk.IAstVisitor import java.util.* -import kotlin.math.abs val associativeOperators = setOf("+", "*", "&", "|", "^", "or", "and", "xor", "==", "!=") @@ -719,51 +718,8 @@ class RangeExpr(var from: Expression, return "RangeExpr(from $from, to $to, step $step, pos=$position)" } - fun size(encoding: IStringEncoding): Int? { - val fromLv = (from as? NumericLiteralValue) - val toLv = (to as? NumericLiteralValue) - if(fromLv==null || toLv==null) - return null - return toConstantIntegerRange(encoding)?.count() - } - - fun toConstantIntegerRange(encoding: IStringEncoding): IntProgression? { - val fromVal: Int - val toVal: Int - val fromString = from as? StringLiteralValue - val toString = to as? StringLiteralValue - if(fromString!=null && toString!=null ) { - // string range -> int range over character values - fromVal = encoding.encodeString(fromString.value, fromString.altEncoding)[0].toInt() - toVal = encoding.encodeString(toString.value, fromString.altEncoding)[0].toInt() - } else { - val fromLv = from as? NumericLiteralValue - val toLv = to as? NumericLiteralValue - if(fromLv==null || toLv==null) - return null // non-constant range - // integer range - fromVal = fromLv.number.toInt() - toVal = toLv.number.toInt() - } - val stepVal = (step as? NumericLiteralValue)?.number?.toInt() ?: 1 - return makeRange(fromVal, toVal, stepVal) - } } -internal fun makeRange(fromVal: Int, toVal: Int, stepVal: Int): IntProgression { - return when { - fromVal <= toVal -> when { - stepVal <= 0 -> IntRange.EMPTY - stepVal == 1 -> fromVal..toVal - else -> fromVal..toVal step stepVal - } - else -> when { - stepVal >= 0 -> IntRange.EMPTY - stepVal == -1 -> fromVal downTo toVal - else -> fromVal downTo toVal step abs(stepVal) - } - } -} data class IdentifierReference(val nameInSource: List, override val position: Position) : Expression(), IAssignable { override lateinit var parent: Node diff --git a/compilerAst/src/prog8/parser/PetsciiEncoding.kt b/compilerAst/src/prog8/parser/PetsciiEncoding.kt index 58f752834..9817003bd 100644 --- a/compilerAst/src/prog8/parser/PetsciiEncoding.kt +++ b/compilerAst/src/prog8/parser/PetsciiEncoding.kt @@ -5,7 +5,7 @@ import java.io.CharConversionException /** - * TODO: remove once [IStringEncoding] has been to compiler module + * TODO: remove once [IStringEncoding] has been moved to compiler module */ object PetsciiEncoding : IStringEncoding { override fun encodeString(str: String, altEncoding: Boolean) = diff --git a/compilerAst/src/prog8/parser/ThrowTodoEncoding.kt b/compilerAst/src/prog8/parser/ThrowTodoEncoding.kt index 674c3d77e..57f48871e 100644 --- a/compilerAst/src/prog8/parser/ThrowTodoEncoding.kt +++ b/compilerAst/src/prog8/parser/ThrowTodoEncoding.kt @@ -3,7 +3,7 @@ package prog8.parser import prog8.ast.IStringEncoding /** - * TODO: remove once [IStringEncoding] has been to compiler module + * TODO: remove once [IStringEncoding] has been moved to compiler module */ object ThrowTodoEncoding: IStringEncoding { override fun encodeString(str: String, altEncoding: Boolean): List {