Skip to content

Commit

Permalink
Replace experimental interface primitives with proper LF primitives (d…
Browse files Browse the repository at this point in the history
…igital-asset#12678)

* Add new primitives to proto spec

* implement E{Signatory,Observer}Interface in terms of EResolveVirtual{Signatory,Observer}

* define EToTypeRep primitive in terms of EToTypeRep Expr

* Remove experimental primitives TO_TYPE_REP and RESOLVE_VIRTUAL_{SIGNATORY,OBSERVER} 

changelog_begin
changelog_end
  • Loading branch information
akrmn authored Feb 3, 2022
1 parent de444b2 commit 3ce272b
Show file tree
Hide file tree
Showing 23 changed files with 234 additions and 28 deletions.
8 changes: 4 additions & 4 deletions bazel-haskell-deps.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ load("@os_info//:os_info.bzl", "is_linux", "is_windows")
load("@dadew//:dadew.bzl", "dadew_tool_home")
load("@rules_haskell//haskell:cabal.bzl", "stack_snapshot")

GHC_LIB_REV = "3ef58e2259fe20f4b4740c6d33e29d22"
GHC_LIB_SHA256 = "e40f0bfa98544dbf510aef0972945bad0ec4a62f667283d8bf0792598f9e2951"
GHC_LIB_REV = "806f92a22b1234a566d69cc0b1dd72ff"
GHC_LIB_SHA256 = "56ea6aa7bbdf8c2a763cac1a85be459ac3637b6f665d304f4a8cdc8f2e444650"
GHC_LIB_VERSION = "8.8.1"
GHC_LIB_PARSER_REV = "3ef58e2259fe20f4b4740c6d33e29d22"
GHC_LIB_PARSER_SHA256 = "4184527540d6e50bac1b628e3e7737c19d4d8259fa96805b947d800673a35c4f"
GHC_LIB_PARSER_REV = "806f92a22b1234a566d69cc0b1dd72ff"
GHC_LIB_PARSER_SHA256 = "9494a22b44fde688fd9f3f2b26273750206a43551082ca676f84905a66f208b3"
GHC_LIB_PARSER_VERSION = "8.8.1"
GHCIDE_REV = "4146f08b729e1f4e4a3ac789570e9c0b9010944e"
GHCIDE_SHA256 = "bd16242397b67ac0d803c7e0452b03396133d9b7aaf2ba3bddd834260a78bd80"
Expand Down
2 changes: 1 addition & 1 deletion ci/da-ghc-lib/compile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
variables:
ghc-lib-sha: '905f51296d979d79da511bed9ab2da7cb9429c9f'
base-sha: '9c787d4d24f2b515934c8503ee2bbd7cfac4da20'
patches: '95f84b61f4f22570fc78313ecf54b522743a3f41 833ca63be2ab14871874ccb6974921e8952802e9'
patches: '529f84a976031206d3c581b965e69f1871ae541d 833ca63be2ab14871874ccb6974921e8952802e9'
flavor: 'da-ghc-8.8.1'
steps:
- checkout: self
Expand Down
15 changes: 15 additions & 0 deletions compiler/daml-lf-ast/src/DA/Daml/LF/Ast/Alpha.hs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,21 @@ alphaExpr' env = \case
&& alphaTypeCon t1b t2b
&& alphaExpr' env e1 e2
_ -> False
EInterfaceTemplateTypeRep ty1 expr1 -> \case
EInterfaceTemplateTypeRep ty2 expr2
-> alphaTypeCon ty1 ty2
&& alphaExpr' env expr1 expr2
_ -> False
ESignatoryInterface ty1 expr1 -> \case
ESignatoryInterface ty2 expr2
-> alphaTypeCon ty1 ty2
&& alphaExpr' env expr1 expr2
_ -> False
EObserverInterface ty1 expr1 -> \case
EObserverInterface ty2 expr2
-> alphaTypeCon ty1 ty2
&& alphaExpr' env expr1 expr2
_ -> False
EUpdate u1 -> \case
EUpdate u2 -> alphaUpdate env u1 u2
_ -> False
Expand Down
15 changes: 15 additions & 0 deletions compiler/daml-lf-ast/src/DA/Daml/LF/Ast/Base.hs
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,21 @@ data Expr
, friRequiringInterface :: !(Qualified TypeConName)
, friExpr :: !Expr
}
-- | Obtain type representation of contract's template through an interface
| EInterfaceTemplateTypeRep
{ ttrInterface :: !(Qualified TypeConName)
, ttrExpr :: !Expr
}
-- | Obtain signatories of contract through an interface
| ESignatoryInterface
{ rvsInterface :: !(Qualified TypeConName)
, rvsExpr :: !Expr
}
-- | Obtain observers of contract through an interface
| EObserverInterface
{ rvoInterface :: !(Qualified TypeConName)
, rvoExpr :: !Expr
}
-- | Update expression.
| EUpdate !Update
-- | Scenario expression.
Expand Down
3 changes: 3 additions & 0 deletions compiler/daml-lf-ast/src/DA/Daml/LF/Ast/FreeVars.hs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ freeVarsStep = \case
ECallInterfaceF _ _ e -> e
EToRequiredInterfaceF _ _ e -> e
EFromRequiredInterfaceF _ _ e -> e
EInterfaceTemplateTypeRepF _ e -> e
ESignatoryInterfaceF _ e -> e
EObserverInterfaceF _ e -> e
EExperimentalF _ t -> freeVarsInType t

