make colon valid fro party literals + spec cleanup (#1467)

This commit is contained in:
Remy 2019-06-04 17:50:02 +02:00 committed by mergify[bot]
parent e400bc7eb8
commit e115c39b67
7 changed files with 86 additions and 88 deletions

View File

@ -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')

View File

@ -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_

View File

@ -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

View File

@ -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
}
}
}

View File

@ -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")

View File

@ -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*]

View File

@ -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)))