diff --git a/docs/samples/happy_numbers.lyng.bad b/docs/samples/happy_numbers.lyng.bad index c5810dc..e66d13f 100644 --- a/docs/samples/happy_numbers.lyng.bad +++ b/docs/samples/happy_numbers.lyng.bad @@ -21,10 +21,10 @@ import lyng.time // // After all optimizations it takes ~120ms. // -//for( r in 1..100 ) { -// val start = Instant.now() +for( r in 1..100 ) { + val start = Instant.now() val found = naiveCountHappyNumbers() -// println("Found happy numbers: %d time %s"(found, Instant.now() - start)) + println("Found happy numbers: %d time %s"(found, Instant.now() - start)) assert( found == 55252 ) -// delay(0.01) -//} \ No newline at end of file + delay(0.1) +} \ No newline at end of file diff --git a/lynglib/build.gradle.kts b/lynglib/build.gradle.kts index 036ac7e..b242058 100644 --- a/lynglib/build.gradle.kts +++ b/lynglib/build.gradle.kts @@ -21,7 +21,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl import org.jetbrains.kotlin.gradle.dsl.JvmTarget group = "net.sergeych" -version = "0.9.1-SNAPSHOT" +version = "0.9.2-SNAPSHOT" buildscript { repositories { @@ -66,6 +66,7 @@ kotlin { // iosArm64() // iosSimulatorArm64() linuxX64() + linuxArm64() js { browser() nodejs() @@ -79,9 +80,9 @@ kotlin { sourceSets { all { languageSettings.optIn("kotlinx.coroutines.ExperimentalCoroutinesApi") - languageSettings.optIn("kotlin.contracts.ExperimentalContracts") languageSettings.optIn("kotlin.ExperimentalUnsignedTypes") languageSettings.optIn("kotlin.coroutines.DelicateCoroutinesApi") + languageSettings.optIn("kotlin.contracts.ExperimentalContracts") languageSettings.optIn("kotlinx.coroutines.flow.DelicateCoroutinesApi") } diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/CompilerContext.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/CompilerContext.kt index f5e7209..16f9b21 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/CompilerContext.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/CompilerContext.kt @@ -164,6 +164,7 @@ class CompilerContext(val tokens: List) { } } + @Suppress("NOTHING_TO_INLINE") inline fun addBreak() { breakFound = true } diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Script.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Script.kt index da204bd..4f89647 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Script.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Script.kt @@ -26,6 +26,7 @@ import net.sergeych.lynon.ObjLynonClass import net.sergeych.mp_tools.globalDefer import kotlin.math.* +@Suppress("TYPE_INTERSECTION_AS_REIFIED_WARNING") class Script( override val pos: Pos, private val statements: List = emptyList(), diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/Obj.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/Obj.kt index 19cd6be..b559a3a 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/Obj.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/Obj.kt @@ -367,6 +367,7 @@ open class Obj { } + @Suppress("NOTHING_TO_INLINE") inline fun from(obj: Any?): Obj { @Suppress("UNCHECKED_CAST") return when (obj) { diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjBitBuffer.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjBitBuffer.kt index 0f7a9c8..6389808 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjBitBuffer.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjBitBuffer.kt @@ -35,12 +35,12 @@ class ObjBitBuffer(val bitArray: BitArray) : Obj() { }.apply { addFn("toBuffer") { requireNoArgs() - ObjBuffer(thisAs().bitArray.asUbyteArray()) + ObjBuffer(thisAs().bitArray.asUByteArray()) } addFn("toDump") { requireNoArgs() ObjString( - thisAs().bitArray.asUbyteArray().toDump() + thisAs().bitArray.asUByteArray().toDump() ) } addFn("size") { diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lynon/BitList.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lynon/BitList.kt index 8900b12..7940920 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lynon/BitList.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lynon/BitList.kt @@ -17,8 +17,10 @@ package net.sergeych.lynon +import kotlin.math.min + @Suppress("unused") -interface BitList { +interface BitList: Comparable { operator fun get(bitIndex: Long): Int operator fun set(bitIndex: Long,value: Int) val size: Long @@ -31,6 +33,22 @@ interface BitList { if( index < size) this@BitList[index++] else null } + + override fun compareTo(other: BitList): Int { + val m = min(size, other.size) + for( i in 0 ..< m) { + val a = this[i] + val b = other[i] + when { + a < b -> return -1 + a > b -> return 1 + } + } + if( size > other.size) return 1 + if( size < other.size) return -1 + return 0 + } + } fun bitListOf(vararg bits: Int): BitList { diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lynon/MemoryBitOutput.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lynon/MemoryBitOutput.kt index 4c914ce..7dd8080 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lynon/MemoryBitOutput.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lynon/MemoryBitOutput.kt @@ -17,13 +17,18 @@ package net.sergeych.lynon +import kotlinx.serialization.Serializable import kotlin.math.min /** * BitList implementation as fixed suze array of bits; indexing works exactly same as if * [MemoryBitInput] is used with [MemoryBitInput.getBit]. See [MemoryBitOutput] for * bits order and more information. + * + * It is [BitList] - comparable, and provides valid [hashCode] and [equals], so it could + * also be used as a key in maps. */ +@Serializable class BitArray(val bytes: UByteArray, val lastByteBits: Int) : BitList { val bytesSize: Int get() = bytes.size @@ -73,7 +78,15 @@ class BitArray(val bytes: UByteArray, val lastByteBits: Int) : BitList { fun asByteArray(): ByteArray = bytes.asByteArray() @Suppress("unused") - fun asUbyteArray(): UByteArray = bytes + fun asUByteArray(): UByteArray = bytes + + override fun equals(other: Any?): Boolean { + return other is BitList && this.compareTo(other) == 0 + } + + override fun hashCode(): Int { + return bytes.contentHashCode() + } companion object { diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lynon/huffman.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lynon/huffman.kt index bdf840f..138e26c 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lynon/huffman.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lynon/huffman.kt @@ -18,7 +18,6 @@ package net.sergeych.lynon import net.sergeych.collections.SortedList -import net.sergeych.lynon.Huffman.Alphabet /** @@ -285,7 +284,7 @@ object Huffman { fun decompress(bin: BitInput,alphabet: Alphabet): UByteArray { val codes = deserializeCanonicCodes(bin, alphabet) - return decompressUsingCodes(bin, codes, alphabet).asUbyteArray() + return decompressUsingCodes(bin, codes, alphabet).asUByteArray() } } \ No newline at end of file diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lynon/packer.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lynon/packer.kt index d849efa..2aa54ad 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lynon/packer.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lynon/packer.kt @@ -56,7 +56,7 @@ object ObjLynonClass : ObjClass("Lynon") { @Suppress("unused") suspend fun lynonEncodeAny(scope: Scope, value: Obj): UByteArray = (ObjLynonClass.encodeAny(scope, value)) - .bitArray.asUbyteArray() + .bitArray.asUByteArray() @Suppress("unused") suspend fun lynonDecodeAny(scope: Scope, encoded: UByteArray): Obj = diff --git a/lynglib/src/jvmTest/kotlin/OtherTests.kt b/lynglib/src/jvmTest/kotlin/OtherTests.kt index f2e9c6b..66fc8ce 100644 --- a/lynglib/src/jvmTest/kotlin/OtherTests.kt +++ b/lynglib/src/jvmTest/kotlin/OtherTests.kt @@ -22,7 +22,10 @@ import net.sergeych.lyng.Source import net.sergeych.lyng.eval import net.sergeych.lyng.pacman.InlineSourcesImportProvider import net.sergeych.lyng.toSource +import net.sergeych.lynon.BitArray +import net.sergeych.lynon.BitList import kotlin.test.Test +import kotlin.test.assertNotEquals class OtherTests { @Test @@ -67,4 +70,33 @@ class OtherTests { Unit } + @Test + fun testBitArrayEqAndHash() { + + val b1 = BitArray.ofBits(1, 0, 1, 1) + val b11 = BitArray.ofBits(1, 0, 1, 1) + val b2 = BitArray.ofBits(1, 1, 1, 1) + val b3 = BitArray.ofBits(1, 0, 1, 1, 0) + + assert( b3 > b1 ) + assert( b2 > b1) + assert( b11.compareTo(b1) == 0) + + assertEquals(b1, b11) + assertNotEquals(b1, b2) + assertNotEquals(b1, b3) + + assert( b1.hashCode() == b11.hashCode() ) + + val x = mutableMapOf() + x[b1] = "wrong" + x[b11] = "OK" + x[b2] = "other" + + assertEquals("OK", x[b11]) + assertEquals("OK", x[b1]) + assertEquals("other", x[b2]) + + } + } \ No newline at end of file