mirror of
https://github.com/irmen/prog8.git
synced 2025-08-14 22:27:48 +00:00
boolean not expression tweaks and optimizations
This commit is contained in:
@@ -18,7 +18,7 @@ class AtariTarget: ICompilationTarget, IStringEncoding by Encoder, IMemSizer {
|
|||||||
in ByteDatatypes -> 1
|
in ByteDatatypes -> 1
|
||||||
in WordDatatypes, in PassByReferenceDatatypes -> 2
|
in WordDatatypes, in PassByReferenceDatatypes -> 2
|
||||||
DataType.FLOAT -> machine.FLOAT_MEM_SIZE
|
DataType.FLOAT -> machine.FLOAT_MEM_SIZE
|
||||||
else -> Int.MIN_VALUE
|
else -> throw IllegalArgumentException("invalid datatype")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -17,7 +17,7 @@ class VMTarget: ICompilationTarget, IStringEncoding by Encoder, IMemSizer {
|
|||||||
in ByteDatatypes -> 1
|
in ByteDatatypes -> 1
|
||||||
in WordDatatypes, in PassByReferenceDatatypes -> 2
|
in WordDatatypes, in PassByReferenceDatatypes -> 2
|
||||||
DataType.FLOAT -> machine.FLOAT_MEM_SIZE
|
DataType.FLOAT -> machine.FLOAT_MEM_SIZE
|
||||||
else -> Int.MIN_VALUE
|
else -> throw IllegalArgumentException("invalid datatype")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -9,7 +9,7 @@ internal object CbmMemorySizer: IMemSizer {
|
|||||||
in ByteDatatypes -> 1
|
in ByteDatatypes -> 1
|
||||||
in WordDatatypes, in PassByReferenceDatatypes -> 2
|
in WordDatatypes, in PassByReferenceDatatypes -> 2
|
||||||
DataType.FLOAT -> Mflpt5.FLOAT_MEM_SIZE
|
DataType.FLOAT -> Mflpt5.FLOAT_MEM_SIZE
|
||||||
else -> Int.MIN_VALUE
|
else -> throw IllegalArgumentException("invalid datatype")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -67,14 +67,12 @@ class ExpressionSimplifier(private val program: Program,
|
|||||||
}
|
}
|
||||||
if(elsepart.statements.singleOrNull() is Jump) {
|
if(elsepart.statements.singleOrNull() is Jump) {
|
||||||
val invertedCondition = invertCondition(ifElse.condition)
|
val invertedCondition = invertCondition(ifElse.condition)
|
||||||
if(invertedCondition!=null) {
|
return listOf(
|
||||||
return listOf(
|
IAstModification.ReplaceNode(ifElse.condition, invertedCondition, ifElse),
|
||||||
IAstModification.ReplaceNode(ifElse.condition, invertedCondition, ifElse),
|
IAstModification.InsertAfter(ifElse, truepart, parent as IStatementContainer),
|
||||||
IAstModification.InsertAfter(ifElse, truepart, parent as IStatementContainer),
|
IAstModification.ReplaceNode(elsepart, AnonymousScope(mutableListOf(), elsepart.position), ifElse),
|
||||||
IAstModification.ReplaceNode(elsepart, AnonymousScope(mutableListOf(), elsepart.position), ifElse),
|
IAstModification.ReplaceNode(truepart, elsepart, ifElse)
|
||||||
IAstModification.ReplaceNode(truepart, elsepart, ifElse)
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,23 +317,13 @@ class ExpressionSimplifier(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(rightVal!=null && leftDt==DataType.BOOL) {
|
if(rightVal!=null && leftDt==DataType.BOOL) {
|
||||||
// see if we can replace comparison against true/1 with simpler comparison against zero
|
// boolean compare against a number -> just keep the boolean, no compare
|
||||||
if (expr.operator == "==") {
|
if(expr.operator=="==" || expr.operator=="!=") {
|
||||||
if (rightVal.number == 1.0) {
|
val test = if (expr.operator == "==") rightVal.asBooleanValue else !rightVal.asBooleanValue
|
||||||
val zero = NumericLiteral(DataType.UBYTE, 0.0, expr.right.position)
|
return if (test) {
|
||||||
return listOf(
|
listOf(IAstModification.ReplaceNode(expr, expr.left, parent))
|
||||||
IAstModification.SetExpression({expr.operator="!="}, expr, parent),
|
} else {
|
||||||
IAstModification.ReplaceNode(expr.right, zero, expr)
|
listOf(IAstModification.ReplaceNode(expr, invertCondition(expr.left), parent))
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (expr.operator == "!=") {
|
|
||||||
if (rightVal.number == 1.0) {
|
|
||||||
val zero = NumericLiteral(DataType.UBYTE, 0.0, expr.right.position)
|
|
||||||
return listOf(
|
|
||||||
IAstModification.SetExpression({expr.operator="=="}, expr, parent),
|
|
||||||
IAstModification.ReplaceNode(expr.right, zero, expr)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -117,11 +117,10 @@ class StatementOptimizer(private val program: Program,
|
|||||||
if(jump is Jump) {
|
if(jump is Jump) {
|
||||||
val newTruePart = AnonymousScope(mutableListOf(jump), ifElse.elsepart.position)
|
val newTruePart = AnonymousScope(mutableListOf(jump), ifElse.elsepart.position)
|
||||||
val newElsePart = AnonymousScope(ifElse.truepart.statements, ifElse.truepart.position)
|
val newElsePart = AnonymousScope(ifElse.truepart.statements, ifElse.truepart.position)
|
||||||
val invertedCondition = PrefixExpression("not", ifElse.condition, ifElse.condition.position)
|
|
||||||
return listOf(
|
return listOf(
|
||||||
IAstModification.ReplaceNode(ifElse.elsepart, newElsePart, ifElse),
|
IAstModification.ReplaceNode(ifElse.elsepart, newElsePart, ifElse),
|
||||||
IAstModification.ReplaceNode(ifElse.truepart, newTruePart, ifElse),
|
IAstModification.ReplaceNode(ifElse.truepart, newTruePart, ifElse),
|
||||||
IAstModification.ReplaceNode(ifElse.condition, invertedCondition, ifElse)
|
IAstModification.ReplaceNode(ifElse.condition, invertCondition(ifElse.condition), ifElse)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -91,17 +91,15 @@ do { STUFF } until CONDITION
|
|||||||
===>
|
===>
|
||||||
_loop:
|
_loop:
|
||||||
STUFF
|
STUFF
|
||||||
if CONDITION==0
|
if not CONDITION
|
||||||
goto _loop
|
goto _loop
|
||||||
*/
|
*/
|
||||||
val pos = untilLoop.position
|
val pos = untilLoop.position
|
||||||
val loopLabel = program.makeLabel("untilloop", pos)
|
val loopLabel = program.makeLabel("untilloop", pos)
|
||||||
val ifCondition = invertCondition(untilLoop.condition)
|
|
||||||
?: BinaryExpression(untilLoop.condition, "==", NumericLiteral(DataType.UBYTE, 0.0, pos), pos)
|
|
||||||
val replacement = AnonymousScope(mutableListOf(
|
val replacement = AnonymousScope(mutableListOf(
|
||||||
loopLabel,
|
loopLabel,
|
||||||
untilLoop.body,
|
untilLoop.body,
|
||||||
IfElse(ifCondition,
|
IfElse(invertCondition(untilLoop.condition),
|
||||||
AnonymousScope(mutableListOf(program.jumpLabel(loopLabel)), pos),
|
AnonymousScope(mutableListOf(program.jumpLabel(loopLabel)), pos),
|
||||||
AnonymousScope(mutableListOf(), pos),
|
AnonymousScope(mutableListOf(), pos),
|
||||||
pos)
|
pos)
|
||||||
@@ -130,7 +128,7 @@ if CONDITION==0
|
|||||||
while CONDITION { STUFF }
|
while CONDITION { STUFF }
|
||||||
==>
|
==>
|
||||||
_whileloop:
|
_whileloop:
|
||||||
if INVERTED-CONDITION goto _after
|
if not CONDITION goto _after
|
||||||
STUFF
|
STUFF
|
||||||
goto _whileloop
|
goto _whileloop
|
||||||
_after:
|
_after:
|
||||||
@@ -138,11 +136,9 @@ _after:
|
|||||||
val pos = whileLoop.position
|
val pos = whileLoop.position
|
||||||
val loopLabel = program.makeLabel("whileloop", pos)
|
val loopLabel = program.makeLabel("whileloop", pos)
|
||||||
val afterLabel = program.makeLabel("afterwhile", pos)
|
val afterLabel = program.makeLabel("afterwhile", pos)
|
||||||
val ifCondition = invertCondition(whileLoop.condition)
|
|
||||||
?: BinaryExpression(whileLoop.condition, "==", NumericLiteral(DataType.UBYTE, 0.0, pos), pos)
|
|
||||||
val replacement = AnonymousScope(mutableListOf(
|
val replacement = AnonymousScope(mutableListOf(
|
||||||
loopLabel,
|
loopLabel,
|
||||||
IfElse(ifCondition,
|
IfElse(invertCondition(whileLoop.condition),
|
||||||
AnonymousScope(mutableListOf(program.jumpLabel(afterLabel)), pos),
|
AnonymousScope(mutableListOf(program.jumpLabel(afterLabel)), pos),
|
||||||
AnonymousScope(mutableListOf(), pos),
|
AnonymousScope(mutableListOf(), pos),
|
||||||
pos),
|
pos),
|
||||||
|
@@ -6,6 +6,7 @@ import prog8.ast.base.FatalAstException
|
|||||||
import prog8.ast.expressions.BinaryExpression
|
import prog8.ast.expressions.BinaryExpression
|
||||||
import prog8.ast.expressions.NumericLiteral
|
import prog8.ast.expressions.NumericLiteral
|
||||||
import prog8.ast.expressions.PrefixExpression
|
import prog8.ast.expressions.PrefixExpression
|
||||||
|
import prog8.ast.expressions.invertCondition
|
||||||
import prog8.ast.walk.AstWalker
|
import prog8.ast.walk.AstWalker
|
||||||
import prog8.ast.walk.IAstModification
|
import prog8.ast.walk.IAstModification
|
||||||
import prog8.code.core.DataType
|
import prog8.code.core.DataType
|
||||||
@@ -44,8 +45,7 @@ internal class NotExpressionAndIfComparisonExprChanger(val program: Program, val
|
|||||||
|
|
||||||
if(expr.operator=="^" && expr.left.inferType(program) istype DataType.BOOL && expr.right.constValue(program)?.number == 1.0) {
|
if(expr.operator=="^" && expr.left.inferType(program) istype DataType.BOOL && expr.right.constValue(program)?.number == 1.0) {
|
||||||
// boolean ^ 1 --> not boolean
|
// boolean ^ 1 --> not boolean
|
||||||
val notExpr = PrefixExpression("not", expr.left, expr.position)
|
return listOf(IAstModification.ReplaceNode(expr, invertCondition(expr.left), parent))
|
||||||
return listOf(IAstModification.ReplaceNode(expr, notExpr, parent))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -987,22 +987,18 @@ main {
|
|||||||
val result = compileText(Cx16Target(), true, src, writeAssembly = false)!!
|
val result = compileText(Cx16Target(), true, src, writeAssembly = false)!!
|
||||||
val st = result.compilerAst.entrypoint.statements
|
val st = result.compilerAst.entrypoint.statements
|
||||||
st.size shouldBe 8
|
st.size shouldBe 8
|
||||||
val if1c = (st[4] as IfElse).condition as BinaryExpression
|
val if1c = (st[4] as IfElse).condition as PrefixExpression
|
||||||
val if2c = (st[5] as IfElse).condition as BinaryExpression
|
val if2c = (st[5] as IfElse).condition as PrefixExpression
|
||||||
val if3c = (st[6] as IfElse).condition as BinaryExpression
|
val if3c = (st[6] as IfElse).condition as PrefixExpression
|
||||||
val if4c = (st[7] as IfElse).condition as BinaryExpression
|
val if4c = (st[7] as IfElse).condition as PrefixExpression
|
||||||
if1c.operator shouldBe "=="
|
if1c.operator shouldBe "not"
|
||||||
(if1c.right as NumericLiteral).number shouldBe 0.0
|
if2c.operator shouldBe "not"
|
||||||
(if1c.left as BinaryExpression).operator shouldBe "or"
|
if3c.operator shouldBe "not"
|
||||||
if2c.operator shouldBe "=="
|
if4c.operator shouldBe "not"
|
||||||
(if2c.right as NumericLiteral).number shouldBe 0.0
|
(if1c.expression as BinaryExpression).operator shouldBe "or"
|
||||||
(if2c.left as BinaryExpression).operator shouldBe "and"
|
(if2c.expression as BinaryExpression).operator shouldBe "and"
|
||||||
if3c.operator shouldBe "=="
|
(if3c.expression as BinaryExpression).operator shouldBe "and"
|
||||||
(if3c.right as NumericLiteral).number shouldBe 0.0
|
(if4c.expression as BinaryExpression).operator shouldBe "or"
|
||||||
(if3c.left as BinaryExpression).operator shouldBe "and"
|
|
||||||
if4c.operator shouldBe "=="
|
|
||||||
(if4c.right as NumericLiteral).number shouldBe 0.0
|
|
||||||
(if4c.left as BinaryExpression).operator shouldBe "or"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test("absorption laws") {
|
test("absorption laws") {
|
||||||
|
@@ -475,17 +475,17 @@ main {
|
|||||||
st.size shouldBe 7
|
st.size shouldBe 7
|
||||||
|
|
||||||
val ifCond = (st[4] as IfElse).condition as BinaryExpression
|
val ifCond = (st[4] as IfElse).condition as BinaryExpression
|
||||||
ifCond.operator shouldBe "=="
|
ifCond.operator shouldBe ">="
|
||||||
(ifCond.right as NumericLiteral).number shouldBe 0.0
|
(ifCond.left as IdentifierReference).nameInSource shouldBe listOf("n")
|
||||||
(ifCond.left as BinaryExpression).operator shouldBe "<"
|
(ifCond.right as IdentifierReference).nameInSource shouldBe listOf("x")
|
||||||
val assign1 = (st[5] as Assignment).value as BinaryExpression
|
val assign1 = (st[5] as Assignment).value as BinaryExpression
|
||||||
val assign2 = (st[6] as Assignment).value as BinaryExpression
|
val assign2 = (st[6] as Assignment).value as BinaryExpression
|
||||||
assign1.operator shouldBe "=="
|
assign1.operator shouldBe ">="
|
||||||
(assign1.right as NumericLiteral).number shouldBe 0.0
|
(assign1.left as IdentifierReference).nameInSource shouldBe listOf("n")
|
||||||
(assign1.left as BinaryExpression).operator shouldBe "<"
|
(assign1.right as IdentifierReference).nameInSource shouldBe listOf("x")
|
||||||
assign2.operator shouldBe "=="
|
assign2.operator shouldBe ">="
|
||||||
(assign2.right as NumericLiteral).number shouldBe 0.0
|
(assign1.left as IdentifierReference).nameInSource shouldBe listOf("n")
|
||||||
(assign2.left as BinaryExpression).operator shouldBe "<"
|
(assign1.right as IdentifierReference).nameInSource shouldBe listOf("x")
|
||||||
}
|
}
|
||||||
|
|
||||||
test("modulo is not directive") {
|
test("modulo is not directive") {
|
||||||
|
@@ -95,7 +95,8 @@ class AstToSourceTextConverter(val output: (text: String) -> Unit, val program:
|
|||||||
private fun datatypeString(dt: DataType): String {
|
private fun datatypeString(dt: DataType): String {
|
||||||
return when (dt) {
|
return when (dt) {
|
||||||
in NumericDatatypes -> dt.toString().lowercase()
|
in NumericDatatypes -> dt.toString().lowercase()
|
||||||
DataType.STR -> dt.toString().lowercase()
|
DataType.BOOL -> "bool"
|
||||||
|
DataType.STR -> "str"
|
||||||
DataType.ARRAY_UB -> "ubyte["
|
DataType.ARRAY_UB -> "ubyte["
|
||||||
DataType.ARRAY_B -> "byte["
|
DataType.ARRAY_B -> "byte["
|
||||||
DataType.ARRAY_UW -> "uword["
|
DataType.ARRAY_UW -> "uword["
|
||||||
|
@@ -226,10 +226,10 @@ class BinaryExpression(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"&", "|", "^" -> if(leftDt istype DataType.BOOL) InferredTypes.knownFor(DataType.UBYTE) else leftDt
|
"&", "|", "^" -> if(leftDt istype DataType.BOOL) InferredTypes.knownFor(DataType.UBYTE) else leftDt
|
||||||
"and", "or", "xor", "not" -> InferredTypes.knownFor(DataType.BOOL)
|
"and", "or", "xor", "not", "in", "not in",
|
||||||
"<", ">",
|
"<", ">",
|
||||||
"<=", ">=",
|
"<=", ">=",
|
||||||
"==", "!=", "in", "not in" -> InferredTypes.knownFor(DataType.BOOL)
|
"==", "!=" -> InferredTypes.knownFor(DataType.BOOL)
|
||||||
"<<", ">>" -> leftDt
|
"<<", ">>" -> leftDt
|
||||||
else -> throw FatalAstException("resulting datatype check for invalid operator $operator")
|
else -> throw FatalAstException("resulting datatype check for invalid operator $operator")
|
||||||
}
|
}
|
||||||
@@ -550,137 +550,137 @@ class NumericLiteral(val type: DataType, // only numerical types allowed
|
|||||||
|
|
||||||
operator fun compareTo(other: NumericLiteral): Int = number.compareTo(other.number)
|
operator fun compareTo(other: NumericLiteral): Int = number.compareTo(other.number)
|
||||||
|
|
||||||
class CastValue(val isValid: Boolean, val whyFailed: String?, private val value: NumericLiteral?) {
|
class ValueAfterCast(val isValid: Boolean, val whyFailed: String?, private val value: NumericLiteral?) {
|
||||||
fun valueOrZero() = if(isValid) value!! else NumericLiteral(DataType.UBYTE, 0.0, Position.DUMMY)
|
fun valueOrZero() = if(isValid) value!! else NumericLiteral(DataType.UBYTE, 0.0, Position.DUMMY)
|
||||||
fun linkParent(parent: Node) {
|
fun linkParent(parent: Node) {
|
||||||
value?.linkParents(parent)
|
value?.linkParents(parent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun cast(targettype: DataType): CastValue {
|
fun cast(targettype: DataType): ValueAfterCast {
|
||||||
val result = internalCast(targettype)
|
val result = internalCast(targettype)
|
||||||
result.linkParent(this.parent)
|
result.linkParent(this.parent)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun internalCast(targettype: DataType): CastValue {
|
private fun internalCast(targettype: DataType): ValueAfterCast {
|
||||||
if(type==targettype)
|
if(type==targettype)
|
||||||
return CastValue(true, null, this)
|
return ValueAfterCast(true, null, this)
|
||||||
when(type) {
|
when(type) {
|
||||||
DataType.UBYTE -> {
|
DataType.UBYTE -> {
|
||||||
if(targettype==DataType.BYTE)
|
if(targettype==DataType.BYTE)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number.toInt().toByte().toDouble(), position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number.toInt().toByte().toDouble(), position))
|
||||||
if(targettype==DataType.WORD || targettype==DataType.UWORD)
|
if(targettype==DataType.WORD || targettype==DataType.UWORD)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype==DataType.FLOAT)
|
if(targettype==DataType.FLOAT)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype==DataType.LONG)
|
if(targettype==DataType.LONG)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype==DataType.BOOL)
|
if(targettype==DataType.BOOL)
|
||||||
return CastValue(true, null, fromBoolean(number!=0.0, position))
|
return ValueAfterCast(true, null, fromBoolean(number!=0.0, position))
|
||||||
}
|
}
|
||||||
DataType.BYTE -> {
|
DataType.BYTE -> {
|
||||||
if(targettype==DataType.UBYTE) {
|
if(targettype==DataType.UBYTE) {
|
||||||
if(number in -128.0..0.0)
|
if(number in -128.0..0.0)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number.toInt().toUByte().toDouble(), position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number.toInt().toUByte().toDouble(), position))
|
||||||
else if(number in 0.0..255.0)
|
else if(number in 0.0..255.0)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
}
|
}
|
||||||
if(targettype==DataType.UWORD) {
|
if(targettype==DataType.UWORD) {
|
||||||
if(number in -32768.0..0.0)
|
if(number in -32768.0..0.0)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number.toInt().toUShort().toDouble(), position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number.toInt().toUShort().toDouble(), position))
|
||||||
else if(number in 0.0..65535.0)
|
else if(number in 0.0..65535.0)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
}
|
}
|
||||||
if(targettype==DataType.WORD)
|
if(targettype==DataType.WORD)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype==DataType.FLOAT)
|
if(targettype==DataType.FLOAT)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype==DataType.BOOL)
|
if(targettype==DataType.BOOL)
|
||||||
return CastValue(true, null, fromBoolean(number!=0.0, position))
|
return ValueAfterCast(true, null, fromBoolean(number!=0.0, position))
|
||||||
if(targettype==DataType.LONG)
|
if(targettype==DataType.LONG)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
}
|
}
|
||||||
DataType.UWORD -> {
|
DataType.UWORD -> {
|
||||||
if(targettype==DataType.BYTE && number <= 127)
|
if(targettype==DataType.BYTE && number <= 127)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype==DataType.UBYTE && number <= 255)
|
if(targettype==DataType.UBYTE && number <= 255)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype==DataType.WORD)
|
if(targettype==DataType.WORD)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number.toInt().toShort().toDouble(), position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number.toInt().toShort().toDouble(), position))
|
||||||
if(targettype==DataType.FLOAT)
|
if(targettype==DataType.FLOAT)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype==DataType.BOOL)
|
if(targettype==DataType.BOOL)
|
||||||
return CastValue(true, null, fromBoolean(number!=0.0, position))
|
return ValueAfterCast(true, null, fromBoolean(number!=0.0, position))
|
||||||
if(targettype==DataType.LONG)
|
if(targettype==DataType.LONG)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
}
|
}
|
||||||
DataType.WORD -> {
|
DataType.WORD -> {
|
||||||
if(targettype==DataType.BYTE && number >= -128 && number <=127)
|
if(targettype==DataType.BYTE && number >= -128 && number <=127)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype==DataType.UBYTE) {
|
if(targettype==DataType.UBYTE) {
|
||||||
if(number in -128.0..0.0)
|
if(number in -128.0..0.0)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number.toInt().toUByte().toDouble(), position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number.toInt().toUByte().toDouble(), position))
|
||||||
else if(number in 0.0..255.0)
|
else if(number in 0.0..255.0)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
}
|
}
|
||||||
if(targettype==DataType.UWORD) {
|
if(targettype==DataType.UWORD) {
|
||||||
if(number in -32768.0 .. 0.0)
|
if(number in -32768.0 .. 0.0)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number.toInt().toUShort().toDouble(), position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number.toInt().toUShort().toDouble(), position))
|
||||||
else if(number in 0.0..65535.0)
|
else if(number in 0.0..65535.0)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
}
|
}
|
||||||
if(targettype==DataType.FLOAT)
|
if(targettype==DataType.FLOAT)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype==DataType.BOOL)
|
if(targettype==DataType.BOOL)
|
||||||
return CastValue(true, null, fromBoolean(number!=0.0, position))
|
return ValueAfterCast(true, null, fromBoolean(number!=0.0, position))
|
||||||
if(targettype==DataType.LONG)
|
if(targettype==DataType.LONG)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
}
|
}
|
||||||
DataType.FLOAT -> {
|
DataType.FLOAT -> {
|
||||||
try {
|
try {
|
||||||
if (targettype == DataType.BYTE && number >= -128 && number <= 127)
|
if (targettype == DataType.BYTE && number >= -128 && number <= 127)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
if (targettype == DataType.UBYTE && number >= 0 && number <= 255)
|
if (targettype == DataType.UBYTE && number >= 0 && number <= 255)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
if (targettype == DataType.WORD && number >= -32768 && number <= 32767)
|
if (targettype == DataType.WORD && number >= -32768 && number <= 32767)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
if (targettype == DataType.UWORD && number >= 0 && number <= 65535)
|
if (targettype == DataType.UWORD && number >= 0 && number <= 65535)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype==DataType.LONG && number >=0 && number <= 2147483647)
|
if(targettype==DataType.LONG && number >=0 && number <= 2147483647)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype==DataType.BOOL)
|
if(targettype==DataType.BOOL)
|
||||||
return CastValue(true, null, fromBoolean(number!=0.0, position))
|
return ValueAfterCast(true, null, fromBoolean(number!=0.0, position))
|
||||||
} catch (x: ExpressionError) {
|
} catch (x: ExpressionError) {
|
||||||
return CastValue(false, x.message,null)
|
return ValueAfterCast(false, x.message,null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataType.BOOL -> {
|
DataType.BOOL -> {
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
}
|
}
|
||||||
DataType.LONG -> {
|
DataType.LONG -> {
|
||||||
try {
|
try {
|
||||||
if (targettype == DataType.BYTE && number >= -128 && number <= 127)
|
if (targettype == DataType.BYTE && number >= -128 && number <= 127)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
if (targettype == DataType.UBYTE && number >= 0 && number <= 255)
|
if (targettype == DataType.UBYTE && number >= 0 && number <= 255)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
if (targettype == DataType.WORD && number >= -32768 && number <= 32767)
|
if (targettype == DataType.WORD && number >= -32768 && number <= 32767)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
if (targettype == DataType.UWORD && number >= 0 && number <= 65535)
|
if (targettype == DataType.UWORD && number >= 0 && number <= 65535)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
if(targettype==DataType.BOOL)
|
if(targettype==DataType.BOOL)
|
||||||
return CastValue(true, null, fromBoolean(number!=0.0, position))
|
return ValueAfterCast(true, null, fromBoolean(number!=0.0, position))
|
||||||
if(targettype==DataType.FLOAT)
|
if(targettype==DataType.FLOAT)
|
||||||
return CastValue(true, null, NumericLiteral(targettype, number, position))
|
return ValueAfterCast(true, null, NumericLiteral(targettype, number, position))
|
||||||
} catch (x: ExpressionError) {
|
} catch (x: ExpressionError) {
|
||||||
return CastValue(false, x.message, null)
|
return ValueAfterCast(false, x.message, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
throw FatalAstException("type cast of weird type $type")
|
throw FatalAstException("type cast of weird type $type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return CastValue(false, "no cast available between these types", null)
|
return ValueAfterCast(false, "no cast available between these types", null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1257,11 +1257,12 @@ class BuiltinFunctionCall(override var target: IdentifierReference,
|
|||||||
override fun inferType(program: Program) = program.builtinFunctions.returnType(name)
|
override fun inferType(program: Program) = program.builtinFunctions.returnType(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun invertCondition(cond: Expression): BinaryExpression? {
|
fun invertCondition(cond: Expression): Expression {
|
||||||
if(cond is BinaryExpression) {
|
if(cond is BinaryExpression) {
|
||||||
val invertedOperator = invertedComparisonOperator(cond.operator)
|
val invertedOperator = invertedComparisonOperator(cond.operator)
|
||||||
if (invertedOperator != null)
|
if (invertedOperator != null)
|
||||||
return BinaryExpression(cond.left, invertedOperator, cond.right, cond.position)
|
return BinaryExpression(cond.left, invertedOperator, cond.right, cond.position)
|
||||||
}
|
}
|
||||||
return null
|
|
||||||
|
return PrefixExpression("not", cond, cond.position)
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,11 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
[on branch 'booleans']: keep Bool alive longer until codegen? (don't replace by UBYTE so quickly?)
|
consolidate the various type-to-string tables, look for: DataType.BOOL -> "bool"
|
||||||
|
|
||||||
|
"all other not(x) --> x==0" SOMETIMES if removed, improves code, sometimes it makes it worse.
|
||||||
|
Find out what is what! (paint)
|
||||||
|
ALSO: when adding a expr.issimple to that, it crashes with a parent node mismatch error. FIX THAT.
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
|
@@ -683,7 +683,13 @@ class FunctionCallArgs(
|
|||||||
val returns: RegSpec?
|
val returns: RegSpec?
|
||||||
) {
|
) {
|
||||||
class RegSpec(val dt: IRDataType, val registerNum: Int, val cpuRegister: RegisterOrStatusflag?)
|
class RegSpec(val dt: IRDataType, val registerNum: Int, val cpuRegister: RegisterOrStatusflag?)
|
||||||
class ArgumentSpec(val name: String, val address: Int?, val reg: RegSpec)
|
class ArgumentSpec(val name: String, val address: Int?, val reg: RegSpec) {
|
||||||
|
init {
|
||||||
|
require(address==null || address>=0) {
|
||||||
|
"address must be >=0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class IRInstruction(
|
data class IRInstruction(
|
||||||
@@ -759,6 +765,9 @@ data class IRInstruction(
|
|||||||
else
|
else
|
||||||
require(immediate != null || immediateFp != null) { "missing immediate value" }
|
require(immediate != null || immediateFp != null) { "missing immediate value" }
|
||||||
}
|
}
|
||||||
|
require(address==null || address>=0) {
|
||||||
|
"address must be >=0"
|
||||||
|
}
|
||||||
|
|
||||||
reg1direction = format.reg1
|
reg1direction = format.reg1
|
||||||
reg2direction = format.reg2
|
reg2direction = format.reg2
|
||||||
|
@@ -165,17 +165,18 @@ class IRStMemVar(name: String,
|
|||||||
|
|
||||||
val typeString: String
|
val typeString: String
|
||||||
get() = when (dt) {
|
get() = when (dt) {
|
||||||
|
DataType.BOOL -> "bool"
|
||||||
DataType.UBYTE -> "ubyte"
|
DataType.UBYTE -> "ubyte"
|
||||||
DataType.BYTE -> "byte"
|
DataType.BYTE -> "byte"
|
||||||
DataType.UWORD -> "uword"
|
DataType.UWORD -> "uword"
|
||||||
DataType.WORD -> "word"
|
DataType.WORD -> "word"
|
||||||
DataType.FLOAT -> "float"
|
DataType.FLOAT -> "float"
|
||||||
DataType.BOOL, DataType.ARRAY_BOOL -> throw InternalCompilerException("bool should have been converted to ubyte")
|
DataType.ARRAY_BOOL -> "bool[$length]"
|
||||||
DataType.ARRAY_UB, DataType.STR -> "ubyte[${length}]"
|
DataType.ARRAY_UB, DataType.STR -> "ubyte[$length]"
|
||||||
DataType.ARRAY_B -> "byte[${length}]"
|
DataType.ARRAY_B -> "byte[$length]"
|
||||||
DataType.ARRAY_UW -> "uword[${length}]"
|
DataType.ARRAY_UW -> "uword[$length]"
|
||||||
DataType.ARRAY_W -> "word[${length}]"
|
DataType.ARRAY_W -> "word[$length]"
|
||||||
DataType.ARRAY_F -> "float[${length}]"
|
DataType.ARRAY_F -> "float[$length]"
|
||||||
in SplitWordArrayTypes -> throw InternalCompilerException("@split can't be used on memory mapped arrays")
|
in SplitWordArrayTypes -> throw InternalCompilerException("@split can't be used on memory mapped arrays")
|
||||||
else -> throw InternalCompilerException("weird dt")
|
else -> throw InternalCompilerException("weird dt")
|
||||||
}
|
}
|
||||||
@@ -221,17 +222,18 @@ class IRStStaticVariable(name: String,
|
|||||||
|
|
||||||
val typeString: String
|
val typeString: String
|
||||||
get() = when (dt) {
|
get() = when (dt) {
|
||||||
|
DataType.BOOL -> "bool"
|
||||||
DataType.UBYTE -> "ubyte"
|
DataType.UBYTE -> "ubyte"
|
||||||
DataType.BYTE -> "byte"
|
DataType.BYTE -> "byte"
|
||||||
DataType.UWORD -> "uword"
|
DataType.UWORD -> "uword"
|
||||||
DataType.WORD -> "word"
|
DataType.WORD -> "word"
|
||||||
DataType.FLOAT -> "float"
|
DataType.FLOAT -> "float"
|
||||||
DataType.BOOL, DataType.ARRAY_BOOL -> throw InternalCompilerException("bool should have been converted to ubyte")
|
DataType.ARRAY_BOOL -> "bool[$length]"
|
||||||
DataType.ARRAY_UB, DataType.STR -> "ubyte[${length}]"
|
DataType.ARRAY_UB, DataType.STR -> "ubyte[$length]"
|
||||||
DataType.ARRAY_B -> "byte[${length}]"
|
DataType.ARRAY_B -> "byte[$length]"
|
||||||
DataType.ARRAY_UW -> "uword[${length}]"
|
DataType.ARRAY_UW -> "uword[$length]"
|
||||||
DataType.ARRAY_W -> "word[${length}]"
|
DataType.ARRAY_W -> "word[$length]"
|
||||||
DataType.ARRAY_F -> "float[${length}]"
|
DataType.ARRAY_F -> "float[$length]"
|
||||||
in SplitWordArrayTypes -> throw InternalCompilerException("split array should have been converted to 2 ubyte arrays")
|
in SplitWordArrayTypes -> throw InternalCompilerException("split array should have been converted to 2 ubyte arrays")
|
||||||
else -> throw InternalCompilerException("weird dt")
|
else -> throw InternalCompilerException("weird dt")
|
||||||
}
|
}
|
||||||
|
@@ -7,12 +7,13 @@ import prog8.code.right
|
|||||||
|
|
||||||
|
|
||||||
fun getTypeString(dt : DataType): String = when(dt) {
|
fun getTypeString(dt : DataType): String = when(dt) {
|
||||||
|
DataType.BOOL -> "bool"
|
||||||
DataType.UBYTE -> "ubyte"
|
DataType.UBYTE -> "ubyte"
|
||||||
DataType.BYTE -> "byte"
|
DataType.BYTE -> "byte"
|
||||||
DataType.UWORD -> "uword"
|
DataType.UWORD -> "uword"
|
||||||
DataType.WORD -> "word"
|
DataType.WORD -> "word"
|
||||||
DataType.FLOAT -> "float"
|
DataType.FLOAT -> "float"
|
||||||
DataType.BOOL, DataType.ARRAY_BOOL -> throw InternalCompilerException("bool should have been converted to ubyte")
|
DataType.ARRAY_BOOL -> "bool[]"
|
||||||
DataType.ARRAY_UB, DataType.STR -> "ubyte[]"
|
DataType.ARRAY_UB, DataType.STR -> "ubyte[]"
|
||||||
DataType.ARRAY_B -> "byte[]"
|
DataType.ARRAY_B -> "byte[]"
|
||||||
DataType.ARRAY_UW -> "uword[]"
|
DataType.ARRAY_UW -> "uword[]"
|
||||||
|
Reference in New Issue
Block a user