where
Expand Down
6 changes: 6 additions & 0 deletions compiler/daml-lf-ast/src/DA/Daml/LF/Ast/Pretty.hs
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,12 @@ instance Pretty Expr where
[interfaceArg ty1, interfaceArg ty2, TmArg expr]
EFromRequiredInterface ty1 ty2 expr -> pPrintAppKeyword lvl prec "from_required_interface"
[interfaceArg ty1, interfaceArg ty2, TmArg expr]
EInterfaceTemplateTypeRep ty expr -> pPrintAppKeyword lvl prec "interface_template_type_rep"
[interfaceArg ty, TmArg expr]
ESignatoryInterface ty expr -> pPrintAppKeyword lvl prec "signatory_interface"
[interfaceArg ty, TmArg expr]
EObserverInterface ty expr -> pPrintAppKeyword lvl prec "observer_interface"
[interfaceArg ty, TmArg expr]
EExperimental name _ -> pPrint $ "$" <> name

instance Pretty DefTypeSyn where
Expand Down
9 changes: 9 additions & 0 deletions compiler/daml-lf-ast/src/DA/Daml/LF/Ast/Recursive.hs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ data ExprF expr
| ECallInterfaceF !(Qualified TypeConName) !MethodName !expr
| EToRequiredInterfaceF !(Qualified TypeConName) !(Qualified TypeConName) !expr
| EFromRequiredInterfaceF !(Qualified TypeConName) !(Qualified TypeConName) !expr
| EInterfaceTemplateTypeRepF !(Qualified TypeConName) !expr
| ESignatoryInterfaceF !(Qualified TypeConName) !expr
| EObserverInterfaceF !(Qualified TypeConName) !expr
| EExperimentalF !T.Text !Type
deriving (Foldable, Functor, Traversable)

Expand Down Expand Up @@ -211,6 +214,9 @@ instance Recursive Expr where
ECallInterface a b c -> ECallInterfaceF a b c
EToRequiredInterface a b c -> EToRequiredInterfaceF a b c
EFromRequiredInterface a b c -> EFromRequiredInterfaceF a b c
EInterfaceTemplateTypeRep a b -> EInterfaceTemplateTypeRepF a b
ESignatoryInterface a b -> ESignatoryInterfaceF a b
EObserverInterface a b -> EObserverInterfaceF a b
EExperimental a b -> EExperimentalF a b

