[LF] Remove last remaining of Decimal (#18438)

This commit is contained in:
Remy 2024-02-12 14:16:52 +01:00 committed by GitHub
parent 2a7d9715ed
commit 71f0183b7a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
34 changed files with 78 additions and 467 deletions

View File

@ -955,7 +955,7 @@ prettyValue' lvl showRecordType prec world (Value (Just vsum)) = case vsum of
brackets (fcommasep (mapV (prettyValue' lvl True prec world) elems))
ValueSumContractId coid -> prettyContractId coid
ValueSumInt64 i -> string (show i)
ValueSumDecimal ds -> ltext ds
ValueSumNumeric ds -> ltext ds
ValueSumText t -> char '"' <> ltext t <> char '"'
ValueSumTimestamp ts -> prettyTimestamp ts
ValueSumParty p -> char '\'' <> ltext p <> char '\''

View File

@ -418,7 +418,7 @@ message Value {
string contract_id = 3;
List list = 4;
sint64 int64 = 5;
string decimal = 6;
string numeric = 6;
string text = 7;
sfixed64 timestamp = 8;
string party = 9;

View File

@ -848,7 +848,7 @@ final class Conversions(
.build
)
case V.ValueInt64(v) => builder.setInt64(v)
case V.ValueNumeric(d) => builder.setDecimal(Numeric.toString(d))
case V.ValueNumeric(d) => builder.setNumeric(Numeric.toString(d))
case V.ValueText(t) => builder.setText(t)
case V.ValueTimestamp(ts) => builder.setTimestamp(ts.micros)
case V.ValueDate(d) => builder.setDate(d.days)

View File

@ -1863,7 +1863,6 @@ private[lf] object DecodeV2 {
val builtinTypeInfos: List[BuiltinTypeInfo] = {
import LV.Features._
import PLF.PrimType._
// DECIMAL is not there and should be handled in an ad-hoc way.
List(
BuiltinTypeInfo(UNIT, BTUnit),
BuiltinTypeInfo(BOOL, BTBool),

View File

@ -6,7 +6,7 @@ package com.daml.lf.archive
import java.math.BigDecimal
import java.nio.file.Paths
import com.daml.bazeltools.BazelRunfiles._
import com.daml.lf.data.{Decimal, Numeric, Ref}
import com.daml.lf.data.{Numeric, Ref}
import com.daml.lf.language.Util._
import com.daml.lf.language.{Ast, LanguageVersion => LV}
import com.daml.lf.data.ImmArray.ImmArraySeq
@ -188,22 +188,12 @@ class DecodeV2Spec
.setPrim(DamlLf2.Type.Prim.newBuilder().setPrim(primType).addAllArgs(args.asJava))
.build()
val decimalTestCases = Table(
"input" -> "expected output",
buildPrimType(DECIMAL) ->
TNumeric(Ast.TNat(Decimal.scale)),
buildPrimType(DECIMAL, buildPrimType(TEXT)) ->
Ast.TApp(TNumeric(Ast.TNat(Decimal.scale)), TText),
buildPrimType(ARROW, buildPrimType(TEXT), buildPrimType(DECIMAL)) ->
TFun(TText, TNumeric(Ast.TNat(Decimal.scale))),
)
val numericTestCases = Table(
"input" -> "expected output",
buildPrimType(NUMERIC) ->
TNumeric.cons,
buildPrimType(NUMERIC, DamlLf2.Type.newBuilder().setNat(Decimal.scale.toLong).build()) ->
TNumeric(Ast.TNat(Decimal.scale)),
buildPrimType(NUMERIC, DamlLf2.Type.newBuilder().setNat(10.toLong).build()) ->
TNumeric(Ast.TNat(Numeric.Scale.assertFromInt(10))),
buildPrimType(NUMERIC, buildPrimType(TEXT)) ->
Ast.TApp(TNumeric.cons, TText),
buildPrimType(ARROW, buildPrimType(TEXT), buildPrimType(NUMERIC)) ->
@ -219,20 +209,6 @@ class DecodeV2Spec
}
}
"reject Decimal types" in {
forEveryVersion { version =>
val decoder = moduleDecoder(version)
forEvery(decimalTestCases) { (input, _) =>
try {
decoder.uncheckedDecodeTypeForTest(input)
} catch {
case e: Throwable => e.printStackTrace()
}
an[Error.Parsing] shouldBe thrownBy(decoder.uncheckedDecodeTypeForTest(input))
}
}
}
"accept Any" in {
forEveryVersion { version =>
val decoder = moduleDecoder(version)
@ -387,74 +363,6 @@ class DecodeV2Spec
.setPrimLit(DamlLf2.PrimLit.newBuilder().setNumericInternedStr(id))
.build()
val decimalBuiltinTestCases = Table[DamlLf2.BuiltinFunction, String, Ast.Expr](
("decimal builtins", "minVersion", "expected output"),
(
DamlLf2.BuiltinFunction.ADD_DECIMAL,
"6",
Ast.ETyApp(Ast.EBuiltin(Ast.BAddNumeric), TDecimalScale),
),
(
DamlLf2.BuiltinFunction.SUB_DECIMAL,
"6",
Ast.ETyApp(Ast.EBuiltin(Ast.BSubNumeric), TDecimalScale),
),
(
DamlLf2.BuiltinFunction.MUL_DECIMAL,
"6",
Ast.ETyApp(
Ast.ETyApp(Ast.ETyApp(Ast.EBuiltin(Ast.BMulNumericLegacy), TDecimalScale), TDecimalScale),
TDecimalScale,
),
),
(
DamlLf2.BuiltinFunction.DIV_DECIMAL,
"6",
Ast.ETyApp(
Ast.ETyApp(Ast.ETyApp(Ast.EBuiltin(Ast.BDivNumericLegacy), TDecimalScale), TDecimalScale),
TDecimalScale,
),
),
(
DamlLf2.BuiltinFunction.ROUND_DECIMAL,
"6",
Ast.ETyApp(Ast.EBuiltin(Ast.BRoundNumeric), TDecimalScale),
),
(DamlLf2.BuiltinFunction.LEQ_DECIMAL, "6", Ast.ETyApp(Ast.EBuiltin(Ast.BLessEq), TDecimal)),
(DamlLf2.BuiltinFunction.LESS_DECIMAL, "6", Ast.ETyApp(Ast.EBuiltin(Ast.BLess), TDecimal)),
(
DamlLf2.BuiltinFunction.GEQ_DECIMAL,
"6",
Ast.ETyApp(Ast.EBuiltin(Ast.BGreaterEq), TDecimal),
),
(
DamlLf2.BuiltinFunction.GREATER_DECIMAL,
"6",
Ast.ETyApp(Ast.EBuiltin(Ast.BGreater), TDecimal),
),
(
DamlLf2.BuiltinFunction.DECIMAL_TO_TEXT,
"6",
Ast.ETyApp(Ast.EBuiltin(Ast.BNumericToText), TDecimalScale),
),
(
DamlLf2.BuiltinFunction.TEXT_TO_DECIMAL,
"6",
Ast.ETyApp(Ast.EBuiltin(Ast.BTextToNumericLegacy), TDecimalScale),
),
(
DamlLf2.BuiltinFunction.INT64_TO_DECIMAL,
"6",
Ast.ETyApp(Ast.EBuiltin(Ast.BInt64ToNumericLegacy), TDecimalScale),
),
(
DamlLf2.BuiltinFunction.DECIMAL_TO_INT64,
"6",
Ast.ETyApp(Ast.EBuiltin(Ast.BNumericToInt64), TDecimalScale),
),
(DamlLf2.BuiltinFunction.EQUAL_DECIMAL, "6", Ast.ETyApp(Ast.EBuiltin(Ast.BEqual), TDecimal)),
)
val numericBuiltinTestCases = Table(
"numeric builtins" -> "expected output",
DamlLf2.BuiltinFunction.ADD_NUMERIC -> Ast.EBuiltin(Ast.BAddNumeric),
@ -539,17 +447,6 @@ class DecodeV2Spec
}
}
"reject Decimal builtins" in {
forEveryVersion { version =>
val decoder = moduleDecoder(version)
forEvery(decimalBuiltinTestCases) { (proto, _, _) =>
an[Error.Parsing] shouldBe thrownBy(decoder.decodeExprForTest(toProtoExpr(proto), "test"))
}
}
}
"parse properly numeric literals" in {
val testCases =

View File

@ -1,35 +0,0 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.lf
package data
import java.math.BigDecimal
import scala.math.{BigDecimal => BigDec}
// Our legacy Numerics are fix scale 10, aka Decimals
// This object provides some legacy utility functions for Decimal
object Decimal {
val scale: Numeric.Scale = Numeric.Scale.assertFromInt(10)
def MaxValue: Numeric = Numeric.maxValue(scale)
def MinValue: Numeric = Numeric.minValue(scale)
def fromBigDecimal(x: BigDec): Either[String, data.Numeric.Numeric] =
Numeric.fromBigDecimal(scale, x)
private val hasExpectedFormat =
"""[+-]?\d{1,28}(\.\d{1,10})?""".r.pattern
final def fromString(s: String): Either[String, Numeric] =
if (hasExpectedFormat.matcher(s).matches())
Numeric.fromBigDecimal(scale, new BigDecimal(s))
else
Left(s"""Could not read Decimal string "$s"""")
final def assertFromString(s: String): Numeric =
assertRight(fromString(s))
}

View File

@ -1,144 +0,0 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.lf.data
import org.scalatest.prop.TableDrivenPropertyChecks
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec
class DecimalSpec extends AnyWordSpec with Matchers with TableDrivenPropertyChecks {
private def d(s: String) = BigDecimal(s).setScale(Decimal.scale).bigDecimal
"Decimal.fromString" should {
"accept properly formed string" in {
val testCases = Table(
"decimal without sign",
"0",
"1",
"123",
"123.4",
"0.123",
"1.234",
"12.34",
"00000",
"01",
)
val signs = Table("sign", "", "+", "-")
forEvery(signs) { sign =>
forEvery(testCases) { testCase =>
val decimal = sign + testCase
Decimal.fromString(decimal) shouldBe Right(d(decimal))
}
}
}
"reject strings that contain non expected characters" in {
val testCases = Table("strings", "a", "decimal", "0x00", "1E10", "2-1", "2+2", "2*3", "55/11")
forEvery(testCases) { testCase =>
Decimal.fromString(testCase) shouldBe a[Left[_, _]]
}
}
"reject improperly formatted decimal with one dot" in {
val testCases = Table(
"string",
".",
".0",
"0.",
"1.",
".1",
"123.",
".0",
".0123",
".123",
)
val signs = Table("sign", "", "+", "-")
forEvery(signs) { sign =>
forEvery(testCases) { testCase =>
val decimal = sign + testCase
Decimal.fromString(decimal) shouldBe a[Left[_, _]]
}
}
}
"reject strings containing more than one dot" in {
val testCases = Table(
"string",
"..",
"0..",
"..1",
"112..123",
"0.0.",
".1.",
)
forEvery(testCases)(testCase => Decimal.fromString(testCase) shouldBe a[Left[_, _]])
}
"reject string with too many signs" in {
val testCases = Table(
"decimal without sign",
"1",
"123",
"12.34",
)
val signs = Table("sign", "++", "-+", "+-", "--", "+++", "-+-")
forEvery(signs) { sign =>
forEvery(testCases) { testCase =>
val decimal = sign + testCase
Decimal.fromString(decimal) shouldBe a[Left[_, _]]
}
}
}
"reject string with too many digit" in {
val negativeTestCases = Table(
"string",
"0" * 1 + "." + "0" * 1,
"0" * 28 + "." + "0" * 1,
"0" * 1 + "." + "0" * 10,
"0" * 28 + "." + "0" * 10,
)
val positiveTestCases = Table(
"string",
"0" * 29 + "." + "0" * 1,
"0" * 1 + "." + "0" * 11,
"0" * 29 + "." + "0" * 11,
"1" * 29 + "." + "1" * 1,
"1" * 50 + "." + "1" * 1,
"1" * 1 + "." + "1" * 11,
"1" * 1 + "." + "1" * 30,
"1" * 29 + "." + "1" * 11,
"1" * 55 + "." + "1" * 33,
)
forEvery(negativeTestCases)(testCase =>
Decimal.fromString(testCase) shouldBe Right(d(testCase))
)
forEvery(positiveTestCases)(testCase => Decimal.fromString(testCase) shouldBe a[Left[_, _]])
}
}
}

View File

@ -1,29 +0,0 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
module DecimalMod {
record @serializable Box = { x: Numeric 10, party: Party } ;
template (this : Box) = {
precondition True;
signatories (PartyMod:one (DecimalMod:Box {party} this));
observers (Nil @Party);
};
val build0: Party -> DecimalMod:Box = \(p : Party) -> DecimalMod:Box {
x = 0.0000000000 ,
party = p
};
val buildMax: Party -> DecimalMod:Box = \(p : Party) -> DecimalMod:Box {
x = 9999999999999999999999999999.9999999999 ,
party = p
};
val buildMin: Party -> DecimalMod:Box = \(p : Party) -> DecimalMod:Box {
x = -9999999999999999999999999999.9999999999 ,
party = p
};
}

View File

@ -41,7 +41,6 @@ class DamlLfEncoderTest
"BoolMod",
"Int64Mod",
"TextMod",
"DecimalMod",
"DateMod",
"TimestampMod",
"ListMod",

View File

@ -102,7 +102,7 @@ class EncodeSpec(languageVersion: LanguageVersion)
val myFalse: Bool = False;
val myTrue: Bool = True;
val aInt: Int64 = 14;
val aDecimal: Numeric 10 = 2.2000000000;
val aNumeric10: Numeric 10 = 2.2000000000;
val aDate: Date = 1879-03-14;
val aTimestamp: Timestamp = 1970-01-01T00:00:00.000001Z;
val aString: Text = "a string";

View File

@ -113,7 +113,7 @@ class ValueEnricherSpec(majorLanguageVersion: LanguageMajorVersion)
(TDate, ValueDate("1879-03-14"), ValueDate("1879-03-14")),
(TText, ValueText("daml"), ValueText("daml")),
(
TNumeric(TNat(Decimal.scale)),
TNumeric(TNat(Numeric.Scale.assertFromInt(10))),
ValueNumeric("10."),
ValueNumeric("10.0000000000"),
),

View File

@ -97,12 +97,10 @@ class ValueTranslatorSpec(majorLanguageVersion: LanguageMajorVersion)
),
(TText, ValueText("daml"), SText("daml")),
(
TNumeric(Ast.TNat(Decimal.scale)),
TNumeric(Ast.TNat(Numeric.Scale.assertFromInt(10))),
ValueNumeric(Numeric.assertFromString("10.")),
SNumeric(Numeric.assertFromString("10.0000000000")),
),
// TNumeric(TNat(9)) ,
// ValueNumeric(Numeric.assertFromString("9.000000000")),
(TParty, ValueParty("Alice"), SParty("Alice")),
(
TContractId(t"Mod:Template"),

View File

@ -110,7 +110,7 @@ class ComparisonSBuiltinTest(majorLanguageVersion: LanguageMajorVersion)
t"Unit" -> List(e"()"),
t"Bool" -> List(e"False", e"True"),
t"Int64" -> List(e"-3", e"0", e"1"),
t"Decimal" -> List(e"-10000.0000000000", e"0.0000000000", e"10000.0000000000"),
t"Numeric 10" -> List(e"-10000.0000000000", e"0.0000000000", e"10000.0000000000"),
t"Numeric 0" -> List(e"-10000.", e"0.", e"10000."),
t"Text" ->
// Note that in UTF8 "。" < "😂" but in UTF16 "。" > "😂"

View File

@ -45,8 +45,8 @@ class SBuiltinBigNumericTest(majorLanguageVersion: LanguageMajorVersion)
else
"0." + "0" * (-i - 1) + "1" + "0" * (scale + i)
private val decimals = Table[String](
"Decimals",
private val numerics = Table[String](
"Numeric",
"161803398.87499",
"3.1415926536",
"2.7182818285",
@ -88,8 +88,8 @@ class SBuiltinBigNumericTest(majorLanguageVersion: LanguageMajorVersion)
)
forEvery(testCases) { (builtin, ref) =>
forEvery(decimals) { a =>
forEvery(decimals) { b =>
forEvery(numerics) { a =>
forEvery(numerics) { b =>
val actualResult = eval(
e"$builtin (NUMERIC_TO_BIGNUMERIC @10 ${s(10, a)}) (NUMERIC_TO_BIGNUMERIC @10 ${s(10, b)})"
)

View File

@ -237,16 +237,16 @@ class SBuiltinTest(majorLanguageVersion: LanguageMajorVersion)
"Numeric operations" - {
val maxDecimal = Decimal.MaxValue
val maxNumeric = Numeric.maxValue(Numeric.Scale.assertFromInt(10))
val minPosDecimal = BigDecimal("0000000000000000000000000000.0000000001")
val minPosNumeric = BigDecimal("0000000000000000000000000000.0000000001")
val bigBigDecimal = BigDecimal("8765432109876543210987654321.0987654321")
val zero = BigDecimal("0.0000000000")
val one = BigDecimal("1.0000000000")
val two = BigDecimal("2.0000000000")
val decimals = Table[String](
"Decimals",
val numerics = Table[String](
"Numerics",
"161803398.87499",
"3.1415926536",
"2.7182818285",
@ -270,8 +270,8 @@ class SBuiltinTest(majorLanguageVersion: LanguageMajorVersion)
eval(e"$builtin @10 ${s(10, bigBigDecimal)} ${s(10, two)}") shouldBe Right(
SNumeric(n(10, bigBigDecimal + 2))
)
eval(e"$builtin @10 ${s(10, maxDecimal)} ${s(10, minPosDecimal)}") shouldBe a[Left[_, _]]
eval(e"$builtin @10 ${s(10, maxDecimal.negate)} ${s(10, -minPosDecimal)}") shouldBe a[
eval(e"$builtin @10 ${s(10, maxNumeric)} ${s(10, minPosNumeric)}") shouldBe a[Left[_, _]]
eval(e"$builtin @10 ${s(10, maxNumeric.negate)} ${s(10, -minPosNumeric)}") shouldBe a[
Left[_, _]
]
eval(e"$builtin @10 ${s(10, bigBigDecimal)} ${s(10, bigBigDecimal - 1)}") shouldBe a[
@ -291,8 +291,8 @@ class SBuiltinTest(majorLanguageVersion: LanguageMajorVersion)
eval(e"$builtin @10 $bigBigDecimal ${s(10, two)}") shouldBe Right(
SNumeric(n(10, bigBigDecimal - 2))
)
eval(e"$builtin @10 ${s(10, maxDecimal)} -$minPosDecimal") shouldBe a[Left[_, _]]
eval(e"$builtin @10 ${maxDecimal.negate} ${s(10, minPosDecimal)}") shouldBe a[Left[_, _]]
eval(e"$builtin @10 ${s(10, maxNumeric)} -$minPosNumeric") shouldBe a[Left[_, _]]
eval(e"$builtin @10 ${maxNumeric.negate} ${s(10, minPosNumeric)}") shouldBe a[Left[_, _]]
eval(e"$builtin @10 ${-bigBigDecimal} ${s(10, bigBigDecimal)}") shouldBe a[Left[_, _]]
}
}
@ -431,7 +431,7 @@ class SBuiltinTest(majorLanguageVersion: LanguageMajorVersion)
"returns proper result" in {
val d = "8765432109876543210987654321.0987654321"
val testCases = Table[Long, String, String](
("rounding", "decimal", "result"),
("rounding", "numeric", "result"),
(-27, d, "9000000000000000000000000000.0000000000"),
(-1, "45.0", "40.0"),
(-1, "55.0", "60.0"),
@ -446,7 +446,7 @@ class SBuiltinTest(majorLanguageVersion: LanguageMajorVersion)
}
}
"Decimal binary operations compute proper results" in {
"Numeric binary operations compute proper results" in {
def round(x: BigDecimal) = n(10, x.setScale(10, BigDecimal.RoundingMode.HALF_EVEN))
@ -472,8 +472,8 @@ class SBuiltinTest(majorLanguageVersion: LanguageMajorVersion)
)
forEvery(testCases) { (builtin, ref) =>
forEvery(decimals) { a =>
forEvery(decimals) { b =>
forEvery(numerics) { a =>
forEvery(numerics) { b =>
eval(e"$builtin ${s(10, a)} ${s(10, b)}").toOption shouldBe
ref(n(10, a), n(10, b))
}
@ -483,7 +483,7 @@ class SBuiltinTest(majorLanguageVersion: LanguageMajorVersion)
"NUMERIC_TO_TEXT" - {
"returns proper results" in {
forEvery(decimals) { a =>
forEvery(numerics) { a =>
eval(e"NUMERIC_TO_TEXT @10 ${s(10, a)}") shouldBe Right(SText(a))
}
}
@ -1266,7 +1266,7 @@ class SBuiltinTest(majorLanguageVersion: LanguageMajorVersion)
"works as expected" in {
val testCases = Table[Long, String, Long](
("scale", "Decimal", "Int64"),
("scale", "Numeric", "Int64"),
(7, s(7, almostZero(7)), 0),
(2, "0.00", 0),
(8, "1.00000000", 1),
@ -1275,9 +1275,9 @@ class SBuiltinTest(majorLanguageVersion: LanguageMajorVersion)
(20, "123456789.12345678912345678912", 123456789),
)
forEvery(testCases) { (scale, decimal, int64) =>
eval(e"NUMERIC_TO_INT64 @$scale $decimal") shouldBe Right(SInt64(int64))
eval(e"NUMERIC_TO_INT64 @$scale -$decimal") shouldBe Right(SInt64(-int64))
forEvery(testCases) { (scale, numeric, int64) =>
eval(e"NUMERIC_TO_INT64 @$scale $numeric") shouldBe Right(SInt64(int64))
eval(e"NUMERIC_TO_INT64 @$scale -$numeric") shouldBe Right(SInt64(-int64))
}
}
}

View File

@ -347,7 +347,6 @@ object Ast {
// works because Numeric.Scale.MinValue = 0
val values = Numeric.Scale.values.map(new TNat(_))
def apply(n: Numeric.Scale): TNat = values(n)
val Decimal: TNat = values(10)
}
/** Fully applied type synonym. */

View File

@ -4,7 +4,7 @@
package com.daml.lf
package language
import com.daml.lf.data.{Decimal, ImmArray, Ref}
import com.daml.lf.data.{ImmArray, Ref}
import com.daml.lf.language.Ast._
import com.daml.nameof.NameOf
@ -94,8 +94,6 @@ object Util {
val TContractId = new ParametricType1(BTContractId)
val TParties = TList(TParty)
val TDecimalScale = TNat(Decimal.scale)
val TDecimal = TNumeric(TDecimalScale)
val TAnyException = TBuiltin(BTAnyException)

View File

@ -111,7 +111,7 @@ private[parser] object Lexer extends RegexParsers {
(in: Input) =>
data.Numeric.fromString(s) match {
case Right(x) => Success(Numeric(x), in)
case Left(_) => Error(s"cannot interpret $s as a Decimal", in)
case Left(_) => Error(s"cannot interpret $s as a Numeric", in)
}
@SuppressWarnings(Array("org.wartremover.warts.Product", "org.wartremover.warts.Serializable"))

View File

@ -214,7 +214,6 @@ object ValueGenerators {
dateGen.map(ValueDate),
Gen.alphaStr.map(ValueText),
unscaledNumGen.map(ValueNumeric),
numGen(Decimal.scale).map(ValueNumeric),
arbitrary[Long].map(ValueInt64),
Gen.alphaStr.map(ValueText),
timestampGen.map(ValueTimestamp),

View File

@ -4,7 +4,7 @@
package com.daml.lf
package crypto
import com.daml.lf.data.{Decimal, Numeric, Ref, SortedLookupList, Time}
import com.daml.lf.data.{Numeric, Ref, SortedLookupList, Time}
import com.daml.lf.value.test.TypedValueGenerators.{ValueAddend => VA}
import com.daml.lf.value.Value._
import com.daml.lf.value.Value
@ -31,8 +31,8 @@ class HashSpec extends AnyWordSpec with Matchers {
fInt0 = VA.int64,
fInt1 = VA.int64,
fInt2 = VA.int64,
fNumeric0 = VA.numeric(Decimal.scale),
fNumeric1 = VA.numeric(Decimal.scale),
fNumeric0 = VA.numeric(Numeric.Scale.assertFromInt(10)),
fNumeric1 = VA.numeric(Numeric.Scale.assertFromInt(10)),
fBool0 = VA.bool,
fBool1 = VA.bool,
fDate0 = VA.date,
@ -131,9 +131,10 @@ class HashSpec extends AnyWordSpec with Matchers {
}
"not produce collision in list of decimals" in {
// Testing whether decimals are delimited: [10, 10] vs [101, 0]
// Testing whether numeric are delimited: [10, 10] vs [101, 0]
def list(elements: String*) =
VA.list(VA.numeric(Decimal.scale)).inj(elements.map(Numeric.assertFromString).toVector)
VA.list(VA.numeric(Numeric.Scale.assertFromInt(10)))
.inj(elements.map(Numeric.assertFromString).toVector)
val value1 = list("10.0000000000", "10.0000000000")
val value2 = list("101.0000000000", "0.0000000000")
@ -269,7 +270,7 @@ class HashSpec extends AnyWordSpec with Matchers {
hash1 should !==(hash2)
}
"not produce collision in Decimal" in {
"not produce collision in Numeric" in {
val value1 = ValueNumeric(Numeric.assertFromString("0."))
val value2 = ValueNumeric(Numeric.assertFromString("1."))
@ -352,9 +353,9 @@ class HashSpec extends AnyWordSpec with Matchers {
val units = List(ValueUnit)
val bools = List(true, false).map(VA.bool.inj(_))
val ints = List(-1L, 0L, 1L).map(VA.int64.inj(_))
val decimals = List("-10000.0000000000", "0.0000000000", "10000.0000000000")
val numeric10s = List("-10000.0000000000", "0.0000000000", "10000.0000000000")
.map(Numeric.assertFromString)
.map(VA.numeric(Decimal.scale).inj(_))
.map(VA.numeric(Numeric.Scale.assertFromInt(10)).inj(_))
val numeric0s = List("-10000.", "0.", "10000.")
.map(Numeric.assertFromString)
.map(VA.numeric(Numeric.Scale.MinValue).inj(_))
@ -473,7 +474,7 @@ class HashSpec extends AnyWordSpec with Matchers {
List(Some(None), Some(Some(false))).map(VA.optional(VA.optional(VA.bool)).inj(_))
val testCases: List[V] =
units ++ bools ++ ints ++ decimals ++ numeric0s ++ dates ++ timestamps ++ texts ++ parties ++ contractIds ++ optionals ++ lists ++ textMaps ++ genMaps ++ enums ++ records0 ++ records2 ++ variants
units ++ bools ++ ints ++ numeric10s ++ numeric0s ++ dates ++ timestamps ++ texts ++ parties ++ contractIds ++ optionals ++ lists ++ textMaps ++ genMaps ++ enums ++ records0 ++ records2 ++ variants
val expectedOut =
"""ValueUnit

View File

@ -64,7 +64,7 @@ class ValueCoderSpec
whenever(Numeric.fromBigDecimal(s, d).isRight) {
val Right(dec) = Numeric.fromBigDecimal(s, d)
val value = ValueNumeric(dec)
val recoveredDecimal = ValueCoder.decodeValue(
val recoveredNumeric = ValueCoder.decodeValue(
ValueCoder.CidDecoder,
TransactionVersion.minVersion,
assertRight(
@ -80,7 +80,7 @@ class ValueCoderSpec
case x => fail(s"should have got a numeric back, got $x")
}
Numeric.toUnscaledString(value.value) shouldEqual Numeric.toUnscaledString(
recoveredDecimal
recoveredNumeric
)
}
}

View File

@ -36,7 +36,7 @@ class CollisionSpec(majorLanguageVersion: LanguageMajorVersion)
module Mod { // fully resolved name: "Mod"
record R = { // fully resolved name: "Mod.R."
field1: Int64, // fully resolved name: "Mod.R.field1"
field2: Decimal // fully resolved name: "Mod.R.field2"
field2: Numeric 10 // fully resolved name: "Mod.R.field2"
};
}
"""
@ -49,7 +49,7 @@ class CollisionSpec(majorLanguageVersion: LanguageMajorVersion)
module Mod { // fully resolved name: "Mod"
record R = { // fully resolved name: "Mod.R."
field: Int64, // fully resolved name: "Mod.R.field" (collision)
field: Decimal // fully resolved name: "Mod.R.field" (collision)
field: Numeric 10 // fully resolved name: "Mod.R.field" (collision)
};
}
""",
@ -59,7 +59,7 @@ class CollisionSpec(majorLanguageVersion: LanguageMajorVersion)
module Mod { // fully resolved name: "Mod"
record R = { // fully resolved name: "Mod.R."
field: Int64, // fully resolved name: "Mod.R.field" (collision)
FiElD: Decimal // fully resolved name: "Mod.R.FiElD" (collision)
FiElD: Numeric 10 // fully resolved name: "Mod.R.FiElD" (collision)
};
}
""",
@ -79,7 +79,7 @@ class CollisionSpec(majorLanguageVersion: LanguageMajorVersion)
module Mod { // fully resolved name: "Mod"
variant V = // fully resolved name: "Mod.V"
Variant1: Int64 // fully resolved name: "Mod.V.Variant1"
| Variant2: Decimal; // fully resolved name: "Mod.V.Variant2"
| Variant2: Numeric 10; // fully resolved name: "Mod.V.Variant2"
}
"""
@ -91,7 +91,7 @@ class CollisionSpec(majorLanguageVersion: LanguageMajorVersion)
module Mod { // fully resolved name: "Mod"
variant V = // fully resolved name: "Mod.V"
Variant: Int64 // fully resolved name: "Mod.V.Variant" (collision)
| Variant: Decimal; // fully resolved name: "Mod.V.Variant" (collision)
| Variant: Numeric 10; // fully resolved name: "Mod.V.Variant" (collision)
}
""",
// a variant definition with case insensitive collision
@ -100,7 +100,7 @@ class CollisionSpec(majorLanguageVersion: LanguageMajorVersion)
module Mod { // fully resolved name: "Mod"
variant V = // fully resolved name: "Mod.V"
Variant: Int64 // fully resolved name: "Mod.V.Variant" (collision)
| VARIANT: Decimal; // fully resolved name: "Mod.V.VARIANT" (collision)
| VARIANT: Numeric 10; // fully resolved name: "Mod.V.VARIANT" (collision)
}
""",
)

View File

@ -360,7 +360,7 @@ class SerializabilitySpec(majorLanguageVersion: LanguageMajorVersion)
precondition True;
signatories Cons @Party [bob] (Nil @Party);
observers Cons @Party [alice] (Nil @Party);
choice Ch (self) (x: Int64) : Decimal, controllers bob to upure @Int64 (DECIMAL_TO_INT64 x);
choice Ch (self) (x: Int64) : Numeric 10, controllers bob to upure @Int64 (NUMERIC_TO_INT64 @10 x);
} ;
val f : Int64 -> Int64 = ERROR @(Int64 -> Int64) "not implemented";

View File

@ -173,7 +173,7 @@ class TypingSpec(majorLanguageVersion: LanguageMajorVersion)
T"∀ (τ : ⋆). τ → (( Option τ ))",
// ExpLitInt64
E"(( 42 ))" -> T"Int64",
// ExpLitDecimal
// ExpLitNumeric
E"(( 3.1415926536 ))" -> T"(( Numeric 10 ))",
// ExpLitText
E"""(( "text" ))""" -> T"(( Text ))",
@ -405,13 +405,13 @@ class TypingSpec(majorLanguageVersion: LanguageMajorVersion)
E"λ (e: Mod:I) → (( create_by_interface @Mod:I e))" ->
T"Mod:I → (( Update (ContractId Mod:I) ))",
E"λ (e₁: ContractId Mod:T) (e₂: Int64) → (( exercise @Mod:T Ch e₁ e₂ ))" ->
T"ContractId Mod:T → Int64 → (( Update Decimal ))",
T"ContractId Mod:T → Int64 → (( Update (Numeric 10) ))",
E"λ (e₁: ContractId Mod:I) (e₂: Int64) → (( exercise_interface @Mod:I ChIface e₁ e₂ ))" ->
T"ContractId Mod:I → Int64 → (( Update Decimal ))",
T"ContractId Mod:I → Int64 → (( Update (Numeric 10) ))",
E"λ (e₁: ContractId Mod:I) (e₂: Int64) (e₃: Mod:I → Bool) → (( exercise_interface_with_guard @Mod:I ChIface e₁ e₂ e₃ ))" ->
T"ContractId Mod:I → Int64 → (Mod:I → Bool) → (( Update Decimal ))",
T"ContractId Mod:I → Int64 → (Mod:I → Bool) → (( Update (Numeric 10) ))",
E"λ (e₁: Party) (e₂: Int64) → (( exercise_by_key @Mod:T Ch e₁ e₂ ))" ->
T"Party → Int64 → (( Update Decimal ))",
T"Party → Int64 → (( Update (Numeric 10) ))",
E"λ (e: ContractId Mod:T) → (( fetch_template @Mod:T e ))" ->
T"ContractId Mod:T → (( Update Mod:T ))",
E"λ (e: ContractId Mod:I) → (( fetch_interface @Mod:I e ))" ->
@ -1962,16 +1962,16 @@ class TypingSpec(majorLanguageVersion: LanguageMajorVersion)
precondition True;
signatories Nil @Party;
observers Nil @Party;
choice Ch (self) (x: Int64) : Decimal, controllers Nil @Party to upure @INT64 (DECIMAL_TO_INT64 x);
choice Ch (self) (x: Int64) : Numeric 10, controllers Nil @Party to upure @INT64 (NUMERIC_TO_INT64 @1 x);
key @Party (Mod:Person {person} this) (\ (p: Party) -> Cons @Party [p] (Nil @Party));
};
interface (this : I) = {
viewtype Mod:MyUnit;
method getParties: List Party;
choice ChIface (self) (x: Int64) : Decimal,
choice ChIface (self) (x: Int64) : Numeric 10,
controllers Nil @Party
to upure @INT64 (DECIMAL_TO_INT64 x);
to upure @INT64 (NUMERIC_TO_INT64 @10 x);
};
interface (this : SubI) = {
@ -1986,7 +1986,7 @@ class TypingSpec(majorLanguageVersion: LanguageMajorVersion)
precondition True;
signatories Nil @Party;
observers Nil @Party;
choice ChTmpl (self) (x: Int64) : Decimal, controllers Nil @Party to upure @INT64 (DECIMAL_TO_INT64 x);
choice ChTmpl (self) (x: Int64) : Numeric 10, controllers Nil @Party to upure @INT64 (NUMERIC_TO_INT64 @10 x);
implements Mod:I {
view = Mod:MyUnit {};
method getParties = Cons @Party [(Mod:Ti {person} this)] (Nil @Party);

View File

@ -8,7 +8,6 @@ import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
DecimalTestForAll.class,
EnumTestForForAll.class,
NumericTestForAll.class,
GenMapTestFor1_11AndFor1_12ndFor1_13AndFor1_14AndFor1_15AndFor1_devAndFor2_1AndFor2_dev.class,

View File

@ -8,7 +8,6 @@ import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
DecimalTestForAll.class,
EnumTestForForAll.class,
NumericTestForAll.class,
GenMapTestFor1_11AndFor1_12ndFor1_13AndFor1_14AndFor1_15AndFor1_devAndFor2_1AndFor2_dev.class,

View File

@ -8,7 +8,6 @@ import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
DecimalTestForAll.class,
EnumTestForForAll.class,
NumericTestForAll.class,
GenMapTestFor1_11AndFor1_12ndFor1_13AndFor1_14AndFor1_15AndFor1_devAndFor2_1AndFor2_dev.class,

View File

@ -8,7 +8,6 @@ import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
DecimalTestForAll.class,
EnumTestForForAll.class,
NumericTestForAll.class,
GenMapTestFor1_11AndFor1_12ndFor1_13AndFor1_14AndFor1_15AndFor1_devAndFor2_1AndFor2_dev.class,

View File

@ -8,7 +8,6 @@ import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
DecimalTestForAll.class,
EnumTestForForAll.class,
NumericTestForAll.class,
})

View File

@ -8,7 +8,6 @@ import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
DecimalTestForAll.class,
EnumTestForForAll.class,
NumericTestForAll.class,
GenMapTestFor1_11AndFor1_12ndFor1_13AndFor1_14AndFor1_15AndFor1_devAndFor2_1AndFor2_dev.class,

View File

@ -8,7 +8,6 @@ import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
DecimalTestForAll.class,
EnumTestForForAll.class,
NumericTestForAll.class,
GenMapTestFor1_11AndFor1_12ndFor1_13AndFor1_14AndFor1_15AndFor1_devAndFor2_1AndFor2_dev.class,

View File

@ -8,7 +8,6 @@ import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
DecimalTestForAll.class,
EnumTestForForAll.class,
NumericTestForAll.class,
GenMapTestFor1_11AndFor1_12ndFor1_13AndFor1_14AndFor1_15AndFor1_devAndFor2_1AndFor2_dev.class,

View File

@ -1,65 +0,0 @@
// Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.testing;
import static org.junit.jupiter.api.Assertions.assertEquals;
import com.daml.ledger.javaapi.data.DamlRecord;
import com.daml.ledger.javaapi.data.Numeric;
import com.daml.ledger.javaapi.data.Party;
import com.daml.ledger.javaapi.data.codegen.json.JsonLfDecoder;
import java.io.IOException;
import java.math.BigDecimal;
import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;
import test.decimalmod.Box;
@RunWith(JUnitPlatform.class)
public class DecimalTestForAll {
private final String[] goodValues = {
"-9999999999999999999999999999.9999999999",
"-1.0",
"0.0",
"1.0",
"3.1415926536",
"42.0",
"9999999999999999999999999999.9999999999",
};
@Test
void decimal2Value2Decimal() {
for (String s : goodValues) {
Box b = new Box(new BigDecimal(s), "alice");
assertEquals(Box.fromValue(b.toValue()), b);
}
}
@Test
void decimal2Value2DecimalJson() throws JsonLfDecoder.Error {
for (String s : goodValues) {
Box b = new Box(new BigDecimal(s), "alice");
assertEquals(Box.fromJson(b.toJson()), b);
}
}
@Test
void value2Decimal2value() {
DamlRecord.Field partyField = new DamlRecord.Field("party", new Party("alice"));
for (String s : goodValues) {
DamlRecord record =
new DamlRecord(new DamlRecord.Field("x", new Numeric(new BigDecimal(s))), partyField);
assertEquals(Box.fromValue(record).toValue(), record);
}
}
@Test
void testFromJson() throws IOException {
for (String s : goodValues) {
Box b = new Box(new BigDecimal(s), "alice");
assertEquals(Box.fromJson(String.format("{\"x\": \"%s\", \"party\": \"alice\"}", s)), b);
}
}
}

View File

@ -6,7 +6,7 @@ package value.json
import com.daml.bazeltools.BazelRunfiles._
import com.daml.lf.value.Value.ContractId
import data.{Decimal, ImmArray, Ref, SortedLookupList, Time}
import data.{ImmArray, Numeric, Ref, SortedLookupList, Time}
import value.json.{NavigatorModelAliases => model}
import value.test.TypedValueGenerators.{genAddend, genTypeAndValue, ValueAddend => VA}
import value.test.ValueGenerators.coidGen
@ -65,6 +65,8 @@ class ApiCodecCompressedSpec
private def roundtrip(va: VA)(v: va.Inj): Option[va.Inj] =
va.prj(jsValueToApiValue(apiValueToJsValue(va.inj(v)), va.t, typeLookup))
private val decimalScale = Numeric.Scale.assertFromInt(10)
private object C /* based on navigator DamlConstants */ {
import shapeless.syntax.singleton._
val packageId0 = Ref.PackageId assertFromString "hash"
@ -94,7 +96,7 @@ class ApiCodecCompressedSpec
HRecord(
fText = VA.text,
fBool = VA.bool,
fDecimal = VA.numeric(Decimal.scale),
fDecimal = VA.numeric(decimalScale),
fUnit = VA.unit,
fInt64 = VA.int64,
fParty = VA.party,
@ -115,7 +117,7 @@ class ApiCodecCompressedSpec
HRecord(
fText = "foo",
fBool = true,
fDecimal = Decimal assertFromString "100",
fDecimal = Numeric.assertFromString("100.0000000000"),
fUnit = (),
fInt64 = 100L,
fParty = Ref.Party assertFromString "BANK1",
@ -271,38 +273,38 @@ class ApiCodecCompressedSpec
"0000000000000000000000000000000000000000000000000000000000000000000123"
)
),
cn("\"42.0\"", "42.0", VA.numeric(Decimal.scale))(
Decimal assertFromString "42",
cn("\"42.0\"", "42.0", VA.numeric(decimalScale))(
Numeric.assertFromString("42.0000000000"),
"\"42\"",
"42",
"42.0",
"\"+42\"",
),
cn("\"2000.0\"", "2000", VA.numeric(Decimal.scale))(
Decimal assertFromString "2000",
cn("\"2000.0\"", "2000", VA.numeric(decimalScale))(
Numeric.assertFromString("2000.0000000000"),
"\"2000\"",
"2000",
"2e3",
),
cn("\"0.3\"", "0.3", VA.numeric(Decimal.scale))(
Decimal assertFromString "0.3",
cn("\"0.3\"", "0.3", VA.numeric(decimalScale))(
Numeric.assertFromString("0.3000000000"),
"\"0.30000000000000004\"",
"0.30000000000000004",
),
cn(
"\"9999999999999999999999999999.9999999999\"",
"9999999999999999999999999999.9999999999",
VA.numeric(Decimal.scale),
)(Decimal assertFromString "9999999999999999999999999999.9999999999"),
cn("\"0.1234512346\"", "0.1234512346", VA.numeric(Decimal.scale))(
Decimal assertFromString "0.1234512346",
VA.numeric(decimalScale),
)(Numeric.assertFromString("9999999999999999999999999999.9999999999")),
cn("\"0.1234512346\"", "0.1234512346", VA.numeric(decimalScale))(
Numeric.assertFromString("0.1234512346"),
"0.12345123455",
"0.12345123465",
"\"0.12345123455\"",
"\"0.12345123465\"",
),
cn("\"0.1234512345\"", "0.1234512345", VA.numeric(Decimal.scale))(
Decimal assertFromString "0.1234512345",
cn("\"0.1234512345\"", "0.1234512345", VA.numeric(decimalScale))(
Numeric.assertFromString("0.1234512345"),
"0.123451234549",
"0.12345123445001",
"\"0.123451234549\"",