From 7f269c39fd6358e9448e155975efa84e0b4f3d1a Mon Sep 17 00:00:00 2001 From: Sofia Faro Date: Tue, 21 Sep 2021 15:27:57 +0100 Subject: [PATCH] interface: Add to/from interface in scala ast Part of #10810 changelog_begin changelog_end --- .../daml/lf/archive/DecodeV1.scala | 20 +++++++++++++++---- .../daml/lf/archive/testing/EncodeV1.scala | 18 +++++++++++++++++ .../daml/lf/speedy/Compiler.scala | 4 ++++ .../digitalasset/daml/lf/language/Ast.scala | 6 ++++++ .../daml/lf/testing/parser/AstRewriter.scala | 4 ++++ .../daml/lf/validation/Typing.scala | 16 +++++++++++++++ .../daml/lf/validation/ValidationError.scala | 9 +++++++++ .../lf/validation/iterable/ExprIterable.scala | 4 ++++ .../lf/validation/iterable/TypeIterable.scala | 4 ++++ 9 files changed, 81 insertions(+), 4 deletions(-) diff --git a/daml-lf/archive/src/main/scala/com/digitalasset/daml/lf/archive/DecodeV1.scala b/daml-lf/archive/src/main/scala/com/digitalasset/daml/lf/archive/DecodeV1.scala index 81d005c0533f..7c1621e802ae 100644 --- a/daml-lf/archive/src/main/scala/com/digitalasset/daml/lf/archive/DecodeV1.scala +++ b/daml-lf/archive/src/main/scala/com/digitalasset/daml/lf/archive/DecodeV1.scala @@ -1096,11 +1096,23 @@ private[archive] class DecodeV1(minor: LV.Minor) { value = decodeExpr(fromAnyException.getExpr, definition), ) - case PLF.Expr.SumCase.TO_INTERFACE => // TODO https://github.com/digital-asset/daml/issues/10810 - throw Error.Parsing("to_interface not yet implemented") + case PLF.Expr.SumCase.TO_INTERFACE => + assertSince(LV.Features.interfaces, "Expr.to_interface") + val toInterface = lfExpr.getToInterface + EToInterface( + iface = decodeTypeConName(toInterface.getInterfaceType), + tpl = decodeTypeConName(toInterface.getTemplateType), + value = decodeExpr(toInterface.getTemplateExpr, definition), + ) - case PLF.Expr.SumCase.FROM_INTERFACE => // TODO https://github.com/digital-asset/daml/issues/10810 - throw Error.Parsing("from_interface not yet implemented") + case PLF.Expr.SumCase.FROM_INTERFACE => + assertSince(LV.Features.interfaces, "Expr.from_interface") + val fromInterface = lfExpr.getFromInterface + EFromInterface( + iface = decodeTypeConName(fromInterface.getInterfaceType), + tpl = decodeTypeConName(fromInterface.getTemplateType), + value = decodeExpr(fromInterface.getInterfaceExpr, definition), + ) case PLF.Expr.SumCase.SUM_NOT_SET => throw Error.Parsing("Expr.SUM_NOT_SET") diff --git a/daml-lf/encoder/src/main/scala/com/digitalasset/daml/lf/archive/testing/EncodeV1.scala b/daml-lf/encoder/src/main/scala/com/digitalasset/daml/lf/archive/testing/EncodeV1.scala index 22766d9522ac..2f59c2bb0c69 100644 --- a/daml-lf/encoder/src/main/scala/com/digitalasset/daml/lf/archive/testing/EncodeV1.scala +++ b/daml-lf/encoder/src/main/scala/com/digitalasset/daml/lf/archive/testing/EncodeV1.scala @@ -655,6 +655,24 @@ private[daml] class EncodeV1(minor: LV.Minor) { builder.setFromAnyException( PLF.Expr.FromAnyException.newBuilder().setType(ty).setExpr(body) ) + case EToInterface(iface, tpl, value) => + assertSince(LV.Features.interfaces, "Expr.ToInterface") + builder.setToInterface( + PLF.Expr.ToInterface + .newBuilder() + .setInterfaceType(iface) + .setTemplateType(tpl) + .setTemplateExpr(value) + ) + case EFromInterface(iface, tpl, value) => + assertSince(LV.Features.interfaces, "Expr.FromInterface") + builder.setFromInterface( + PLF.Expr.FromInterface + .newBuilder() + .setInterfaceType(iface) + .setTemplateType(tpl) + .setInterfaceExpr(value) + ) case EExperimental(name, ty) => assertSince(LV.v1_dev, "Expr.experimental") builder.setExperimental(PLF.Expr.Experimental.newBuilder().setName(name).setType(ty)) diff --git a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Compiler.scala b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Compiler.scala index f52b056843be..f9024abcf6c3 100644 --- a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Compiler.scala +++ b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Compiler.scala @@ -500,6 +500,10 @@ private[lf] final class Compiler( SBFromAny(ty)(compile(e)) case EThrow(_, ty, e) => SBThrow(SBToAny(ty)(compile(e))) + case EToInterface(_, _, _) => // TODO https://github.com/digital-asset/daml/issues/10810 + throw CompilationError("EToInterface not yet implemented in speedy compiler") + case EFromInterface(_, _, _) => // TODO https://github.com/digital-asset/daml/issues/10810 + throw CompilationError("EFromInterface not yet implemented in speedy compiler") case EExperimental(name, _) => SBExperimental(name) diff --git a/daml-lf/language/src/main/scala/com/digitalasset/daml/lf/language/Ast.scala b/daml-lf/language/src/main/scala/com/digitalasset/daml/lf/language/Ast.scala index 7f2eaec2090d..162bb1b4476c 100644 --- a/daml-lf/language/src/main/scala/com/digitalasset/daml/lf/language/Ast.scala +++ b/daml-lf/language/src/main/scala/com/digitalasset/daml/lf/language/Ast.scala @@ -155,6 +155,12 @@ object Ast { /** Extract the payload from an AnyException if it matches the given exception type */ final case class EFromAnyException(typ: Type, value: Expr) extends Expr + /** Convert template payload to interface it implements */ + final case class EToInterface(iface: TypeConName, tpl: TypeConName, value: Expr) extends Expr + + /** Convert interface back to template payload if possible */ + final case class EFromInterface(iface: TypeConName, tpl: TypeConName, value: Expr) extends Expr + // // Kinds // diff --git a/daml-lf/parser/src/main/scala/com/digitalasset/daml/lf/testing/parser/AstRewriter.scala b/daml-lf/parser/src/main/scala/com/digitalasset/daml/lf/testing/parser/AstRewriter.scala index 3b083eda36ba..fbbf8e35989d 100644 --- a/daml-lf/parser/src/main/scala/com/digitalasset/daml/lf/testing/parser/AstRewriter.scala +++ b/daml-lf/parser/src/main/scala/com/digitalasset/daml/lf/testing/parser/AstRewriter.scala @@ -125,6 +125,10 @@ private[daml] class AstRewriter( EFromAnyException(apply(ty), apply(body)) case EToAnyException(typ, body) => EToAnyException(apply(typ), apply(body)) + case EToInterface(iface, tpl, value) => + EToInterface(apply(iface), apply(tpl), apply(value)) + case EFromInterface(iface, tpl, value) => + EFromInterface(apply(iface), apply(tpl), apply(value)) } def apply(x: TypeConApp): TypeConApp = x match { diff --git a/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/Typing.scala b/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/Typing.scala index b265db0aaa83..87e91d38e2d7 100644 --- a/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/Typing.scala +++ b/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/Typing.scala @@ -931,6 +931,14 @@ private[validation] object Typing { TUpdate(TTyCon(tpl)) } + private def checkImplements(tpl: TypeConName, iface: TypeConName): Unit = { + handleLookup(ctx, interface.lookupInterface(iface)) + val template = handleLookup(ctx, interface.lookupTemplate(tpl)) + if (!template.implements.contains(iface)) + throw ETemplateDoesNotImplementInterface(ctx, tpl, iface) + () + } + private def checkByKey(tmplId: TypeConName, key: Expr): Unit = { val tmplKey = handleLookup(ctx, interface.lookupTemplateKey(tmplId)) checkExpr(key, tmplKey.typ) @@ -1135,6 +1143,14 @@ private[validation] object Typing { checkExceptionType(typ) checkExpr(value, TAnyException) TOptional(typ) + case EToInterface(iface, tpl, value) => + checkImplements(tpl, iface) + checkExpr(value, TTyCon(tpl)) + TTyCon(iface) + case EFromInterface(iface, tpl, value) => + checkImplements(tpl, iface) + checkExpr(value, TTyCon(iface)) + TOptional(TTyCon(tpl)) case EExperimental(_, typ) => typ } diff --git a/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/ValidationError.scala b/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/ValidationError.scala index 2d9359e652a6..52a87ef3def3 100644 --- a/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/ValidationError.scala +++ b/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/ValidationError.scala @@ -457,3 +457,12 @@ final case class EBadInterfaceChoiceImplRetType( override protected def prettyInternal: String = s"The implementation of the choice $choice of interface $iface in template $template differs from the interface definition in the return type.\nExpected: $ifaceRetType\n But got: $tplRetType" } + +final case class ETemplateDoesNotImplementInterface( + context: Context, + template: TypeConName, + iface: TypeConName, +) extends ValidationError { + override protected def prettyInternal: String = + s"Template $template does not implement interface $iface" +} diff --git a/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/iterable/ExprIterable.scala b/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/iterable/ExprIterable.scala index dd55faa9daf4..3b82b04ad485 100644 --- a/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/iterable/ExprIterable.scala +++ b/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/iterable/ExprIterable.scala @@ -64,6 +64,10 @@ private[validation] object ExprIterable { Iterator(value) case EFromAnyException(typ @ _, value) => Iterator(value) + case EToInterface(iface @ _, tpl @ _, value) => + Iterator(value) + case EFromInterface(iface @ _, tpl @ _, value) => + Iterator(value) } } diff --git a/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/iterable/TypeIterable.scala b/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/iterable/TypeIterable.scala index a68f3c2d900a..84a378772f37 100644 --- a/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/iterable/TypeIterable.scala +++ b/daml-lf/validation/src/main/scala/com/digitalasset/daml/lf/validation/iterable/TypeIterable.scala @@ -78,6 +78,10 @@ private[validation] object TypeIterable { case EFromAnyException(typ, value) => Iterator(typ) ++ iterator(value) + case EToInterface(iface, tpl, value) => + Iterator(TTyCon(iface), TTyCon(tpl)) ++ iterator(value) + case EFromInterface(iface, tpl, value) => + Iterator(TTyCon(iface), TTyCon(tpl)) ++ iterator(value) case EVar(_) | EVal(_) | EBuiltin(_) | EPrimCon(_) | EPrimLit(_) | EApp(_, _) | ECase(_, _) | ELocation(_, _) | EStructCon(_) | EStructProj(_, _) | EStructUpd(_, _, _) | ETyAbs(_, _) | EExperimental(_, _) =>