instance Corecursive Expr where
Expand Down Expand Up @@ -250,4 +256,7 @@ instance Corecursive Expr where
ECallInterfaceF a b c -> ECallInterface a b c
EToRequiredInterfaceF a b c -> EToRequiredInterface a b c
EFromRequiredInterfaceF a b c -> EFromRequiredInterface a b c
EInterfaceTemplateTypeRepF a b -> EInterfaceTemplateTypeRep a b
ESignatoryInterfaceF a b -> ESignatoryInterface a b
EObserverInterfaceF a b -> EObserverInterface a b
EExperimentalF a b -> EExperimental a b
6 changes: 6 additions & 0 deletions compiler/daml-lf-ast/src/DA/Daml/LF/Ast/Subst.hs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,12 @@ applySubstInExpr subst@Subst{..} = \case
(applySubstInExpr subst e)
EFromRequiredInterface t1 t2 e -> EFromRequiredInterface t1 t2
(applySubstInExpr subst e)
EInterfaceTemplateTypeRep ty e -> EInterfaceTemplateTypeRep ty
(applySubstInExpr subst e)
ESignatoryInterface ty e -> ESignatoryInterface ty
(applySubstInExpr subst e)
EObserverInterface ty e -> EObserverInterface ty
(applySubstInExpr subst e)
EUpdate u -> EUpdate
(applySubstInUpdate subst u)
EScenario s -> EScenario
Expand Down
9 changes: 9 additions & 0 deletions compiler/daml-lf-proto/src/DA/Daml/LF/Proto3/DecodeV1.hs
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,15 @@ decodeExprSum exprSum = mayDecode "exprSum" exprSum $ \case
<$> mayDecode "expr_FromRequiredInterfaceRequiredInterface" expr_FromRequiredInterfaceRequiredInterface decodeTypeConName
<*> mayDecode "expr_FromRequiredInterfaceRequiringInterface" expr_FromRequiredInterfaceRequiringInterface decodeTypeConName
<*> mayDecode "expr_FromRequiredInterfaceExpr" expr_FromRequiredInterfaceExpr decodeExpr
LF1.ExprSumInterfaceTemplateTypeRep LF1.Expr_InterfaceTemplateTypeRep {..} -> EInterfaceTemplateTypeRep
<$> mayDecode "expr_InterfaceTemplateTypeRepInterface" expr_InterfaceTemplateTypeRepInterface decodeTypeConName
<*> mayDecode "expr_InterfaceTemplateTypeRepExpr" expr_InterfaceTemplateTypeRepExpr decodeExpr
LF1.ExprSumSignatoryInterface LF1.Expr_SignatoryInterface {..} -> ESignatoryInterface
<$> mayDecode "expr_SignatoryInterfaceInterface" expr_SignatoryInterfaceInterface decodeTypeConName
<*> mayDecode "expr_SignatoryInterfaceExpr" expr_SignatoryInterfaceExpr decodeExpr
LF1.ExprSumObserverInterface LF1.Expr_ObserverInterface {..} -> EObserverInterface
<$> mayDecode "expr_ObserverInterfaceInterface" expr_ObserverInterfaceInterface decodeTypeConName
<*> mayDecode "expr_ObserverInterfaceExpr" expr_ObserverInterfaceExpr decodeExpr
LF1.ExprSumExperimental (LF1.Expr_Experimental name mbType) -> do
ty <- mayDecode "expr_Experimental" mbType decodeType
pure $ EExperimental (decodeString name) ty
Expand Down
12 changes: 12 additions & 0 deletions compiler/daml-lf-proto/src/DA/Daml/LF/Proto3/EncodeV1.hs
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,18 @@ encodeExpr' = \case
expr_FromRequiredInterfaceRequiringInterface <- encodeQualTypeConName ty2
expr_FromRequiredInterfaceExpr <- encodeExpr val
pureExpr $ P.ExprSumFromRequiredInterface P.Expr_FromRequiredInterface{..}
EInterfaceTemplateTypeRep ty val -> do
expr_InterfaceTemplateTypeRepInterface <- encodeQualTypeConName ty
expr_InterfaceTemplateTypeRepExpr <- encodeExpr val
pureExpr $ P.ExprSumInterfaceTemplateTypeRep P.Expr_InterfaceTemplateTypeRep{..}
ESignatoryInterface ty val -> do
expr_SignatoryInterfaceInterface <- encodeQualTypeConName ty
expr_SignatoryInterfaceExpr <- encodeExpr val
pureExpr $ P.ExprSumSignatoryInterface P.Expr_SignatoryInterface{..}
EObserverInterface ty val -> do
expr_ObserverInterfaceInterface <- encodeQualTypeConName ty
expr_ObserverInterfaceExpr <- encodeExpr val
pureExpr $ P.ExprSumObserverInterface P.Expr_ObserverInterface{..}
EExperimental name ty -> do
let expr_ExperimentalName = encodeString name
expr_ExperimentalType <- encodeType ty
Expand Down
3 changes: 3 additions & 0 deletions compiler/daml-lf-tools/src/DA/Daml/LF/Simplifier.hs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,9 @@ safetyStep = \case
ECallInterfaceF _ _ _ -> Unsafe
EToRequiredInterfaceF _ _ s -> s <> Safe 0
EFromRequiredInterfaceF _ _ s -> s <> Safe 0
EInterfaceTemplateTypeRepF _ s -> s <> Safe 0
ESignatoryInterfaceF _ s -> s <> Safe 0
EObserverInterfaceF _ s -> s <> Safe 0
EExperimentalF _ _ -> Unsafe

