Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add optional typerep argument in UExerciseInterface. #11910

Merged
merged 6 commits into from
Nov 30, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions compiler/daml-lf-ast/src/DA/Daml/LF/Ast/Alpha.hs
Original file line number Diff line number Diff line change
Expand Up @@ -309,11 +309,13 @@ alphaUpdate env = \case
&& alphaExpr' env e1a e2a
&& alphaExpr' env e1b e2b
_ -> False
UExerciseInterface i1 c1 e1a e1b -> \case
UExerciseInterface i2 c2 e2a e2b -> alphaTypeCon i1 i2
UExerciseInterface i1 c1 e1a e1b e1c e1d -> \case
UExerciseInterface i2 c2 e2a e2b e2c e2d -> alphaTypeCon i1 i2
&& c1 == c2
&& alphaExpr' env e1a e2a
&& alphaExpr' env e1b e2b
&& alphaExpr' env e1c e2c
&& alphaExpr' env e1d e2d
_ -> False
UExerciseByKey t1 c1 e1a e1b -> \case
UExerciseByKey t2 c2 e2a e2b -> alphaTypeCon t1 t2
Expand Down
5 changes: 5 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 @@ -683,6 +683,11 @@ data Update
-- ^ Contract id of the contract template instance to exercise choice on.
, exeArg :: !Expr
-- ^ Argument for the choice.
, exeTypeRep :: !Expr
-- ^ Optional TypeRep with the expected template ID.
, exeGuard :: !Expr
-- ^ Exercise guard (Interface -> Bool) to abort the transaction eagerly
-- if the payload does not satisfy the predicate.
}
-- | Exercise a choice on a contract by key.
| UExerciseByKey
Expand Down
2 changes: 1 addition & 1 deletion compiler/daml-lf-ast/src/DA/Daml/LF/Ast/FreeVars.hs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ freeVarsStep = \case
UCreateF _ e -> e
UCreateInterfaceF _ e -> e
UExerciseF _ _ e1 e2 -> e1 <> e2
UExerciseInterfaceF _ _ e1 e2 -> e1 <> e2
UExerciseInterfaceF _ _ e1 e2 e3 e4 -> e1 <> e2 <> e3 <> e4
UExerciseByKeyF _ _ e1 e2 -> e1 <> e2
UFetchF _ e -> e
UFetchInterfaceF _ e -> e
Expand Down
4 changes: 2 additions & 2 deletions compiler/daml-lf-ast/src/DA/Daml/LF/Ast/Pretty.hs
Original file line number Diff line number Diff line change
Expand Up @@ -418,10 +418,10 @@ instance Pretty Update where
-- NOTE(MH): Converting the choice name into a variable is a bit of a hack.
pPrintAppKeyword lvl prec "exercise"
[tplArg tpl, TmArg (EVar (ExprVarName (unChoiceName choice))), TmArg cid, TmArg arg]
UExerciseInterface interface choice cid arg ->
UExerciseInterface interface choice cid arg typeRep guard ->
-- NOTE(MH): Converting the choice name into a variable is a bit of a hack.
pPrintAppKeyword lvl prec "exercise_interface"
[interfaceArg interface, TmArg (EVar (ExprVarName (unChoiceName choice))), TmArg cid, TmArg arg]
[interfaceArg interface, TmArg (EVar (ExprVarName (unChoiceName choice))), TmArg cid, TmArg arg, TmArg typeRep, TmArg guard]
UExerciseByKey tpl choice key arg ->
pPrintAppKeyword lvl prec "exercise_by_key"
[tplArg tpl, TmArg (EVar (ExprVarName (unChoiceName choice))), TmArg key, TmArg arg]
Expand Down
6 changes: 3 additions & 3 deletions compiler/daml-lf-ast/src/DA/Daml/LF/Ast/Recursive.hs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ data UpdateF expr
| UCreateF !(Qualified TypeConName) !expr
| UCreateInterfaceF !(Qualified TypeConName) !expr
| UExerciseF !(Qualified TypeConName) !ChoiceName !expr !expr
| UExerciseInterfaceF !(Qualified TypeConName) !ChoiceName !expr !expr
| UExerciseInterfaceF !(Qualified TypeConName) !ChoiceName !expr !expr !expr !expr
| UExerciseByKeyF !(Qualified TypeConName) !ChoiceName !expr !expr
| UFetchF !(Qualified TypeConName) !expr
| UFetchInterfaceF !(Qualified TypeConName) !expr
Expand Down Expand Up @@ -114,7 +114,7 @@ projectUpdate = \case
UCreate a b -> UCreateF a b
UCreateInterface a b -> UCreateInterfaceF a b
UExercise a b c d -> UExerciseF a b c d
UExerciseInterface a b c d -> UExerciseInterfaceF a b c d
UExerciseInterface a b c d e f -> UExerciseInterfaceF a b c d e f
UExerciseByKey a b c d -> UExerciseByKeyF a b c d
UFetch a b -> UFetchF a b
UFetchInterface a b -> UFetchInterfaceF a b
Expand All @@ -134,7 +134,7 @@ embedUpdate = \case
UCreateF a b -> UCreate a b
UCreateInterfaceF a b -> UCreateInterface a b
UExerciseF a b c d -> UExercise a b c d
UExerciseInterfaceF a b c d -> UExerciseInterface a b c d
UExerciseInterfaceF a b c d e f -> UExerciseInterface a b c d e f
UExerciseByKeyF a b c d -> UExerciseByKey a b c d
UFetchF a b -> UFetch a b
UFetchInterfaceF a b -> UFetchInterface a b
Expand Down
4 changes: 3 additions & 1 deletion compiler/daml-lf-ast/src/DA/Daml/LF/Ast/Subst.hs
Original file line number Diff line number Diff line change
Expand Up @@ -252,11 +252,13 @@ applySubstInUpdate subst = \case
choiceName
(applySubstInExpr subst e1)
(applySubstInExpr subst e2)
UExerciseInterface interface choiceName e1 e2 -> UExerciseInterface
UExerciseInterface interface choiceName e1 e2 e3 e4 -> UExerciseInterface
interface
choiceName
(applySubstInExpr subst e1)
(applySubstInExpr subst e2)
(applySubstInExpr subst e3)
(applySubstInExpr subst e4)
UExerciseByKey templateName choiceName e1 e2 -> UExerciseByKey
templateName
choiceName
Expand Down
2 changes: 2 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 @@ -696,6 +696,8 @@ decodeUpdate LF1.Update{..} = mayDecode "updateSum" updateSum $ \case
<*> decodeNameId ChoiceName update_ExerciseInterfaceChoiceInternedStr
<*> mayDecode "update_ExerciseInterfaceCid" update_ExerciseInterfaceCid decodeExpr
<*> mayDecode "update_ExerciseInterfaceArg" update_ExerciseInterfaceArg decodeExpr
<*> mayDecode "update_ExerciseInterfaceTypeRep" update_ExerciseInterfaceTypeRep decodeExpr
<*> mayDecode "update_ExerciseInterfaceGuard" update_ExerciseInterfaceGuard decodeExpr
LF1.UpdateSumExerciseByKey LF1.Update_ExerciseByKey{..} ->
fmap EUpdate $ UExerciseByKey
<$> mayDecode "update_ExerciseByKeyTemplate" update_ExerciseByKeyTemplate decodeTypeConName
Expand Down
2 changes: 2 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 @@ -761,6 +761,8 @@ encodeUpdate = fmap (P.Update . Just) . \case
update_ExerciseInterfaceChoiceInternedStr <- encodeNameId unChoiceName exeChoice
update_ExerciseInterfaceCid <- encodeExpr exeContractId
update_ExerciseInterfaceArg <- encodeExpr exeArg
update_ExerciseInterfaceTypeRep <- encodeExpr exeTypeRep
update_ExerciseInterfaceGuard <- encodeExpr exeGuard
pure $ P.UpdateSumExerciseInterface P.Update_ExerciseInterface{..}
UExerciseByKey{..} -> do
update_ExerciseByKeyTemplate <- encodeQualTypeConName exeTemplate
Expand Down
13 changes: 8 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 @@ -598,11 +598,13 @@ typeOfExercise tpl chName cid arg = do
pure (TUpdate (chcReturnType choice))

