Intern all strings: proto cleanup (#3296)

* daml-lf: cleanup strings/names interning for 1.dev

* change level of dottedName intening
* make interning mandatory
* rational name of proto field

* fix tests

* spec update

* fix test

* formatting

* Address Gerolf's comments

* Address Jussi's comments
This commit is contained in:
Remy 2019-11-01 18:03:42 +01:00 committed by mergify[bot]
parent bd19291632
commit d56a4aa715
17 changed files with 1151 additions and 762 deletions

View File

@ -96,9 +96,13 @@ decodeNameString wrapName mangled =
-- | Decode the multi-component name of a syntactic object, e.g., a type
-- constructor. All compononents are mangled. Dotted names will be interned
-- in DAML-LF 1.7 and onwards.
decodeDottedName :: ([T.Text] -> a) -> LF1.DottedName -> Decode a
decodeDottedName wrapDottedName (LF1.DottedName mangled dnId) =
wrapDottedName <$> (decodeInternableStrings mangled dnId >>= mapM (decodeNameString id))
decodeDottedName :: Util.EitherLike LF1.DottedName Int32 e
=> ([T.Text] -> a) -> Maybe e -> Decode a
decodeDottedName wrapDottedName mbDottedNameOrId = mayDecode "dottedName" mbDottedNameOrId $ \dottedNameOrId -> do
mangled <- case Util.toEither dottedNameOrId of
Left (LF1.DottedName mangledV) -> decodeInternableStrings mangledV 0
Right dnId -> decodeInternableStrings V.empty dnId
wrapDottedName <$> mapM (decodeNameString id) mangled
-- | Decode the name of a top-level value. The name is mangled and will be
-- interned in DAML-LF 1.7 and onwards.
@ -121,7 +125,7 @@ decodeValueName ident mangledV dnId = do
decodeValName :: LF1.ValName -> Decode (Qualified ExprValName)
decodeValName LF1.ValName{..} = do
(pref, mname) <- mayDecode "valNameModule" valNameModule decodeModuleRef
name <- decodeValueName "valNameName" valNameName valNameNameInternedId
name <- decodeValueName "valNameName" valNameNameDname valNameNameInternedDname
pure $ Qualified pref mname name
-- | Decode a reference to a package. Package names are not mangled. Package
@ -130,8 +134,8 @@ decodePackageRef :: LF1.PackageRef -> Decode PackageRef
decodePackageRef (LF1.PackageRef pref) =
mayDecode "packageRefSum" pref $ \case
LF1.PackageRefSumSelf _ -> pure PRSelf
LF1.PackageRefSumPackageId pkgId -> pure $ PRImport $ PackageId $ decodeString pkgId
LF1.PackageRefSumInternedId strId -> PRImport . PackageId <$> lookupString strId
LF1.PackageRefSumPackageIdStr pkgId -> pure $ PRImport $ PackageId $ decodeString pkgId
LF1.PackageRefSumPackageIdInternedStr strId -> PRImport . PackageId <$> lookupString strId
------------------------------------------------------------------------
-- Decodings of everything else
@ -170,7 +174,7 @@ decodePackage minorText (LF1.Package mods internedStringsV internedDottedNamesV)
decodeModule :: LF1.Module -> Decode Module
decodeModule (LF1.Module name flags dataTypes values templates) =
Module
<$> mayDecode "moduleName" name (decodeDottedName ModuleName)
<$> decodeDottedName ModuleName name
<*> pure Nothing
<*> mayDecode "flags" flags decodeFeatureFlags
<*> decodeNM DuplicateDataType decodeDefDataType dataTypes
@ -190,7 +194,7 @@ decodeDefDataType :: LF1.DefDataType -> Decode DefDataType
decodeDefDataType LF1.DefDataType{..} =
DefDataType
<$> traverse decodeLocation defDataTypeLocation
<*> mayDecode "dataTypeName" defDataTypeName (decodeDottedName TypeConName)
<*> decodeDottedName TypeConName defDataTypeName
<*> pure (IsSerializable defDataTypeSerializable)
<*> traverse decodeTypeVarWithKind (V.toList defDataTypeParams)
<*> mayDecode "dataTypeDataCons" defDataTypeDataCons decodeDataCons
@ -210,7 +214,7 @@ decodeDataCons = \case
decodeDefValueNameWithType :: LF1.DefValue_NameWithType -> Decode (ExprValName, Type)
decodeDefValueNameWithType LF1.DefValue_NameWithType{..} = (,)
<$> decodeValueName "defValueName" defValue_NameWithTypeName defValue_NameWithTypeNameInternedId
<$> decodeValueName "defValueName" defValue_NameWithTypeNameDname defValue_NameWithTypeNameInternedDname
<*> mayDecode "defValueType" defValue_NameWithTypeType decodeType
decodeDefValue :: LF1.DefValue -> Decode DefValue
@ -227,7 +231,7 @@ decodeDefTemplate LF1.DefTemplate{..} = do
tplParam <- decodeName ExprVarName defTemplateParam
Template
<$> traverse decodeLocation defTemplateLocation
<*> mayDecode "defTemplateTycon" defTemplateTycon (decodeDottedName TypeConName)
<*> decodeDottedName TypeConName defTemplateTycon
<*> pure tplParam
<*> mayDecode "defTemplatePrecond" defTemplatePrecond decodeExpr
<*> mayDecode "defTemplateSignatories" defTemplateSignatories decodeExpr
@ -409,8 +413,8 @@ decodeExpr (LF1.Expr mbLoc exprSum) = case mbLoc of
decodeExprSum :: Maybe LF1.ExprSum -> Decode Expr
decodeExprSum exprSum = mayDecode "exprSum" exprSum $ \case
LF1.ExprSumVar var -> EVar <$> decodeNameString ExprVarName (decodeString var)
LF1.ExprSumVarInternedId strId -> EVar <$> (lookupString strId >>= decodeNameString ExprVarName)
LF1.ExprSumVarStr var -> EVar <$> decodeNameString ExprVarName (decodeString var)
LF1.ExprSumVarInternedStr strId -> EVar <$> (lookupString strId >>= decodeNameString ExprVarName)
LF1.ExprSumVal val -> EVal <$> decodeValName val
LF1.ExprSumBuiltin (Proto.Enumerated (Right bi)) -> EBuiltin <$> decodeBuiltinFunction bi
LF1.ExprSumBuiltin (Proto.Enumerated (Left num)) -> throwError (UnknownEnum "ExprSumBuiltin" num)
@ -625,15 +629,15 @@ decodeVarWithType LF1.VarWithType{..} =
decodePrimLit :: LF1.PrimLit -> Decode BuiltinExpr
decodePrimLit (LF1.PrimLit mbSum) = mayDecode "primLitSum" mbSum $ \case
LF1.PrimLitSumInt64 sInt -> pure $ BEInt64 sInt
LF1.PrimLitSumDecimal sDec -> decodeDecimalLit $ decodeString sDec
LF1.PrimLitSumDecimalInternedId strId -> lookupString strId >>= decodeDecimalLit
LF1.PrimLitSumNumeric sNum -> decodeNumericLit $ decodeString sNum
LF1.PrimLitSumNumericInternedId strId -> lookupString strId >>= decodeNumericLit
LF1.PrimLitSumDecimalStr sDec -> decodeDecimalLit $ decodeString sDec
LF1.PrimLitSumDecimalInternedStr strId -> lookupString strId >>= decodeDecimalLit
LF1.PrimLitSumNumericStr sNum -> decodeNumericLit $ decodeString sNum
LF1.PrimLitSumNumericInternedStr strId -> lookupString strId >>= decodeNumericLit
LF1.PrimLitSumTimestamp sTime -> pure $ BETimestamp sTime
LF1.PrimLitSumText x -> pure $ BEText $ decodeString x
LF1.PrimLitSumTextInternedId strId -> BEText <$> lookupString strId
LF1.PrimLitSumParty p -> pure $ BEParty $ PartyLiteral $ decodeString p
LF1.PrimLitSumPartyInternedId strId -> BEParty . PartyLiteral <$> lookupString strId
LF1.PrimLitSumTextStr x -> pure $ BEText $ decodeString x
LF1.PrimLitSumTextInternedStr strId -> BEText <$> lookupString strId
LF1.PrimLitSumPartyStr p -> pure $ BEParty $ PartyLiteral $ decodeString p
LF1.PrimLitSumPartyInternedStr strId -> BEParty . PartyLiteral <$> lookupString strId
LF1.PrimLitSumDate days -> pure $ BEDate days
decodeDecimalLit :: T.Text -> Decode BuiltinExpr
@ -729,14 +733,14 @@ decodeTypeConApp LF1.Type_Con{..} =
decodeTypeConName :: LF1.TypeConName -> Decode (Qualified TypeConName)
decodeTypeConName LF1.TypeConName{..} = do
(pref, mname) <- mayDecode "typeConNameModule" typeConNameModule decodeModuleRef
con <- mayDecode "typeConNameName" typeConNameName (decodeDottedName TypeConName)
con <- decodeDottedName TypeConName typeConNameName
pure $ Qualified pref mname con
decodeModuleRef :: LF1.ModuleRef -> Decode (PackageRef, ModuleName)
decodeModuleRef LF1.ModuleRef{..} =
(,)
<$> mayDecode "moduleRefPackageRef" moduleRefPackageRef decodePackageRef
<*> mayDecode "moduleRefModuleName" moduleRefModuleName (decodeDottedName ModuleName)
<*> decodeDottedName ModuleName moduleRefModuleName
------------------------------------------------------------------------
-- Helpers

View File

@ -13,6 +13,7 @@ import Control.Lens ((^.), matching)
import Control.Lens.Ast (rightSpine)
import Control.Monad.State.Strict
import qualified Data.Bifunctor as Bf
import Data.Coerce
import Data.Functor.Identity
import qualified Data.HashMap.Strict as HMS
@ -134,21 +135,26 @@ encodeNames = encodeInternableStrings . fmap mangleName
Left err -> error $ "IMPOSSIBLE: could not mangle name " ++ show unmangled ++ ": " ++ err
Right mangled -> mangled
-- | Encode the multi-component name of a syntactic object, e.g., a type
-- constructor. All compononents are mangled. Dotted names will be interned
-- in DAML-LF 1.7 and onwards.
encodeDottedName :: (a -> [T.Text]) -> a -> Encode (Just P.DottedName)
encodeDottedName :: Util.EitherLike P.DottedName Int32 e
=> (a -> [T.Text]) -> a -> Encode (Just e)
encodeDottedName unwrapDottedName (unwrapDottedName -> unmangled) =
Just . uncurry P.DottedName <$> encodeDottedName' unmangled
Just <$>
Util.fromEither @P.DottedName @Int32 <$>
Bf.first P.DottedName <$>
encodeDottedName' unmangled
encodeDottedName' :: [T.Text] -> Encode (V.Vector TL.Text, Int32)
encodeDottedName' :: [T.Text] -> Encode (Either (V.Vector TL.Text) Int32)
encodeDottedName' unmangled = do
mangledAndInterned <- encodeNames unmangled
case mangledAndInterned of
Left mangled -> pure (V.fromList mangled, 0)
Left mangled -> pure $ Left (V.fromList mangled)
Right ids -> do
id <- allocDottedName ids
pure (V.empty, id)
pure $ Right id
-- | Encode the name of a top-level value. The name is mangled and will be
-- interned in DAML-LF 1.7 and onwards.
@ -159,7 +165,11 @@ encodeDottedName' unmangled = do
-- have to handle separatedly. So for now, considering that we do not
-- use values in codegen, just mangle the entire thing.
encodeValueName :: ExprValName -> Encode (V.Vector TL.Text, Int32)
encodeValueName valName = encodeDottedName' [unExprValName valName]
encodeValueName valName = do
either <- encodeDottedName' [unExprValName valName]
case either of
Left mangled -> pure (mangled, 0)
Right id -> pure (V.empty, id)
-- | Encode a reference to a package. Package names are not mangled. Package
-- name are interned since DAML-LF 1.6.
@ -169,8 +179,9 @@ encodePackageRef = fmap (Just . P.PackageRef . Just) . \case
PRImport (PackageId pkgId) -> do
EncodeEnv{..} <- get
if getWithInterning withInterning
then P.PackageRefSumInternedId <$> allocString pkgId
else pure $ P.PackageRefSumPackageId $ encodeString pkgId
then P.PackageRefSumPackageIdInternedStr <$> allocString pkgId
else pure $ P.PackageRefSumPackageIdStr $ encodeString pkgId
------------------------------------------------------------------------
-- Simple encodings
@ -316,17 +327,17 @@ encodeBuiltinExpr :: BuiltinExpr -> Encode P.ExprSum
encodeBuiltinExpr = \case
BEInt64 x -> pureLit $ P.PrimLitSumInt64 x
BEDecimal dec ->
lit . either P.PrimLitSumDecimal P.PrimLitSumDecimalInternedId
lit . either P.PrimLitSumDecimalStr P.PrimLitSumDecimalInternedStr
<$> encodeInternableString (T.pack (show dec))
BENumeric n ->
lit . either P.PrimLitSumNumeric P.PrimLitSumNumericInternedId
lit . either P.PrimLitSumNumericStr P.PrimLitSumNumericInternedStr
<$> encodeInternableString (T.pack (show n))
BEText x ->
lit . either P.PrimLitSumText P.PrimLitSumTextInternedId
lit . either P.PrimLitSumTextStr P.PrimLitSumTextInternedStr
<$> encodeInternableString x
BETimestamp x -> pureLit $ P.PrimLitSumTimestamp x
BEParty x ->
lit . either P.PrimLitSumParty P.PrimLitSumPartyInternedId
lit . either P.PrimLitSumPartyStr P.PrimLitSumPartyInternedStr
<$> encodeInternableString (unPartyLiteral x)
BEDate x -> pureLit $ P.PrimLitSumDate x
@ -464,10 +475,10 @@ encodeBuiltinExpr = \case
encodeExpr' :: Expr -> Encode P.Expr
encodeExpr' = \case
EVar v -> expr . either P.ExprSumVar P.ExprSumVarInternedId <$> encodeName' unExprVarName v
EVar v -> expr . either P.ExprSumVarStr P.ExprSumVarInternedStr <$> encodeName' unExprVarName v
EVal (Qualified pkgRef modName val) -> do
valNameModule <- encodeModuleRef pkgRef modName
(valNameName, valNameNameInternedId) <- encodeValueName val
(valNameNameDname, valNameNameInternedDname) <- encodeValueName val
pureExpr $ P.ExprSumVal P.ValName{..}
EBuiltin bi -> expr <$> encodeBuiltinExpr bi
ERecCon{..} -> do
@ -700,7 +711,7 @@ encodeDefDataType DefDataType{..} = do
pure $ P.DefDataTypeDataConsVariant P.DefDataType_Fields{..}
DataEnum cs -> do
mangledAndInterned <- encodeNames (map unVariantConName cs)
let (defDataType_EnumConstructorsConstructors, defDataType_EnumConstructorsConstructorsInternedIds) = case mangledAndInterned of
let (defDataType_EnumConstructorsConstructorsStr, defDataType_EnumConstructorsConstructorsInternedStr) = case mangledAndInterned of
Left mangled -> (V.fromList mangled, V.empty)
Right mangledIds -> (V.empty, V.fromList mangledIds)
pure $ P.DefDataTypeDataConsEnum P.DefDataType_EnumConstructors{..}
@ -710,7 +721,7 @@ encodeDefDataType DefDataType{..} = do
encodeDefValue :: DefValue -> Encode P.DefValue
encodeDefValue DefValue{..} = do
(defValue_NameWithTypeName, defValue_NameWithTypeNameInternedId) <- encodeValueName (fst dvalBinder)
(defValue_NameWithTypeNameDname, defValue_NameWithTypeNameInternedDname) <- encodeValueName (fst dvalBinder)
defValue_NameWithTypeType <- encodeType (snd dvalBinder)
let defValueNameWithType = Just P.DefValue_NameWithType{..}
defValueExpr <- encodeExpr dvalBody

View File

@ -61,3 +61,9 @@ instance EitherLike TL.Text Int32 P.Type_VarVar
instance EitherLike TL.Text Int32 P.TypeVarWithKindVar
instance EitherLike TL.Text Int32 P.Update_ExerciseChoice
instance EitherLike TL.Text Int32 P.VarWithTypeVar
instance EitherLike P.DottedName Int32 P.ModuleRefModuleName
instance EitherLike P.DottedName Int32 P.TypeConNameName
instance EitherLike P.DottedName Int32 P.DefTemplateTycon
instance EitherLike P.DottedName Int32 P.DefDataTypeName
instance EitherLike P.DottedName Int32 P.ModuleName

View File

@ -3,10 +3,10 @@
-- Check that enum types get translated to DAML-LF's enum types.
-- @SINCE-LF 1.6
-- @QUERY-LF .modules[] | .data_types[] | select(.name | lf::get_dotted_name($pkg) == ["Color"]) | has("enum")
-- @QUERY-LF .modules[] | .data_types[] | select(lf::get_dotted_name($pkg) == ["Color"]) | has("enum")
-- @QUERY-LF .modules[] | .values[] | select(.name_with_type | lf::get_value_name($pkg) == ["red"]) | .expr | has("enum_con")
-- @QUERY-LF .modules[] | .values[] | select(.name_with_type | lf::get_value_name($pkg) == ["isRed"]) | .expr.abs.body.case.alts | .[0] | has("enum")
-- @QUERY-LF .modules[] | .data_types[] | select(.name | lf::get_dotted_name($pkg) == ["Tag"]) | (has("enum") | not)
-- @QUERY-LF .modules[] | .data_types[] | select(lf::get_dotted_name($pkg) == ["Tag"]) | (has("enum") | not)
daml 1.2
module EnumLF where

View File

@ -2,7 +2,7 @@
-- All rights reserved.
-- @ SINCE-LF 1.6
-- @QUERY-LF [.modules[] | .values[] | .expr.val.module.package_ref | select(has("interned_id"))] | length == 2
-- @QUERY-LF [.modules[] | .values[] | .expr.val.module.package_ref | select(has("package_id_interned_str"))] | length == 2
-- @QUERY-LF .interned_strings | length >= 2
-- We test that interning of package ids works. The two packages we reference are

View File

@ -1,8 +1,8 @@
-- Copyright (c) 2019, Digital Asset (Switzerland) GmbH and/or its affiliates.
-- All rights reserved.
-- @QUERY-LF .modules[] | .templates[] | select(.tycon | lf::get_dotted_name($pkg) == ["A"]) | .location.range | (.start_line == 8 and .start_col == 9)
-- @QUERY-LF .modules[] | .templates[] | select(.tycon | lf::get_dotted_name($pkg) == ["TA"]) | .location.range | (.start_line == 19 and .start_col == 18)
-- @QUERY-LF .modules[] | .templates[] | select(lf::get_template_name($pkg) == ["A"]) | .location.range | (.start_line == 8 and .start_col == 9)
-- @QUERY-LF .modules[] | .templates[] | select(lf::get_template_name($pkg) == ["TA"]) | .location.range | (.start_line == 19 and .start_col == 18)
daml 1.2
module Locations where

View File

@ -3,7 +3,7 @@
-- An IOU to be proposed using the generic proposal workflow.
-- @SINCE-LF 1.5
-- @QUERY-LF [.modules[] | .data_types[] | select(.name | lf::get_dotted_name($pkg) == ["ProposalIou"]) | .record | .fields[] | lf::get_field($pkg)] == ["asset", "receivers", "name"]
-- @QUERY-LF [.modules[] | .data_types[] | select(lf::get_dotted_name($pkg) == ["ProposalIou"]) | .record | .fields[] | lf::get_field($pkg)] == ["asset", "receivers", "name"]
daml 1.2
module ProposalIou where

View File

@ -1,12 +1,12 @@
-- Copyright (c) 2019, Digital Asset (Switzerland) GmbH and/or its affiliates.
-- All rights reserved.
-- @ QUERY-LF .modules[] | .data_types[] | select(.name | lf::get_dotted_name($pkg) == ["Unserializable"]) | has("serializable") | not
-- @ QUERY-LF .modules[] | .data_types[] | select(.name | lf::get_dotted_name($pkg) == ["UnserializableReferenced"]) | has("serializable") | not
-- @ QUERY-LF .modules[] | .data_types[] | select(.name | lf::get_dotted_name($pkg) == ["UnserializableImported"]) | has("serializable") | not
-- @ QUERY-LF .modules[] | .data_types[] | select(.name | lf::get_dotted_name($pkg) == ["Serializable"]) | .serializable
-- @ QUERY-LF .modules[] | .data_types[] | select(.name | lf::get_dotted_name($pkg) == ["SerializableReferenced"]) | .serializable
-- @ QUERY-LF .modules[] | .data_types[] | select(.name | lf::get_dotted_name($pkg) == ["SerializableImported"]) | .serializable
-- @ QUERY-LF .modules[] | .data_types[] | select(lf::get_dotted_name($pkg) == ["Unserializable"]) | has("serializable") | not
-- @ QUERY-LF .modules[] | .data_types[] | select(lf::get_dotted_name($pkg) == ["UnserializableReferenced"]) | has("serializable") | not
-- @ QUERY-LF .modules[] | .data_types[] | select(lf::get_dotted_name($pkg) == ["UnserializableImported"]) | has("serializable") | not
-- @ QUERY-LF .modules[] | .data_types[] | select(lf::get_dotted_name($pkg) == ["Serializable"]) | .serializable
-- @ QUERY-LF .modules[] | .data_types[] | select(lf::get_dotted_name($pkg) == ["SerializableReferenced"]) | .serializable
-- @ QUERY-LF .modules[] | .data_types[] | select(lf::get_dotted_name($pkg) == ["SerializableImported"]) | .serializable
daml 1.2
module SerializableAnnotation where

View File

@ -4,7 +4,7 @@
-- Test that the type `GHC.Tuple.Unit`, which is only produced by ghc's
-- desugarer, works correctly (cf. DEL-6656).
-- Test that the generated code actually uses `GHC.Tuple.Unit`.
-- @ QUERY-LF [.modules[] | .values[] | .. | objects | select(has("rec_con")) | .rec_con.tycon.tycon | select((.name | lf::get_dotted_name($pkg)) == ["Unit"] and (.module.module_name | lf::get_dotted_name($pkg)) == ["GHC", "Tuple"])] | any
-- @QUERY-LF [.modules[] | .values[] | .. | objects | select(has("rec_con")) | .rec_con.tycon | select((.tycon | lf::get_dotted_name($pkg)) == ["Unit"] and (.tycon | lf::get_module_name($pkg)) == ["GHC", "Tuple"])] | any
daml 1.2
module SugarUnit where

View File

@ -1,9 +1,17 @@
def get_value_name(pkg): pkg.interned_dotted_names[.name_interned_id] | .segment_ids | map(pkg.interned_strings[.]);
def get_int64(pkg): .int64;
def get_dotted_name(pkg): pkg.interned_dotted_names[.segments_interned_id // 0] | .segment_ids | map(pkg.interned_strings[.]);
def resolve_interned_string(pkg): pkg.interned_strings[.];
def get_field(pkg): pkg.interned_strings[.interned_id];
def resolve_interned_dname(pkg): pkg.interned_dotted_names[.] | .segments_interned_str | map(resolve_interned_string(pkg));
def get_name(pkg): .name;
def get_value_name(pkg): .name_interned_dname | resolve_interned_dname(pkg);
def get_template_name(pkg): .tycon_interned_dname | resolve_interned_dname(pkg);
def get_module_name(pkg): .module.module_name_interned_dname // 0 | resolve_interned_dname(pkg);
def get_dotted_name(pkg): .name_interned_dname | resolve_interned_dname(pkg);
def get_field(pkg): .field_interned_str | resolve_interned_string(pkg);
def get_name(pkg): .name_interned_str | resolve_interned_string(pkg);

View File

@ -1,9 +1,13 @@
def get_value_name(pkg): .name;
def get_int64(pkg): .int64;
def get_dotted_name(pkg): .segments;
def get_value_name(pkg): .name_dname;
def get_field(pkg): .name;
def get_template_name(pkg): .tycon_dname.segments;
def get_name(pkg): .name;
def get_module_name(pkg): .module.module_name_dname.segments;
def get_dotted_name(pkg): .name_dname.segments;
def get_field(pkg): .field_str;
def get_name(pkg): .name_str;

View File

@ -57,23 +57,23 @@ message PackageRef {
Unit self = 1;
// A `Package identifier` for an imported Package.
// A ascii7 lowercase hex-encoded package identifier. This refers
// to the DAML LF Archive Hash.
string package_id = 2;
// *Must be a list of valid packageId string*
string package_id_str = 2; // *Available in versions < 1.dev*
// An index into `interned_package_ids` of the Package containing
// this reference.
int32 interned_id = 3; // *Available in versions >= 1.6*
// *Must be a valid interned package Id string*
int32 package_id_interned_str = 3; // *Available in versions >= 1.6*
}
}
// A `name`, e.g. Util.Either.isLeft
// *Available in version < 1.dev*
message DottedName {
// *Must be a non-empty list of a valid identifiers unless `segments_interned_id` is set.*
// *Must be a non-empty list of a valid identifiers*
repeated string segments = 1;
// *Must be set if and only if `segments` is an empty list.*
int32 segments_interned_id = 2; // *Available in versions >= 1.dev*
}
// A fully qualified module reference
@ -82,8 +82,12 @@ message ModuleRef {
// package where the module is defined.
PackageRef package_ref = 1;
oneof module_name {
// module name
DottedName module_name = 2;
DottedName module_name_dname = 2; // *Available in version < 1.dev*
int32 module_name_interned_dname = 3; // *Available in version >= 1.dev*
}
}
@ -93,9 +97,13 @@ message TypeConName {
// Module where the type is defined.
ModuleRef module = 1;
oneof name {
// type constructor name.
DottedName name = 2;
DottedName name_dname = 2;
// *Must be a valid interned name*
int32 name_interned_dname = 3; // *Available in versions >= 1.dev*
}
}
// A fully qualified reference to a value definition.
@ -104,21 +112,22 @@ message ValName {
// Module where the value is defined
ModuleRef module = 1;
// *Must be a non-empty list of a valid identifiers unless `interned_id` is set.*
repeated string name = 2;
// *Must be a non-empty list of valid identifier*
repeated string name_dname = 2; // *Available in version < 1.dev*
// *Must be set if and only if `segments` is an empty list.*
int32 name_interned_id = 3; // *Available in versions >= 1.dev*
// *Must be a valid interned name*
int32 name_interned_dname = 3; // *Available in versions >= 1.dev*
}
// A field name definition in a record or a variant associated with a type.
message FieldWithType {
// Name of the field .
// *Must be a valid identifier*
oneof field {
string name = 1;
int32 interned_id = 3; // *Available in versions >= 1.dev*
// *Must be a valid identifier*
string field_str = 1; // *Available in version < 1.dev*
// *Must a valid interned identifier*
int32 field_interned_str = 3; // *Available in versions >= 1.dev*
}
// Type associated
@ -129,10 +138,12 @@ message FieldWithType {
message VarWithType {
// Name of the bound expression variable.
// *Must be a valid identifier*
oneof var {
string name = 1;
int32 interned_id = 3; // *Available in versions >= 1.dev*
// *Must be a valid identifier*
string var_str = 1; // *Available in version < 1.dev*
// *Must be a valid interned identifier*
int32 var_interned_str = 3; // *Available in versions >= 1.dev*
}
// Type of the bound variable
@ -141,11 +152,14 @@ message VarWithType {
// Type binder associated with a kind.
message TypeVarWithKind {
// Name of the bound expression variable
// *Must be a valid identifier*
oneof var {
string name = 1;
int32 interned_id = 3; // *Available in versions >= 1.dev*
// *Must be a valid identifier*
string var_str = 1; // *Available in version < 1.dev*
// *Must be a valid interned identifier*
int32 var_interned_str = 3; // *Available in versions >= 1.dev*
}
// Kind of the bound variable
@ -154,11 +168,13 @@ message TypeVarWithKind {
// A field in a record with its value.
message FieldWithExpr {
// Name of the field
// *Must be a valid identifier*
oneof field {
string name = 1;
int32 interned_id = 3; // *Available in versions >= 1.dev*
// *Must be a valid identifier*
string field_str = 1; // *Available in version < 1.dev*
// *Must be a valid interned identifier*
int32 field_interned_str = 3; // *Available in versions >= 1.dev*
}
// Value of the field
@ -267,10 +283,12 @@ message Type {
message Var {
// Name of the variable.
// *Must be a valid identifier*
oneof var {
string var_name = 1;
int32 var_interned_id = 3; // *Available in versions >= 1.dev*
// *Must be a valid identifier*
string var_str = 1; // *Available in version < 1.dev*
// *Must be a valid interned identifier*
int32 var_interned_str = 3; // *Available in versions >= 1.dev*
}
// Types to which the variable is applied
@ -483,57 +501,34 @@ message PrimLit {
// 64-bit integer literal ('LitInt64')
sint64 int64 = 1;
// Legacy Decimal literal ('LitDecimal')
//
// Serialization of number in ``[-1E28, 1E28]``
// with at most 10 digits of decimal precision.
//
// *Must be a string that matched
// `[+-]*[0-9]{0,28}(\.[0-9]{0,10})*`*
//
// It would fit in an int128, but sadly protobuf does not have
// one. so, string it is. note that we can't store the whole and
// decimal part in two numbers either, because 10^28 > 2^63.
string decimal = 2; // *Available in versions < 1.dev*
int32 decimal_interned_id = 10; // *Available in versions >= 1.dev*
// *Must be a valid representation of decimal*
string decimal_str = 2; // *Available in versions < 1.dev*
// Unicode string literal ('LitText')
string text = 4;
int32 text_interned_id = 11; // *Available in versions >= 1.dev*
// *Must be a valid interned decimal*
int32 decimal_interned_str = 10; // *Available in versions >= 1.dev* // *Available in version < 1.dev*
// UTC timestamp literal ('LitTimestamp')
//
// Microseconds since the UNIX epoch. can go backwards.
//
// *Must be in range 001-01-01T00:00:00Z to
// 9999-12-31T23:59:59.999999Z
string text_str = 4; // *Available in version < 1.dev*
// sfixed since the vast majority of values will be greater than
// 2^28, since currently the number of microseconds since the
// epoch is greater than that.
// *Must be a valid interned text*
int32 text_interned_str = 11; // *Available in versions >= 1.dev*
// *Must be a valid timestamp*
sfixed64 timestamp = 5;
// Party literal ('LitParty')
// *Must be a PartyId string*
string party = 7;
int32 party_interned_id = 12; // *Available in versions >= 1.dev*
// *Must be a valid PartyId string*
string party_str = 7; // *Available in version < 1.dev*
// Date literal ('Date')
// Serialization of the number of days since the unix epoch. can go backwards.
//
// *Must be in range '0001-01-01' to '9999-12-31'*
// *Must be a valid interned PartyId string*
int32 party_interned_str = 12; // *Available in versions >= 1.dev*
// *Must be a valid date*
int32 date = 8;
// Numeric literal ('LitNumeric')
//
// Serialization of number with precision 38 and scale between 0 and 37
//
// *Must be a string that matched
// `-?([0-1]\d*|0)\.(\d*)
//
// The number of decimal digits indicate the scale of the number.
string numeric = 9; // *Available in versions >= 1.dev*
int32 numeric_interned_id = 13; // *Available in versions >= 1.dev*
// *Must be a valid numeric */
string numeric_str = 9; // *Available in versions >= 1.dev* // *Available in version < 1.dev*
// *Must be a valid interned numeric */
int32 numeric_interned_str = 13; // *Available in versions >= 1.dev*
}
reserved 3; // This was char.
@ -576,10 +571,12 @@ message Expr {
Type.Con tycon = 1;
// Name of the record field to be projected on.
// *must be a valid Identifier*
oneof field {
string name = 2;
int32 interned_id = 4; // *Available in versions >= 1.dev*
// *Must be a valid identifier*
string field_str = 2; // *Available in version < 1.dev*
// *Must be a valid interned identifier*
int32 field_interned_str = 4; // *Available in versions >= 1.dev*
}
// projected expression
@ -593,10 +590,12 @@ message Expr {
Type.Con tycon = 1;
// Name of the updated field.
// *must be a valid identifier*
oneof field {
string name = 2;
int32 interned_id = 5; // *Available in versions >= 1.dev*
// *Must be a valid identifier*
string field_str = 2; // *Available in version < 1.dev*
// *Must be a valid interned identifier*
int32 field_interned_str = 5; // *Available in versions >= 1.dev*
}
// Actual record being updated
@ -613,10 +612,12 @@ message Expr {
Type.Con tycon = 1;
// name of the variant constructor
// *Must be a valid identifier*
oneof variant_con {
string name = 2;
int32 interned_id = 4; // *Available in versions >= 1.dev*
// *Must be a valid identifier*
string variant_con_str = 2; // *Available in version < 1.dev*
// *Must be a valid interned identifier*
int32 variant_con_interned_str = 4; // *Available in versions >= 1.dev*
}
// Argument of the variant.
@ -631,10 +632,12 @@ message Expr {
TypeConName tycon = 1;
// name of the enum constructor
// *Must be a valid identifier*
oneof enum_con {
string name = 2;
int32 interned_id = 3; // *Available in versions >= 1.dev*
// *Must be a valid identifier*
string enum_con_str = 2; // *Available in version < 1.dev*
// *Must be a valid interned identifier*
int32 enum_con_interned_str = 3; // *Available in versions >= 1.dev*
}
}
@ -648,10 +651,12 @@ message Expr {
message TupleProj {
// Name of the field to be projected on.
// *Must be a valid Identifier*
oneof field {
string name = 1;
int32 interned_id = 3; // *Available in versions >= 1.dev*
// *Must be a valid Identifier*
string field_str = 1; // *Available in version < 1.dev*
// *Must be a valid interned identifier*
int32 field_interned_str = 3; // *Available in versions >= 1.dev*
}
// tuple to be projected.
@ -662,10 +667,12 @@ message Expr {
message TupleUpd {
// Name of the updated field.
// *must be a valid identifier*.
oneof field {
string name = 1;
int32 interned_id = 4; // *Available in versions >= 1.dev*
// *Must be a valid identifier*.
string field_str = 1; // *Available in version < 1.dev*
// *Must be a valid interned identifier*
int32 field_interned_str = 4; // *Available in versions >= 1.dev*
}
// Actual tuple being updated.
@ -675,7 +682,6 @@ message Expr {
Expr update = 3;
}
// Application ('ExpApp')
message App {
@ -784,10 +790,11 @@ message Expr {
oneof Sum {
// Expression variable ('ExpVar')
// *must be a valid identifier*
string var = 1;
int32 var_interned_id = 29; // *Available in versions >= 1.dev*
// *Must be a valid identifier*
string var_str = 1; // *Available in version < 1.dev*
// *Must be a valid interned identifier*
int32 var_interned_str = 29; // *Available in versions >= 1.dev*
// Defined value ('ExpVal')
ValName val = 2;
@ -890,17 +897,21 @@ message CaseAlt {
TypeConName con = 1;
// name of the variant constructor
// *Must be a valid identifier*
oneof variant {
string variant_name = 2;
int32 variant_interned_id = 4; // *Available in versions >= 1.dev*
// *Must be a valid identifier*
string variant_str = 2; // *Available in version < 1.dev*
// *Must be a valid interned identifier*
int32 variant_interned_str = 4; // *Available in versions >= 1.dev*
}
// name of the variant binder
// *Must be a valid identifier*
oneof binder {
string binder_name = 3;
int32 binder_interned_id = 5; // *Available in versions >= 1.dev*
// *Must be a valid identifier*
string binder_str = 3; // *Available in version < 1.dev*
// *Must be a valid interned identifier*
int32 binder_interned_str = 5; // *Available in versions >= 1.dev*
}
}
@ -914,34 +925,46 @@ message CaseAlt {
// name of the variant constructor
// *Must be a valid identifier*
oneof constructor {
string name = 2;
int32 interned_id = 3; // *Available in versions >= 1.dev*
// *Must be a valid identifier*
string constructor_str = 2; // *Available in version < 1.dev*
// *Must be a valid interned identifier*
int32 constructor_interned_str = 3; // *Available in versions >= 1.dev*
}
}
// Non empty list pattern
message Cons {
// name of the binder for the head
// *Must be a valid identifier*
oneof var_head {
string var_head_name = 1;
int32 var_head_interned_id = 3; // *Available in versions >= 1.dev*
// *Must be a valid identifier*
string var_head_str = 1; // *Available in version < 1.dev*
// *Must be a valid interned identifier*
int32 var_head_interned_str = 3; // *Available in versions >= 1.dev*
}
// name of the binder for the tail
// *Must be a valid identifier*
oneof var_tail {
string var_tail_name = 2;
int32 var_tail_interned_id = 4; // *Available in versions >= 1.dev*
// *Must be a valid identifier*
string var_tail_str = 2; // *Available in version < 1.dev*
// *Must be a valid interned identifier*
int32 var_tail_interned_str = 4; // *Available in versions >= 1.dev*
}
}
// Non empty option patterm
// *Available in versions >= 1.1*
message OptionalSome {
oneof var_body {
string name = 1;
int32 interned_id = 2; // *Available in versions >= 1.dev*
// *Must be a valid identifier*
string var_body_str = 1; // *Available in version < 1.dev*
// *Must be a valid interned identifier*
int32 var_body_interned_str = 2; // *Available in versions >= 1.dev*
}
}
@ -993,11 +1016,16 @@ message Update {
message Exercise {
// Template type
TypeConName template = 1;
// name of the exercised template choice
oneof choice {
string name = 2;
int32 interned_id = 6; // *Available in versions >= 1.dev*
// *Must be a valid identifier*
string choice_str = 2; // *Available in version < 1.dev*
// *Must be a valid interned identifier*
int32 choice_interned_str = 6; // *Available in versions >= 1.dev*
}
// contract id
Expr cid = 3;
// actors
@ -1089,8 +1117,10 @@ message TemplateChoice {
// *Must be a valid identifier*
oneof name {
string choice_name = 1;
int32 choice_interned_id = 9; // *Available in versions >= 1.dev*
string name_str = 1; // *Available in version < 1.dev*
// *Must be a valid interned identifier*
int32 name_interned_str = 9; // *Available in versions >= 1.dev*
}
// Choice type
@ -1114,8 +1144,11 @@ message TemplateChoice {
// Name to bind the ContractId of the contract this choice is exercised on to.
oneof self_binder {
string self_binder_name = 7;
int32 self_binder_interned_id = 10; // *Available in versions >= 1.dev*
// *Must be a valid identifier*
string self_binder_str = 7; // *Available in version < 1.dev*
// *Must be a valid interned identifier*
int32 self_binder_interned_str = 10; // *Available in versions >= 1.dev*
}
Location location = 8;
@ -1125,9 +1158,13 @@ message TemplateChoice {
message KeyExpr {
message Projection {
Type.Con tycon = 1; // Always fully applied
oneof field {
string name = 2;
int32 interned_id = 3; // *Available in versions >= 1.dev*
// *Must be a valid identifier*
string field_str = 2; // *Available in version < 1.dev*
// *Must be a valid interned identifier*
int32 field_interned_str = 3; // *Available in versions >= 1.dev*
}
}
@ -1138,8 +1175,11 @@ message KeyExpr {
message RecordField {
oneof field {
string name = 1;
int32 interned_id = 3; // *Available in versions >= 1.dev*
// *Must be a valid identifier*
string field_str = 1; // *Available in version < 1.dev*
// *Must be a valid identifier*
int32 field_interned_str = 3; // *Available in versions >= 1.dev*
}
KeyExpr expr = 2;
}
@ -1172,12 +1212,20 @@ message DefTemplate {
// The type constructor for the template, acting as both
// the name of the template and the type of the template argument.
DottedName tycon = 1;
oneof tycon {
DottedName tycon_dname = 1;
// *Must be a valid interned name*
int32 tycon_interned_dname = 12; // *Available in versions >= 1.dev*
}
// Name to which the template argument is bound.
oneof param {
string param_name = 2;
int32 param_interned_id = 11; // *Available in versions >= 1.dev*
// *Must be a valid identifier*
string param_str = 2; // *Available in version < 1.dev*
// *Must be a valid interned identifier*
int32 param_interned_str = 11; // *Available in versions >= 1.dev*
}
// NOTE(MH): The new runtime authorization check for DAML 1.0 does not rely
@ -1221,12 +1269,21 @@ message DefDataType {
// *Available in versions >= 1.6*
message EnumConstructors {
repeated string constructors = 1;
repeated int32 constructors_interned_ids = 2; // *Available in versions >= 1.dev*
// *Must be a list of valid identifiers*
repeated string constructors_str = 1; // *Available in version < 1.dev*
// *Must be a list of valid interned identifiers*
repeated int32 constructors_interned_str = 2; // *Available in versions >= 1.dev*
}
// name of the defined data type
DottedName name = 1;
oneof name {
DottedName name_dname = 1;
// *Must be a valid interned name*
int32 name_interned_dname = 8; // *Available in versions >= 1.dev*
}
// type parameters
// *Must be empty if enum field is set*
@ -1257,11 +1314,11 @@ message DefValue {
// want to be binary-compatible with it.
message NameWithType {
// Name of the value
// *each element of name must be a valid identifier*
// `name` can be empty if and only if `name_interned_id` is set.
repeated string name = 1;
int32 name_interned_id = 6; // *Available in versions >= 1.dev*
// *Must a non-empty list a valid identifier*
repeated string name_dname = 1; // *Available in version < 1.dev*
// *Must be a valid interned name*
int32 name_interned_dname = 3; // *Available in versions >= 1.dev*
// Type of the value
Type type = 2;
@ -1291,7 +1348,11 @@ message FeatureFlags {
}
message Module {
DottedName name = 1;
oneof name {
DottedName name_dname = 1;
int32 name_interned_dname = 8; // *Available in versions >= 1.dev*
}
// repeated Definition definitions = 2; // Removed in favour of data_types, values and templates.
reserved 2;
// repeated string scenario_tests = 3; // Removed in favour of DefValue.is_test.
@ -1303,7 +1364,7 @@ message Module {
}
message InternedDottedName {
repeated int32 segment_ids = 1; // *Available in versions >= 1.dev*
repeated int32 segments_interned_str = 1; // *Available in versions >= 1.dev*
}
message Package {

View File

@ -4,6 +4,8 @@
package com.digitalasset.daml.lf
package archive
import java.util
import com.digitalasset.daml.lf.archive.Decode.ParseError
import com.digitalasset.daml.lf.data.Ref._
import com.digitalasset.daml.lf.data.{Decimal, ImmArray, Numeric, Time}
@ -34,7 +36,7 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
if (internedStrings.nonEmpty)
assertSince(LV.Features.internedPackageId, "interned strings table")
val internedDottedNames: ImmArraySeq[DottedName] =
val internedDottedNames =
decodeInternedDottedNames(lfPackage.getInternedDottedNamesList.asScala, internedStrings)
Package(
@ -82,6 +84,7 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
private[this] def decodeInternedDottedNames(
internedList: Seq[PLF.InternedDottedName],
internedStrings: ImmArraySeq[String]): ImmArraySeq[DottedName] = {
if (internedList.nonEmpty)
assertSince(LV.Features.internedDottedNames, "interned dotted names table")
@ -92,13 +95,13 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
.map(
idn =>
decodeSegments(
idn.getSegmentIdsList.asScala
idn.getSegmentsInternedStrList.asScala
.map(id => internedStrings.lift(id).getOrElse(throw outOfRange(id)))(breakOut))
)(breakOut)
}
private[this] def decodeSegments(segments: ImmArray[String]): DottedName =
DottedName.fromSegments(segments.toSeq) match {
private[this] def decodeSegments(segments: Seq[String]): DottedName =
DottedName.fromSegments(segments) match {
case Left(err) => throw new ParseError(err)
case Right(x) => x
}
@ -111,8 +114,15 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
onlySerializableDataDefs: Boolean
) {
val moduleName: ModuleName =
decodeDottedName(lfModule.getName)
private val moduleName: ModuleName =
handleDottedName(
lfModule.getNameCase,
PLF.Module.NameCase.NAME_DNAME,
lfModule.getNameDname,
PLF.Module.NameCase.NAME_INTERNED_DNAME,
lfModule.getNameInternedDname,
"Module.name.name"
)
private var currentDefinitionRef: Option[DefinitionRef] = None
@ -124,7 +134,14 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
lfModule.getDataTypesList.asScala
.filter(!onlySerializableDataDefs || _.getSerializable)
.foreach { defn =>
val defName = decodeDottedName(defn.getName)
val defName = handleDottedName(
defn.getNameCase,
PLF.DefDataType.NameCase.NAME_DNAME,
defn.getNameDname,
PLF.DefDataType.NameCase.NAME_INTERNED_DNAME,
defn.getNameInternedDname,
"DefDataType.name.name"
)
currentDefinitionRef = Some(DefinitionRef(packageId, QualifiedName(moduleName, defName)))
val d = decodeDefDataType(defn)
defs += (defName -> d)
@ -134,13 +151,12 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
// collect values
lfModule.getValuesList.asScala.foreach { defn =>
val nameWithType = defn.getNameWithType
val defName =
if (nameWithType.getNameCount == 0) {
assertSince(LV.Features.internedDottedNames, "interned dotted names table")
getInternedDottedName(nameWithType.getNameInternedId)
} else {
decodeSegments(ImmArray(nameWithType.getNameList.asScala))
}
val defName = handleDottedName(
nameWithType.getNameDnameList.asScala,
nameWithType.getNameInternedDname,
"NameWithType.name"
)
currentDefinitionRef = Some(DefinitionRef(packageId, QualifiedName(moduleName, defName)))
val d = decodeDefValue(defn)
defs += (defName -> d)
@ -149,7 +165,14 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
// collect templates
lfModule.getTemplatesList.asScala.foreach { defn =>
val defName = decodeDottedName(defn.getTycon)
val defName = handleDottedName(
defn.getTyconCase,
PLF.DefTemplate.TyconCase.TYCON_DNAME,
defn.getTyconDname,
PLF.DefTemplate.TyconCase.TYCON_INTERNED_DNAME,
defn.getTyconInternedDname,
"DefTemplate.tycon.tycon"
)
currentDefinitionRef = Some(DefinitionRef(packageId, QualifiedName(moduleName, defName)))
templates += ((defName, decodeTemplate(defn)))
}
@ -158,52 +181,54 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
}
// -----------------------------------------------------------------------
private[this] def getInternedString(id: Int) =
private[this] def getInternedStr(id: Int) =
internedStrings.lift(id).getOrElse {
throw ParseError(s"invalid internedString table index $id")
}
private[this] def getInternedPackageId(id: Int): PackageId = {
assertSince(LV.Features.internedPackageId, "interned PackageId")
toPackageId(getInternedString(id))
eitherToParseError(PackageId.fromString(getInternedStr(id)))
}
private[this] def getInternedName(id: Int): Name = {
assertSince(LV.Features.internedStrings, "interned Name")
toName(getInternedString(id))
private[this] def getInternedName(id: Int, description: => String): Name = {
assertSince(LV.Features.internedStrings, description)
eitherToParseError(Name.fromString(getInternedStr(id)))
}
private[this] def getInternedText(id: Int): PLText = {
assertSince(LV.Features.internedStrings, "interned Text")
PLText(getInternedString(id))
}
private[this] def getInternedNumeric(id: Int): PrimLit = {
assertSince(LV.Features.internedStrings, "interned Numeric")
toNumericLiteral(getInternedString(id))
}
private[this] def getInternedDecimal(id: Int): PLNumeric = {
assertSince(LV.Features.internedStrings, "interned Decimal")
toDecimalLiteral(getInternedString(id))
}
private[this] def getInternedParty(id: Int): PLParty = {
assertSince(LV.Features.internedStrings, "interned Party")
toPartyLiteral(getInternedString(id))
}
private[this] def getInternedDottedName(id: Int): DottedName =
private[this] def getInternedDottedName(id: Int) =
internedDottedNames.lift(id).getOrElse {
assertSince(LV.Features.internedDottedNames, "interned DottedNames")
throw ParseError(s"invalid dotted name table index $id")
}
private[this] def decodeDottedName(name: PLF.DottedName): DottedName =
if (name.getSegmentsCount == 0) {
getInternedDottedName(name.getSegmentsInternedId)
private[this] def handleDottedName(
segments: Seq[String],
interned_id: Int,
description: => String,
): DottedName =
if (versionIsOlderThan(LV.Features.internedDottedNames)) {
assertUndefined(interned_id, s"${description}_interned_id")
decodeSegments(segments)
} else {
decodeSegments(ImmArray(name.getSegmentsList.asScala))
assertUndefined(segments, description)
getInternedDottedName(interned_id)
}
private[this] def handleDottedName[Case](
actualCase: Case,
dNameCase: Case,
dName: => PLF.DottedName,
internedDNameCase: Case,
internedDName: => Int,
description: => String): DottedName =
if (versionIsOlderThan(LV.Features.internedDottedNames)) {
if (actualCase != dNameCase)
throw ParseError(s"${description}_dname is required by DAML-LF 1.$minor")
decodeSegments(dName.getSegmentsList.asScala)
} else {
if (actualCase != internedDNameCase)
throw ParseError(s"${description}_interned_dname is required by DAML-LF 1.$minor")
getInternedDottedName(internedDName)
}
private[this] def decodeFeatureFlags(flags: PLF.FeatureFlags): FeatureFlags = {
@ -218,10 +243,10 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
}
private[this] def decodeDefDataType(lfDataType: PLF.DefDataType): DDataType = {
val params = ImmArray(lfDataType.getParamsList.asScala).map(decodeTypeVarWithKind)
val params = lfDataType.getParamsList.asScala
DDataType(
lfDataType.getSerializable,
params,
ImmArray(params).map(decodeTypeVarWithKind),
lfDataType.getDataConsCase match {
case PLF.DefDataType.DataConsCase.RECORD =>
DataRecord(decodeFields(ImmArray(lfDataType.getRecord.getFieldsList.asScala)), None)
@ -229,7 +254,7 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
DataVariant(decodeFields(ImmArray(lfDataType.getVariant.getFieldsList.asScala)))
case PLF.DefDataType.DataConsCase.ENUM =>
assertSince(LV.Features.enum, "DefDataType.DataCons.Enum")
assertEmpty(params.toSeq, "params")
assertEmpty(params, "params")
DataEnum(decodeEnumCon(lfDataType.getEnum))
case PLF.DefDataType.DataConsCase.DATACONS_NOT_SET =>
throw ParseError("DefDataType.DATACONS_NOT_SET")
@ -238,15 +263,46 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
)
}
def handleInternedName[Case](
actualCase: Case,
stringCase: Case,
string: => String,
internedStringCase: Case,
internedString: => Int,
description: => String) = {
val str = if (versionIsOlderThan(LV.Features.internedStrings)) {
if (actualCase != stringCase)
throw ParseError(s"${description}_str is required by DAML-LF 1.$minor")
string
} else {
if (actualCase != internedStringCase)
throw ParseError(s"${description}_interned_str is required by DAML-LF 1.$minor")
internedStrings(internedString)
}
toName(str)
}
def handleInternedNames(
strings: util.List[String],
stringIds: util.List[Integer],
description: => String): Seq[Name] =
if (versionIsOlderThan(LV.Features.internedStrings)) {
assertEmpty(stringIds, description + "_interned_string")
strings.asScala.map(toName)
} else {
assertEmpty(strings, description)
stringIds.asScala.map(id => toName(internedStrings(id)))
}
private[this] def decodeFieldWithType(lfFieldWithType: PLF.FieldWithType): (Name, Type) =
(lfFieldWithType.getFieldCase match {
case PLF.FieldWithType.FieldCase.NAME =>
toName(lfFieldWithType.getName)
case PLF.FieldWithType.FieldCase.INTERNED_ID =>
getInternedName(lfFieldWithType.getInternedId)
case PLF.FieldWithType.FieldCase.FIELD_NOT_SET =>
throw ParseError("FieldWithType.FIELD_NOT_SET")
}) -> decodeType(lfFieldWithType.getType)
handleInternedName(
lfFieldWithType.getFieldCase,
PLF.FieldWithType.FieldCase.FIELD_STR,
lfFieldWithType.getFieldStr,
PLF.FieldWithType.FieldCase.FIELD_INTERNED_STR,
lfFieldWithType.getFieldInternedStr,
"FieldWithType.field.field",
) -> decodeType(lfFieldWithType.getType)
private[this] def decodeFields(lfFields: ImmArray[PLF.FieldWithType]): ImmArray[(Name, Type)] =
lfFields.map(decodeFieldWithType)
@ -255,33 +311,34 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
lfFieldWithExpr: PLF.FieldWithExpr,
definition: String
): (Name, Expr) =
(lfFieldWithExpr.getFieldCase match {
case PLF.FieldWithExpr.FieldCase.NAME => toName(lfFieldWithExpr.getName)
case PLF.FieldWithExpr.FieldCase.INTERNED_ID =>
getInternedName(lfFieldWithExpr.getInternedId)
case PLF.FieldWithExpr.FieldCase.FIELD_NOT_SET =>
throw ParseError("FieldWithExpr.FIELD_NOT_SET")
}) -> decodeExpr(lfFieldWithExpr.getExpr, definition)
handleInternedName(
lfFieldWithExpr.getFieldCase,
PLF.FieldWithExpr.FieldCase.FIELD_STR,
lfFieldWithExpr.getFieldStr,
PLF.FieldWithExpr.FieldCase.FIELD_INTERNED_STR,
lfFieldWithExpr.getFieldInternedStr,
"FieldWithType.name",
) -> decodeExpr(lfFieldWithExpr.getExpr, definition)
private[this] def decodeEnumCon(
enumCon: PLF.DefDataType.EnumConstructors): ImmArray[EnumConName] =
if (enumCon.getConstructorsCount == 0)
enumCon.getConstructorsInternedIdsList.asScala
.map(id => getInternedName(id))(breakOut)
else
enumCon.getConstructorsList.asScala.map(toName)(breakOut)
ImmArray(
handleInternedNames(
enumCon.getConstructorsStrList,
enumCon.getConstructorsInternedStrList,
"EnumConstructors.constructors"
))
private[this] def decodeDefValue(lfValue: PLF.DefValue): DValue = {
val nameWithType = lfValue.getNameWithType
val definition =
if (nameWithType.getNameCount == 0)
getInternedDottedName(nameWithType.getNameInternedId).segments.toSeq.mkString(".")
else
nameWithType.getNameList.asScala.mkString(".")
val name = handleDottedName(
lfValue.getNameWithType.getNameDnameList.asScala,
lfValue.getNameWithType.getNameInternedDname,
"DefValue.NameWithType.name"
)
DValue(
typ = decodeType(lfValue.getNameWithType.getType),
noPartyLiterals = lfValue.getNoPartyLiterals,
body = decodeExpr(lfValue.getExpr, definition),
body = decodeExpr(lfValue.getExpr, name.toString),
isTest = lfValue.getIsTest
)
}
@ -335,16 +392,16 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
val recCon = expr.getRecord
ERecCon(
tycon = decodeTypeConApp(recCon.getTycon),
fields = ImmArray(recCon.getFieldsList.asScala).map(field =>
(field.getFieldCase match {
case PLF.KeyExpr.RecordField.FieldCase.NAME =>
toName(field.getName)
case PLF.KeyExpr.RecordField.FieldCase.INTERNED_ID =>
getInternedName(field.getInternedId)
case PLF.KeyExpr.RecordField.FieldCase.FIELD_NOT_SET =>
throw ParseError("KeyExpr.Record.Field.FIELD_NOT_SET")
}) -> decodeKeyExpr(field.getExpr, tplVar))
fields = ImmArray(recCon.getFieldsList.asScala).map(
field =>
handleInternedName(
field.getFieldCase,
PLF.KeyExpr.RecordField.FieldCase.FIELD_STR,
field.getFieldStr,
PLF.KeyExpr.RecordField.FieldCase.FIELD_INTERNED_STR,
field.getFieldInternedStr,
"KeyExpr.field"
) -> decodeKeyExpr(field.getExpr, tplVar))
)
case PLF.KeyExpr.SumCase.PROJECTIONS =>
@ -353,13 +410,14 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
(acc, lfProj) =>
ERecProj(
decodeTypeConApp(lfProj.getTycon),
lfProj.getFieldCase match {
case PLF.KeyExpr.Projection.FieldCase.NAME => toName(lfProj.getName)
case PLF.KeyExpr.Projection.FieldCase.INTERNED_ID =>
getInternedName(lfProj.getInternedId)
case PLF.KeyExpr.Projection.FieldCase.FIELD_NOT_SET =>
throw ParseError("KeyExpr.Projection.Field.FIELD_NOT_SET")
},
handleInternedName(
lfProj.getFieldCase,
PLF.KeyExpr.Projection.FieldCase.FIELD_STR,
lfProj.getFieldStr,
PLF.KeyExpr.Projection.FieldCase.FIELD_INTERNED_STR,
lfProj.getFieldInternedStr,
"KeyExpr.Projection.field"
),
acc
))
@ -369,15 +427,22 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
}
private[this] def decodeTemplate(lfTempl: PLF.DefTemplate): Template = {
val tpl = decodeDottedName(lfTempl.getTycon)
val paramName = lfTempl.getParamCase match {
case PLF.DefTemplate.ParamCase.PARAM_NAME =>
toName(lfTempl.getParamName)
case PLF.DefTemplate.ParamCase.PARAM_INTERNED_ID =>
getInternedName(lfTempl.getParamInternedId)
case PLF.DefTemplate.ParamCase.PARAM_NOT_SET =>
throw ParseError("DefTemplate.PARAM_NOT_SET")
}
val tpl = handleDottedName(
lfTempl.getTyconCase,
PLF.DefTemplate.TyconCase.TYCON_DNAME,
lfTempl.getTyconDname,
PLF.DefTemplate.TyconCase.TYCON_INTERNED_DNAME,
lfTempl.getTyconInternedDname,
"DefTemplate.tycon.tycon"
)
val paramName = handleInternedName(
lfTempl.getParamCase,
PLF.DefTemplate.ParamCase.PARAM_STR,
lfTempl.getParamStr,
PLF.DefTemplate.ParamCase.PARAM_INTERNED_STR,
lfTempl.getParamInternedStr,
"DefTemplate.param.param"
)
Template(
param = paramName,
precond = if (lfTempl.hasPrecond) decodeExpr(lfTempl.getPrecond, s"$tpl:ensure") else ETrue,
@ -397,24 +462,22 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
tpl: DottedName,
lfChoice: PLF.TemplateChoice): TemplateChoice = {
val (v, t) = decodeBinder(lfChoice.getArgBinder)
val chName: Name = lfChoice.getNameCase match {
case PLF.TemplateChoice.NameCase.CHOICE_NAME =>
toName(lfChoice.getChoiceName)
case PLF.TemplateChoice.NameCase.CHOICE_INTERNED_ID =>
getInternedName(lfChoice.getChoiceInternedId)
case PLF.TemplateChoice.NameCase.NAME_NOT_SET =>
throw ParseError("TemplateChoice.NAME_NOT_SET")
}
val selfBinder: Name = lfChoice.getSelfBinderCase match {
case PLF.TemplateChoice.SelfBinderCase.SELF_BINDER_NAME =>
toName(lfChoice.getSelfBinderName)
case PLF.TemplateChoice.SelfBinderCase.SELF_BINDER_INTERNED_ID =>
getInternedName(lfChoice.getSelfBinderInternedId)
case PLF.TemplateChoice.SelfBinderCase.SELFBINDER_NOT_SET =>
throw ParseError("TemplateChoice.SELFBINDER_NOT_SET")
}
val chName = handleInternedName(
lfChoice.getNameCase,
PLF.TemplateChoice.NameCase.NAME_STR,
lfChoice.getNameStr,
PLF.TemplateChoice.NameCase.NAME_INTERNED_STR,
lfChoice.getNameInternedStr,
"TemplateChoice.name.name"
)
val selfBinder = handleInternedName(
lfChoice.getSelfBinderCase,
PLF.TemplateChoice.SelfBinderCase.SELF_BINDER_STR,
lfChoice.getSelfBinderStr,
PLF.TemplateChoice.SelfBinderCase.SELF_BINDER_INTERNED_STR,
lfChoice.getSelfBinderInternedStr,
"TemplateChoice.self_binder.self_binder"
)
TemplateChoice(
name = chName,
consuming = lfChoice.getConsuming,
@ -445,14 +508,14 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
lfType.getSumCase match {
case PLF.Type.SumCase.VAR =>
val tvar = lfType.getVar
val varName = tvar.getVarCase match {
case PLF.Type.Var.VarCase.VAR_NAME =>
toName(tvar.getVarName)
case PLF.Type.Var.VarCase.VAR_INTERNED_ID =>
getInternedName(tvar.getVarInternedId)
case PLF.Type.Var.VarCase.VAR_NOT_SET =>
throw ParseError("Type.VAR_NOT_SET")
}
val varName = handleInternedName(
tvar.getVarCase,
PLF.Type.Var.VarCase.VAR_STR,
tvar.getVarStr,
PLF.Type.Var.VarCase.VAR_INTERNED_STR,
tvar.getVarInternedStr,
"Type.var.var"
)
tvar.getArgsList.asScala
.foldLeft[Type](TVar(varName))((typ, arg) => TApp(typ, decodeType(arg)))
case PLF.Type.SumCase.NAT =>
@ -504,16 +567,23 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
}
private[this] def decodeModuleRef(lfRef: PLF.ModuleRef): (PackageId, ModuleName) = {
val modName = decodeDottedName(lfRef.getModuleName)
val modName = handleDottedName(
lfRef.getModuleNameCase,
PLF.ModuleRef.ModuleNameCase.MODULE_NAME_DNAME,
lfRef.getModuleNameDname,
PLF.ModuleRef.ModuleNameCase.MODULE_NAME_INTERNED_DNAME,
lfRef.getModuleNameInternedDname,
"ModuleRef.module_name.module_name"
)
import PLF.PackageRef.{SumCase => SC}
val pkgId = lfRef.getPackageRef.getSumCase match {
case SC.SELF =>
this.packageId
case SC.PACKAGE_ID =>
toPackageId(lfRef.getPackageRef.getPackageId)
case SC.INTERNED_ID =>
getInternedPackageId(lfRef.getPackageRef.getInternedId)
case SC.PACKAGE_ID_STR =>
toPackageId(lfRef.getPackageRef.getPackageIdStr, "PackageRef.packageId")
case SC.PACKAGE_ID_INTERNED_STR =>
getInternedPackageId(lfRef.getPackageRef.getPackageIdInternedStr)
case SC.SUM_NOT_SET =>
throw ParseError("PackageRef.SUM_NOT_SET")
}
@ -522,18 +592,21 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
private[this] def decodeValName(lfVal: PLF.ValName): ValueRef = {
val (packageId, module) = decodeModuleRef(lfVal.getModule)
val name: DottedName =
if (lfVal.getNameCount == 0) {
getInternedDottedName(lfVal.getNameInternedId)
} else {
decodeSegments(ImmArray(lfVal.getNameList.asScala))
}
val name =
handleDottedName(lfVal.getNameDnameList.asScala, lfVal.getNameInternedDname, "ValName.name")
ValueRef(packageId, QualifiedName(module, name))
}
private[this] def decodeTypeConName(lfTyConName: PLF.TypeConName): TypeConName = {
val (packageId, module) = decodeModuleRef(lfTyConName.getModule)
val name = decodeDottedName(lfTyConName.getName)
val name = handleDottedName(
lfTyConName.getNameCase,
PLF.TypeConName.NameCase.NAME_DNAME,
lfTyConName.getNameDname,
PLF.TypeConName.NameCase.NAME_INTERNED_DNAME,
lfTyConName.getNameInternedDname,
"TypeConName.name.name"
)
Identifier(packageId, QualifiedName(module, name))
}
@ -551,11 +624,12 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
private[this] def decodeExprBody(lfExpr: PLF.Expr, definition: String): Expr =
lfExpr.getSumCase match {
case PLF.Expr.SumCase.VAR =>
EVar(toName(lfExpr.getVar))
case PLF.Expr.SumCase.VAR_STR =>
assertUntil(LV.Features.internedStrings, "Expr.var_str")
EVar(toName(lfExpr.getVarStr))
case PLF.Expr.SumCase.VAR_INTERNED_ID =>
EVar(getInternedName(lfExpr.getVarInternedId))
case PLF.Expr.SumCase.VAR_INTERNED_STR =>
EVar(getInternedName(lfExpr.getVarInternedStr, "Expr.var_interned_id"))
case PLF.Expr.SumCase.VAL =>
EVal(decodeValName(lfExpr.getVal))
@ -592,14 +666,14 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
val recProj = lfExpr.getRecProj
ERecProj(
tycon = decodeTypeConApp(recProj.getTycon),
field = recProj.getFieldCase match {
case PLF.Expr.RecProj.FieldCase.NAME =>
toName(recProj.getName)
case PLF.Expr.RecProj.FieldCase.INTERNED_ID =>
getInternedName(recProj.getInternedId)
case PLF.Expr.RecProj.FieldCase.FIELD_NOT_SET =>
throw ParseError("Expr.RecProj.FIELD_NOT_SET")
},
field = handleInternedName(
recProj.getFieldCase,
PLF.Expr.RecProj.FieldCase.FIELD_STR,
recProj.getFieldStr,
PLF.Expr.RecProj.FieldCase.FIELD_INTERNED_STR,
recProj.getFieldInternedStr,
"Expr.RecProj.field.field"
),
record = decodeExpr(recProj.getRecord, definition)
)
@ -607,14 +681,14 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
val recUpd = lfExpr.getRecUpd
ERecUpd(
tycon = decodeTypeConApp(recUpd.getTycon),
field = (recUpd.getFieldCase match {
case PLF.Expr.RecUpd.FieldCase.NAME =>
toName(recUpd.getName)
case PLF.Expr.RecUpd.FieldCase.INTERNED_ID =>
getInternedName(recUpd.getInternedId)
case PLF.Expr.RecUpd.FieldCase.FIELD_NOT_SET =>
throw ParseError("Expr.RecUpd.FIELD_NOT_SET")
}),
field = handleInternedName(
recUpd.getFieldCase,
PLF.Expr.RecUpd.FieldCase.FIELD_STR,
recUpd.getFieldStr,
PLF.Expr.RecUpd.FieldCase.FIELD_INTERNED_STR,
recUpd.getFieldInternedStr,
"Expr.RecUpd.field.field"
),
record = decodeExpr(recUpd.getRecord, definition),
update = decodeExpr(recUpd.getUpdate, definition)
)
@ -623,14 +697,14 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
val varCon = lfExpr.getVariantCon
EVariantCon(
decodeTypeConApp(varCon.getTycon),
varCon.getVariantConCase match {
case PLF.Expr.VariantCon.VariantConCase.NAME =>
toName(varCon.getName)
case PLF.Expr.VariantCon.VariantConCase.INTERNED_ID =>
getInternedName(varCon.getInternedId)
case PLF.Expr.VariantCon.VariantConCase.VARIANTCON_NOT_SET =>
throw ParseError("Expr.VariantCon.VARIANTCON_NOT_SET")
},
handleInternedName(
varCon.getVariantConCase,
PLF.Expr.VariantCon.VariantConCase.VARIANT_CON_STR,
varCon.getVariantConStr,
PLF.Expr.VariantCon.VariantConCase.VARIANT_CON_INTERNED_STR,
varCon.getVariantConInternedStr,
"Expr.VariantCon.variant_con.variant_con"
),
decodeExpr(varCon.getVariantArg, definition)
)
@ -639,14 +713,14 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
val enumCon = lfExpr.getEnumCon
EEnumCon(
decodeTypeConName(enumCon.getTycon),
enumCon.getEnumConCase match {
case PLF.Expr.EnumCon.EnumConCase.NAME =>
toName(enumCon.getName)
case PLF.Expr.EnumCon.EnumConCase.INTERNED_ID =>
getInternedName(enumCon.getInternedId)
case PLF.Expr.EnumCon.EnumConCase.ENUMCON_NOT_SET =>
throw ParseError("Expr.EnumCon.ENUMCON_NOT_SET")
}
handleInternedName(
enumCon.getEnumConCase,
PLF.Expr.EnumCon.EnumConCase.ENUM_CON_STR,
enumCon.getEnumConStr,
PLF.Expr.EnumCon.EnumConCase.ENUM_CON_INTERNED_STR,
enumCon.getEnumConInternedStr,
"Expr.EnumCon.enum_con.enum_con"
)
)
case PLF.Expr.SumCase.TUPLE_CON =>
@ -658,28 +732,28 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
case PLF.Expr.SumCase.TUPLE_PROJ =>
val tupleProj = lfExpr.getTupleProj
ETupleProj(
tupleProj.getFieldCase match {
case PLF.Expr.TupleProj.FieldCase.NAME =>
toName(tupleProj.getName)
case PLF.Expr.TupleProj.FieldCase.INTERNED_ID =>
getInternedName(tupleProj.getInternedId)
case PLF.Expr.TupleProj.FieldCase.FIELD_NOT_SET =>
throw ParseError("Expr.TupleProj.FIELD_NOT_SET")
},
decodeExpr(tupleProj.getTuple, definition)
field = handleInternedName(
tupleProj.getFieldCase,
PLF.Expr.TupleProj.FieldCase.FIELD_STR,
tupleProj.getFieldStr,
PLF.Expr.TupleProj.FieldCase.FIELD_INTERNED_STR,
tupleProj.getFieldInternedStr,
"Expr.TupleProj.field.field"
),
tuple = decodeExpr(tupleProj.getTuple, definition)
)
case PLF.Expr.SumCase.TUPLE_UPD =>
val tupleUpd = lfExpr.getTupleUpd
ETupleUpd(
field = tupleUpd.getFieldCase match {
case PLF.Expr.TupleUpd.FieldCase.NAME =>
toName(tupleUpd.getName)
case PLF.Expr.TupleUpd.FieldCase.INTERNED_ID =>
getInternedName(tupleUpd.getInternedId)
case PLF.Expr.TupleUpd.FieldCase.FIELD_NOT_SET =>
throw ParseError("Expr.TupleUpd.FIELD_NOT_SET")
},
field = handleInternedName(
tupleUpd.getFieldCase,
PLF.Expr.TupleUpd.FieldCase.FIELD_STR,
tupleUpd.getFieldStr,
PLF.Expr.TupleUpd.FieldCase.FIELD_INTERNED_STR,
tupleUpd.getFieldInternedStr,
"Expr.TupleUpd.field.field"
),
tuple = decodeExpr(tupleUpd.getTuple, definition),
update = decodeExpr(tupleUpd.getUpdate, definition)
)
@ -783,37 +857,37 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
case PLF.CaseAlt.SumCase.VARIANT =>
val variant = lfCaseAlt.getVariant
CPVariant(
decodeTypeConName(variant.getCon),
variant.getVariantCase match {
case PLF.CaseAlt.Variant.VariantCase.VARIANT_NAME =>
toName(variant.getVariantName)
case PLF.CaseAlt.Variant.VariantCase.VARIANT_INTERNED_ID =>
getInternedName(variant.getVariantInternedId)
case PLF.CaseAlt.Variant.VariantCase.VARIANT_NOT_SET =>
throw ParseError("CaseAlt.Variant.VARIANT_NOT_SET")
},
variant.getBinderCase match {
case PLF.CaseAlt.Variant.BinderCase.BINDER_NAME =>
toName(variant.getBinderName)
case PLF.CaseAlt.Variant.BinderCase.BINDER_INTERNED_ID =>
getInternedName(variant.getBinderInternedId)
case PLF.CaseAlt.Variant.BinderCase.BINDER_NOT_SET =>
throw ParseError("CaseAlt.Variant.BINDER_NOT_SET")
}
tycon = decodeTypeConName(variant.getCon),
variant = handleInternedName(
variant.getVariantCase,
PLF.CaseAlt.Variant.VariantCase.VARIANT_STR,
variant.getVariantStr,
PLF.CaseAlt.Variant.VariantCase.VARIANT_INTERNED_STR,
variant.getVariantInternedStr,
"CaseAlt.Variant.variant.variant"
),
binder = handleInternedName(
variant.getBinderCase,
PLF.CaseAlt.Variant.BinderCase.BINDER_STR,
variant.getBinderStr,
PLF.CaseAlt.Variant.BinderCase.BINDER_INTERNED_STR,
variant.getBinderInternedStr,
"CaseAlt.Variant.binder.binder"
)
)
case PLF.CaseAlt.SumCase.ENUM =>
assertSince(LV.Features.enum, "CaseAlt.Enum")
val enum = lfCaseAlt.getEnum
CPEnum(
decodeTypeConName(enum.getCon),
enum.getConstructorCase match {
case PLF.CaseAlt.Enum.ConstructorCase.NAME =>
toName(enum.getName)
case PLF.CaseAlt.Enum.ConstructorCase.INTERNED_ID =>
getInternedName(enum.getInternedId)
case PLF.CaseAlt.Enum.ConstructorCase.CONSTRUCTOR_NOT_SET =>
throw ParseError("CaseAlt.Enum.CONSTRUCTOR_NOT_SET")
}
tycon = decodeTypeConName(enum.getCon),
constructor = handleInternedName(
enum.getConstructorCase,
PLF.CaseAlt.Enum.ConstructorCase.CONSTRUCTOR_STR,
enum.getConstructorStr,
PLF.CaseAlt.Enum.ConstructorCase.CONSTRUCTOR_INTERNED_STR,
enum.getConstructorInternedStr,
"CaseAlt.Enum.constructor.constructor"
)
)
case PLF.CaseAlt.SumCase.PRIM_CON =>
decodePrimCon(lfCaseAlt.getPrimCon)
@ -822,22 +896,22 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
case PLF.CaseAlt.SumCase.CONS =>
val cons = lfCaseAlt.getCons
CPCons(
cons.getVarHeadCase match {
case PLF.CaseAlt.Cons.VarHeadCase.VAR_HEAD_NAME =>
toName(cons.getVarHeadName)
case PLF.CaseAlt.Cons.VarHeadCase.VAR_HEAD_INTERNED_ID =>
getInternedName(cons.getVarHeadInternedId)
case PLF.CaseAlt.Cons.VarHeadCase.VARHEAD_NOT_SET =>
throw ParseError("CaseAlt.Cons.VARHEAD_NOT_SET")
},
cons.getVarTailCase match {
case PLF.CaseAlt.Cons.VarTailCase.VAR_TAIL_NAME =>
toName(cons.getVarTailName)
case PLF.CaseAlt.Cons.VarTailCase.VAR_TAIL_INTERNED_ID =>
getInternedName(cons.getVarTailInternedId)
case PLF.CaseAlt.Cons.VarTailCase.VARTAIL_NOT_SET =>
throw ParseError("CaseAlt.Cons.VARTAIL_NOT_SET")
}
head = handleInternedName(
cons.getVarHeadCase,
PLF.CaseAlt.Cons.VarHeadCase.VAR_HEAD_STR,
cons.getVarHeadStr,
PLF.CaseAlt.Cons.VarHeadCase.VAR_HEAD_INTERNED_STR,
cons.getVarHeadInternedStr,
"CaseAlt.Cons.var_head.var_head"
),
tail = handleInternedName(
cons.getVarTailCase,
PLF.CaseAlt.Cons.VarTailCase.VAR_TAIL_STR,
cons.getVarTailStr,
PLF.CaseAlt.Cons.VarTailCase.VAR_TAIL_INTERNED_STR,
cons.getVarTailInternedStr,
"CaseAlt.Cons.var_tail.var_tail"
)
)
case PLF.CaseAlt.SumCase.OPTIONAL_NONE =>
@ -846,14 +920,16 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
case PLF.CaseAlt.SumCase.OPTIONAL_SOME =>
assertSince(LV.Features.optional, "CaseAlt.OptionalSome")
CPSome(lfCaseAlt.getOptionalSome.getVarBodyCase match {
case PLF.CaseAlt.OptionalSome.VarBodyCase.NAME =>
toName(lfCaseAlt.getOptionalSome.getName)
case PLF.CaseAlt.OptionalSome.VarBodyCase.INTERNED_ID =>
getInternedName(lfCaseAlt.getOptionalSome.getInternedId)
case PLF.CaseAlt.OptionalSome.VarBodyCase.VARBODY_NOT_SET =>
throw ParseError("CaseAlt.OptionalSome.VARBODY_NOT_SET")
})
val some = lfCaseAlt.getOptionalSome
CPSome(
handleInternedName(
some.getVarBodyCase,
PLF.CaseAlt.OptionalSome.VarBodyCase.VAR_BODY_STR,
some.getVarBodyStr,
PLF.CaseAlt.OptionalSome.VarBodyCase.VAR_BODY_INTERNED_STR,
some.getVarBodyInternedStr,
"CaseAlt.OptionalSom.var_body.var_body"
))
case PLF.CaseAlt.SumCase.SUM_NOT_SET =>
throw ParseError("CaseAlt.SUM_NOT_SET")
@ -893,14 +969,14 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
val exercise = lfUpdate.getExercise
UpdateExercise(
templateId = decodeTypeConName(exercise.getTemplate),
choice = exercise.getChoiceCase match {
case PLF.Update.Exercise.ChoiceCase.NAME =>
toName(exercise.getName)
case PLF.Update.Exercise.ChoiceCase.INTERNED_ID =>
getInternedName(exercise.getInternedId)
case PLF.Update.Exercise.ChoiceCase.CHOICE_NOT_SET =>
throw ParseError("Update.Exercise.CHOICE_NOT_SET")
},
choice = handleInternedName(
exercise.getChoiceCase,
PLF.Update.Exercise.ChoiceCase.CHOICE_STR,
exercise.getChoiceStr,
PLF.Update.Exercise.ChoiceCase.CHOICE_INTERNED_STR,
exercise.getChoiceInternedStr,
"Update.Exercise.choice.choice"
),
cidE = decodeExpr(exercise.getCid, definition),
actorsE =
if (exercise.hasActor)
@ -984,15 +1060,14 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
private[this] def decodeTypeVarWithKind(
lfTypeVarWithKind: PLF.TypeVarWithKind): (TypeVarName, Kind) =
(lfTypeVarWithKind.getVarCase match {
case PLF.TypeVarWithKind.VarCase.NAME =>
toName(lfTypeVarWithKind.getName)
case PLF.TypeVarWithKind.VarCase.INTERNED_ID =>
getInternedName(lfTypeVarWithKind.getInternedId)
case PLF.TypeVarWithKind.VarCase.VAR_NOT_SET =>
throw ParseError("TypeVarWithKind.VAR_NOT_SET")
}) -> decodeKind(lfTypeVarWithKind.getKind)
handleInternedName(
lfTypeVarWithKind.getVarCase,
PLF.TypeVarWithKind.VarCase.VAR_STR,
lfTypeVarWithKind.getVarStr,
PLF.TypeVarWithKind.VarCase.VAR_INTERNED_STR,
lfTypeVarWithKind.getVarInternedStr,
"TypeVarWithKind.var.var"
) -> decodeKind(lfTypeVarWithKind.getKind)
private[this] def decodeBinding(lfBinding: PLF.Binding, definition: String): Binding = {
val (binder, typ) = decodeBinder(lfBinding.getBinder)
@ -1000,14 +1075,14 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
}
private[this] def decodeBinder(lfBinder: PLF.VarWithType): (ExprVarName, Type) =
(lfBinder.getVarCase match {
case PLF.VarWithType.VarCase.NAME =>
toName(lfBinder.getName)
case PLF.VarWithType.VarCase.INTERNED_ID =>
getInternedName(lfBinder.getInternedId)
case PLF.VarWithType.VarCase.VAR_NOT_SET =>
throw ParseError("VarWithType.VAR_NOT_SET")
}) -> decodeType(lfBinder.getType)
handleInternedName(
lfBinder.getVarCase,
PLF.VarWithType.VarCase.VAR_STR,
lfBinder.getVarStr,
PLF.VarWithType.VarCase.VAR_INTERNED_STR,
lfBinder.getVarInternedStr,
"VarWithType.var.var"
) -> decodeType(lfBinder.getType)
private[this] def decodePrimCon(lfPrimCon: PLF.PrimCon): CPPrimCon =
lfPrimCon match {
@ -1024,32 +1099,40 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
lfPrimLit.getSumCase match {
case PLF.PrimLit.SumCase.INT64 =>
PLInt64(lfPrimLit.getInt64)
case PLF.PrimLit.SumCase.DECIMAL =>
case PLF.PrimLit.SumCase.DECIMAL_STR =>
assertUntil(LV.Features.numeric, "PrimLit.decimal")
toDecimalLiteral(lfPrimLit.getDecimal)
case PLF.PrimLit.SumCase.NUMERIC =>
assertUntil(LV.Features.internedStrings, "PrimLit.decimal_str")
toPLDecimal(lfPrimLit.getDecimalStr)
case PLF.PrimLit.SumCase.NUMERIC_STR =>
assertSince(LV.Features.numeric, "PrimLit.numeric")
toNumericLiteral(lfPrimLit.getNumeric)
case PLF.PrimLit.SumCase.TEXT =>
PLText(lfPrimLit.getText)
case PLF.PrimLit.SumCase.PARTY =>
toPartyLiteral(lfPrimLit.getParty)
assertUntil(LV.Features.internedStrings, "PrimLit.numeric_str")
toPLNumeric(lfPrimLit.getNumericStr)
case PLF.PrimLit.SumCase.TEXT_STR =>
assertUntil(LV.Features.internedStrings, "PrimLit.text_str")
PLText(lfPrimLit.getTextStr)
case PLF.PrimLit.SumCase.PARTY_STR =>
assertUntil(LV.Features.internedStrings, "PrimLit.party_str")
toPLParty(lfPrimLit.getPartyStr)
case PLF.PrimLit.SumCase.TIMESTAMP =>
val t = Time.Timestamp.fromLong(lfPrimLit.getTimestamp)
t.fold(e => throw ParseError("error decoding timestamp: " + e), PLTimestamp)
case PLF.PrimLit.SumCase.DATE =>
val d = Time.Date.fromDaysSinceEpoch(lfPrimLit.getDate)
d.fold(e => throw ParseError("error decoding date: " + e), PLDate)
case PLF.PrimLit.SumCase.TEXT_INTERNED_ID =>
getInternedText(lfPrimLit.getTextInternedId)
case PLF.PrimLit.SumCase.DECIMAL_INTERNED_ID =>
assertUntil(LV.Features.numeric, "PrimLit.decimal")
getInternedDecimal(lfPrimLit.getDecimalInternedId)
case PLF.PrimLit.SumCase.NUMERIC_INTERNED_ID =>
case PLF.PrimLit.SumCase.TEXT_INTERNED_STR =>
assertSince(LV.Features.internedStrings, "PrimLit.text_interned_str")
PLText(getInternedStr(lfPrimLit.getTextInternedStr))
case PLF.PrimLit.SumCase.DECIMAL_INTERNED_STR =>
assertUntil(LV.Features.numeric, "PrimLit.decimal_interned_str")
assertSince(LV.Features.internedStrings, "PrimLit.decimal_interned_str")
toPLDecimal(getInternedStr(lfPrimLit.getDecimalInternedStr))
case PLF.PrimLit.SumCase.NUMERIC_INTERNED_STR =>
assertSince(LV.Features.numeric, "PrimLit.numeric")
getInternedNumeric(lfPrimLit.getNumericInternedId)
case PLF.PrimLit.SumCase.PARTY_INTERNED_ID =>
getInternedParty(lfPrimLit.getPartyInternedId)
assertSince(LV.Features.internedStrings, "PrimLit.decimal_interned_str")
toPLNumeric(getInternedStr(lfPrimLit.getNumericInternedStr))
case PLF.PrimLit.SumCase.PARTY_INTERNED_STR =>
assertSince(LV.Features.internedStrings, "PrimLit.party_interned_str")
toPLParty(getInternedStr(lfPrimLit.getPartyInternedStr))
case PLF.PrimLit.SumCase.SUM_NOT_SET =>
throw ParseError("PrimLit.SUM_NOT_SET")
}
@ -1058,19 +1141,50 @@ private[archive] class DecodeV1(minor: LV.Minor) extends Decode.OfPackage[PLF.Pa
private def versionIsOlderThan(minVersion: LV): Boolean =
LV.ordering.lt(languageVersion, minVersion)
private def assertUntil(maxVersion: LV, description: => String): Unit =
private def toPackageId(s: String, description: => String): PackageId = {
assertUntil(LV.Features.internedStrings, description)
eitherToParseError(PackageId.fromString(s))
}
private[this] def toName(s: String): Name =
eitherToParseError(Name.fromString(s))
private[this] def toPLNumeric(s: String) =
PLNumeric(eitherToParseError(Numeric.fromString(s)))
private[this] def toPLDecimal(s: String) =
PLNumeric(eitherToParseError(Decimal.fromString(s)))
private[this] def toPLParty(s: String) =
PLParty(eitherToParseError(Party.fromString(s)))
// maxVersion excluded
private[this] def assertUntil(maxVersion: LV, description: => String): Unit =
if (!versionIsOlderThan(maxVersion))
throw ParseError(s"$description is not supported by DAML-LF 1.$minor")
private def assertSince(minVersion: LV, description: => String): Unit =
// minVersion included
private[this] def assertSince(minVersion: LV, description: => String): Unit =
if (versionIsOlderThan(minVersion))
throw ParseError(s"$description is not supported by DAML-LF 1.$minor")
private def assertUndefined(i: Int, description: => String): Unit =
if (i != 0)
throw ParseError(s"$description is not supported by DAML-LF 1.$minor")
private def assertUndefined(s: Seq[_], description: => String): Unit =
if (s.nonEmpty)
throw ParseError(s"$description is not supported by DAML-LF 1.$minor")
private def assertNonEmpty(s: Seq[_], description: => String): Unit =
if (s.isEmpty) throw ParseError(s"Unexpected empty $description")
private def assertEmpty(s: Seq[_], description: => String): Unit =
private[this] def assertEmpty(s: Seq[_], description: => String): Unit =
if (s.nonEmpty) throw ParseError(s"Unexpected non-empty $description")
private[this] def assertEmpty(s: util.List[_], description: => String): Unit =
if (!s.isEmpty) throw ParseError(s"Unexpected non-empty $description")
}
private[lf] object DecodeV1 {
@ -1082,19 +1196,6 @@ private[lf] object DecodeV1 {
private def eitherToParseError[A](x: Either[String, A]): A =
x.fold(err => throw new ParseError(err), identity)
private def toName(s: String): Name = eitherToParseError(Name.fromString(s))
private def toPackageId(s: String): PackageId = eitherToParseError(PackageId.fromString(s))
private def toNumericLiteral(s: String): PrimLit =
PLNumeric(eitherToParseError(Numeric.fromString(s)))
private def toDecimalLiteral(s: String): PLNumeric =
PLNumeric(eitherToParseError(Decimal.fromString(s)))
private def toPartyLiteral(s: String): PLParty =
PLParty(eitherToParseError(Party.fromString(s)))
case class BuiltinTypeInfo(
proto: PLF.PrimType,
bTyp: BuiltinType,

View File

@ -44,15 +44,16 @@ class DarReaderTest extends WordSpec with Matchers with Inside with BazelRunfile
archive3.getDamlLf1.getModulesCount should be > 0
val archive1Modules = archive1.getDamlLf1.getModulesList.asScala
inside(archive1Modules.find(m => name(m.getName) == "DarReaderTest")) {
inside(archive1Modules.find(m => name(m.getNameDname) == "DarReaderTest")) {
case Some(module) =>
val actualTypes: Set[String] =
module.getDataTypesList.asScala.toSet.map((t: DamlLf1.DefDataType) => name(t.getName))
module.getDataTypesList.asScala.toSet.map((t: DamlLf1.DefDataType) =>
name(t.getNameDname))
actualTypes should contain allOf ("Transfer", "Call2", "CallablePayout", "PayOut")
}
val archive2Modules = archive2.getDamlLf1.getModulesList.asScala
val archive2ModuleNames: Set[String] = archive2Modules.map(m => name(m.getName)).toSet
val archive2ModuleNames: Set[String] = archive2Modules.map(m => name(m.getNameDname)).toSet
archive2ModuleNames shouldBe Set(
"GHC.Prim",
"GHC.Types",

View File

@ -8,10 +8,12 @@ import java.nio.file.{Files, Paths}
import com.digitalasset.daml.bazeltools.BazelRunfiles._
import com.digitalasset.daml.lf.archive.Reader.ParseError
import com.digitalasset.daml.lf.data.{Decimal, ImmArray, Numeric, Ref}
import com.digitalasset.daml.lf.data.{Decimal, Numeric, Ref}
import com.digitalasset.daml.lf.language.Util._
import com.digitalasset.daml.lf.language.{Ast, LanguageMinorVersion, LanguageVersion => LV}
import LanguageMinorVersion.Implicits._
import com.digitalasset.daml.lf.data.ImmArray.ImmArraySeq
import com.digitalasset.daml.lf.data.Ref.DottedName
import com.digitalasset.daml_lf_dev.DamlLf1
import org.scalatest.prop.TableDrivenPropertyChecks
import org.scalatest.{Inside, Matchers, OptionValues, WordSpec}
@ -40,18 +42,34 @@ class DecodeV1Spec
DamlLf1.BuiltinFunction.values().toSet
}
private val dummyModule = DamlLf1.Module
.newBuilder()
.setName(DamlLf1.DottedName.newBuilder().addSegments("dummyModule")) build ()
val dummyModuleStr = "dummyModule"
val dummyModuleDName = DamlLf1.DottedName.newBuilder().addSegments(dummyModuleStr).build()
val dummyModuleName = DottedName.assertFromString(dummyModuleStr)
private def moduleDecoder(minVersion: LV.Minor) =
private def dummyModule(version: LV.Minor, interningIdx: Int) = {
val builder = DamlLf1.Module.newBuilder()
if (LV.ordering.lt(LV(LV.Major.V1, version), LV.Features.internedDottedNames))
builder.setNameDname(dummyModuleDName)
else
builder.setNameInternedDname(interningIdx)
builder.build()
}
private def moduleDecoder(
minVersion: LV.Minor,
stringTable: ImmArraySeq[String] = ImmArraySeq.empty,
dottedNameTable: ImmArraySeq[DottedName] = ImmArraySeq.empty
) =
new DecodeV1(minVersion)
.ModuleDecoder(
Ref.PackageId.assertFromString("noPkgId"),
ImmArray.empty.toSeq,
ImmArray.empty.toSeq,
dummyModule,
onlySerializableDataDefs = false)
stringTable,
dottedNameTable :+ dummyModuleName,
dummyModule(minVersion, dottedNameTable.length),
onlySerializableDataDefs = false
)
private val preNumericMinVersions = Table(
"minVersion",
@ -219,11 +237,17 @@ class DecodeV1Spec
def toProtoExpr(b: DamlLf1.BuiltinFunction) =
DamlLf1.Expr.newBuilder().setBuiltin(b).build()
def toDecimalProto(s: String) =
DamlLf1.Expr.newBuilder().setPrimLit(DamlLf1.PrimLit.newBuilder().setDecimal(s)).build()
def toDecimalProto(s: String): DamlLf1.Expr =
DamlLf1.Expr.newBuilder().setPrimLit(DamlLf1.PrimLit.newBuilder().setDecimalStr(s)).build()
def toNumericProto(s: String) =
DamlLf1.Expr.newBuilder().setPrimLit(DamlLf1.PrimLit.newBuilder().setNumeric(s)).build()
//def toNumericProto(s: String): DamlLf1.Expr =
// DamlLf1.Expr.newBuilder().setPrimLit(DamlLf1.PrimLit.newBuilder().setNumeric(s)).build()
def toNumericProto(id: Int): DamlLf1.Expr =
DamlLf1.Expr
.newBuilder()
.setPrimLit(DamlLf1.PrimLit.newBuilder().setNumericInternedStr(id))
.build()
val decimalBuiltinTestCases = Table[DamlLf1.BuiltinFunction, LanguageMinorVersion, Ast.Expr](
("decimal builtins", "minVersion", "expected output"),
@ -421,9 +445,12 @@ class DecodeV1Spec
"reject numeric literal if version < 1.dev" in {
val decoder = moduleDecoder(LV.Features.numeric.minor, ImmArraySeq("0.0"))
decoder.decodeExpr(toNumericProto(0), "test")
forEvery(preNumericMinVersions) { version =>
val decoder = moduleDecoder(version)
a[ParseError] shouldBe thrownBy(decoder.decodeExpr(toNumericProto("0.0"), "test"))
val decoder = moduleDecoder(version, ImmArraySeq("0.0"))
a[ParseError] shouldBe thrownBy(decoder.decodeExpr(toNumericProto(0), "test"))
}
}
@ -431,21 +458,21 @@ class DecodeV1Spec
val testCases =
Table(
"string",
"9999999999999999999999999999.9999999999",
"0.0000000000",
"1000000000000000000000000000000.",
"99999999999999999999999999999999999999.",
"-0.0",
"0.",
"3.1415",
"-99999999999999999999.999999999999999999"
"id" -> "string",
0 -> "9999999999999999999999999999.9999999999",
1 -> "0.0000000000",
2 -> "1000000000000000000000000000000.",
3 -> "99999999999999999999999999999999999999.",
4 -> "-0.0",
5 -> "0.",
6 -> "3.1415",
7 -> "-99999999999999999999.999999999999999999"
)
forEvery(postNumericMinVersions) { version =>
val decoder = moduleDecoder(version)
forEvery(testCases) { string =>
decoder.decodeExpr(toNumericProto(string), "test") match {
val decoder = moduleDecoder(version, ImmArraySeq(testCases.map(_._2): _*))
forEvery(testCases) { (id, string) =>
decoder.decodeExpr(toNumericProto(id), "test") match {
case Ast.EPrimLit(Ast.PLNumeric(num)) =>
num shouldBe new BigDecimal(string)
case _ =>
@ -459,20 +486,21 @@ class DecodeV1Spec
val testCases =
Table(
"string",
"10000000000000000000000000000.0000000000",
"-1000000000000000000000000000000000000000.",
"0.000000000000000000000000000000000000001",
"0000000000000000000000000000.0000000000",
"0.0.0",
"+0.0",
"0"
"id" -> "string",
1 -> "10000000000000000000000000000.0000000000",
2 -> "-1000000000000000000000000000000000000000.",
3 -> "0.000000000000000000000000000000000000001",
4 -> "0000000000000000000000000000.0000000000",
5 -> "0.0.0",
6 -> "+0.0",
7 -> "0"
)
forEvery(postNumericMinVersions) { version =>
val decoder = moduleDecoder(version)
forEvery(testCases) { string =>
a[ParseError] shouldBe thrownBy(decoder.decodeExpr(toNumericProto(string), "test"))
val decoder = moduleDecoder(version, ImmArraySeq("0." +: testCases.map(_._2): _*))
forEvery(testCases) { (id, _) =>
decoder.decodeExpr(toNumericProto(0), "test")
a[ParseError] shouldBe thrownBy(decoder.decodeExpr(toNumericProto(id), "test"))
}
}
}
@ -503,10 +531,11 @@ class DecodeV1Spec
.getValuesList
.asScala
.collectFirst {
case dv if dv.getNameWithType.getNameList.asScala.lastOption contains "reverseCopy" =>
case dv
if dv.getNameWithType.getNameDnameList.asScala.lastOption contains "reverseCopy" =>
val pr = dv.getExpr.getVal.getModule.getPackageRef
pr.getSumCase shouldBe DamlLf1.PackageRef.SumCase.INTERNED_ID
pr.getInternedId
pr.getSumCase shouldBe DamlLf1.PackageRef.SumCase.PACKAGE_ID_INTERNED_STR
pr.getPackageIdInternedStr
}
.value
dalf1.getInternedStringsList.asScala.lift(iix.toInt).value

View File

@ -11,7 +11,9 @@ import com.digitalasset.daml.lf.language.{LanguageVersion => LV}
import com.digitalasset.daml_lf_dev.{DamlLf1 => PLF}
import scala.annotation.tailrec
import scala.collection.mutable
import scala.language.implicitConversions
import scala.reflect.ClassTag
// Important: do not use this in production code. It is designed for testing only.
private[digitalasset] class EncodeV1(val minor: LV.Minor) {
@ -23,15 +25,37 @@ private[digitalasset] class EncodeV1(val minor: LV.Minor) {
private val languageVersion = LV(LV.Major.V1, minor)
def encodePackage(pkgId: PackageId, pkg: Package): PLF.Package = {
val moduleEncoder = new ModuleEncoder(pkgId)
PLF.Package
.newBuilder()
.accumulateLeft(pkg.modules.sortByKey.values)(_ addModules moduleEncoder.encode(_))
.build()
val stringsTable = new EncodeV1.TableBuilder[String]
val dottedNameTable = new EncodeV1.TableBuilder[DottedName]
// moduleEncoder is not thread safe, because neither are stringsTable and dottedNameTable
val moduleEncoder = new ModuleEncoder(pkgId, stringsTable, dottedNameTable)
val builder = PLF.Package.newBuilder()
pkg.modules.sortByKey.values.foreach(m => builder.addModules(moduleEncoder.encode(m)))
if (!versionIsOlderThan(LV.Features.internedDottedNames)) {
dottedNameTable.build.foreach { dottedName =>
val b = PLF.InternedDottedName.newBuilder()
dottedName.segments.foreach { segment =>
b.addSegmentsInternedStr(stringsTable.insert(segment))
()
}
builder.addInternedDottedNames(b)
}
}
class ModuleEncoder(selfPkgId: PackageId) {
if (!versionIsOlderThan(LV.Features.internedPackageId))
stringsTable.build.foreach(builder.addInternedStrings)
builder.build()
}
class ModuleEncoder(
selfPkgId: PackageId,
stringsTable: TableBuilder[String],
dottedNameTable: TableBuilder[DottedName]) {
def encode(module: Module): PLF.Module = {
@ -54,18 +78,17 @@ private[digitalasset] class EncodeV1(val minor: LV.Minor) {
builder
}
PLF.Module
.newBuilder()
.setName(module.name)
.setFlags(
val builder = PLF.Module.newBuilder()
setDottedName_(module.name, builder.setNameDname, builder.setNameInternedDname)
builder.setFlags(
PLF.FeatureFlags
.newBuilder()
.setForbidPartyLiterals(module.featureFlags.forbidPartyLiterals)
.setDontDivulgeContractIdsInCreateArguments(true)
.setDontDiscloseNonConsumingChoicesToObservers(true)
)
.accumulateLeft(module.definitions.sortByKey)(addDefinition)
.build()
builder.accumulateLeft(module.definitions.sortByKey)(addDefinition)
builder.build()
}
/** * Encode Reference ***/
@ -76,31 +99,34 @@ private[digitalasset] class EncodeV1(val minor: LV.Minor) {
private implicit def encodePackageId(pkgId: PackageId): PLF.PackageRef =
if (pkgId == this.selfPkgId)
selfPgkId
else
PLF.PackageRef.newBuilder().setPackageId(pkgId).build()
private implicit def encodeDottedName(name: DottedName): PLF.DottedName =
PLF.DottedName.newBuilder().accumulateLeft(name.segments)(_ addSegments _).build()
else {
val builder = PLF.PackageRef.newBuilder()
setString(pkgId, builder.setPackageIdStr, builder.setPackageIdInternedStr)
builder.build()
}
@inline
private implicit def encodeModuleRef(modRef: (PackageId, ModuleName)): PLF.ModuleRef = {
val (pkgId, modName) = modRef
PLF.ModuleRef.newBuilder().setPackageRef(pkgId).setModuleName(modName).build()
val builder = PLF.ModuleRef.newBuilder()
builder.setPackageRef(pkgId)
setDottedName_(modName, builder.setModuleNameDname, builder.setModuleNameInternedDname)
builder.build()
}
private implicit def encodeTypeConName(identifier: Identifier): PLF.TypeConName =
PLF.TypeConName
.newBuilder()
.setModule(identifier.moduleRef)
.setName(identifier.name)
.build()
private implicit def encodeTypeConName(identifier: Identifier): PLF.TypeConName = {
val builder = PLF.TypeConName.newBuilder()
builder.setModule(identifier.moduleRef)
setDottedName_(identifier.name, builder.setNameDname, builder.setNameInternedDname)
builder.build()
}
private implicit def encodeValName(identifier: Identifier): PLF.ValName =
PLF.ValName
.newBuilder()
.setModule(identifier.moduleRef)
.accumulateLeft(identifier.name.segments)(_ addName _)
.build()
private implicit def encodeValName(identifier: Identifier): PLF.ValName = {
val b = PLF.ValName.newBuilder()
b.setModule(identifier.moduleRef)
setDottedName(identifier.name, b.addNameDname, b.setNameInternedDname)
b.build()
}
/** * Encoding of Kinds ***/
private val kStar =
@ -141,17 +167,18 @@ private[digitalasset] class EncodeV1(val minor: LV.Minor) {
@inline
private implicit def encodeTypeBinder(binder: (String, Kind)): PLF.TypeVarWithKind = {
val (varName, kind) = binder
PLF.TypeVarWithKind
.newBuilder()
.setName(varName)
.setKind(kind)
.build()
val b = PLF.TypeVarWithKind.newBuilder()
setString(varName, b.setVarStr, b.setVarInternedStr)
b.setKind(kind)
b.build()
}
@inline
private implicit def encodeFieldWithType(nameWithType: (String, Type)): PLF.FieldWithType = {
val (name, typ) = nameWithType
PLF.FieldWithType.newBuilder().setName(name).setType(typ).build()
val b = PLF.FieldWithType.newBuilder()
setString(name, b.setFieldStr, b.setFieldInternedStr)
b.setType(typ).build()
}
private val TForalls = RightRecMatcher[(TypeVarName, Kind), Type]({
@ -180,8 +207,10 @@ private[digitalasset] class EncodeV1(val minor: LV.Minor) {
val builder = PLF.Type.newBuilder()
typ match {
case TVar(varName) =>
builder.setVar(
PLF.Type.Var.newBuilder().setVarName(varName).accumulateLeft(args)(_ addArgs _))
val b = PLF.Type.Var.newBuilder()
setString(varName, b.setVarStr, b.setVarInternedStr)
args.foldLeft(b)(_ addArgs _)
builder.setVar(b)
case TNat(n) =>
assertSince(LV.Features.numeric, "Type.TNat")
builder.setNat(n.toLong)
@ -240,13 +269,17 @@ private[digitalasset] class EncodeV1(val minor: LV.Minor) {
@inline
private implicit def encodeFieldWithExpr(fieldWithExpr: (Name, Expr)): PLF.FieldWithExpr = {
val (name, expr) = fieldWithExpr
PLF.FieldWithExpr.newBuilder().setName(name).setExpr(expr).build()
val b = PLF.FieldWithExpr.newBuilder()
setString(name, b.setFieldStr, b.setFieldInternedStr)
b.setExpr(expr).build()
}
@inline
private implicit def encodeExprBinder(binder: (String, Type)): PLF.VarWithType = {
val (varName, typ) = binder
PLF.VarWithType.newBuilder().setName(varName).setType(typ).build()
val b = PLF.VarWithType.newBuilder()
setString(varName, b.setVarStr, b.setVarInternedStr)
b.setType(typ).build()
}
private implicit def encodeLocation(loc: Location): PLF.Location = {
@ -294,15 +327,13 @@ private[digitalasset] class EncodeV1(val minor: LV.Minor) {
case UpdateExercise(templateId, choice, cid, actors, arg) =>
if (actors.isEmpty)
assertSince(LV.Features.optionalExerciseActor, "Update.Exercise.actors optional")
builder.setExercise(
PLF.Update.Exercise
.newBuilder()
.setTemplate(templateId)
.setName(choice)
.setCid(cid)
.accumulateLeft(actors)(_ setActor _)
.setArg(arg)
)
val b = PLF.Update.Exercise.newBuilder()
b.setTemplate(templateId)
setString(choice, b.setChoiceStr, b.setChoiceInternedStr)
b.setCid(cid)
actors.foreach(b.setActor(_))
b.setArg(arg)
builder.setExercise(b)
case UpdateGetTime =>
builder.setGetTime(unit)
case UpdateFetchByKey(rbk) =>
@ -353,17 +384,25 @@ private[digitalasset] class EncodeV1(val minor: LV.Minor) {
private implicit def encodePrimLit(primLit: PrimLit): PLF.PrimLit = {
val builder = PLF.PrimLit.newBuilder()
primLit match {
case PLInt64(value) => builder.setInt64(value)
case PLInt64(value) =>
builder.setInt64(value)
case PLNumeric(value) =>
if (versionIsOlderThan(LV.Features.numeric)) {
assert(value.scale == Decimal.scale)
builder.setDecimal(Numeric.toUnscaledString(value))
setString(
Numeric.toUnscaledString(value),
builder.setDecimalStr,
builder.setDecimalInternedStr)
} else
builder.setNumeric(Numeric.toString(value))
case PLText(value) => builder.setText(value)
case PLTimestamp(value) => builder.setTimestamp(value.micros)
case PLParty(party) => builder.setParty(party)
case PLDate(date) => builder.setDate(date.days)
setString(Numeric.toString(value), builder.setNumericStr, builder.setNumericInternedStr)
case PLText(value) =>
setString(value, builder.setTextStr, builder.setTextInternedStr)
case PLTimestamp(value) =>
builder.setTimestamp(value.micros)
case PLParty(party) =>
setString(party, builder.setPartyStr, builder.setPartyInternedStr)
case PLDate(date) =>
builder.setDate(date.days)
}
builder.build()
}
@ -372,27 +411,34 @@ private[digitalasset] class EncodeV1(val minor: LV.Minor) {
val builder = PLF.CaseAlt.newBuilder().setBody(alt.expr)
alt.pattern match {
case CPVariant(tyCon, variant, binder) =>
builder.setVariant(
PLF.CaseAlt.Variant
.newBuilder()
.setCon(tyCon)
.setVariantName(variant)
.setBinderName(binder))
val b = PLF.CaseAlt.Variant.newBuilder()
b.setCon(tyCon)
setString(variant, b.setVariantStr, b.setVariantInternedStr)
setString(binder, b.setBinderStr, b.setBinderInternedStr)
builder.setVariant(b)
case CPEnum(tyCon, con) =>
assertSince(LV.Features.enum, "CaseAlt.Enum")
builder.setEnum(PLF.CaseAlt.Enum.newBuilder().setCon(tyCon).setName(con))
val b = PLF.CaseAlt.Enum.newBuilder()
b.setCon(tyCon)
setString(con, b.setConstructorStr, b.setConstructorInternedStr)
builder.setEnum(b)
case CPPrimCon(primCon) =>
builder.setPrimCon(primCon)
case CPNil =>
builder.setNil(unit)
case CPCons(head, tail) =>
builder.setCons(PLF.CaseAlt.Cons.newBuilder().setVarHeadName(head).setVarTailName(tail))
val b = PLF.CaseAlt.Cons.newBuilder()
setString(head, b.setVarHeadStr, b.setVarHeadInternedStr)
setString(tail, b.setVarTailStr, b.setVarTailInternedStr)
builder.setCons(b)
case CPNone =>
assertSince(LV.Features.optional, "CaseAlt.OptionalNone")
builder.setOptionalNone(unit)
case CPSome(x) =>
assertSince(LV.Features.optional, "CaseAlt.OptionalSome")
builder.setOptionalSome(PLF.CaseAlt.OptionalSome.newBuilder().setName(x))
val b = PLF.CaseAlt.OptionalSome.newBuilder()
setString(x, b.setVarBodyStr, b.setVarBodyInternedStr)
builder.setOptionalSome(b)
case CPDefault =>
builder.setDefault(unit)
}
@ -419,81 +465,88 @@ private[digitalasset] class EncodeV1(val minor: LV.Minor) {
}
private def encodeExprBuilder(expr0: Expr): PLF.Expr.Builder = {
def newBuilder = PLF.Expr.newBuilder()
val builder = PLF.Expr.newBuilder()
expr0 match {
case EVar(value) =>
newBuilder.setVar(value)
setString(value, builder.setVarStr, builder.setVarInternedStr)
case EVal(value) =>
newBuilder.setVal(value)
builder.setVal(value)
case EBuiltin(value) =>
newBuilder.setBuiltin(value)
builder.setBuiltin(value)
case EPrimCon(primCon) =>
newBuilder.setPrimCon(primCon)
builder.setPrimCon(primCon)
case EPrimLit(primLit) =>
newBuilder.setPrimLit(primLit)
builder.setPrimLit(primLit)
case ERecCon(tyCon, fields) =>
newBuilder.setRecCon(
builder.setRecCon(
PLF.Expr.RecCon.newBuilder().setTycon(tyCon).accumulateLeft(fields)(_ addFields _))
case ERecProj(tycon, field, expr) =>
newBuilder.setRecProj(
PLF.Expr.RecProj.newBuilder().setTycon(tycon).setName(field).setRecord(expr))
val b = PLF.Expr.RecProj.newBuilder()
b.setTycon(tycon)
setString(field, b.setFieldStr, b.setFieldInternedStr)
b.setRecord(expr)
builder.setRecProj(b)
case ERecUpd(tyCon, field, expr, update) =>
newBuilder.setRecUpd(
PLF.Expr.RecUpd
.newBuilder()
.setTycon(tyCon)
.setName(field)
.setRecord(expr)
.setUpdate(update))
val b = PLF.Expr.RecUpd.newBuilder()
b.setTycon(tyCon)
setString(field, b.setFieldStr, b.setFieldInternedStr)
b.setRecord(expr)
b.setUpdate(update)
builder.setRecUpd(b)
case EVariantCon(tycon, variant, arg) =>
newBuilder.setVariantCon(
PLF.Expr.VariantCon
.newBuilder()
.setTycon(tycon)
.setName(variant)
.setVariantArg(arg))
val b = PLF.Expr.VariantCon.newBuilder()
b.setTycon(tycon)
setString(variant, b.setVariantConStr, b.setVariantConInternedStr)
b.setVariantArg(arg)
builder.setVariantCon(b)
case EEnumCon(tyCon, con) =>
assertSince(LV.Features.enum, "Expr.Enum")
newBuilder.setEnumCon(PLF.Expr.EnumCon.newBuilder().setTycon(tyCon).setName(con))
val b = PLF.Expr.EnumCon.newBuilder().setTycon(tyCon)
setString(con, b.setEnumConStr, b.setEnumConInternedStr)
builder.setEnumCon(b.build())
case ETupleCon(fields) =>
newBuilder.setTupleCon(
PLF.Expr.TupleCon.newBuilder().accumulateLeft(fields)(_ addFields _))
builder.setTupleCon(PLF.Expr.TupleCon.newBuilder().accumulateLeft(fields)(_ addFields _))
case ETupleProj(field, expr) =>
newBuilder.setTupleProj(PLF.Expr.TupleProj.newBuilder().setName(field).setTuple(expr))
val b = PLF.Expr.TupleProj.newBuilder()
setString(field, b.setFieldStr, b.setFieldInternedStr)
b.setTuple(expr)
builder.setTupleProj(b)
case ETupleUpd(field, tuple, update) =>
newBuilder.setTupleUpd(
PLF.Expr.TupleUpd.newBuilder().setName(field).setTuple(tuple).setUpdate(update))
val b = PLF.Expr.TupleUpd.newBuilder()
setString(field, b.setFieldStr, b.setFieldInternedStr)
b.setTuple(tuple)
b.setUpdate(update)
builder.setTupleUpd(b)
case EApps(fun, args) =>
newBuilder.setApp(PLF.Expr.App.newBuilder().setFun(fun).accumulateLeft(args)(_ addArgs _))
builder.setApp(PLF.Expr.App.newBuilder().setFun(fun).accumulateLeft(args)(_ addArgs _))
case ETyApps(expr, typs1) =>
val typs =
ntimes(implicitDecimalScaleParameters(expr), ignoreOneDecimalScaleParameter, typs1)
newBuilder.setTyApp(
builder.setTyApp(
PLF.Expr.TyApp.newBuilder().setExpr(expr).accumulateLeft(typs)(_ addTypes _))
case ETyApps(expr, typs) =>
newBuilder.setTyApp(
builder.setTyApp(
PLF.Expr.TyApp.newBuilder().setExpr(expr).accumulateLeft(typs)(_ addTypes _))
case EAbss(binders, body) =>
newBuilder.setAbs(
builder.setAbs(
PLF.Expr.Abs.newBuilder().accumulateLeft(binders)(_ addParam _).setBody(body))
case ETyAbss(binders, body) =>
newBuilder.setTyAbs(
builder.setTyAbs(
PLF.Expr.TyAbs.newBuilder().accumulateLeft(binders)(_ addParam _).setBody(body))
case ECase(scrut, alts) =>
newBuilder.setCase(
PLF.Case.newBuilder().setScrut(scrut).accumulateLeft(alts)(_ addAlts _))
builder.setCase(PLF.Case.newBuilder().setScrut(scrut).accumulateLeft(alts)(_ addAlts _))
case ELet(binding, body) =>
newBuilder.setLet(
builder.setLet(
PLF.Block
.newBuilder()
.accumulateLeft(List(binding))(_ addBindings _)
.setBody(body)
)
case ENil(typ) =>
newBuilder.setNil(PLF.Expr.Nil.newBuilder().setType(typ))
builder.setNil(PLF.Expr.Nil.newBuilder().setType(typ))
case ECons(typ, front, tail) =>
newBuilder.setCons(
builder.setCons(
PLF.Expr.Cons
.newBuilder()
.setType(typ)
@ -501,27 +554,27 @@ private[digitalasset] class EncodeV1(val minor: LV.Minor) {
.setTail(tail))
case ENone(typ) =>
assertSince(LV.Features.optional, "Expr.OptionalNone")
newBuilder.setOptionalNone(PLF.Expr.OptionalNone.newBuilder().setType(typ))
builder.setOptionalNone(PLF.Expr.OptionalNone.newBuilder().setType(typ))
case ESome(typ, x) =>
assertSince(LV.Features.optional, "Expr.OptionalSome")
newBuilder.setOptionalSome(PLF.Expr.OptionalSome.newBuilder().setType(typ).setBody(x))
builder.setOptionalSome(PLF.Expr.OptionalSome.newBuilder().setType(typ).setBody(x))
case ELocation(loc, expr) =>
encodeExprBuilder(expr).setLocation(loc)
case EUpdate(u) =>
newBuilder.setUpdate(u)
builder.setUpdate(u)
case EScenario(s) =>
newBuilder.setScenario(s)
builder.setScenario(s)
}
builder
}
private implicit def encodeDataDef(nameWithDef: (DottedName, DDataType)): PLF.DefDataType = {
val (name, dataType) = nameWithDef
val builder =
PLF.DefDataType
.newBuilder()
.setName(name)
.accumulateLeft(dataType.params)(_ addParams _)
.setSerializable(dataType.serializable)
val (dottedName, dataType) = nameWithDef
val builder = PLF.DefDataType.newBuilder()
setDottedName_(dottedName, builder.setNameDname, builder.setNameInternedDname)
builder.accumulateLeft(dataType.params)(_ addParams _)
builder.setSerializable(dataType.serializable)
dataType.cons match {
case DataRecord(fields, _) =>
builder.setRecord(
@ -531,22 +584,29 @@ private[digitalasset] class EncodeV1(val minor: LV.Minor) {
PLF.DefDataType.Fields.newBuilder().accumulateLeft(variants)(_ addFields _))
case DataEnum(constructors) =>
assertSince(LV.Features.enum, "DefDataType.Enum")
builder.setEnum(
PLF.DefDataType.EnumConstructors
.newBuilder()
.accumulateLeft(constructors)(_ addConstructors _))
val b = PLF.DefDataType.EnumConstructors.newBuilder()
constructors.foreach(
setString(_, b.addConstructorsStr, b.addConstructorsInternedStr)
)
builder.setEnum(b)
}
builder.build()
}
private implicit def encodeNameWithType(
nameWithType: (DottedName, Type)): PLF.DefValue.NameWithType = {
val (name, typ) = nameWithType
val b = PLF.DefValue.NameWithType.newBuilder
setDottedName(name, b.addNameDname, b.setNameInternedDname)
b.setType(typ)
b.build()
}
private implicit def encodeValueDef(nameWithDef: (DottedName, DValue)): PLF.DefValue = {
val (name, value) = nameWithDef
val (dottedName, value) = nameWithDef
PLF.DefValue
.newBuilder()
.setNameWithType(
PLF.DefValue.NameWithType.newBuilder
.accumulateLeft(name.segments)(_ addName _)
.setType(value.typ))
.setNameWithType(dottedName -> value.typ)
.setExpr(value.body)
.setNoPartyLiterals(value.noPartyLiterals)
.setIsTest(value.isTest)
@ -557,16 +617,15 @@ private[digitalasset] class EncodeV1(val minor: LV.Minor) {
nameWithChoice: (ChoiceName, TemplateChoice)
): PLF.TemplateChoice = {
val (name, choice) = nameWithChoice
PLF.TemplateChoice
.newBuilder()
.setChoiceName(name)
.setConsuming(choice.consuming)
.setControllers(choice.controllers)
.setArgBinder(choice.argBinder._1.getOrElse("") -> choice.argBinder._2)
.setRetType(choice.returnType)
.setUpdate(choice.update)
.setSelfBinderName(choice.selfBinder)
.build()
val b = PLF.TemplateChoice.newBuilder()
setString(name, b.setNameStr, b.setNameInternedStr)
b.setConsuming(choice.consuming)
b.setControllers(choice.controllers)
b.setArgBinder(choice.argBinder._1.getOrElse("") -> choice.argBinder._2)
b.setRetType(choice.returnType)
b.setUpdate(choice.update)
setString(choice.selfBinder, b.setSelfBinderStr, b.setSelfBinderInternedStr)
b.build()
}
private implicit def encodeTemplateKey(key: TemplateKey): PLF.DefTemplate.DefKey =
@ -580,17 +639,47 @@ private[digitalasset] class EncodeV1(val minor: LV.Minor) {
private implicit def encodeTemplate(
nameWithTemplate: (DottedName, Template)): PLF.DefTemplate = {
val (name, template) = nameWithTemplate
PLF.DefTemplate
.newBuilder()
.setTycon(name)
.setParamName(template.param)
.setPrecond(template.precond)
.setSignatories(template.signatories)
.setAgreement(template.agreementText)
.accumulateLeft(template.choices.sortByKey)(_ addChoices _)
.setObservers(template.observers)
.accumulateLeft(template.key)(_ setKey _)
.build()
val b = PLF.DefTemplate.newBuilder()
setDottedName_(name, b.setTyconDname, b.setTyconInternedDname)
setString(template.param, b.setParamStr, b.setParamInternedStr)
b.setPrecond(template.precond)
b.setSignatories(template.signatories)
b.setAgreement(template.agreementText)
b.accumulateLeft(template.choices.sortByKey)(_ addChoices _)
b.setObservers(template.observers)
template.key.foreach(b.setKey(_))
b.build()
}
private def setString[X](s: String, setDirect: String => X, setThroughTable: Int => X) = {
if (versionIsOlderThan(LV.Features.internedStrings))
setDirect(s)
else
setThroughTable(stringsTable.insert(s))
()
}
private def setDottedName[X](
name: Ref.DottedName,
addDirect: String => X,
setThroughTable: Int => X) = {
if (versionIsOlderThan(LV.Features.internedDottedNames))
name.segments.map(addDirect)
else
setThroughTable(dottedNameTable.insert(name))
()
}
private def setDottedName_[X](
name: Ref.DottedName,
addDirect: PLF.DottedName => X,
setThroughTable: Int => X) = {
if (versionIsOlderThan(LV.Features.internedDottedNames))
addDirect(
PLF.DottedName.newBuilder().accumulateLeft(name.segments)(_ addSegments _).build())
else
setThroughTable(dottedNameTable.insert(name))
()
}
}
@ -687,4 +776,15 @@ object EncodeV1 {
def values: Iterable[Y] = iterable.map(_._2)
}
private class TableBuilder[X] {
private val map = mutable.Map.empty[X, Int]
private var idx = -1
def insert(x: X) = map.getOrElseUpdate(x, { idx = idx + 1; idx })
def build(implicit classTag: ClassTag[X]): Array[X] = {
val a = new Array[X](map.size)
for ((x, i) <- map) a(i) = x
a
}
}
}

View File

@ -222,7 +222,7 @@ Version: 1.6
* **Add** ``TEXT_FROM_CODE_POINTS`` and ``TEXT_TO_CODE_POINTS``
primitives for (un)packing strings.
* **Add** intern package IDs in external package references.
* **Add** package IDs interning in external package references.
Version: 1.dev
..............
@ -237,6 +237,10 @@ Version: 1.dev
* **Drop** support for Decimal type. Use Numeric of scale 10 instead.
* **Add** string interning in external package references.
* **Add** name interning in external package references.
* **Add** existential ``Any`` type and
``from_any`` and ``to_any`` functions to convert from/to
an arbitrary ground type (i.e. a type with no free type variables) to ``Any``.
@ -2673,23 +2677,14 @@ message::
message PackageRef {
oneof Sum {
Unit self = 1;
string package_id = 2;
uint32 interned_id = 3;
string package_id_str = 2;
}
}
One should use either the field ``self`` to refer the current package or
one of ``interned_id`` [Available in versions >= 1.6] or ``package_id``
to refer to an external package. During deserialization ``self``
references are replaced by the actual digest of the package in which it
appears.
[*Available in versions >= 1.6*]
``Package.interned_package_ids`` is a list of package IDs.
``interned_id``, if used, must be a valid zero-based index into this
list in the ``Package`` that contains the ``PackageRef`` in question;
such a ``PackageRef`` refers to the external package ID at that index.
``package_id_str`` to refer to an external package. During deserialization
``self`` references are replaced by the actual digest of the package in
which it appears.
Template precondition
@ -2900,18 +2895,73 @@ Enum
The deserialization process will reject any DAML-LF 1.5 (or earlier)
program using the field ``enum`` in ``DefDataType`` messages, the
field ``enum`` in ``CaseAlt`` messages, or the field ``enum_con``
field ``enum`` in ``CaseAlt`` messages, or the field ``enum_con_str``
in ``Expr`` messages.
intern package IDs
..................
String Interning
................
[*Available in versions >= 1.6*]
In ``PackageRef``, the alternative ``interned_id`` may be used in place
of ``package_id``, in which case the package ID will be that at the
given index into ``Package.interned_package_ids``.
See `Package reference`_.
To provide string sharing, the so-called *string interning* mechanism
allows the strings within messages to be stored in a global table and
referenced by their index.
The field ``Package.interned_strings`` is a list of strings. A
so-called `interned string` is a valid zero-based index of this
list. An `interned string` is interpreted as the string it points to
in ``Package.interned_strings``.
+ An `interned package id` is an `interned string` that can be
interpreted as a valid `PackageId string`.
+ An `interned party` is an `interned string` that can be interpreted
as a valid `Party string`.
+ An `interned numeric id` is an `interned string` that can be
interpreted as a valid `numeric` literal.
+ An `interned text` is an `interned string` interpreted as a text
literal
+ An `interned identifier` is an `interned string` that can be
interpreted as a valid `identifier`
Starting from DAML-LF 1.6, the field
``PackageRef.package_id_interned_str`` [*Available in versions >=
1.6*] may be used instead of ``PackageRef.package_id_str`` and it
must be a valid *interned packageId*.
Starting from DAML-LF 1.dev, all ``string`` (or ``repeated string``)
fields with the suffix ``_str`` are forbidden. Alternative fields of
type ``int32`` (or ``repeated int32``) with the suffix
``_interned_str`` must be used instead. Except
``PackageRef.package_id_interned_str`` which is [*Available in
versions >= 1.6*], all fields with suffix ``_interned_str`` are
[*Available in versions >= 1.dev*]. The deserialization process will
reject any DAML-LF 1.dev (or later) that does not comply with this
restriction.
Name Interning
..............
[*Available in versions >= 1.dev*]
To provide sharing of `names <Identifiers_>`_, the so-called *name
interning* mechanism allows the *names* within messages to be stored
in a global table and be referenced by their index.
``InternedDottedName`` is a non-empty list of valid `interned
identifiers`. Such message is interpreted as the name built from the
sequence the interned identifiers it contains. The field
``Package.interned_dotted_names`` is a list of such messages. A
so-called `interned name` is a valid zero-based index of this list. An
`interned name` is interpreted as the name built form the `name` it
points to in ``Package.interned_dotted_names``.
Starting from DAML-LF 1.dev, all ``DottedName`` (or ``repeated
string``) fields with the suffix ``_dname`` are forbidden. Alternative
fields of type ``int32`` with the suffix ``_interned_dname``
[*Available in versions >= 1.dev*] must be used instead. The
deserialization process will reject any DAML-LF 1.dev (or later) that
that does not comply this restriction.
Nat kind and Nat types
......................
@ -2996,9 +3046,23 @@ On the other hand, starting from DAML-LF 1.dev:
In other words ``decimal`` fields in ``PrimLit`` and ``PrimType``
messages must remain unset and Decimal ``BuiltinFunction`` (those
containing ``DECIMAL`` in their name are forbidden). The
deserialization process will reject any DAML-LF 1.dev (or latter)
deserialization process will reject any DAML-LF 1.dev (or later)
that does not comply those restrictions.
Any template
............
[*Available in versions >= 1.dev*]
This is an experimental feature used in DAML Triggers.
More details will be provided in a near future.
The curious reader can temporarily refer to the following PRs for more details:
* https://github.com/digital-asset/daml/issues/2876
* https://github.com/digital-asset/daml/issues/3072
.. Local Variables:
.. eval: (flyspell-mode 1)
.. eval: (set-input-method "TeX")