isTypeClassDictionary :: DefValue -> Bool
Expand Down
17 changes: 12 additions & 5 deletions compiler/daml-lf-tools/src/DA/Daml/LF/TypeChecker/Check.hs
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,18 @@ typeOf' = \case
throwWithContext (EWrongInterfaceRequirement requiringIface requiredIface)
checkExpr expr (TCon requiredIface)
pure (TOptional (TCon requiringIface))
EInterfaceTemplateTypeRep iface expr -> do
void $ inWorld (lookupInterface iface)
checkExpr expr (TCon iface)
pure TTypeRep
ESignatoryInterface iface expr -> do
void $ inWorld (lookupInterface iface)
checkExpr expr (TCon iface)
pure (TList TParty)
EObserverInterface iface expr -> do
void $ inWorld (lookupInterface iface)
checkExpr expr (TCon iface)
pure (TList TParty)
EUpdate upd -> typeOfUpdate upd
EScenario scen -> typeOfScenario scen
ELocation _ expr -> typeOf' expr
Expand All @@ -775,11 +787,6 @@ typeOf' = \case

checkExperimentalType :: MonadGamma m => T.Text -> Type -> m ()
checkExperimentalType "ANSWER" (TUnit :-> TInt64) = pure ()
checkExperimentalType "TO_TYPE_REP" (TCon _iface :-> TTypeRep) = pure ()
checkExperimentalType "RESOLVE_VIRTUAL_SIGNATORY"
(TCon iface1 :-> TCon iface2 :-> TList TParty) | iface1 == iface2 = pure ()
checkExperimentalType "RESOLVE_VIRTUAL_OBSERVER"
(TCon iface1 :-> TCon iface2 :-> TList TParty) | iface1 == iface2 = pure ()
checkExperimentalType name ty =
throwWithContext (EUnknownExperimental name ty)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,17 +358,17 @@ convertPrim _ "EToAnyContractKey"
ETmLam (mkVar "key", key) $
EToAny key (EVar $ mkVar "key")

