fixed Decimal conversion bug
This commit is contained in:
parent
aa9565b40b
commit
c3c0a3292b
@ -88,7 +88,7 @@ object ObjDecimalSupport {
|
|||||||
}
|
}
|
||||||
decimalClass.addClassFn("fromInt") {
|
decimalClass.addClassFn("fromInt") {
|
||||||
val value = requiredArg<ObjInt>(0).value
|
val value = requiredArg<ObjInt>(0).value
|
||||||
newInstance(decimalClass, IonBigDecimal.fromLongAsSignificand(value))
|
newInstance(decimalClass, IonBigDecimal.fromLong(value))
|
||||||
}
|
}
|
||||||
decimalClass.addClassFn("fromReal") {
|
decimalClass.addClassFn("fromReal") {
|
||||||
val value = requiredArg<ObjReal>(0).value
|
val value = requiredArg<ObjReal>(0).value
|
||||||
@ -204,7 +204,7 @@ object ObjDecimalSupport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun coerceArg(scope: Scope, value: Obj): IonBigDecimal = when (value) {
|
private fun coerceArg(scope: Scope, value: Obj): IonBigDecimal = when (value) {
|
||||||
is ObjInt -> IonBigDecimal.fromLongAsSignificand(value.value)
|
is ObjInt -> IonBigDecimal.fromLong(value.value)
|
||||||
is ObjReal -> IonBigDecimal.fromDouble(value.value, realConversionMode)
|
is ObjReal -> IonBigDecimal.fromDouble(value.value, realConversionMode)
|
||||||
is ObjInstance -> {
|
is ObjInstance -> {
|
||||||
if (value.objClass.className != "Decimal") {
|
if (value.objClass.className != "Decimal") {
|
||||||
@ -303,7 +303,7 @@ object ObjDecimalSupport {
|
|||||||
doc = "Convert this integer to a Decimal.",
|
doc = "Convert this integer to a Decimal.",
|
||||||
type = type("lyng.decimal.Decimal"),
|
type = type("lyng.decimal.Decimal"),
|
||||||
moduleName = "lyng.decimal",
|
moduleName = "lyng.decimal",
|
||||||
getter = { newInstance(decimalClass, IonBigDecimal.fromLongAsSignificand(thisAs<ObjInt>().value)) }
|
getter = { newInstance(decimalClass, IonBigDecimal.fromLong(thisAs<ObjInt>().value)) }
|
||||||
)
|
)
|
||||||
ObjInt.type.members["d"] = ObjInt.type.members.getValue("d").copy(typeDecl = decimalTypeDecl)
|
ObjInt.type.members["d"] = ObjInt.type.members.getValue("d").copy(typeDecl = decimalTypeDecl)
|
||||||
ObjReal.type.addPropertyDoc(
|
ObjReal.type.addPropertyDoc(
|
||||||
@ -347,7 +347,7 @@ object ObjDecimalSupport {
|
|||||||
),
|
),
|
||||||
leftToCommon = ObjExternCallable.fromBridge {
|
leftToCommon = ObjExternCallable.fromBridge {
|
||||||
val value = requiredArg<ObjInt>(0).value
|
val value = requiredArg<ObjInt>(0).value
|
||||||
newInstance(decimalClass, IonBigDecimal.fromLongAsSignificand(value))
|
newInstance(decimalClass, IonBigDecimal.fromLong(value))
|
||||||
},
|
},
|
||||||
rightToCommon = ObjExternCallable.fromBridge {
|
rightToCommon = ObjExternCallable.fromBridge {
|
||||||
requiredArg<Obj>(0)
|
requiredArg<Obj>(0)
|
||||||
|
|||||||
@ -17,14 +17,15 @@
|
|||||||
|
|
||||||
package net.sergeych.lyng
|
package net.sergeych.lyng
|
||||||
|
|
||||||
|
import com.ionspin.kotlin.bignum.decimal.BigDecimal
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import net.sergeych.lyng.bridge.bindGlobalFun1
|
import net.sergeych.lyng.bridge.*
|
||||||
import net.sergeych.lyng.bridge.bindGlobalFun3
|
import net.sergeych.lyng.obj.ObjInstance
|
||||||
import net.sergeych.lyng.bridge.bindGlobalVar
|
|
||||||
import net.sergeych.lyng.bridge.globalBinder
|
|
||||||
import net.sergeych.lyng.obj.ObjInt
|
import net.sergeych.lyng.obj.ObjInt
|
||||||
|
import net.sergeych.lyng.obj.ObjReal
|
||||||
import net.sergeych.lyng.obj.ObjString
|
import net.sergeych.lyng.obj.ObjString
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class GlobalBindingTest {
|
class GlobalBindingTest {
|
||||||
@ -136,4 +137,87 @@ class GlobalBindingTest {
|
|||||||
assertTrue(readonlySetter)
|
assertTrue(readonlySetter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun rawDecimalExternBindingDoesNotBreakDecimalLiteralRendering() = runTest {
|
||||||
|
val scope = Script.newScope()
|
||||||
|
var x = BigDecimal.ZERO
|
||||||
|
|
||||||
|
scope.eval(
|
||||||
|
"""
|
||||||
|
import lyng.decimal
|
||||||
|
extern var X: Decimal
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
|
scope.globalBinder().bindGlobalVarRaw(
|
||||||
|
name = "X",
|
||||||
|
get = { it.newDecimal(x) },
|
||||||
|
set = { _, value ->
|
||||||
|
x = when (value) {
|
||||||
|
is ObjInt -> BigDecimal.fromLong(value.value)
|
||||||
|
is ObjReal -> BigDecimal.fromDouble(value.value)
|
||||||
|
is ObjInstance -> value.data as BigDecimal
|
||||||
|
else -> error("unexpected value: $value")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
scope.eval(
|
||||||
|
"""
|
||||||
|
fun main() {
|
||||||
|
assertEquals("42", 42.d.toStringExpanded())
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(BigDecimal.ZERO, x)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun externDecimalDeclarationAloneDoesNotBreakDecimalLiteralRendering() = runTest {
|
||||||
|
val scope = Script.newScope()
|
||||||
|
|
||||||
|
scope.eval(
|
||||||
|
"""
|
||||||
|
import lyng.decimal
|
||||||
|
extern var X: Decimal
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
assertEquals("42", 42.d.toStringExpanded())
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun parserKeeps42DotDAsIntDotIdentifierAfterExternDecimalDeclaration() = runTest {
|
||||||
|
val tokens = parseLyng(
|
||||||
|
Source(
|
||||||
|
"test",
|
||||||
|
"""
|
||||||
|
import lyng.decimal
|
||||||
|
extern var X: Decimal
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
42.d.toStringExpanded()
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val tokenTexts = tokens.map { it.type to it.value }
|
||||||
|
val needle = listOf(
|
||||||
|
Token.Type.INT to "42",
|
||||||
|
Token.Type.DOT to ".",
|
||||||
|
Token.Type.ID to "d",
|
||||||
|
Token.Type.DOT to ".",
|
||||||
|
Token.Type.ID to "toStringExpanded",
|
||||||
|
)
|
||||||
|
val found = tokenTexts.windowed(needle.size).any { it == needle }
|
||||||
|
assertTrue(found, tokenTexts.joinToString())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,8 +32,10 @@ class DecimalModuleTest {
|
|||||||
|
|
||||||
assertEquals("12.34", Decimal.fromString("12.34").toStringExpanded())
|
assertEquals("12.34", Decimal.fromString("12.34").toStringExpanded())
|
||||||
assertEquals("1", Decimal.fromInt(1).toStringExpanded())
|
assertEquals("1", Decimal.fromInt(1).toStringExpanded())
|
||||||
|
assertEquals("42", Decimal.fromInt(42).toStringExpanded())
|
||||||
assertEquals("2.5", "2.5".d.toStringExpanded())
|
assertEquals("2.5", "2.5".d.toStringExpanded())
|
||||||
assertEquals("1", 1.d.toStringExpanded())
|
assertEquals("1", 1.d.toStringExpanded())
|
||||||
|
assertEquals("42", 42.d.toStringExpanded())
|
||||||
assertEquals("2.2", 2.2.d.toStringExpanded())
|
assertEquals("2.2", 2.2.d.toStringExpanded())
|
||||||
assertEquals("3", (1 + 2).d.toStringExpanded())
|
assertEquals("3", (1 + 2).d.toStringExpanded())
|
||||||
assertEquals("1.5", (1 + 0.5).d.toStringExpanded())
|
assertEquals("1.5", (1 + 0.5).d.toStringExpanded())
|
||||||
@ -229,6 +231,21 @@ class DecimalModuleTest {
|
|||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun decimalPropertyWorksInsideFunctionBody() = runTest {
|
||||||
|
eval("""
|
||||||
|
import lyng.decimal
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val x = 42.d
|
||||||
|
assertEquals(42.d, x)
|
||||||
|
assertEquals(53.d, x + 11)
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
|
""".trimIndent())
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun kotlinHelperCanWrapIonBigDecimal() = runTest {
|
fun kotlinHelperCanWrapIonBigDecimal() = runTest {
|
||||||
val scope = Script.newScope()
|
val scope = Script.newScope()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user