mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-20 01:07:18 +03:00
make colon valid fro party literals + spec cleanup (#1467)
This commit is contained in:
parent
e400bc7eb8
commit
e115c39b67
@ -446,7 +446,7 @@ message PrimLit {
|
||||
sfixed64 timestamp = 5;
|
||||
|
||||
// Party literal ('LitParty')
|
||||
// *Must be a SimpleString*
|
||||
// *Must be a PartyId string*
|
||||
string party = 7;
|
||||
|
||||
// Date literal ('Date')
|
||||
|
@ -27,10 +27,12 @@ abstract class DecimalModule {
|
||||
cast(BigDecimal(new java.math.BigDecimal(x, MathContext.UNLIMITED)))
|
||||
|
||||
// we use these to compare only, therefore set the precision to unlimited to make sure
|
||||
// we can compare every number we're given
|
||||
val max: T = unlimitedBigDecimal("9999999999999999999999999999.9999999999")
|
||||
// we can compare every number we're given.
|
||||
private val max: BigDecimal = unlimitedBigDecimal("9999999999999999999999999999.9999999999")
|
||||
private val min: BigDecimal = unlimitedBigDecimal("-9999999999999999999999999999.9999999999")
|
||||
|
||||
val min: T = unlimitedBigDecimal("-9999999999999999999999999999.9999999999")
|
||||
val MaxValue: T = assertFromBigDecimal(max)
|
||||
val MinValue: T = assertFromBigDecimal(min)
|
||||
|
||||
/** Checks that a `T` falls between `min` and `max`, and
|
||||
* round the number according to `scale`. Note that it does _not_
|
||||
|
@ -138,7 +138,7 @@ object Ref {
|
||||
underscore. We use them to represent [PackageId]s and [Party] literals. In this way, we avoid
|
||||
empty identifiers, escaping problems, and other similar pitfalls.
|
||||
*/
|
||||
val Party = ConcatenableMatchingStringModule("-_ ".contains(_))
|
||||
val Party = ConcatenableMatchingStringModule(":-_ ".contains(_))
|
||||
type Party = Party.T
|
||||
|
||||
/** Reference to a package via a package identifier. The identifier is the ascii7
|
||||
|
@ -73,80 +73,58 @@ class RefTest extends FreeSpec with Matchers {
|
||||
|
||||
"Party and PackageId" - {
|
||||
|
||||
val simpleChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_ "
|
||||
|
||||
"accepts simple characters" in {
|
||||
for (c <- simpleChars) {
|
||||
Party.fromString(s"the character $c is simple") shouldBe 'right
|
||||
PackageId.fromString(s"the character $c is simple") shouldBe 'right
|
||||
}
|
||||
}
|
||||
|
||||
"rejects the empty string" in {
|
||||
Party.fromString("") shouldBe 'left
|
||||
PackageId.fromString("") shouldBe 'left
|
||||
}
|
||||
|
||||
"rejects non simple US-ASCII characters" in {
|
||||
for (c <- '\u0001' to '\u007f' if !simpleChars.contains(c)) {
|
||||
Party.fromString(s"the US-ASCII character $c is not simple") shouldBe 'left
|
||||
PackageId.fromString(s"the US-ASCII character $c is not simple") shouldBe 'left
|
||||
}
|
||||
}
|
||||
|
||||
"rejects no US-ASCII characters" in {
|
||||
for (c <- '\u0080' to '\u00ff') {
|
||||
Party.fromString(s"the character '$c' is not US-ASCII") shouldBe 'left
|
||||
PackageId.fromString(s"the character '$c' is not US-ASCII") shouldBe 'left
|
||||
}
|
||||
for (s <- List(
|
||||
"español",
|
||||
"東京",
|
||||
"Λ (τ : ⋆) (σ: ⋆ → ⋆). λ (e : ∀ (α : ⋆). σ α) → (( e @τ ))"
|
||||
)) {
|
||||
Party.fromString(s) shouldBe 'left
|
||||
PackageId.fromString(s) shouldBe 'left
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"LedgerString" - {
|
||||
|
||||
val packageIdChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_ "
|
||||
val partyIdChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:-_ "
|
||||
val ledgerStringChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._:-# "
|
||||
|
||||
"accepts simple characters" in {
|
||||
for (c <- ledgerStringChars) {
|
||||
LedgerString.fromString(s"the_character_${c}_should_be_accepted") shouldBe 'right
|
||||
}
|
||||
}
|
||||
def makeString(c: Char): String = s"the character $c is not US-ASCII"
|
||||
|
||||
"rejects the empty string" in {
|
||||
PackageId.fromString("") shouldBe 'left
|
||||
Party.fromString("") shouldBe 'left
|
||||
LedgerString.fromString("") shouldBe 'left
|
||||
}
|
||||
|
||||
"reject too long string" in {
|
||||
LedgerString.fromString("a" * 255) shouldBe 'right
|
||||
LedgerString.fromString("a" * 256) shouldBe 'left
|
||||
LedgerString.fromString("a" * 500) shouldBe 'left
|
||||
}
|
||||
|
||||
"rejects non allowed US-ASCII characters" in {
|
||||
for (c <- '\u0001' to '\u007f' if !ledgerStringChars.contains(c)) {
|
||||
LedgerString.fromString(s"the_character_${c}_should_be_rejected") shouldBe 'left
|
||||
"treats US-ASCII characters as expected" in {
|
||||
for (c <- '\u0001' to '\u007f') {
|
||||
val s = makeString(c)
|
||||
PackageId.fromString(s) shouldBe (if (packageIdChars.contains(c)) 'right else 'left)
|
||||
Party.fromString(s) shouldBe (if (partyIdChars.contains(c)) 'right else 'left)
|
||||
LedgerString.fromString(s) shouldBe (if (ledgerStringChars.contains(c)) 'right else 'left)
|
||||
}
|
||||
}
|
||||
|
||||
"rejects no US-ASCII characters" in {
|
||||
|
||||
val negativeTestCase = makeString('a')
|
||||
|
||||
PackageId.fromString(negativeTestCase) shouldBe 'right
|
||||
Party.fromString(negativeTestCase) shouldBe 'right
|
||||
LedgerString.fromString(negativeTestCase) shouldBe 'right
|
||||
|
||||
for (c <- '\u0080' to '\u00ff') {
|
||||
LedgerString.fromString(s"the_character_${c}_should_be_rejected") shouldBe 'left
|
||||
val positiveTestCase = makeString(c)
|
||||
PackageId.fromString(positiveTestCase) shouldBe 'left
|
||||
Party.fromString(positiveTestCase) shouldBe 'left
|
||||
LedgerString.fromString(positiveTestCase) shouldBe 'left
|
||||
}
|
||||
for (s <- List(
|
||||
for (positiveTestCase <- List(
|
||||
"español",
|
||||
"東京",
|
||||
"Λ (τ : ⋆) (σ: ⋆ → ⋆). λ (e : ∀ (α : ⋆). σ α) → (( e @τ ))"
|
||||
)) {
|
||||
LedgerString.fromString(s) shouldBe 'left
|
||||
Party.fromString(positiveTestCase) shouldBe 'left
|
||||
PackageId.fromString(positiveTestCase) shouldBe 'left
|
||||
}
|
||||
}
|
||||
|
||||
"LedgerString should reject too long strings" in {
|
||||
val negativeTestCase = "a" * 255
|
||||
val positiveTestCase1 = "a" * 256
|
||||
val positiveTestCase2 = "a" * 500
|
||||
LedgerString.fromString(negativeTestCase) shouldBe 'right
|
||||
LedgerString.fromString(positiveTestCase1) shouldBe 'left
|
||||
LedgerString.fromString(positiveTestCase2) shouldBe 'left
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -188,7 +188,7 @@ class SBuiltinTest extends FreeSpec with Matchers with TableDrivenPropertyChecks
|
||||
|
||||
"Decimal operations" - {
|
||||
|
||||
val maxDecimal = Decimal.max
|
||||
val maxDecimal = Decimal.MaxValue
|
||||
|
||||
val minPosDecimal = BigDecimal("0000000000000000000000000000.0000000001")
|
||||
val bigBigDecimal = BigDecimal("8765432109876543210987654321.0987654321")
|
||||
|
@ -315,40 +315,52 @@ any code point with an integer value in the range from
|
||||
(bounds included).
|
||||
|
||||
|
||||
Then, we define the so-called *simple strings*. Simple strings are
|
||||
non-empty US-ASCII strings built with letters, digits, space, minus
|
||||
and, underscore. We use them in instances when we want to avoid empty
|
||||
identifiers, escaping problems, and other similar pitfalls. ::
|
||||
Then, we define the so-called *PackageId strings* and *PartyId
|
||||
strings*. Those are non-empty strings built with a limited set of
|
||||
US-ASCII characters (See the rules `PackageIdChar` and `PartyIdChar`
|
||||
below for the exact sets of characters). We use those string in
|
||||
instances when we want to avoid empty identifiers, escaping problems,
|
||||
and other similar pitfalls. ::
|
||||
|
||||
Simple strings
|
||||
SimpleString ::= ' SimpleChars ' -- SimpleString
|
||||
PackageId strings
|
||||
PackageIdString ::= ' PackageIdChars ' -- PackageIdString
|
||||
|
||||
Sequences of simple characters
|
||||
SimpleChars ::= SimpleChar -- SimpleChars
|
||||
| SimpleChars SimpleChar
|
||||
Sequences of PackageId character
|
||||
PackageIdChars ::= PackageIdChar -- PackageIdChars
|
||||
| PackageIdChars PackageIdChar
|
||||
|
||||
Simple characters
|
||||
SimpleChar ∈ [a-zA-Z0-9\-_ ] -- SimpleChar
|
||||
PackageId character
|
||||
PackageIdChar ∈ [a-zA-Z0-9\-_ ] -- PackageIdChar
|
||||
|
||||
PartyId strings
|
||||
PartyIdString ::= ' PartyIdChars ' -- PartyIdString
|
||||
|
||||
Sequences of PartyId character
|
||||
PartyIdChars ::= PartyIdChar -- PartyIdChars
|
||||
| PartyIdChars PartyIdChar
|
||||
|
||||
PartyId character
|
||||
PartyIdChar ∈ [a-zA-Z0-9:\-_ ] -- PartyIdChar
|
||||
|
||||
We can now define all the literals that a program can handle::
|
||||
|
||||
64-bits integer literals:
|
||||
LitInt64 ∈ (-?)[0-9]+ -- LitInt64:
|
||||
LitInt64 ∈ (-?)[0-9]+ -- LitInt64:
|
||||
|
||||
Decimal literals:
|
||||
LitDecimal ∈ ([+-]?)\d{1,28}(.[0-9]\d{1-10})? -- LitDecimal
|
||||
|
||||
Date literals:
|
||||
LitDate ∈ \d{4}-\d{4}-\d{4} -- LitDate
|
||||
LitDate ∈ \d{4}-\d{4}-\d{4} -- LitDate
|
||||
|
||||
UTC timestamp literals:
|
||||
LitTimestamp ∈ \d{4}-\d{4}-\d{4}T\d{2}:\d{2}:\d{2}(.\d{1,3})?Z
|
||||
-- LitTimestamp
|
||||
-- LitTimestamp
|
||||
UTF8 string literals:
|
||||
LitText ::= String -- LitText
|
||||
LitText ::= String -- LitText
|
||||
|
||||
Party literals:
|
||||
LitParty ::= SimpleString -- LitParty
|
||||
LitParty ::= PartyIdString -- LitParty
|
||||
|
||||
The literals represent actual DAML-LF values:
|
||||
|
||||
@ -400,8 +412,8 @@ In the following, we will use identifiers to represent *built-in
|
||||
functions*, term and type *variable names*, record and tuple *field
|
||||
names*, *variant constructors*, and *template choices*. On the other
|
||||
hand, we will use names to represent *type constructors*, *value
|
||||
references*, and *module names*. Finally, we will use simple strings
|
||||
as *package identifiers*. ::
|
||||
references*, and *module names*. Finally, we will use PackageId
|
||||
strings as *package identifiers*. ::
|
||||
|
||||
Expression variables
|
||||
x, y, z ::= Ident -- VarExp
|
||||
@ -434,7 +446,7 @@ as *package identifiers*. ::
|
||||
cid -- ContractId
|
||||
|
||||
Package identifiers
|
||||
pid ::= SimpleString -- PkgId
|
||||
pid ::= PackageIdString -- PkgId
|
||||
|
||||
We do not specify an explicit syntax for contract identifiers as it is
|
||||
not possible to refer to them statically within a program. In
|
||||
@ -2033,12 +2045,18 @@ Decimal functions
|
||||
|
||||
* ``MUL_DECIMAL : 'Decimal' → 'Decimal' → 'Decimal'``
|
||||
|
||||
Multiplies the two decimals. Throws an error in case of overflow.
|
||||
Multiplies the two decimals and rounds the result to the closest
|
||||
multiple of ``10⁻¹⁰`` using `banker's rounding convention
|
||||
<https://en.wikipedia.org/wiki/Rounding#Round_half_to_even>`_.
|
||||
Throws an error in case of overflow.
|
||||
|
||||
* ``DIV_DECIMAL : 'Decimal' → 'Decimal' → 'Decimal'``
|
||||
|
||||
Divides the first decimal by the second one. Throws an error in
|
||||
case of overflow.
|
||||
Divides the first decimal by the second one and rounds the result to
|
||||
the closest multiple of ``10⁻¹⁰`` using `banker's rounding
|
||||
convention
|
||||
<https://en.wikipedia.org/wiki/Rounding#Round_half_to_even>`_. Throws
|
||||
an error in case of overflow.
|
||||
|
||||
* ``ROUND_DECIMAL : 'Int64' → 'Decimal' → 'Decimal'``
|
||||
|
||||
@ -2292,7 +2310,7 @@ Party functions
|
||||
|
||||
Returns the string representation of the party. This function,
|
||||
together with ``FROM_TEXT_PARTY``, forms an isomorphism between
|
||||
`simple strings <Literals_>`_ and parties. In other words,
|
||||
`PartyId strings <Literals_>`_ and parties. In other words,
|
||||
the following equations hold::
|
||||
|
||||
∀ p. FROM_TEXT_PARTY (TO_TEXT_PARTY p) = 'Some' p
|
||||
@ -2303,7 +2321,7 @@ Party functions
|
||||
* ``FROM_TEXT_PARTY : 'Text' → 'Optional' 'Party'``
|
||||
|
||||
Given the string representation of the party, returns the party,
|
||||
if the input string is a `simple string <Literals_>`_.
|
||||
if the input string is a `PartyId strings <Literals_>`_.
|
||||
|
||||
[*Available since version 1.2*]
|
||||
|
||||
|
@ -93,8 +93,8 @@ object ValueGenerators {
|
||||
Gen
|
||||
.frequency(
|
||||
(1, Gen.const(BigDecimal("0.0"))),
|
||||
(1, Gen.const(Decimal.max)),
|
||||
(1, Gen.const(Decimal.min)),
|
||||
(1, Gen.const(Decimal.MaxValue)),
|
||||
(1, Gen.const(Decimal.MinValue)),
|
||||
(5, bd)
|
||||
)
|
||||
.map(d => ValueDecimal(Decimal.assertFromBigDecimal(d)))
|
||||
|
Loading…
Reference in New Issue
Block a user