convertPrim _ "EInterfaceTemplateTypeRep" (TCon interface :-> TTypeRep) =
ETmLam (mkVar "this", TCon interface) $
EInterfaceTemplateTypeRep interface (EVar (mkVar "this"))

convertPrim _ "ESignatoryInterface" (TCon interface :-> TList TParty) =
ETmLam (mkVar "this", TCon interface) $
EExperimental "RESOLVE_VIRTUAL_SIGNATORY"
(TCon interface :-> TCon interface :-> TList TParty)
`ETmApp` EVar (mkVar "this") `ETmApp` EVar (mkVar "this")
ESignatoryInterface interface (EVar (mkVar "this"))

convertPrim _ "EObserverInterface" (TCon interface :-> TList TParty) =
ETmLam (mkVar "this", TCon interface) $
EExperimental "RESOLVE_VIRTUAL_OBSERVER"
(TCon interface :-> TCon interface :-> TList TParty)
`ETmApp` EVar (mkVar "this") `ETmApp` EVar (mkVar "this")
EObserverInterface interface (EVar (mkVar "this"))

-- Exceptions
convertPrim _ "BEAnyExceptionMessage" (TBuiltin BTAnyException :-> TText) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ module InterfaceDesugared where
import DA.Assert ( (===) )
data GHC.Types.DamlInterface => Token = Token GHC.Types.Opaque
instance DA.Internal.Desugar.HasInterfaceTypeRep Token where
interfaceTypeRep = GHC.Types.primitive @"$TO_TYPE_REP"
interfaceTypeRep = GHC.Types.primitive @"EInterfaceTemplateTypeRep"
instance DA.Internal.Desugar.HasToInterface Token Token where
_toInterface this = this
instance DA.Internal.Desugar.HasFromInterface Token Token where
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,31 @@ message Expr {
Expr interface_expr = 3;
}

// Obtain the type representation of a contract through an interface
// *Available in versions >= 1.dev*
message InterfaceTemplateTypeRep {
// interface type
TypeConName interface = 1;
// interface argument
Expr expr = 2;
}

// Obtain the signatories of a contract through an interface
message SignatoryInterface {
// Interface type
TypeConName interface = 1;
// Interface argument
Expr expr = 2;
}

// Obtain the observers of a contract through an interface
message ObserverInterface {
// Interface type
TypeConName interface = 1;
// Interface argument
Expr expr = 2;
}

