diff --git a/compiler/src/prog8/ast/AST.kt b/compiler/src/prog8/ast/AST.kt index 7e2812ced..7bd3bb98f 100644 --- a/compiler/src/prog8/ast/AST.kt +++ b/compiler/src/prog8/ast/AST.kt @@ -1296,12 +1296,11 @@ open class LiteralValue(val type: DataType, val bytevalue: Short? = null, val wordvalue: Int? = null, val floatvalue: Double? = null, - strvalue: String? = null, + val strvalue: String? = null, val arrayvalue: Array? = null, var heapId: Int? =null, override val position: Position) : IExpression { override lateinit var parent: Node - private val initialstrvalue = strvalue override fun referencesIdentifier(name: String) = arrayvalue?.any { it.referencesIdentifier(name) } ?: false @@ -1356,12 +1355,12 @@ open class LiteralValue(val type: DataType, in WordDatatypes -> if(wordvalue==null) throw FatalAstException("literal value missing wordvalue") DataType.FLOAT -> if(floatvalue==null) throw FatalAstException("literal value missing floatvalue") in StringDatatypes -> - if(initialstrvalue==null && heapId==null) throw FatalAstException("literal value missing strvalue/heapId") + if(strvalue==null && heapId==null) throw FatalAstException("literal value missing strvalue/heapId") in ArrayDatatypes -> if(arrayvalue==null && heapId==null) throw FatalAstException("literal value missing arrayvalue/heapId") else -> throw FatalAstException("invalid type $type") } - if(bytevalue==null && wordvalue==null && floatvalue==null && arrayvalue==null && initialstrvalue==null && heapId==null) + if(bytevalue==null && wordvalue==null && floatvalue==null && arrayvalue==null && strvalue==null && heapId==null) throw FatalAstException("literal value without actual value") } @@ -1383,7 +1382,7 @@ open class LiteralValue(val type: DataType, (floatvalue!=null && floatvalue != 0.0) || (bytevalue!=null && bytevalue != 0.toShort()) || (wordvalue!=null && wordvalue != 0) || - (initialstrvalue!=null && initialstrvalue.isNotEmpty()) || + (strvalue!=null && strvalue.isNotEmpty()) || (arrayvalue != null && arrayvalue.isNotEmpty()) override fun linkParents(parent: Node) { @@ -1409,14 +1408,8 @@ open class LiteralValue(val type: DataType, DataType.UWORD -> "uword:$wordvalue" DataType.WORD -> "word:$wordvalue" DataType.FLOAT -> "float:$floatvalue" - in StringDatatypes -> { - if(heapId!=null) "str:#$heapId" - else "str:$initialstrvalue" - } - in ArrayDatatypes -> { - if(heapId!=null) "array:#$heapId" - else "array:$arrayvalue" - } + in StringDatatypes -> "str:$strvalue" + in ArrayDatatypes -> "array:$arrayvalue" else -> throw FatalAstException("weird datatype") } return "LiteralValue($vstr)" @@ -1428,7 +1421,7 @@ open class LiteralValue(val type: DataType, val bh = bytevalue?.hashCode() ?: 0x10001234 val wh = wordvalue?.hashCode() ?: 0x01002345 val fh = floatvalue?.hashCode() ?: 0x00103456 - val sh = initialstrvalue?.hashCode() ?: 0x00014567 + val sh = strvalue?.hashCode() ?: 0x00014567 val ah = arrayvalue?.hashCode() ?: 0x11119876 var hash = bh * 31 xor wh hash = hash*31 xor fh @@ -1446,7 +1439,7 @@ open class LiteralValue(val type: DataType, if(isArray && other.isArray) return arrayvalue!!.contentEquals(other.arrayvalue!!) && heapId==other.heapId if(isString && other.isString) - return initialstrvalue==other.initialstrvalue && heapId==other.heapId + return strvalue==other.strvalue && heapId==other.heapId if(type!=other.type) return false @@ -1460,8 +1453,8 @@ open class LiteralValue(val type: DataType, if(numLeft!=null && numRight!=null) return numLeft.compareTo(numRight) - if(initialstrvalue!=null && other.initialstrvalue!=null) - return initialstrvalue.compareTo(other.initialstrvalue) + if(strvalue!=null && other.strvalue!=null) + return strvalue.compareTo(other.strvalue) throw ExpressionError("cannot order compare type $type with ${other.type}", other.position) } @@ -1529,12 +1522,6 @@ open class LiteralValue(val type: DataType, } return null // invalid type conversion from $this to $targettype } - - fun strvalue(heap: HeapValues): String { - if(initialstrvalue!=null) - return initialstrvalue - return heap.get(heapId!!).str!! - } } @@ -1572,15 +1559,15 @@ class RangeExpr(var from: IExpression, return "RangeExpr(from $from, to $to, step $step, pos=$position)" } - fun size(heap: HeapValues): Int? { + fun size(): Int? { val fromLv = (from as? LiteralValue) val toLv = (to as? LiteralValue) if(fromLv==null || toLv==null) return null - return toConstantIntegerRange(heap)?.count() + return toConstantIntegerRange()?.count() } - fun toConstantIntegerRange(heap: HeapValues): IntProgression? { + fun toConstantIntegerRange(): IntProgression? { val fromLv = from as? LiteralValue val toLv = to as? LiteralValue if(fromLv==null || toLv==null) @@ -1589,8 +1576,8 @@ class RangeExpr(var from: IExpression, val toVal: Int if(fromLv.isString && toLv.isString) { // string range -> int range over petscii values - fromVal = Petscii.encodePetscii(fromLv.strvalue(heap), true)[0].toInt() - toVal = Petscii.encodePetscii(toLv.strvalue(heap), true)[0].toInt() + fromVal = Petscii.encodePetscii(fromLv.strvalue!!, true)[0].toInt() + toVal = Petscii.encodePetscii(toLv.strvalue!!, true)[0].toInt() } else { // integer range fromVal = (from as LiteralValue).asIntegerValue!! diff --git a/compiler/src/prog8/ast/AstChecker.kt b/compiler/src/prog8/ast/AstChecker.kt index eb14d4d7d..271fb2f56 100644 --- a/compiler/src/prog8/ast/AstChecker.kt +++ b/compiler/src/prog8/ast/AstChecker.kt @@ -788,8 +788,8 @@ private class AstChecker(private val program: Program, err("descending range requires step < 0") } from.isString && to.isString -> { - val fromString = from.strvalue(program.heap) - val toString = to.strvalue(program.heap) + val fromString = from.strvalue!! + val toString = to.strvalue!! if(fromString.length!=1 || toString.length!=1) err("range from and to must be a single character") if(fromString[0] == toString[0]) @@ -977,7 +977,7 @@ private class AstChecker(private val program: Program, checkResult.add(ExpressionError("range for string must have single characters from and to values", range.position)) return false } - val rangeSize=range.size(program.heap) + val rangeSize=range.size() if(rangeSize!=null && (rangeSize<0 || rangeSize>255)) { checkResult.add(ExpressionError("size of range for string must be 0..255, instead of $rangeSize", range.position)) return false @@ -987,7 +987,7 @@ private class AstChecker(private val program: Program, in ArrayDatatypes -> { // range and length check bytes val expectedSize = arrayspec.size() - val rangeSize=range.size(program.heap) + val rangeSize=range.size() if(rangeSize!=null && rangeSize != expectedSize) { checkResult.add(ExpressionError("range size doesn't match array size, expected $expectedSize found $rangeSize", range.position)) return false @@ -1049,8 +1049,7 @@ private class AstChecker(private val program: Program, DataType.STR, DataType.STR_S -> { if(!value.isString) return err("string value expected") - val str = value.strvalue(heap) - if (str.length > 255) + if (value.strvalue!!.length > 255) return err("string length must be 0-255") } DataType.ARRAY_UB, DataType.ARRAY_B -> { diff --git a/compiler/src/prog8/astvm/Expressions.kt b/compiler/src/prog8/astvm/Expressions.kt index 1e627ac73..6cd89f32d 100644 --- a/compiler/src/prog8/astvm/Expressions.kt +++ b/compiler/src/prog8/astvm/Expressions.kt @@ -127,7 +127,7 @@ fun evaluate(expr: IExpression, ctx: EvalContext): RuntimeValue { } } is RangeExpr -> { - val cRange = expr.toConstantIntegerRange(ctx.program.heap) + val cRange = expr.toConstantIntegerRange() if(cRange!=null) return RuntimeValueRange(expr.inferType(ctx.program)!!, cRange) val fromVal = evaluate(expr.from, ctx).integerValue() diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 4ffcadf45..0d2c76821 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -1563,7 +1563,7 @@ internal class Compiler(private val program: Program): IAstProcessor { } if(loop.iterable is RangeExpr) { - val range = (loop.iterable as RangeExpr).toConstantIntegerRange(program.heap) + val range = (loop.iterable as RangeExpr).toConstantIntegerRange() if(range!=null) { // loop over a range with constant start, last and step values if (range.isEmpty()) @@ -1630,7 +1630,7 @@ internal class Compiler(private val program: Program): IAstProcessor { when(iterableValue.type) { !in IterableDatatypes -> throw CompilerException("non-iterableValue type") DataType.STR, DataType.STR_S -> { - numElements = iterableValue.strvalue(program.heap).length + numElements = iterableValue.strvalue!!.length if(numElements>255) throw CompilerException("string length > 255") } DataType.ARRAY_UB, DataType.ARRAY_B, diff --git a/compiler/src/prog8/functions/BuiltinFunctions.kt b/compiler/src/prog8/functions/BuiltinFunctions.kt index 47e8ff1dc..e0e3c3f2e 100644 --- a/compiler/src/prog8/functions/BuiltinFunctions.kt +++ b/compiler/src/prog8/functions/BuiltinFunctions.kt @@ -314,7 +314,7 @@ private fun builtinStrlen(args: List, position: Position, program: val argument = args[0].constValue(program) ?: throw NotConstArgumentException() if(argument.type !in StringDatatypes) throw SyntaxError("strlen must have string argument", position) - val string = argument.strvalue(program.heap) + val string = argument.strvalue!! val zeroIdx = string.indexOf('\u0000') return if(zeroIdx>=0) LiteralValue.optimalInteger(zeroIdx, position=position) @@ -353,7 +353,7 @@ private fun builtinLen(args: List, position: Position, program: Pro LiteralValue.optimalInteger(arraySize, args[0].position) } in StringDatatypes -> { - val str = argument.strvalue(program.heap) + val str = argument.strvalue!! if(str.length>255) throw CompilerException("string length exceeds byte limit ${argument.position}") LiteralValue.optimalInteger(str.length, args[0].position) diff --git a/compiler/src/prog8/optimizing/ConstExprEvaluator.kt b/compiler/src/prog8/optimizing/ConstExprEvaluator.kt index c3f8d9224..7d99a0313 100644 --- a/compiler/src/prog8/optimizing/ConstExprEvaluator.kt +++ b/compiler/src/prog8/optimizing/ConstExprEvaluator.kt @@ -10,11 +10,11 @@ val associativeOperators = setOf("+", "*", "&", "|", "^", "or", "and", "xor", "= class ConstExprEvaluator { - fun evaluate(left: LiteralValue, operator: String, right: LiteralValue, heap: HeapValues): IExpression { + fun evaluate(left: LiteralValue, operator: String, right: LiteralValue): IExpression { return when(operator) { - "+" -> plus(left, right, heap) + "+" -> plus(left, right) "-" -> minus(left, right) - "*" -> multiply(left, right, heap) + "*" -> multiply(left, right) "/" -> divide(left, right) "%" -> remainder(left, right) "**" -> power(left, right) @@ -161,7 +161,7 @@ class ConstExprEvaluator { } } - private fun plus(left: LiteralValue, right: LiteralValue, heap: HeapValues): LiteralValue { + private fun plus(left: LiteralValue, right: LiteralValue): LiteralValue { val error = "cannot add $left and $right" return when { left.asIntegerValue!=null -> when { @@ -176,7 +176,7 @@ class ConstExprEvaluator { } left.isString -> when { right.isString -> { - val newStr = left.strvalue(heap) + right.strvalue(heap) + val newStr = left.strvalue!! + right.strvalue!! if(newStr.length > 255) throw ExpressionError("string too long", left.position) LiteralValue(DataType.STR, strvalue = newStr, position = left.position) } @@ -203,15 +203,15 @@ class ConstExprEvaluator { } } - private fun multiply(left: LiteralValue, right: LiteralValue, heap: HeapValues): LiteralValue { + private fun multiply(left: LiteralValue, right: LiteralValue): LiteralValue { val error = "cannot multiply ${left.type} and ${right.type}" return when { left.asIntegerValue!=null -> when { right.asIntegerValue!=null -> LiteralValue.optimalNumeric(left.asIntegerValue * right.asIntegerValue, left.position) right.floatvalue!=null -> LiteralValue(DataType.FLOAT, floatvalue = left.asIntegerValue * right.floatvalue, position = left.position) right.isString -> { - if(right.strvalue(heap).length * left.asIntegerValue > 255) throw ExpressionError("string too long", left.position) - LiteralValue(DataType.STR, strvalue = right.strvalue(heap).repeat(left.asIntegerValue), position = left.position) + if(right.strvalue!!.length * left.asIntegerValue > 255) throw ExpressionError("string too long", left.position) + LiteralValue(DataType.STR, strvalue = right.strvalue.repeat(left.asIntegerValue), position = left.position) } else -> throw ExpressionError(error, left.position) } diff --git a/compiler/src/prog8/optimizing/ConstantFolding.kt b/compiler/src/prog8/optimizing/ConstantFolding.kt index 42afe7591..3b9ef88b0 100644 --- a/compiler/src/prog8/optimizing/ConstantFolding.kt +++ b/compiler/src/prog8/optimizing/ConstantFolding.kt @@ -68,9 +68,9 @@ class ConstantFolding(private val program: Program) : IAstProcessor { if(rangeExpr!=null) { // convert the initializer range expression to an actual array (will be put on heap later) val declArraySize = decl.arraysize?.size() - if(declArraySize!=null && declArraySize!=rangeExpr.size(program.heap)) + if(declArraySize!=null && declArraySize!=rangeExpr.size()) errors.add(ExpressionError("range expression size doesn't match declared array size", decl.value?.position!!)) - val constRange = rangeExpr.toConstantIntegerRange(program.heap) + val constRange = rangeExpr.toConstantIntegerRange() if(constRange!=null) { val eltType = rangeExpr.inferType(program)!! if(eltType in ByteDatatypes) { @@ -335,7 +335,7 @@ class ConstantFolding(private val program: Program) : IAstProcessor { return when { leftconst != null && rightconst != null -> { optimizationsDone++ - evaluator.evaluate(leftconst, expr.operator, rightconst, program.heap) + evaluator.evaluate(leftconst, expr.operator, rightconst) } else -> expr } @@ -595,10 +595,10 @@ class ConstantFolding(private val program: Program) : IAstProcessor { val litval = super.process(literalValue) if(litval.isString) { // intern the string; move it into the heap - if(litval.strvalue(program.heap).length !in 1..255) + if(litval.strvalue!!.length !in 1..255) addError(ExpressionError("string literal length must be between 1 and 255", litval.position)) else { - litval.heapId = program.heap.addString(litval.type, litval.strvalue(program.heap)) // TODO: we don't know the actual string type yet, STR != STR_S etc... + litval.heapId = program.heap.addString(litval.type, litval.strvalue) // TODO: we don't know the actual string type yet, STR != STR_S etc... } } else if(litval.arrayvalue!=null) { // first, adjust the array datatype diff --git a/compiler/src/prog8/optimizing/StatementOptimizer.kt b/compiler/src/prog8/optimizing/StatementOptimizer.kt index 526f53731..4511c508e 100644 --- a/compiler/src/prog8/optimizing/StatementOptimizer.kt +++ b/compiler/src/prog8/optimizing/StatementOptimizer.kt @@ -325,7 +325,7 @@ internal class StatementOptimizer(private val program: Program, private val opti val range = forLoop.iterable as? RangeExpr if(range!=null) { - if(range.size(program.heap)==1) { + if(range.size()==1) { // for loop over a (constant) range of just a single value-- optimize the loop away // loopvar/reg = range value , follow by block val assignment = Assignment(listOf(AssignTarget(forLoop.loopRegister, forLoop.loopVar, null, null, forLoop.position)), null, range.from, forLoop.position)