mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-20 01:07:18 +03:00
daml-lf: add FROM_TEXT_INT64 and FROM_TEXT_DECIMAL (#1407)
* daml-lf: add FROM_TEXT_INT64 and FROM_TEXT_DECIMAL * Fix typos in Haskell * cosmetic change * Fix DAML-LF type checker * Fix merging fallout
This commit is contained in:
parent
53c5351144
commit
439613bee8
@ -221,8 +221,6 @@ data BuiltinExpr
|
||||
| BEGreater !BuiltinType -- :: t -> t -> Bool, where t is the builtin type
|
||||
| BEToText !BuiltinType -- :: t -> Text, where t is one of the builtin types
|
||||
-- {Int64, Decimal, Text, Timestamp, Date, Party}
|
||||
| BEPartyFromText -- :: Text -> Optional Party
|
||||
| BEPartyToQuotedText -- :: Party -> Text
|
||||
|
||||
-- Decimal arithmetic
|
||||
| BEAddDecimal -- :: Decimal -> Decimal -> Decimal, crashes on overflow
|
||||
@ -266,6 +264,10 @@ data BuiltinExpr
|
||||
| BEAppendText -- :: Text -> Text -> Text
|
||||
| BEImplodeText -- :: List Text -> Text
|
||||
| BESha256Text -- :: Text -> Text
|
||||
| BEPartyFromText -- :: Text -> Optional Party
|
||||
| BEInt64FromText -- :: Text -> Optional Int64
|
||||
| BEDecimalFromText -- :: Text -> Optional Decimal
|
||||
| BEPartyToQuotedText -- :: Party -> Text
|
||||
|
||||
| BETrace -- :: forall a. Text -> a -> a
|
||||
| BEEqualContractId -- :: forall a. ContractId a -> ContractId a -> Bool
|
||||
|
@ -223,7 +223,9 @@ instance Pretty BuiltinExpr where
|
||||
BESha256Text -> "SHA256_TEXT"
|
||||
BETrace -> "TRACE"
|
||||
BEEqualContractId -> "EQUAL_CONTRACT_ID"
|
||||
BEPartyFromText -> "PARTY_FROM_TEXT"
|
||||
BEPartyFromText -> "FROM_TEXT_PARTY"
|
||||
BEInt64FromText -> "FROM_TEXT_INT64"
|
||||
BEDecimalFromText -> "FROM_TEXT_DECIMAL"
|
||||
BEPartyToQuotedText -> "PARTY_TO_QUOTED_TEXT"
|
||||
BECoerceContractId -> "COERCE_CONTRACT_ID"
|
||||
where
|
||||
|
@ -75,6 +75,9 @@ featureCoerceContractId = Feature "Coerce function for contract ids" version1_5
|
||||
featureExerciseActorsOptional :: Feature
|
||||
featureExerciseActorsOptional = Feature "Optional exercise actors" version1_5
|
||||
|
||||
featureNumberFromText :: Feature
|
||||
featureNumberFromText = Feature "Number parsing functions" version1_5
|
||||
|
||||
supports :: Version -> Feature -> Bool
|
||||
supports version feature = version >= featureMinVersion feature
|
||||
|
||||
|
@ -198,6 +198,8 @@ decodeBuiltinFunction = pure . \case
|
||||
LF1.BuiltinFunctionTO_TEXT_PARTY -> BEToText BTParty
|
||||
LF1.BuiltinFunctionTO_TEXT_DATE -> BEToText BTDate
|
||||
LF1.BuiltinFunctionFROM_TEXT_PARTY -> BEPartyFromText
|
||||
LF1.BuiltinFunctionFROM_TEXT_INT64 -> BEInt64FromText
|
||||
LF1.BuiltinFunctionFROM_TEXT_DECIMAL -> BEDecimalFromText
|
||||
LF1.BuiltinFunctionTO_QUOTED_TEXT_PARTY -> BEPartyToQuotedText
|
||||
|
||||
LF1.BuiltinFunctionADD_DECIMAL -> BEAddDecimal
|
||||
|
@ -235,6 +235,8 @@ encodeBuiltinExpr = \case
|
||||
BTParty -> builtin P.BuiltinFunctionTO_TEXT_PARTY
|
||||
other -> error $ "BEToText unexpected type " <> show other
|
||||
BEPartyFromText -> builtin P.BuiltinFunctionFROM_TEXT_PARTY
|
||||
BEInt64FromText -> builtin P.BuiltinFunctionFROM_TEXT_INT64
|
||||
BEDecimalFromText-> builtin P.BuiltinFunctionFROM_TEXT_DECIMAL
|
||||
BEPartyToQuotedText -> builtin P.BuiltinFunctionTO_QUOTED_TEXT_PARTY
|
||||
|
||||
BEAddDecimal -> builtin P.BuiltinFunctionADD_DECIMAL
|
||||
|
@ -149,6 +149,8 @@ safetyStep = \case
|
||||
BEEqualContractId -> Safe 2
|
||||
BEPartyToQuotedText -> Safe 1
|
||||
BEPartyFromText -> Safe 1
|
||||
BEInt64FromText -> Safe 1
|
||||
BEDecimalFromText -> Safe 1
|
||||
BECoerceContractId -> Safe 1
|
||||
ERecConF _ fs -> minimum (Safe 0 : map snd fs)
|
||||
ERecProjF _ _ s -> s `min` Safe 0
|
||||
|
@ -161,6 +161,12 @@ typeOfBuiltin = \case
|
||||
BEToText btype -> pure $ TBuiltin btype :-> TText
|
||||
BEPartyToQuotedText -> pure $ TParty :-> TText
|
||||
BEPartyFromText -> pure $ TText :-> TOptional TParty
|
||||
BEInt64FromText -> do
|
||||
checkFeature featureNumberFromText
|
||||
pure $ TText :-> TOptional TInt64
|
||||
BEDecimalFromText -> do
|
||||
checkFeature featureNumberFromText
|
||||
pure $ TText :-> TOptional TDecimal
|
||||
BEAddDecimal -> pure $ tBinop TDecimal
|
||||
BESubDecimal -> pure $ tBinop TDecimal
|
||||
BEMulDecimal -> pure $ tBinop TDecimal
|
||||
|
@ -129,6 +129,10 @@ convertPrim _ "BEPartyToQuotedText" (TParty :-> TText) =
|
||||
EBuiltin BEPartyToQuotedText
|
||||
convertPrim _ "BEPartyFromText" (TText :-> TOptional TParty) =
|
||||
EBuiltin BEPartyFromText
|
||||
convertPrim version "BEInt64FromText" t@(TText :-> TOptional TInt64) =
|
||||
whenRuntimeSupports version featureNumberFromText t $ EBuiltin BEInt64FromText
|
||||
convertPrim version "BEDecimalFromText" t@(TText :-> TOptional TDecimal) =
|
||||
whenRuntimeSupports version featureNumberFromText t $ EBuiltin BEDecimalFromText
|
||||
|
||||
-- Map operations
|
||||
|
||||
|
@ -372,7 +372,9 @@ enum BuiltinFunction {
|
||||
TO_TEXT_DATE = 71;
|
||||
TO_QUOTED_TEXT_PARTY = 63; // legacy, remove in next major version
|
||||
TO_TEXT_PARTY = 94; // *Available Since version 1.2*
|
||||
FROM_TEXT_PARTY = 95; // *Available Since version 1.2*
|
||||
FROM_TEXT_PARTY = 95; // *Available Since version 1.2*, was named FROM_TEXT_PARTY in 1.2, 1.3 and 1.4
|
||||
FROM_TEXT_INT64 = 103; // *Available Since version 1.5*
|
||||
FROM_TEXT_DECIMAL = 104; // *Available Since version 1.5*
|
||||
SHA256_TEXT = 93; // *Available Since version 1.2*
|
||||
|
||||
DATE_TO_UNIX_DAYS = 72; // Date -> Int64
|
||||
@ -400,7 +402,7 @@ enum BuiltinFunction {
|
||||
|
||||
COERCE_CONTRACT_ID = 102;
|
||||
|
||||
// Next id is 103. 102 is COERCE_CONTRACT_ID.
|
||||
// Next id is 105. 104 is FROM_TEXT_DECIMAL.
|
||||
}
|
||||
|
||||
// Builtin literals
|
||||
|
@ -185,6 +185,8 @@ final case class Compiler(packages: PackageId PartialFunction Package) {
|
||||
case BToTextDate => SBToText
|
||||
case BToQuotedTextParty => SBToQuotedTextParty
|
||||
case BFromTextParty => SBFromTextParty
|
||||
case BFromTextInt64 => SBFromTextInt64
|
||||
case BFromTextDecimal => SBFromTextDecimal
|
||||
|
||||
case BSHA256Text => SBSHA256Text
|
||||
|
||||
|
@ -233,6 +233,38 @@ object SBuiltin {
|
||||
}
|
||||
}
|
||||
|
||||
final case object SBFromTextInt64 extends SBuiltin(1) {
|
||||
private val pattern = """[+-]?\d+""".r.pattern
|
||||
|
||||
def execute(args: util.ArrayList[SValue], machine: Machine): Unit = {
|
||||
val s = args.get(0).asInstanceOf[SText].value
|
||||
val int64 =
|
||||
if (pattern.matcher(s).matches())
|
||||
try {
|
||||
Some(SInt64(java.lang.Long.parseLong(s)))
|
||||
} catch {
|
||||
case _: NumberFormatException =>
|
||||
None
|
||||
} else
|
||||
None
|
||||
machine.ctrl = CtrlValue(SOptional(int64))
|
||||
}
|
||||
}
|
||||
|
||||
final case object SBFromTextDecimal extends SBuiltin(1) {
|
||||
private val pattern = """[+-]?[0-9]+(\.[0-9]+)?""".r.pattern
|
||||
|
||||
def execute(args: util.ArrayList[SValue], machine: Machine): Unit = {
|
||||
val s = args.get(0).asInstanceOf[SText].value
|
||||
val decimal =
|
||||
if (pattern.matcher(s).matches())
|
||||
Decimal.fromBigDecimal(BigDecimal(s)).fold(_ => None, x => Some(SDecimal(x)))
|
||||
else
|
||||
None
|
||||
machine.ctrl = CtrlValue(SOptional(decimal))
|
||||
}
|
||||
}
|
||||
|
||||
final case object SBSHA256Text extends SBuiltin(1) {
|
||||
def execute(args: util.ArrayList[SValue], machine: Machine): Unit = {
|
||||
machine.ctrl = CtrlValue(args.get(0) match {
|
||||
|
@ -738,7 +738,7 @@ class SBuiltinTest extends FreeSpec with Matchers with TableDrivenPropertyChecks
|
||||
}
|
||||
}
|
||||
|
||||
"TO_TEXT_PARTY & TO_QUOTED_TEXT_PARTY & FROM_TEXT_PARTY" - {
|
||||
"Text Operations" - {
|
||||
"TO_QUOTED_TEXT_PARTY single quotes" in {
|
||||
eval(e"TO_QUOTED_TEXT_PARTY 'alice'") shouldBe Right(SText("'alice'"))
|
||||
}
|
||||
@ -752,7 +752,99 @@ class SBuiltinTest extends FreeSpec with Matchers with TableDrivenPropertyChecks
|
||||
SOptional(Some(SParty(Ref.Party.assertFromString("alice")))))
|
||||
eval(e"""FROM_TEXT_PARTY "bad%char" """) shouldBe Right(SOptional(None))
|
||||
}
|
||||
|
||||
"FROM_TEXT_INT64" in {
|
||||
val positiveTestCases =
|
||||
Table(
|
||||
"strings",
|
||||
"-9223372036854775808",
|
||||
"-9223372036854775807",
|
||||
"-22",
|
||||
"0",
|
||||
"42",
|
||||
"9223372036854775806",
|
||||
"9223372036854775807",
|
||||
"+9223372036854775807",
|
||||
"01",
|
||||
"0" * 20 + "42",
|
||||
"-003",
|
||||
)
|
||||
val negativeTestCases =
|
||||
Table(
|
||||
"strings",
|
||||
"pi",
|
||||
"0x11",
|
||||
"1.0",
|
||||
"2.",
|
||||
"1L",
|
||||
"+-1",
|
||||
"9223372036854775808",
|
||||
"9223372036854775809",
|
||||
"-9223372036854775809",
|
||||
"-9223372036854775810",
|
||||
"1" * 20
|
||||
)
|
||||
|
||||
forEvery(positiveTestCases) { s =>
|
||||
eval(e"""FROM_TEXT_INT64 "$s"""") shouldBe Right(SOptional(Some(SInt64(s.toLong))))
|
||||
}
|
||||
forEvery(negativeTestCases) { s =>
|
||||
eval(e"""FROM_TEXT_INT64 "$s"""") shouldBe Right(SOptional(None))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"FROM_TEXT_DECIMAL" in {
|
||||
val positiveTestCases =
|
||||
Table(
|
||||
"strings" -> "canonical string",
|
||||
("9" * 28 + "." + "9" * 10) -> ("9" * 28 + "." + "9" * 10),
|
||||
("0" * 20 + "1" * 28) -> ("0" * 20 + "1" * 28),
|
||||
"161803398.87499" -> "161803398.87499",
|
||||
"3.1415926536" -> "3.1415926536",
|
||||
"2.7182818285" -> "2.7182818285",
|
||||
"0.0000000001" -> "0.0000000001",
|
||||
"0.0005" + "0" * 20 -> "0.0005",
|
||||
"+0.0" -> "0.0",
|
||||
"0.0" -> "0.0",
|
||||
"0" -> "0.0",
|
||||
"-0" -> "0.0",
|
||||
"42" -> "42.0",
|
||||
"-0.0005" + "0" * 20 -> "-0.0005",
|
||||
"-0.0000000001" -> "-0.0000000001",
|
||||
"-2.7182818285" -> "-2.7182818285",
|
||||
"-3.1415926536" -> "-3.1415926536",
|
||||
"-161803398.87499" -> "-161803398.87499",
|
||||
("-" + "0" * 20 + "1" * 28) -> ("-" + "1" * 28),
|
||||
("-" + "9" * 28 + "." + "9" * 10) -> ("-" + "9" * 28 + "." + "9" * 10)
|
||||
)
|
||||
val negativeTestCases =
|
||||
Table(
|
||||
"strings",
|
||||
"pi",
|
||||
"0x11",
|
||||
"1E10",
|
||||
"2.",
|
||||
"1L",
|
||||
"+-1",
|
||||
"1" * 29,
|
||||
"-" + "1" * 29,
|
||||
"+" + "1" * 29,
|
||||
"1" * 29,
|
||||
"0." + "0" * 10 + "1",
|
||||
"42" + "0" * 24 + "2019",
|
||||
)
|
||||
|
||||
forEvery(positiveTestCases) { (input, expected) =>
|
||||
eval(e"""FROM_TEXT_DECIMAL "$input"""") shouldBe Right(
|
||||
SOptional(
|
||||
Some(SDecimal(Decimal.assertFromBigDecimal(BigDecimal(expected).setScale(10))))))
|
||||
}
|
||||
forEvery(negativeTestCases) { s =>
|
||||
eval(e"""FROM_TEXT_DECIMAL "$s"""") shouldBe Right(SOptional(None))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
"Debugging builtins" - {
|
||||
|
@ -340,6 +340,8 @@ object Ast {
|
||||
final case object BToTextDate extends BuiltinFunction(1) // :: Date -> Text
|
||||
final case object BToQuotedTextParty extends BuiltinFunction(1) // :: Party -> Text
|
||||
final case object BFromTextParty extends BuiltinFunction(1) // :: Text -> Optional Party
|
||||
final case object BFromTextInt64 extends BuiltinFunction(1) // :: Text -> Optional Int64
|
||||
final case object BFromTextDecimal extends BuiltinFunction(1) // :: Text -> Optional Decimal
|
||||
|
||||
final case object BSHA256Text extends BuiltinFunction(arity = 1) // :: Text -> Text
|
||||
|
||||
|
@ -729,6 +729,8 @@ object DecodeV1 {
|
||||
TO_TEXT_TEXT -> (BToTextText -> "0"),
|
||||
TO_QUOTED_TEXT_PARTY -> (BToQuotedTextParty -> "0"),
|
||||
FROM_TEXT_PARTY -> (BFromTextParty -> "2"),
|
||||
FROM_TEXT_INT64 -> (BFromTextInt64 -> "5"),
|
||||
FROM_TEXT_DECIMAL -> (BFromTextInt64 -> "5"),
|
||||
SHA256_TEXT -> (BSHA256Text -> "2"),
|
||||
DATE_TO_UNIX_DAYS -> (BDateToUnixDays -> "0"),
|
||||
EXPLODE_TEXT -> (BExplodeText -> "0"),
|
||||
|
@ -229,6 +229,8 @@ private[parser] object ExprParser {
|
||||
"TO_TEXT_DATE" -> BToTextDate,
|
||||
"TO_QUOTED_TEXT_PARTY" -> BToQuotedTextParty,
|
||||
"FROM_TEXT_PARTY" -> BFromTextParty,
|
||||
"FROM_TEXT_INT64" -> BFromTextInt64,
|
||||
"FROM_TEXT_DECIMAL" -> BFromTextDecimal,
|
||||
"ERROR" -> BError,
|
||||
"LESS_INT64" -> BLessInt64,
|
||||
"LESS_DECIMAL" -> BLessDecimal,
|
||||
|
@ -1112,7 +1112,7 @@ for the ``DefTemplate`` rule). ::
|
||||
Γ ⊢ 'no_key'
|
||||
|
||||
⊢ₛ τ Γ ⊢ eₖ : τ
|
||||
⊢ₖ eₖ [DAML-LF 1.3]
|
||||
⊢ₖ eₖ [DAML-LF = 1.3]
|
||||
ε ⊢ eₘ : τ → 'List' 'Party'
|
||||
——————————————————————————————————————————————————————————————— KeyDefSome
|
||||
Γ ⊢ 'key' τ eₖ eₘ
|
||||
@ -1962,7 +1962,6 @@ Int64 functions
|
||||
|
||||
Returns the decimal representation of the integer as a string.
|
||||
|
||||
|
||||
Decimal functions
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
@ -2024,7 +2023,6 @@ Decimal functions
|
||||
|
||||
Returns the decimal string representation of the decimal.
|
||||
|
||||
|
||||
String functions
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -121,6 +121,8 @@ private[validation] object Typing {
|
||||
BSHA256Text -> (TText ->: TText),
|
||||
BToQuotedTextParty -> (TParty ->: TText),
|
||||
BFromTextParty -> (TText ->: TOptional(TParty)),
|
||||
BFromTextInt64 -> (TText ->: TOptional(TInt64)),
|
||||
BFromTextDecimal -> (TText ->: TOptional(TDecimal)),
|
||||
BError -> TForall(alpha.name -> KStar, TText ->: alpha),
|
||||
// ComparisonsA
|
||||
BLessInt64 -> tComparison(BTInt64),
|
||||
|
Loading…
Reference in New Issue
Block a user