PtNumber can now be compared

This commit is contained in:
Irmen de Jong 2022-04-10 17:48:03 +02:00
parent b6eb343234
commit 3f6393f732
2 changed files with 192 additions and 1 deletions

View File

@ -3,6 +3,8 @@ package prog8.code.ast
import prog8.code.core.DataType
import prog8.code.core.Encoding
import prog8.code.core.Position
import java.util.*
import kotlin.math.round
sealed class PtExpression(val type: DataType, position: Position) : PtNode(position) {
@ -26,7 +28,14 @@ class PtArrayIndexer(type: DataType, position: Position): PtExpression(type, pos
}
class PtArray(type: DataType, position: Position): PtExpression(type, position)
class PtArray(type: DataType, position: Position): PtExpression(type, position) {
override fun hashCode(): Int = Objects.hash(children, type)
override fun equals(other: Any?): Boolean {
if(other==null || other !is PtArray)
return false
return type==other.type && children == other.children
}
}
class PtBuiltinFunctionCall(val name: String, val void: Boolean, type: DataType, position: Position) : PtExpression(type, position) {
@ -95,9 +104,28 @@ class PtMemoryByte(position: Position) : PtExpression(DataType.UBYTE, position)
class PtNumber(type: DataType, val number: Double, position: Position) : PtExpression(type, position) {
init {
if(type!=DataType.FLOAT) {
val rounded = round(number)
if (rounded != number)
throw IllegalArgumentException("refused rounding of float to avoid loss of precision")
}
}
override fun printProperties() {
print("$number ($type)")
}
override fun hashCode(): Int = Objects.hash(type, number)
override fun equals(other: Any?): Boolean {
if(other==null || other !is PtNumber)
return false
return number==other.number
}
operator fun compareTo(other: PtNumber): Int = number.compareTo(other.number)
}
@ -140,6 +168,13 @@ class PtString(val value: String, val encoding: Encoding, position: Position) :
override fun printProperties() {
print("$encoding:\"$value\"")
}
override fun hashCode(): Int = Objects.hash(value, encoding)
override fun equals(other: Any?): Boolean {
if(other==null || other !is PtString)
return false
return value==other.value && encoding == other.encoding
}
}

View File

@ -0,0 +1,156 @@
package prog8tests
import io.kotest.assertions.throwables.shouldThrow
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import io.kotest.matchers.string.shouldContain
import prog8.code.ast.PtArray
import prog8.code.ast.PtNumber
import prog8.code.ast.PtString
import prog8.code.core.DataType
import prog8.code.core.Encoding
import prog8.code.core.Position
class TestPtNumber: FunSpec({
fun sameValueAndType(lv1: PtNumber, lv2: PtNumber): Boolean {
return lv1.type==lv2.type && lv1==lv2
}
val dummyPos = Position("test", 0, 0, 0)
test("testIdentity") {
val v = PtNumber(DataType.UWORD, 12345.0, dummyPos)
(v==v) shouldBe true
(v != v) shouldBe false
(v <= v) shouldBe true
(v >= v) shouldBe true
(v < v ) shouldBe false
(v > v ) shouldBe false
sameValueAndType(PtNumber(DataType.UWORD, 12345.0, dummyPos), PtNumber(DataType.UWORD, 12345.0, dummyPos)) shouldBe true
}
test("test rounding") {
shouldThrow<IllegalArgumentException> {
PtNumber(DataType.BYTE, -2.345, dummyPos)
}.message shouldContain "refused rounding"
shouldThrow<IllegalArgumentException> {
PtNumber(DataType.BYTE, -2.6, dummyPos)
}.message shouldContain "refused rounding"
shouldThrow<IllegalArgumentException> {
PtNumber(DataType.UWORD, 2222.345, dummyPos)
}.message shouldContain "refused rounding"
PtNumber(DataType.UBYTE, 2.0, dummyPos).number shouldBe 2.0
PtNumber(DataType.BYTE, -2.0, dummyPos).number shouldBe -2.0
PtNumber(DataType.UWORD, 2222.0, dummyPos).number shouldBe 2222.0
PtNumber(DataType.FLOAT, 123.456, dummyPos)
}
test("testEqualsAndNotEquals") {
(PtNumber(DataType.UBYTE, 100.0, dummyPos) == PtNumber(DataType.UBYTE, 100.0, dummyPos)) shouldBe true
(PtNumber(DataType.UBYTE, 100.0, dummyPos) == PtNumber(DataType.UWORD, 100.0, dummyPos)) shouldBe true
(PtNumber(DataType.UBYTE, 100.0, dummyPos) == PtNumber(DataType.FLOAT, 100.0, dummyPos)) shouldBe true
(PtNumber(DataType.UWORD, 254.0, dummyPos) == PtNumber(DataType.UBYTE, 254.0, dummyPos)) shouldBe true
(PtNumber(DataType.UWORD, 12345.0, dummyPos) == PtNumber(DataType.UWORD, 12345.0, dummyPos)) shouldBe true
(PtNumber(DataType.UWORD, 12345.0, dummyPos) == PtNumber(DataType.FLOAT, 12345.0, dummyPos)) shouldBe true
(PtNumber(DataType.FLOAT, 100.0, dummyPos) == PtNumber(DataType.UBYTE, 100.0, dummyPos)) shouldBe true
(PtNumber(DataType.FLOAT, 22239.0, dummyPos) == PtNumber(DataType.UWORD, 22239.0, dummyPos)) shouldBe true
(PtNumber(DataType.FLOAT, 9.99, dummyPos) == PtNumber(DataType.FLOAT, 9.99, dummyPos)) shouldBe true
sameValueAndType(PtNumber(DataType.UBYTE, 100.0, dummyPos), PtNumber(DataType.UBYTE, 100.0, dummyPos)) shouldBe true
sameValueAndType(PtNumber(DataType.UBYTE, 100.0, dummyPos), PtNumber(DataType.UWORD, 100.0, dummyPos)) shouldBe false
sameValueAndType(PtNumber(DataType.UBYTE, 100.0, dummyPos), PtNumber(DataType.FLOAT, 100.0, dummyPos)) shouldBe false
sameValueAndType(PtNumber(DataType.UWORD, 254.0, dummyPos), PtNumber(DataType.UBYTE, 254.0, dummyPos)) shouldBe false
sameValueAndType(PtNumber(DataType.UWORD, 12345.0, dummyPos), PtNumber(DataType.UWORD, 12345.0, dummyPos)) shouldBe true
sameValueAndType(PtNumber(DataType.UWORD, 12345.0, dummyPos), PtNumber(DataType.FLOAT, 12345.0, dummyPos)) shouldBe false
sameValueAndType(PtNumber(DataType.FLOAT, 100.0, dummyPos), PtNumber(DataType.UBYTE, 100.0, dummyPos)) shouldBe false
sameValueAndType(PtNumber(DataType.FLOAT, 22239.0, dummyPos), PtNumber(DataType.UWORD, 22239.0, dummyPos)) shouldBe false
sameValueAndType(PtNumber(DataType.FLOAT, 9.99, dummyPos), PtNumber(DataType.FLOAT, 9.99, dummyPos)) shouldBe true
(PtNumber(DataType.UBYTE, 100.0, dummyPos) != PtNumber(DataType.UBYTE, 101.0, dummyPos)) shouldBe true
(PtNumber(DataType.UBYTE, 100.0, dummyPos) != PtNumber(DataType.UWORD, 101.0, dummyPos)) shouldBe true
(PtNumber(DataType.UBYTE, 100.0, dummyPos) != PtNumber(DataType.FLOAT, 101.0, dummyPos)) shouldBe true
(PtNumber(DataType.UWORD, 245.0, dummyPos) != PtNumber(DataType.UBYTE, 246.0, dummyPos)) shouldBe true
(PtNumber(DataType.UWORD, 12345.0, dummyPos) != PtNumber(DataType.UWORD, 12346.0, dummyPos)) shouldBe true
(PtNumber(DataType.UWORD, 12345.0, dummyPos) != PtNumber(DataType.FLOAT, 12346.0, dummyPos)) shouldBe true
(PtNumber(DataType.FLOAT, 9.99, dummyPos) != PtNumber(DataType.UBYTE, 9.0, dummyPos)) shouldBe true
(PtNumber(DataType.FLOAT, 9.99, dummyPos) != PtNumber(DataType.UWORD, 9.0, dummyPos)) shouldBe true
(PtNumber(DataType.FLOAT, 9.99, dummyPos) != PtNumber(DataType.FLOAT, 9.0, dummyPos)) shouldBe true
sameValueAndType(PtNumber(DataType.UBYTE, 100.0, dummyPos), PtNumber(DataType.UBYTE, 101.0, dummyPos)) shouldBe false
sameValueAndType(PtNumber(DataType.UBYTE, 100.0, dummyPos), PtNumber(DataType.UWORD, 101.0, dummyPos)) shouldBe false
sameValueAndType(PtNumber(DataType.UBYTE, 100.0, dummyPos), PtNumber(DataType.FLOAT, 101.0, dummyPos)) shouldBe false
sameValueAndType(PtNumber(DataType.UWORD, 245.0, dummyPos), PtNumber(DataType.UBYTE, 246.0, dummyPos)) shouldBe false
sameValueAndType(PtNumber(DataType.UWORD, 12345.0, dummyPos), PtNumber(DataType.UWORD, 12346.0, dummyPos)) shouldBe false
sameValueAndType(PtNumber(DataType.UWORD, 12345.0, dummyPos), PtNumber(DataType.FLOAT, 12346.0, dummyPos)) shouldBe false
sameValueAndType(PtNumber(DataType.FLOAT, 9.99, dummyPos), PtNumber(DataType.UBYTE, 9.0, dummyPos)) shouldBe false
sameValueAndType(PtNumber(DataType.FLOAT, 9.99, dummyPos), PtNumber(DataType.UWORD, 9.0, dummyPos)) shouldBe false
sameValueAndType(PtNumber(DataType.FLOAT, 9.99, dummyPos), PtNumber(DataType.FLOAT, 9.0, dummyPos)) shouldBe false
}
test("testEqualsRef") {
(PtString("hello", Encoding.PETSCII, dummyPos) == PtString("hello", Encoding.PETSCII, dummyPos)) shouldBe true
(PtString("hello", Encoding.PETSCII, dummyPos) != PtString("bye", Encoding.PETSCII, dummyPos)) shouldBe true
(PtString("hello", Encoding.SCREENCODES, dummyPos) == PtString("hello", Encoding.SCREENCODES, dummyPos)) shouldBe true
(PtString("hello", Encoding.SCREENCODES, dummyPos) != PtString("bye", Encoding.SCREENCODES, dummyPos)) shouldBe true
(PtString("hello", Encoding.SCREENCODES, dummyPos) != PtString("hello", Encoding.PETSCII, dummyPos)) shouldBe true
val lvOne = PtNumber(DataType.UBYTE, 1.0, dummyPos)
val lvTwo = PtNumber(DataType.UBYTE, 2.0, dummyPos)
val lvThree = PtNumber(DataType.UBYTE, 3.0, dummyPos)
val lvOneR = PtNumber(DataType.UBYTE, 1.0, dummyPos)
val lvTwoR = PtNumber(DataType.UBYTE, 2.0, dummyPos)
val lvThreeR = PtNumber(DataType.UBYTE, 3.0, dummyPos)
val lvFour= PtNumber(DataType.UBYTE, 4.0, dummyPos)
val lv1 = PtArray(DataType.ARRAY_UB, dummyPos)
arrayOf(lvOne, lvTwo, lvThree).forEach { lv1.add(it) }
val lv2 = PtArray(DataType.ARRAY_UB, dummyPos)
arrayOf(lvOneR, lvTwoR, lvThreeR).forEach { lv2.add(it) }
val lv3 = PtArray(DataType.ARRAY_UB, dummyPos)
arrayOf(lvOneR, lvTwoR, lvFour).forEach { lv3.add(it) }
lv1 shouldBe lv2
lv1 shouldNotBe lv3
}
test("testGreaterThan") {
(PtNumber(DataType.UBYTE, 100.0, dummyPos) > PtNumber(DataType.UBYTE, 99.0, dummyPos)) shouldBe true
(PtNumber(DataType.UWORD, 254.0, dummyPos) > PtNumber(DataType.UWORD, 253.0, dummyPos)) shouldBe true
(PtNumber(DataType.FLOAT, 100.0, dummyPos) > PtNumber(DataType.FLOAT, 99.9, dummyPos)) shouldBe true
(PtNumber(DataType.UBYTE, 100.0, dummyPos) >= PtNumber(DataType.UBYTE, 100.0, dummyPos)) shouldBe true
(PtNumber(DataType.UWORD, 254.0, dummyPos) >= PtNumber(DataType.UWORD, 254.0, dummyPos)) shouldBe true
(PtNumber(DataType.FLOAT, 100.0, dummyPos) >= PtNumber(DataType.FLOAT, 100.0, dummyPos)) shouldBe true
(PtNumber(DataType.UBYTE, 100.0, dummyPos) > PtNumber(DataType.UBYTE, 100.0, dummyPos)) shouldBe false
(PtNumber(DataType.UWORD, 254.0, dummyPos) > PtNumber(DataType.UWORD, 254.0, dummyPos)) shouldBe false
(PtNumber(DataType.FLOAT, 100.0, dummyPos) > PtNumber(DataType.FLOAT, 100.0, dummyPos)) shouldBe false
(PtNumber(DataType.UBYTE, 100.0, dummyPos) >= PtNumber(DataType.UBYTE, 101.0, dummyPos)) shouldBe false
(PtNumber(DataType.UWORD, 254.0, dummyPos) >= PtNumber(DataType.UWORD, 255.0, dummyPos)) shouldBe false
(PtNumber(DataType.FLOAT, 100.0, dummyPos) >= PtNumber(DataType.FLOAT, 100.1, dummyPos)) shouldBe false
}
test("testLessThan") {
(PtNumber(DataType.UBYTE, 100.0, dummyPos) < PtNumber(DataType.UBYTE, 101.0, dummyPos)) shouldBe true
(PtNumber(DataType.UWORD, 254.0, dummyPos) < PtNumber(DataType.UWORD, 255.0, dummyPos)) shouldBe true
(PtNumber(DataType.FLOAT, 100.0, dummyPos) < PtNumber(DataType.FLOAT, 100.1, dummyPos)) shouldBe true
(PtNumber(DataType.UBYTE, 100.0, dummyPos) <= PtNumber(DataType.UBYTE, 100.0, dummyPos)) shouldBe true
(PtNumber(DataType.UWORD, 254.0, dummyPos) <= PtNumber(DataType.UWORD, 254.0, dummyPos)) shouldBe true
(PtNumber(DataType.FLOAT, 100.0, dummyPos) <= PtNumber(DataType.FLOAT, 100.0, dummyPos)) shouldBe true
(PtNumber(DataType.UBYTE, 100.0, dummyPos) < PtNumber(DataType.UBYTE, 100.0, dummyPos)) shouldBe false
(PtNumber(DataType.UWORD, 254.0, dummyPos) < PtNumber(DataType.UWORD, 254.0, dummyPos)) shouldBe false
(PtNumber(DataType.FLOAT, 100.0, dummyPos) < PtNumber(DataType.FLOAT, 100.0, dummyPos)) shouldBe false
(PtNumber(DataType.UBYTE, 100.0, dummyPos) <= PtNumber(DataType.UBYTE, 99.0, dummyPos)) shouldBe false
(PtNumber(DataType.UWORD, 254.0, dummyPos) <= PtNumber(DataType.UWORD, 253.0, dummyPos)) shouldBe false
(PtNumber(DataType.FLOAT, 100.0, dummyPos) <= PtNumber(DataType.FLOAT, 99.9, dummyPos)) shouldBe false
}
})