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

interfaces: Add to/from interface in Scala AST #10960

Merged
merged 1 commit into from
Sep 21, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(_, _) =>
Expand Down