typeOfExerciseInterface :: MonadGamma m =>
Qualified TypeConName -> ChoiceName -> Expr -> Expr -> m Type
typeOfExerciseInterface tpl chName cid arg = do
choice <- inWorld (lookupInterfaceChoice (tpl, chName))
checkExpr cid (TContractId (TCon tpl))
Qualified TypeConName -> ChoiceName -> Expr -> Expr -> Expr -> Expr -> m Type
typeOfExerciseInterface iface chName cid arg typeRep guard = do
choice <- inWorld (lookupInterfaceChoice (iface, chName))
checkExpr cid (TContractId (TCon iface))
checkExpr arg (chcArgType choice)
checkExpr typeRep (TOptional TTypeRep)
checkExpr guard (TCon iface :-> TBool)
pure (TUpdate (chcReturnType choice))

typeOfExerciseByKey :: MonadGamma m =>
Expand Down Expand Up @@ -652,7 +654,8 @@ typeOfUpdate = \case
UCreate tpl arg -> checkCreate tpl arg $> TUpdate (TContractId (TCon tpl))
UCreateInterface iface arg -> checkCreateInterface iface arg $> TUpdate (TContractId (TCon iface))
UExercise tpl choice cid arg -> typeOfExercise tpl choice cid arg
UExerciseInterface tpl choice cid arg -> typeOfExerciseInterface tpl choice cid arg
UExerciseInterface tpl choice cid arg typeRep guard ->
typeOfExerciseInterface tpl choice cid arg typeRep guard
UExerciseByKey tpl choice key arg -> typeOfExerciseByKey tpl choice key arg
UFetch tpl cid -> checkFetch tpl cid $> TUpdate (TCon tpl)
UFetchInterface tpl cid -> checkFetchInterface tpl cid $> TUpdate (TCon tpl)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,10 @@ convertPrim _ "UExerciseInterface"
ETmLam (mkVar "this", TContractId (TCon iface)) $
ETmLam (mkVar "arg", TCon choice) $
EUpdate $ UExerciseInterface iface choiceName (EVar (mkVar "this")) (EVar (mkVar "arg"))
-- TODO https://github.com/digital-asset/daml/issues/11703
-- Pass the typeRep and guard arguments in from daml.
(ENone TTypeRep)
(ETmLam (mkVar "payload", TCon iface) (EBuiltin (BEBool True)))
where
choiceName = ChoiceName (T.intercalate "." $ unTypeConName $ qualObject choice)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1230,6 +1230,10 @@ message Update {
Expr cid = 3;
// argument
Expr arg = 4;
// optional type rep for expected template id
Expr type_rep = 5;
// exercise guard (Interface -> Bool)
Expr guard = 6;
}

