mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-19 16:57:40 +03:00
LF: Add interface fixed choices in scala AST and type checker (#11146)
CHANGELOG_BEGIN CHANGELOG_END
This commit is contained in:
parent
08b9f82614
commit
4336184a79
@ -284,7 +284,7 @@ private[archive] class DecodeV1(minor: LV.Minor) {
|
||||
} else {
|
||||
lfModule.getInterfacesList.asScala.foreach { defn =>
|
||||
val defName = getInternedDottedName(defn.getTyconInternedDname)
|
||||
interfaces += (defName -> decodeDefInterface(defn))
|
||||
interfaces += (defName -> decodeDefInterface(defName, defn))
|
||||
}
|
||||
}
|
||||
|
||||
@ -662,15 +662,20 @@ private[archive] class DecodeV1(minor: LV.Minor) {
|
||||
DefException(decodeExpr(lfException.getMessage, s"$exceptionName:message"))
|
||||
|
||||
private[this] def decodeDefInterface(
|
||||
lfInterface: PLF.DefInterface
|
||||
id: DottedName,
|
||||
lfInterface: PLF.DefInterface,
|
||||
): DefInterface =
|
||||
DefInterface(
|
||||
lfInterface.getChoicesList.asScala.toList
|
||||
param = getInternedName(lfInterface.getParamInternedStr, "DefInterface.param"),
|
||||
virtualChoices = lfInterface.getChoicesList.asScala.view
|
||||
.map(decodeInterfaceChoice)
|
||||
.map(choice => (choice.name, choice)),
|
||||
lfInterface.getMethodsList.asScala.toList
|
||||
.map(choice => choice.name -> choice),
|
||||
fixedChoices = lfInterface.getFixedChoicesList.asScala.view
|
||||
.map(decodeChoice(id, _))
|
||||
.map(choice => choice.name -> choice),
|
||||
methods = lfInterface.getMethodsList.asScala.view
|
||||
.map(decodeInterfaceMethod)
|
||||
.map(method => (method.name, method)),
|
||||
.map(method => method.name -> method),
|
||||
)
|
||||
|
||||
private[this] def decodeInterfaceChoice(
|
||||
|
@ -724,7 +724,7 @@ private[daml] class EncodeV1(minor: LV.Minor) {
|
||||
val (dottedName, interface) = nameWithDef
|
||||
val builder = PLF.DefInterface.newBuilder()
|
||||
builder.setTyconInternedDname(dottedNameTable.insert(dottedName))
|
||||
builder.accumulateLeft(interface.choices.sortByKey)(_ addChoices _)
|
||||
builder.accumulateLeft(interface.virtualChoices.sortByKey)(_ addChoices _)
|
||||
// TODO https://github.com/digital-asset/daml/issues/11006
|
||||
// encode interface methods as well
|
||||
builder.build()
|
||||
|
@ -51,7 +51,7 @@ private[lf] final class CommandPreprocessor(
|
||||
case Left(_) =>
|
||||
handleLookup(interface.lookupChoice(identifier, choiceId)).argBinder._2
|
||||
case Right(interfaceChoice) =>
|
||||
interfaceChoice.argType
|
||||
interfaceChoice.fold(_.argType, _.argBinder._2)
|
||||
}
|
||||
val arg = valueTranslator.unsafeTranslateValue(choice, argument)
|
||||
speedy.Command.Exercise(identifier, cid, choiceId, arg)
|
||||
|
@ -338,7 +338,7 @@ private[lf] final class Compiler(
|
||||
module.interfaces.foreach { case (ifaceName, iface) =>
|
||||
val identifier = Identifier(pkgId, QualifiedName(module.name, ifaceName))
|
||||
addDef(compileFetchInterface(identifier))
|
||||
iface.choices.values.foreach(
|
||||
iface.virtualChoices.values.foreach(
|
||||
builder += compileChoiceInterface(identifier, _)
|
||||
)
|
||||
}
|
||||
|
@ -637,28 +637,56 @@ object Ast {
|
||||
type TemplateKeySignature = GenTemplateKey[Unit]
|
||||
val TemplateKeySignature = new GenTemplateKeyCompanion[Unit]
|
||||
|
||||
final case class DefInterface(
|
||||
choices: Map[ChoiceName, InterfaceChoice],
|
||||
final case class GenDefInterface[E](
|
||||
param: ExprVarName, // Binder for template argument.
|
||||
virtualChoices: Map[ChoiceName, InterfaceChoice],
|
||||
fixedChoices: Map[ChoiceName, GenTemplateChoice[E]],
|
||||
methods: Map[MethodName, InterfaceMethod],
|
||||
)
|
||||
) {
|
||||
virtualChoices.keys.foreach(name =>
|
||||
if (fixedChoices.isDefinedAt(name))
|
||||
throw PackageError(s"collision on interface choice name $name")
|
||||
)
|
||||
}
|
||||
|
||||
object DefInterface {
|
||||
final class GenDefInterfaceCompanion[E] {
|
||||
def apply(
|
||||
choices: Iterable[(ChoiceName, InterfaceChoice)],
|
||||
param: ExprVarName, // Binder for template argument.
|
||||
virtualChoices: Iterable[(ChoiceName, InterfaceChoice)],
|
||||
fixedChoices: Iterable[(ChoiceName, GenTemplateChoice[E])],
|
||||
methods: Iterable[(MethodName, InterfaceMethod)],
|
||||
): DefInterface = {
|
||||
val choiceMap = toMapWithoutDuplicate(
|
||||
choices,
|
||||
): GenDefInterface[E] = {
|
||||
val virtualChoiceMap = toMapWithoutDuplicate(
|
||||
virtualChoices,
|
||||
(name: ChoiceName) => throw PackageError(s"collision on interface choice name $name"),
|
||||
)
|
||||
val fixedChoiceMap = toMapWithoutDuplicate(
|
||||
fixedChoices,
|
||||
(name: ChoiceName) => throw PackageError(s"collision on interface choice name $name"),
|
||||
)
|
||||
val methodMap = toMapWithoutDuplicate(
|
||||
methods,
|
||||
(name: MethodName) => throw PackageError(s"collision on interface method name $name"),
|
||||
)
|
||||
DefInterface(choiceMap, methodMap)
|
||||
GenDefInterface(param, virtualChoiceMap, fixedChoiceMap, methodMap)
|
||||
}
|
||||
def unapply(arg: GenDefInterface[E]): Some[
|
||||
(
|
||||
ExprVarName,
|
||||
Map[ChoiceName, InterfaceChoice],
|
||||
Map[ChoiceName, GenTemplateChoice[E]],
|
||||
Map[MethodName, InterfaceMethod],
|
||||
)
|
||||
] =
|
||||
Some((arg.param, arg.virtualChoices, arg.fixedChoices, arg.methods))
|
||||
}
|
||||
|
||||
type DefInterface = GenDefInterface[Expr]
|
||||
val DefInterface = new GenDefInterfaceCompanion[Expr]
|
||||
|
||||
type DefInterfaceSignature = GenDefInterface[Unit]
|
||||
val DefInterfaceSignature = new GenDefInterfaceCompanion[Unit]
|
||||
|
||||
final case class InterfaceChoice(
|
||||
name: ChoiceName,
|
||||
consuming: Boolean,
|
||||
@ -925,7 +953,7 @@ object Ast {
|
||||
definitions: Map[DottedName, GenDefinition[E]],
|
||||
templates: Map[DottedName, GenTemplate[E]],
|
||||
exceptions: Map[DottedName, GenDefException[E]],
|
||||
interfaces: Map[DottedName, DefInterface],
|
||||
interfaces: Map[DottedName, GenDefInterface[E]],
|
||||
featureFlags: FeatureFlags,
|
||||
) {
|
||||
templates.keysIterator.foreach(name =>
|
||||
@ -953,7 +981,7 @@ object Ast {
|
||||
definitions: Iterable[(DottedName, GenDefinition[E])],
|
||||
templates: Iterable[(DottedName, GenTemplate[E])],
|
||||
exceptions: Iterable[(DottedName, GenDefException[E])],
|
||||
interfaces: Iterable[(DottedName, DefInterface)],
|
||||
interfaces: Iterable[(DottedName, GenDefInterface[E])],
|
||||
featureFlags: FeatureFlags,
|
||||
): GenModule[E] = {
|
||||
|
||||
@ -990,7 +1018,7 @@ object Ast {
|
||||
Map[DottedName, GenDefinition[E]],
|
||||
Map[DottedName, GenTemplate[E]],
|
||||
Map[DottedName, GenDefException[E]],
|
||||
Map[DottedName, DefInterface],
|
||||
Map[DottedName, GenDefInterface[E]],
|
||||
FeatureFlags,
|
||||
)
|
||||
] = Some(
|
||||
|
@ -182,14 +182,14 @@ private[lf] class PackageInterface(signatures: PartialFunction[PackageId, Packag
|
||||
private[this] def lookupInterface(
|
||||
name: TypeConName,
|
||||
context: => Reference,
|
||||
): Either[LookupError, DefInterface] =
|
||||
): Either[LookupError, DefInterfaceSignature] =
|
||||
lookupModule(name.packageId, name.qualifiedName.module, context).flatMap(
|
||||
_.interfaces
|
||||
.get(name.qualifiedName.name)
|
||||
.toRight(LookupError(Reference.Interface(name), context))
|
||||
)
|
||||
|
||||
def lookupInterface(name: TypeConName): Either[LookupError, DefInterface] =
|
||||
def lookupInterface(name: TypeConName): Either[LookupError, DefInterfaceSignature] =
|
||||
lookupInterface(name, Reference.Interface(name))
|
||||
|
||||
private[this] def lookupChoice(
|
||||
@ -211,15 +211,23 @@ private[lf] class PackageInterface(signatures: PartialFunction[PackageId, Packag
|
||||
ifaceName: TypeConName,
|
||||
chName: ChoiceName,
|
||||
context: => Reference,
|
||||
): Either[LookupError, InterfaceChoice] =
|
||||
lookupInterface(ifaceName, context).flatMap(
|
||||
_.choices.get(chName).toRight(LookupError(Reference.Choice(ifaceName, chName), context))
|
||||
): Either[LookupError, Either[InterfaceChoice, TemplateChoiceSignature]] =
|
||||
lookupInterface(ifaceName, context).flatMap(iface =>
|
||||
iface.virtualChoices.get(chName) match {
|
||||
case Some(choice) =>
|
||||
Right(Left(choice))
|
||||
case None =>
|
||||
iface.fixedChoices.get(chName) match {
|
||||
case Some(choice) => Right(Right(choice))
|
||||
case None => Left(LookupError(Reference.Choice(ifaceName, chName), context))
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
def lookupInterfaceChoice(
|
||||
ifaceName: TypeConName,
|
||||
chName: ChoiceName,
|
||||
): Either[LookupError, InterfaceChoice] =
|
||||
): Either[LookupError, Either[InterfaceChoice, TemplateChoiceSignature]] =
|
||||
lookupInterfaceChoice(ifaceName, chName, Reference.Choice(ifaceName, chName))
|
||||
|
||||
private[this] def lookupInterfaceMethod(
|
||||
|
@ -230,6 +230,17 @@ object Util {
|
||||
)
|
||||
}
|
||||
|
||||
private def toSignature(interface: DefInterface): DefInterfaceSignature =
|
||||
interface match {
|
||||
case DefInterface(param, virtualChoices, fixedChoices, methods) =>
|
||||
DefInterfaceSignature(
|
||||
param,
|
||||
virtualChoices,
|
||||
fixedChoices.transform((_, choice) => toSignature(choice)),
|
||||
methods,
|
||||
)
|
||||
}
|
||||
|
||||
private[this] def toSignature(module: Module): ModuleSignature =
|
||||
module match {
|
||||
case Module(name, definitions, templates, exceptions, interfaces, featureFlags) =>
|
||||
@ -242,7 +253,7 @@ object Util {
|
||||
},
|
||||
templates = templates.transform((_, template) => toSignature(template)),
|
||||
exceptions = exceptions.transform((_, _) => DefExceptionSignature),
|
||||
interfaces = interfaces,
|
||||
interfaces = interfaces.transform((_, iface) => toSignature(iface)),
|
||||
featureFlags = featureFlags,
|
||||
)
|
||||
}
|
||||
|
@ -323,10 +323,12 @@ private[daml] class AstRewriter(
|
||||
|
||||
def apply(x: DefInterface): DefInterface =
|
||||
x match {
|
||||
case DefInterface(choices, methods) =>
|
||||
case DefInterface(param, virtualChoices, fixedChoices, methods) =>
|
||||
DefInterface(
|
||||
choices.transform((_, x) => apply(x)),
|
||||
methods.transform((_, x) => apply(x)),
|
||||
param,
|
||||
virtualChoices.transform((_, v) => apply(v)),
|
||||
fixedChoices.transform((_, v) => apply(v)),
|
||||
methods.transform((_, v) => apply(v)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -308,8 +308,8 @@ private[validation] object Typing {
|
||||
// uniquess of choice names is already checked on construction of the choice map.
|
||||
val tyConName = TypeConName(pkgId, QualifiedName(mod.name, ifaceName))
|
||||
val env = Env(langVersion, interface, ContextDefInterface(tyConName), Map.empty)
|
||||
defInterface.choices.values.foreach { env.checkIfaceChoice(_) }
|
||||
defInterface.methods.values.foreach { env.checkIfaceMethod(_) }
|
||||
defInterface.virtualChoices.values.foreach(env.checkIfaceChoice(_))
|
||||
defInterface.methods.values.foreach(env.checkIfaceMethod(_))
|
||||
}
|
||||
}
|
||||
|
||||
@ -468,9 +468,9 @@ private[validation] object Typing {
|
||||
}
|
||||
|
||||
def checkIfaceImplementation(tplTcon: TypeConName, impl: TemplateImplements): Unit = {
|
||||
val DefInterface(choices, methods) =
|
||||
val DefInterfaceSignature(_, virtualChoices, _, methods) =
|
||||
handleLookup(ctx, interface.lookupInterface(impl.interface))
|
||||
choices.values.foreach { case InterfaceChoice(name, consuming, argType, returnType) =>
|
||||
virtualChoices.values.foreach { case InterfaceChoice(name, consuming, argType, returnType) =>
|
||||
val tplChoice = handleLookup(ctx, interface.lookupChoice(tplTcon, name))
|
||||
if (tplChoice.consuming != consuming)
|
||||
throw EBadInterfaceChoiceImplConsuming(
|
||||
@ -920,10 +920,15 @@ private[validation] object Typing {
|
||||
cid: Expr,
|
||||
arg: Expr,
|
||||
): Type = {
|
||||
val choice = handleLookup(ctx, interface.lookupInterfaceChoice(tpl, chName))
|
||||
checkExpr(cid, TContractId(TTyCon(tpl)))
|
||||
checkExpr(arg, choice.argType)
|
||||
TUpdate(choice.returnType)
|
||||
handleLookup(ctx, interface.lookupInterfaceChoice(tpl, chName)) match {
|
||||
case Left(virtualChoice) =>
|
||||
checkExpr(arg, virtualChoice.argType)
|
||||
TUpdate(virtualChoice.returnType)
|
||||
case Right(fixedChoice) =>
|
||||
checkExpr(arg, fixedChoice.argBinder._2)
|
||||
TUpdate(fixedChoice.returnType)
|
||||
}
|
||||
}
|
||||
|
||||
private def typeOfExerciseByKey(
|
||||
|
@ -238,9 +238,10 @@ private[validation] object TypeIterable {
|
||||
|
||||
private[validation] def iterator(interface: DefInterface): Iterator[Type] =
|
||||
interface match {
|
||||
case DefInterface(choices, methods) =>
|
||||
choices.values.iterator.flatMap(iterator(_)) ++
|
||||
methods.values.iterator.flatMap(iterator(_))
|
||||
case DefInterface(_, virtualChoices, fixedChoice, methods) =>
|
||||
virtualChoices.values.iterator.flatMap(iterator) ++
|
||||
fixedChoice.values.iterator.flatMap(iterator) ++
|
||||
methods.values.iterator.flatMap(iterator)
|
||||
}
|
||||
|
||||
private[validation] def iterator(ichoice: InterfaceChoice): Iterator[Type] =
|
||||
|
Loading…
Reference in New Issue
Block a user