mirror of
https://github.com/irmen/prog8.git
synced 2024-09-07 19:54:26 +00:00
now correctly accepts "xxx" * constexpr (where constexpr is not just a single const number)
This commit is contained in:
parent
09d3451d9d
commit
348b3036ff
@ -108,9 +108,32 @@ class ConstantFoldingOptimizer(private val program: Program) : AstWalker() {
|
||||
* (X + c1) - c2 -> X + (c1-c2)
|
||||
*/
|
||||
override fun after(expr: BinaryExpression, parent: Node): Iterable<IAstModification> {
|
||||
val modifications = mutableListOf<IAstModification>()
|
||||
val leftconst = expr.left.constValue(program)
|
||||
val rightconst = expr.right.constValue(program)
|
||||
val modifications = mutableListOf<IAstModification>()
|
||||
|
||||
if(expr.left.inferType(program) istype DataType.STR) {
|
||||
if(expr.operator=="+" && expr.left is StringLiteral && expr.right is StringLiteral) {
|
||||
// concatenate two strings.
|
||||
val leftString = expr.left as StringLiteral
|
||||
val rightString = expr.right as StringLiteral
|
||||
val concatenated = if(leftString.encoding==rightString.encoding) {
|
||||
leftString.value + rightString.value
|
||||
} else {
|
||||
program.encoding.decodeString(
|
||||
program.encoding.encodeString(leftString.value, leftString.encoding) + program.encoding.encodeString(rightString.value, rightString.encoding),
|
||||
leftString.encoding)
|
||||
}
|
||||
val concatStr = StringLiteral(concatenated, leftString.encoding, expr.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, concatStr, parent))
|
||||
}
|
||||
else if(expr.operator=="*" && rightconst!=null && expr.left is StringLiteral) {
|
||||
// mutiply a string.
|
||||
val part = expr.left as StringLiteral
|
||||
val newStr = StringLiteral(part.value.repeat(rightconst.number.toInt()), part.encoding, expr.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, newStr, parent))
|
||||
}
|
||||
}
|
||||
|
||||
if(expr.operator=="==" && rightconst!=null) {
|
||||
val leftExpr = expr.left as? BinaryExpression
|
||||
|
@ -649,6 +649,9 @@ internal class AstChecker(private val program: Program,
|
||||
if(parameter==null)
|
||||
err("string var must be initialized with a string literal")
|
||||
}
|
||||
|
||||
if(decl.value !is StringLiteral)
|
||||
err("string var must be initialized with a string literal")
|
||||
}
|
||||
|
||||
if(compilerOptions.zeropage==ZeropageType.DONTUSE && decl.zeropage == ZeropageWish.REQUIRE_ZEROPAGE)
|
||||
@ -886,7 +889,7 @@ internal class AstChecker(private val program: Program,
|
||||
if(leftDt!=rightDt) {
|
||||
if(leftDt==DataType.STR && rightDt in IntegerDatatypes) {
|
||||
// only exception allowed: str * constvalue
|
||||
if(expr.right.constValue(program)!=null)
|
||||
if(expr.right.constValue(program)==null)
|
||||
errors.err("can only use string repeat with a constant number value", expr.left.position)
|
||||
} else {
|
||||
errors.err("left and right operands aren't the same type", expr.left.position)
|
||||
|
@ -5,7 +5,6 @@ import prog8.ast.Program
|
||||
import prog8.ast.expressions.ArrayIndexedExpression
|
||||
import prog8.ast.expressions.BinaryExpression
|
||||
import prog8.ast.expressions.DirectMemoryRead
|
||||
import prog8.ast.expressions.StringLiteral
|
||||
import prog8.ast.statements.AssignTarget
|
||||
import prog8.ast.statements.DirectMemoryWrite
|
||||
import prog8.ast.statements.Subroutine
|
||||
@ -39,65 +38,9 @@ internal class AstVariousTransforms(private val program: Program) : AstWalker()
|
||||
return noModifications
|
||||
}
|
||||
|
||||
override fun after(expr: BinaryExpression, parent: Node): Iterable<IAstModification> {
|
||||
val leftStr = expr.left as? StringLiteral
|
||||
val rightStr = expr.right as? StringLiteral
|
||||
if(expr.operator == "+") {
|
||||
val concatenatedString = concatString(expr)
|
||||
if(concatenatedString!=null)
|
||||
return listOf(IAstModification.ReplaceNode(expr, concatenatedString, parent))
|
||||
}
|
||||
else if(expr.operator == "*") {
|
||||
if (leftStr!=null) {
|
||||
val amount = expr.right.constValue(program)
|
||||
if(amount!=null) {
|
||||
val string = leftStr.value.repeat(amount.number.toInt())
|
||||
val strval = StringLiteral(string, leftStr.encoding, expr.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, strval, parent))
|
||||
}
|
||||
}
|
||||
else if (rightStr!=null) {
|
||||
val amount = expr.right.constValue(program)
|
||||
if(amount!=null) {
|
||||
val string = rightStr.value.repeat(amount.number.toInt())
|
||||
val strval = StringLiteral(string, rightStr.encoding, expr.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, strval, parent))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return noModifications
|
||||
}
|
||||
|
||||
override fun after(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> {
|
||||
return replacePointerVarIndexWithMemreadOrMemwrite(program, arrayIndexedExpression, parent)
|
||||
}
|
||||
|
||||
private fun concatString(expr: BinaryExpression): StringLiteral? {
|
||||
val rightStrval = expr.right as? StringLiteral
|
||||
val leftStrval = expr.left as? StringLiteral
|
||||
return when {
|
||||
expr.operator!="+" -> null
|
||||
expr.left is BinaryExpression && rightStrval!=null -> {
|
||||
val subStrVal = concatString(expr.left as BinaryExpression)
|
||||
if(subStrVal==null)
|
||||
null
|
||||
else
|
||||
StringLiteral("${subStrVal.value}${rightStrval.value}", subStrVal.encoding, rightStrval.position)
|
||||
}
|
||||
expr.right is BinaryExpression && leftStrval!=null -> {
|
||||
val subStrVal = concatString(expr.right as BinaryExpression)
|
||||
if(subStrVal==null)
|
||||
null
|
||||
else
|
||||
StringLiteral("${leftStrval.value}${subStrVal.value}", subStrVal.encoding, leftStrval.position)
|
||||
}
|
||||
leftStrval!=null && rightStrval!=null -> {
|
||||
StringLiteral("${leftStrval.value}${rightStrval.value}", leftStrval.encoding, leftStrval.position)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,6 +4,7 @@ import prog8.ast.IFunctionCall
|
||||
import prog8.ast.Node
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.expressions.ArrayLiteral
|
||||
import prog8.ast.expressions.BinaryExpression
|
||||
import prog8.ast.expressions.IdentifierReference
|
||||
import prog8.ast.expressions.StringLiteral
|
||||
import prog8.ast.statements.VarDecl
|
||||
@ -26,7 +27,7 @@ internal class LiteralsToAutoVars(private val program: Program,
|
||||
errors.err("compilation target doesn't support this text encoding", string.position)
|
||||
return noModifications
|
||||
}
|
||||
if(string.parent !is VarDecl && string.parent !is WhenChoice) {
|
||||
if(string.parent !is VarDecl && string.parent !is WhenChoice && string.parent !is BinaryExpression) {
|
||||
// replace the literal string by an identifier reference to the interned string
|
||||
val parentFunc = (string.parent as? IFunctionCall)?.target
|
||||
if(parentFunc!=null) {
|
||||
|
@ -4,7 +4,6 @@ TODO
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- pipe operator: allow non-unary function calls in the pipe that specify the other argument(s) in the calls.
|
||||
- allow "xxx" * constexpr (where constexpr is not a number literal), now gives expression error not same type
|
||||
- make it possible to inline non-asmsub routines that just contain a single statement (return, functioncall, assignment)
|
||||
but this requires all identifiers in the inlined expression to be changed to fully scoped names.
|
||||
If we can do that why not perhaps also able to inline multi-line subroutines? Why would it be limited to just 1 line? Maybe to protect against code size bloat.
|
||||
|
@ -7,9 +7,23 @@
|
||||
main {
|
||||
|
||||
sub start() {
|
||||
ubyte xx=10
|
||||
xx = xx>9
|
||||
txt.print_ub(xx)
|
||||
const ubyte times=3
|
||||
; expected output: aaabbb aaa bbb
|
||||
txt.print("aaa"+"bbb"+"ccc")
|
||||
txt.nl()
|
||||
; txt.print("aaa")
|
||||
; txt.nl()
|
||||
; txt.print("bbb")
|
||||
; txt.nl()
|
||||
; expected output: xxx xxxxxx xxxxxxxxx xxx
|
||||
; txt.print("xxx"*(times-2))
|
||||
; txt.nl()
|
||||
; txt.print("xxx"*(times-1))
|
||||
; txt.nl()
|
||||
txt.print("xxx"*times)
|
||||
txt.nl()
|
||||
; txt.print("xxx")
|
||||
; txt.nl()
|
||||
sys.exit(42)
|
||||
; floats.print_f(-42.42)
|
||||
; float f1 = 1.2345
|
||||
|
Loading…
Reference in New Issue
Block a user