message Experimental {
string name = 1;
Type type = 2 ;
Expand Down Expand Up @@ -1078,6 +1103,15 @@ message Expr {
ToRequiredInterface to_required_interface = 39;
FromRequiredInterface from_required_interface = 40;

// Obtain the type representation of a contract's template through an interface.
// *Available in versions >= 1.dev*
InterfaceTemplateTypeRep interface_template_type_rep = 41;

// Obtain a contract's signatories/observers through an interface.
// *Available in versions >= 1.dev*
SignatoryInterface signatory_interface = 42;
ObserverInterface observer_interface = 43;

Experimental experimental = 9999; // *Available only in 1.dev*
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1160,6 +1160,30 @@ private[archive] class DecodeV1(minor: LV.Minor) {
body = decodeExpr(fromRequiredInterface.getExpr, definition),
)

case PLF.Expr.SumCase.INTERFACE_TEMPLATE_TYPE_REP =>
assertSince(LV.Features.interfaces, "Expr.interface_template_type_rep")
val interfaceTemplateTypeRep = lfExpr.getInterfaceTemplateTypeRep
EInterfaceTemplateTypeRep(
ifaceId = decodeTypeConName(interfaceTemplateTypeRep.getInterface),
body = decodeExpr(interfaceTemplateTypeRep.getExpr, definition),
)

case PLF.Expr.SumCase.SIGNATORY_INTERFACE =>
assertSince(LV.Features.interfaces, "Expr.signatory_interface")
val signatoryInterface = lfExpr.getSignatoryInterface
ESignatoryInterface(
ifaceId = decodeTypeConName(signatoryInterface.getInterface),
body = decodeExpr(signatoryInterface.getExpr, definition),
)

case PLF.Expr.SumCase.OBSERVER_INTERFACE =>
assertSince(LV.Features.interfaces, "Expr.observer_interface")
val observerInterface = lfExpr.getObserverInterface
EObserverInterface(
ifaceId = decodeTypeConName(observerInterface.getInterface),
body = decodeExpr(observerInterface.getExpr, definition),
)

case PLF.Expr.SumCase.SUM_NOT_SET =>
throw Error.Parsing("Expr.SUM_NOT_SET")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,14 @@ private[lf] final class Compiler(
compile(env, body)
case EFromRequiredInterface(requiredIfaceId @ _, requiringIfaceId, body @ _) =>
SBFromRequiredInterface(requiringIfaceId)(compile(env, body))
case EInterfaceTemplateTypeRep(ifaceId, body @ _) =>
SBInterfaceTemplateTypeRep(ifaceId)(compile(env, body))
case ESignatoryInterface(ifaceId, body @ _) =>
val arg = compile(env, body)
SBSignatoryInterface(ifaceId)(arg, arg)
case EObserverInterface(ifaceId, body @ _) =>
val arg = compile(env, body)
SBObserverInterface(ifaceId)(arg, arg)
case EExperimental(name, _) =>
SBExperimental(name)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1220,6 +1220,12 @@ private[lf] object SBuiltin {
final case class SBResolveCreateByInterface(ifaceId: TypeConName)
extends SBResolveVirtual(ref => CreateByInterfaceDefRef(ref, ifaceId))

final case class SBSignatoryInterface(ifaceId: TypeConName)
extends SBResolveVirtual(SignatoriesDefRef)

final case class SBObserverInterface(ifaceId: TypeConName)
extends SBResolveVirtual(ObserversDefRef)

// Convert an interface to a given template type if possible. Since interfaces have the
// same representation as the underlying template, we only need to perform a check
// that the record type matches the template type.
Expand Down Expand Up @@ -1645,6 +1651,17 @@ private[lf] object SBuiltin {
}
}

/** $interface_template_type_rep
* :: t
* -> TypeRep (where t = TTyCon(_))
*/
final case class SBInterfaceTemplateTypeRep(tycon: TypeConName) extends SBuiltinPure(1) {
override private[speedy] def executePure(args: util.ArrayList[SValue]): STypeRep = {
val id = getSRecord(args, 0).id
STypeRep(Ast.TTyCon(id))
}
}

// Unstable text primitives.

/** $text_to_upper :: Text -> Text */
Expand Down Expand Up @@ -1844,20 +1861,10 @@ private[lf] object SBuiltin {
machine.returnValue = SInt64(42L)
}

private object SBExperimentalToTypeRep extends SBuiltinPure(1) {
override private[speedy] def executePure(args: util.ArrayList[SValue]): STypeRep = {
val id = getSRecord(args, 0).id
STypeRep(Ast.TTyCon(id))
}
}

//TODO: move this into the speedy compiler code
private val mapping: Map[String, compileTime.SExpr] =
List(
"ANSWER" -> SBExperimentalAnswer,
"TO_TYPE_REP" -> SBExperimentalToTypeRep,
"RESOLVE_VIRTUAL_SIGNATORY" -> new SBResolveVirtual(SignatoriesDefRef),
"RESOLVE_VIRTUAL_OBSERVER" -> new SBResolveVirtual(ObserversDefRef),
"ANSWER" -> SBExperimentalAnswer
).view.map { case (name, builtin) => name -> compileTime.SEBuiltin(builtin) }.toMap

def apply(name: String): compileTime.SExpr =
Expand Down
Loading

0 comments on commit 3ce272b

Please sign in to comment.