// ExerciseByKey Update
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1304,7 +1304,8 @@ private[archive] class DecodeV1(minor: LV.Minor) {
choice = handleInternedName(exercise.getChoiceInternedStr),
cidE = decodeExpr(exercise.getCid, definition),
argE = decodeExpr(exercise.getArg, definition),
guardE = None, // TODO https://github.com/digital-asset/daml/issues/11703
typeRepE = decodeExpr(exercise.getTypeRep, definition),
guardE = decodeExpr(exercise.getGuard, definition),
)

case PLF.Update.SumCase.EXERCISE_BY_KEY =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,14 +380,14 @@ private[daml] class EncodeV1(minor: LV.Minor) {
b.setCid(cid)
b.setArg(arg)
builder.setExercise(b)
case UpdateExerciseInterface(interface, choice, cid, arg, guard @ _) =>
// TODO https://github.com/digital-asset/daml/issues/11703
// Encode guard.
case UpdateExerciseInterface(interface, choice, cid, arg, typeRep, guard) =>
val b = PLF.Update.ExerciseInterface.newBuilder()
b.setInterface(interface)
setInternedString(choice, b.setChoiceInternedStr)
b.setCid(cid)
b.setArg(arg)
b.setTypeRep(typeRep)
b.setGuard(guard)
builder.setExerciseInterface(b)
case UpdateExerciseByKey(templateId, choice, key, arg) =>
assertSince(LV.Features.exerciseByKey, "exerciseByKey")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,8 @@ class InterfacesTest
"be unable to exercise T1 (disguised as T2) by interface I2 " in {
val command = ExerciseCommand(idT2, cid1, "C2", ValueRecord(None, ImmArray.empty))
inside(run(command)) { case Left(Error.Interpretation(err, _)) =>
// TODO https://github.com/digital-asset/daml/issues/11703
// This should really be a WronglyTypedContract error.
err shouldBe Error.Interpretation.DamlException(
IE.ContractDoesNotImplementInterface(idI2, cid1, idT1)
IE.WronglyTypedContract(cid1, idT2, idT1)
)
}
}
Expand Down Expand Up @@ -265,10 +263,8 @@ class InterfacesTest
val command =
ExerciseByInterfaceCommand(idI2, idT2, cid1, "C2", ValueRecord(None, ImmArray.empty))
inside(run(command)) { case Left(Error.Interpretation(err, _)) =>
// TODO https://github.com/digital-asset/daml/issues/11703
// This should really be a WronglyTypedContract error.
err shouldBe Error.Interpretation.DamlException(
IE.ContractDoesNotImplementInterface(idI2, cid1, idT1)
IE.WronglyTypedContract(cid1, idT2, idT1)
)
}
}
Expand Down Expand Up @@ -299,10 +295,8 @@ class InterfacesTest
"be unable to fetch T1 (disguised as T2) via interface I2" in {
val command = FetchByInterfaceCommand(idI2, idT2, cid1)
inside(run(command)) { case Left(Error.Interpretation(err, _)) =>
// TODO https://github.com/digital-asset/daml/issues/11703
// This should really be a WronglyTypedContract error.
err shouldBe Error.Interpretation.DamlException(
IE.ContractDoesNotImplementInterface(idI2, cid1, idT1)
IE.WronglyTypedContract(cid1, idT2, idT1)
)
}
}
Expand Down
Loading