mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-20 09:17:43 +03:00
LF: Utility to enrich interface views (#14520)
CHANGELOG_BEGIN CHANGELOG_END * fix * Add test
This commit is contained in:
parent
3a33b3bcde
commit
6caedfb0ca
@ -27,17 +27,15 @@ final class ValueEnricher(
|
||||
loadPackage: (PackageId, language.Reference) => Result[Unit],
|
||||
) {
|
||||
|
||||
def this(engine: Engine) = {
|
||||
def this(engine: Engine) =
|
||||
this(
|
||||
engine.compiledPackages(),
|
||||
engine.preprocessor.translateValue,
|
||||
engine.loadPackage,
|
||||
)
|
||||
}
|
||||
|
||||
def enrichValue(typ: Ast.Type, value: Value): Result[Value] = {
|
||||
def enrichValue(typ: Ast.Type, value: Value): Result[Value] =
|
||||
translateValue(typ, value).map(_.toUnnormalizedValue)
|
||||
}
|
||||
|
||||
def enrichVersionedValue(
|
||||
typ: Ast.Type,
|
||||
@ -61,6 +59,29 @@ final class ValueEnricher(
|
||||
arg <- enrichValue(Ast.TTyCon(contract.unversioned.template), contract.unversioned.arg)
|
||||
} yield contract.map(_.copy(arg = arg))
|
||||
|
||||
def enrichView(
|
||||
interfaceId: Identifier,
|
||||
viewValue: Value,
|
||||
): Result[Value] = for {
|
||||
// TODO: https://github.com/digital-asset/daml/issues/14112
|
||||
// Switch to builtin views once those are implemented.
|
||||
method <- handleLookup(
|
||||
compiledPackages.pkgInterface.lookupInterfaceMethod(
|
||||
interfaceId,
|
||||
Name.assertFromString("_view"),
|
||||
)
|
||||
)
|
||||
viewType = method.returnType
|
||||
r <- enrichValue(viewType, viewValue)
|
||||
} yield r
|
||||
|
||||
def enrichVersionedView(
|
||||
interfaceId: Identifier,
|
||||
viewValue: VersionedValue,
|
||||
): Result[VersionedValue] = for {
|
||||
view <- enrichView(interfaceId, viewValue.unversioned)
|
||||
} yield viewValue.copy(unversioned = view)
|
||||
|
||||
def enrichContract(tyCon: Identifier, value: Value): Result[Value] =
|
||||
enrichValue(Ast.TTyCon(tyCon), value)
|
||||
|
||||
|
@ -52,6 +52,21 @@ class ValueEnricherSpec extends AnyWordSpec with Matchers with TableDrivenProper
|
||||
\(contract: Mod:Contract) ->
|
||||
Mod:keyParties (Mod:Contract {key} contract);
|
||||
|
||||
record @serializable View = {
|
||||
signatory: List Party,
|
||||
cids: List (ContractId Mod:Contract)
|
||||
};
|
||||
|
||||
interface (this: I) = {
|
||||
precondition True;
|
||||
method _view : Mod:View;
|
||||
};
|
||||
|
||||
interface (this: J) = {
|
||||
precondition True;
|
||||
method _view : Int64;
|
||||
};
|
||||
|
||||
template (this : Contract) = {
|
||||
precondition True;
|
||||
signatories Mod:contractParties this;
|
||||
@ -62,6 +77,12 @@ class ValueEnricherSpec extends AnyWordSpec with Matchers with TableDrivenProper
|
||||
Mod:contractParties this
|
||||
to
|
||||
upure @Mod:Record r;
|
||||
implements Mod:I {
|
||||
method _view = Mod:View { signatory = Mod:contractParties this, cids = Mod:Contract {cids} this } ;
|
||||
};
|
||||
implements Mod:J {
|
||||
method _view = 42;
|
||||
};
|
||||
key @Mod:Key (Mod:Contract {key} this) Mod:keyParties;
|
||||
};
|
||||
}
|
||||
@ -69,9 +90,12 @@ class ValueEnricherSpec extends AnyWordSpec with Matchers with TableDrivenProper
|
||||
"""
|
||||
|
||||
private[this] val engine = Engine.DevEngine()
|
||||
|
||||
engine
|
||||
.preloadPackage(defaultPackageId, pkg)
|
||||
.consume(_ => None, _ => None, _ => None)
|
||||
.left
|
||||
.foreach(err => sys.error(err.message))
|
||||
|
||||
private[this] val enricher = new ValueEnricher(engine)
|
||||
|
||||
@ -125,12 +149,43 @@ class ValueEnricherSpec extends AnyWordSpec with Matchers with TableDrivenProper
|
||||
)
|
||||
|
||||
"enrich values as expected" in {
|
||||
forAll(testCases) { (typ, input, output) =>
|
||||
forEvery(testCases) { (typ, input, output) =>
|
||||
enricher.enrichValue(typ, input) shouldBe ResultDone(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"enrichValue" should {
|
||||
val alice = Ref.Party.assertFromString("alice")
|
||||
val view = Value.ValueRecord(
|
||||
None,
|
||||
ImmArray(
|
||||
None -> ValueList(FrontStack(ValueParty(alice))),
|
||||
None -> ValueList(FrontStack(ValueContractId(cid("#contractId").coid))),
|
||||
),
|
||||
)
|
||||
|
||||
val enrichedView = Value.ValueRecord(
|
||||
Some("Mod:View": Ref.Identifier),
|
||||
ImmArray(
|
||||
Some("signatory": Ref.Name) -> ValueList(FrontStack(ValueParty(alice))),
|
||||
Some("cids": Ref.Name) -> ValueList(FrontStack(ValueContractId(cid("#contractId").coid))),
|
||||
),
|
||||
)
|
||||
|
||||
val testCases = Table[Ref.Identifier, Value, Value](
|
||||
("interfaceId", "contract input", "expected output"),
|
||||
("Mod:I", view, enrichedView),
|
||||
("Mod:J", ValueInt64(42L), ValueInt64(42L)),
|
||||
)
|
||||
|
||||
"enrich views as expected" in {
|
||||
forEvery(testCases) { (ifaceId, input, output) =>
|
||||
enricher.enrichView(ifaceId, input) shouldBe ResultDone(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"enrichTransaction" should {
|
||||
|
||||
def buildTransaction(
|
||||
|
@ -186,11 +186,11 @@ private[parser] class ExprParser[P](parserParameters: ParserParameters[P]) {
|
||||
rep1sep(binding(`<-`), `;`) <~! `in` ^^ (_.to(ImmArray))
|
||||
|
||||
private def binding(sep: Token): Parser[Binding] =
|
||||
id ~ (`:` ~> typ) ~ (sep ~> expr) ^^ { case vName ~ t ~ value =>
|
||||
Binding(Some(vName), t, value)
|
||||
Id("_") ~> (`:` ~> typ) ~ (sep ~> expr) ^^ { case t ~ value =>
|
||||
Binding(None, t, value)
|
||||
} |
|
||||
`_` ~> (`:` ~> typ) ~ (sep ~> expr) ^^ { case t ~ value =>
|
||||
Binding(None, t, value)
|
||||
id ~ (`:` ~> typ) ~ (sep ~> expr) ^^ { case vName ~ t ~ value =>
|
||||
Binding(Some(vName), t, value)
|
||||
}
|
||||
|
||||
private lazy val eLet: Parser[Expr] =
|
||||
@ -278,7 +278,8 @@ private[parser] class ExprParser[P](parserParameters: ParserParameters[P]) {
|
||||
}
|
||||
|
||||
private lazy val pattern: Parser[CasePat] =
|
||||
primCon ^^ CPPrimCon |
|
||||
Id("_") ^^^ CPDefault |
|
||||
primCon ^^ CPPrimCon |
|
||||
(`nil` ^^^ CPNil) |
|
||||
(`cons` ~>! id ~ id ^^ { case x1 ~ x2 => CPCons(x1, x2) }) |
|
||||
(`none` ^^^ CPNone) |
|
||||
@ -288,8 +289,7 @@ private[parser] class ExprParser[P](parserParameters: ParserParameters[P]) {
|
||||
CPVariant(tyCon, vName, x)
|
||||
case tyCon ~ vName ~ None =>
|
||||
CPEnum(tyCon, vName)
|
||||
} |
|
||||
Token.`_` ^^^ CPDefault
|
||||
}
|
||||
|
||||
private lazy val alternative: Parser[CaseAlt] =
|
||||
pattern ~! (`->` ~>! expr) ^^ { case p ~ e =>
|
||||
|
@ -75,7 +75,6 @@ private[parser] object Lexer extends RegexParsers {
|
||||
"]" ^^^ `]` |
|
||||
"*" ^^^ `*` |
|
||||
"=" ^^^ `=` |
|
||||
"_" ^^^ Token.`_` |
|
||||
"|" ^^^ `|` |
|
||||
"""[a-zA-Z_\$][\w\$]*""".r ^^ (s => keywords.getOrElse(s, Id(s))) |
|
||||
"""#\w+""".r ^^ ContractId |
|
||||
|
Loading…
Reference in New Issue
Block a user