mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-20 01:07:18 +03:00
navigator: add enum types (#1529)
* navigator: add enum types * Address Stephen's comments * do not serialize enum types * add comment dropped in previous commit
This commit is contained in:
parent
504337b5b2
commit
c76274585a
@ -135,13 +135,14 @@ private[engine] class CommandPreprocessor(compiledPackages: ConcurrentCompiledPa
|
||||
case (key0, value0) => go(newNesting, elemType, value0).map(key0 -> _)
|
||||
}
|
||||
.map(l => SMap(HashMap(l.toSeq: _*)))
|
||||
|
||||
// variants
|
||||
case (TTyConApp(tyCon, tyConArgs), ValueVariant(mbVariantId, constructorName, val0)) =>
|
||||
val variantId = tyCon
|
||||
mbVariantId match {
|
||||
case Some(variantId_) if variantId != variantId_ =>
|
||||
fail(
|
||||
s"Mismatching variant id, the types tell us $variantId, but the value tells us $variantId_")
|
||||
s"Mismatching variant id, the type tells us $variantId, but the value tells us $variantId_")
|
||||
case _ =>
|
||||
compiledPackages.getPackage(variantId.packageId) match {
|
||||
// if the package is not there, look it up and restart. stack safe since this will be done
|
||||
@ -179,7 +180,7 @@ private[engine] class CommandPreprocessor(compiledPackages: ConcurrentCompiledPa
|
||||
mbRecordId match {
|
||||
case Some(recordId_) if recordId != recordId_ =>
|
||||
fail(
|
||||
s"Mismatching record id, the types tell us $recordId, but the value tells us $recordId_")
|
||||
s"Mismatching record id, the type tells us $recordId, but the value tells us $recordId_")
|
||||
case _ =>
|
||||
compiledPackages.getPackage(recordId.packageId) match {
|
||||
// if the package is not there, look it up and restart. stack safe since this will be done
|
||||
@ -243,6 +244,33 @@ private[engine] class CommandPreprocessor(compiledPackages: ConcurrentCompiledPa
|
||||
}
|
||||
}
|
||||
|
||||
case (TTyCon(id), ValueEnum(mbId, constructor)) =>
|
||||
mbId match {
|
||||
case Some(id_) if id_ != id =>
|
||||
fail(s"Mismatching enum id, the type tells us $id, but the value tells us $id_")
|
||||
case _ =>
|
||||
compiledPackages.getPackage(id.packageId) match {
|
||||
// if the package is not there, look it up and restart. stack safe since this will be done
|
||||
// very few times as the cache gets warm. this is also why we do not use the `Result.needDataType`, which
|
||||
// would consume stack regardless
|
||||
case None =>
|
||||
Result.needPackage(
|
||||
id.packageId,
|
||||
compiledPackages.addPackage(id.packageId, _).flatMap(_ => restart)
|
||||
)
|
||||
case Some(pkg) =>
|
||||
PackageLookup.lookupEnum(pkg, id.qualifiedName) match {
|
||||
case Left(err) => ResultError(err)
|
||||
case Right(DataEnum(constructors)) =>
|
||||
if (!constructors.toSeq.contains(constructor))
|
||||
fail(
|
||||
s"Couldn't find provided variant constructor $constructor in enum $id")
|
||||
ResultDone(SEnum(id, constructor))
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// every other pairs of types and values are invalid
|
||||
case (otherType, otherValue) =>
|
||||
fail(s"mismatching type: $otherType and value: $otherValue")
|
||||
|
@ -66,8 +66,8 @@ object DataType {
|
||||
Traverse[Record].traverse(r)(f).widen
|
||||
case v @ Variant(_) =>
|
||||
Traverse[Variant].traverse(v)(g).widen
|
||||
case Enum(vs) =>
|
||||
Applicative[G].pure(Enum(vs))
|
||||
case e @ Enum(_) =>
|
||||
Applicative[G].pure(e)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ package reader
|
||||
|
||||
import ErrorFormatter._
|
||||
import com.digitalasset.daml_lf.{DamlLf, DamlLf1}
|
||||
import scalaz._
|
||||
import scalaz.{Enum => _, _}
|
||||
import scalaz.syntax.std.either._
|
||||
import scalaz.std.tuple._
|
||||
import scalaz.syntax.apply._
|
||||
@ -57,6 +57,9 @@ object InterfaceReader {
|
||||
def addVariant(k: QualifiedName, tyVars: ImmArraySeq[Ref.Name], a: Variant.FWT): State =
|
||||
this.copy(typeDecls = this.typeDecls.updated(k, InterfaceType.Normal(DefDataType(tyVars, a))))
|
||||
|
||||
def addEnum(k: QualifiedName, tyVars: ImmArraySeq[Ref.Name], a: Enum) =
|
||||
this.copy(typeDecls = this.typeDecls.updated(k, InterfaceType.Normal(DefDataType(tyVars, a))))
|
||||
|
||||
def removeRecord(k: QualifiedName): Option[(Record.FWT, State)] =
|
||||
this.typeDecls.get(k).flatMap {
|
||||
case InterfaceType.Normal(DefDataType(_, rec: Record.FWT)) =>
|
||||
@ -124,10 +127,12 @@ object InterfaceReader {
|
||||
case (_, (k, typVars, a)) => (k, InterfaceType.Normal(DefDataType(typVars, a)))
|
||||
}, errors = partitions.errorTree |+| recordErrs)
|
||||
val z1 = partitions.templates.foldLeft(z0)(foldTemplate(n, ctx))
|
||||
foldVariants(
|
||||
val z2 = foldVariants(
|
||||
z1,
|
||||
partitionIndexedErrs(partitions.variants)(variant(n, ctx)) rightMap (_.values))
|
||||
.alterErrors(_ locate n)
|
||||
foldEnums(z2, partitionIndexedErrs(partitions.enums)(enum(n)) rightMap (_.values))
|
||||
.alterErrors(_ locate n)
|
||||
}
|
||||
)
|
||||
}
|
||||
@ -170,6 +175,23 @@ object InterfaceReader {
|
||||
(k, tyVars.toSeq, Variant(fields.toSeq))
|
||||
}
|
||||
|
||||
private def foldEnums(
|
||||
state: State,
|
||||
a: (InterfaceReaderError.Tree, Iterable[(QualifiedName, ImmArraySeq[Ref.Name], Enum)]))
|
||||
: State =
|
||||
addPartitionToState(state, a) {
|
||||
case (st, (k, typVars, enum)) => st.addEnum(k, typVars, enum)
|
||||
}
|
||||
|
||||
private[reader] def enum(m: ModuleName)(a: DamlLf1.DefDataType)
|
||||
: InterfaceReaderError.Tree \/ (QualifiedName, ImmArraySeq[Ref.Name], Enum) =
|
||||
(locate('name, rootErrOf[ErrorLoc](fullName(m, a.getName))).validation |@|
|
||||
locate('typeParams, typeParams(a)).validation |@|
|
||||
locate('constructors, rootErrOf[ErrorLoc](enumConstructors(a))).validation) {
|
||||
(k, tyVars, constructors) =>
|
||||
(k, tyVars.toSeq, Enum(constructors))
|
||||
}.disjunction
|
||||
|
||||
private[this] def recordOrVariant[Z](
|
||||
m: ModuleName,
|
||||
a: DamlLf1.DefDataType,
|
||||
@ -266,6 +288,9 @@ object InterfaceReader {
|
||||
ctx: Context): InterfaceReaderError \/ FieldWithType =
|
||||
type_(a.getType, ctx).flatMap(t => name(a.getField).map(_ -> t))
|
||||
|
||||
private def enumConstructors(as: DamlLf1.DefDataType): InterfaceReaderError \/ ImmArraySeq[Name] =
|
||||
ImmArray(as.getEnum.getConstructorsList.asScala).toSeq.traverseU(name)
|
||||
|
||||
/**
|
||||
* `Fun`, `Forall` and `Tuple` should never appear in Records and Variants
|
||||
*/
|
||||
|
@ -485,7 +485,7 @@ object Ast {
|
||||
final case class DataRecord(fields: ImmArray[(FieldName, Type)], optTemplate: Option[Template])
|
||||
extends DataCons
|
||||
final case class DataVariant(variants: ImmArray[(VariantConName, Type)]) extends DataCons
|
||||
final case class DataEnum(values: ImmArray[EnumConName]) extends DataCons
|
||||
final case class DataEnum(constructors: ImmArray[EnumConName]) extends DataCons
|
||||
|
||||
case class TemplateKey(
|
||||
typ: Type,
|
||||
|
@ -23,7 +23,6 @@ object ValueVersions
|
||||
private[this] val minOptional = ValueVersion("2")
|
||||
private[value] val minContractIdStruct = ValueVersion("3")
|
||||
private[this] val minMap = ValueVersion("4")
|
||||
private[this] val minEnum = ValueVersion("dev")
|
||||
|
||||
def assignVersion[Cid](v0: Value[Cid]): Either[String, ValueVersion] = {
|
||||
import com.digitalasset.daml.lf.transaction.VersionTimeline.{maxVersion => maxVV}
|
||||
@ -52,7 +51,8 @@ object ValueVersions
|
||||
case ValueMap(map) =>
|
||||
go(maxVV(minMap, currentVersion), map.values ++: values)
|
||||
case ValueEnum(_, _) =>
|
||||
go(maxVV(minEnum, currentVersion), values)
|
||||
// FixMe (RH) https://github.com/digital-asset/daml/issues/105
|
||||
throw new NotImplementedError("Enum types not supported")
|
||||
// tuples are a no-no
|
||||
case ValueTuple(fields) =>
|
||||
Left(s"Got tuple when trying to assign version. Fields: $fields")
|
||||
|
@ -194,8 +194,7 @@ object Pretty {
|
||||
PrettyField(label, fieldType._2)
|
||||
}))
|
||||
case e: model.DamlLfEnum =>
|
||||
// FixMe (RH) https://github.com/digital-asset/daml/issues/105
|
||||
throw new NotImplementedError("Enum types not supported")
|
||||
PrettyArray(e.constructors.map(PrettyPrimitive).toList)
|
||||
}
|
||||
}
|
||||
|
||||
@ -223,6 +222,8 @@ object Pretty {
|
||||
PrettyObject(
|
||||
PrettyField(constructor, argument(value))
|
||||
)
|
||||
case model.ApiEnum(id, constructor) =>
|
||||
PrettyPrimitive(constructor)
|
||||
case model.ApiList(elements) =>
|
||||
PrettyArray(
|
||||
elements.map(e => argument(e))
|
||||
|
@ -29,6 +29,7 @@ object ApiCodecCompressed {
|
||||
def apiValueToJsValue(value: Model.ApiValue): JsValue = value match {
|
||||
case v: Model.ApiRecord => apiRecordToJsValue(v)
|
||||
case v: Model.ApiVariant => apiVariantToJsValue(v)
|
||||
case v: Model.ApiEnum => apiEnumToJsValue(v)
|
||||
case v: Model.ApiList => apiListToJsValue(v)
|
||||
case Model.ApiText(v) => JsString(v)
|
||||
case Model.ApiInt64(v) => JsString(v.toString)
|
||||
@ -53,6 +54,9 @@ object ApiCodecCompressed {
|
||||
def apiVariantToJsValue(value: Model.ApiVariant): JsValue =
|
||||
JsObject(Map(value.constructor -> apiValueToJsValue(value.value)))
|
||||
|
||||
def apiEnumToJsValue(value: Model.ApiEnum): JsValue =
|
||||
JsString(value.constructor)
|
||||
|
||||
def apiRecordToJsValue(value: Model.ApiRecord): JsValue =
|
||||
JsObject(value.fields.map(f => f.label -> apiValueToJsValue(f.value)).toMap)
|
||||
|
||||
@ -135,6 +139,11 @@ object ApiCodecCompressed {
|
||||
constructor._1,
|
||||
jsValueToApiType(constructor._2, constructorType, defs)
|
||||
)
|
||||
case (JsString(c), Model.DamlLfEnum(cons)) =>
|
||||
Model.ApiEnum(
|
||||
Some(id),
|
||||
c
|
||||
)
|
||||
|
||||
case _ => deserializationError(s"Can't read ${value.prettyPrint} as $dt")
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ object ApiCodecVerbose {
|
||||
private[this] final val tagMap: String = "map"
|
||||
private[this] final val tagRecord: String = "record"
|
||||
private[this] final val tagVariant: String = "variant"
|
||||
private[this] final val tagEnum: String = "enum"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------------------
|
||||
// Encoding
|
||||
@ -47,6 +48,7 @@ object ApiCodecVerbose {
|
||||
def apiValueToJsValue(value: Model.ApiValue): JsValue = value match {
|
||||
case v: Model.ApiRecord => apiRecordToJsValue(v)
|
||||
case v: Model.ApiVariant => apiVariantToJsValue(v)
|
||||
case v: Model.ApiEnum => apiEnumToJsValue(v)
|
||||
case v: Model.ApiList => apiListToJsValue(v)
|
||||
case Model.ApiText(v) => JsObject(propType -> JsString(tagText), propValue -> JsString(v))
|
||||
case Model.ApiInt64(v) =>
|
||||
@ -94,6 +96,13 @@ object ApiCodecVerbose {
|
||||
propValue -> apiValueToJsValue(value.value)
|
||||
)
|
||||
|
||||
def apiEnumToJsValue(value: Model.ApiEnum): JsValue =
|
||||
JsObject(
|
||||
propType -> JsString(tagEnum),
|
||||
propId -> value.enumId.map(_.toJson).getOrElse(JsNull),
|
||||
propConstructor -> JsString(value.constructor),
|
||||
)
|
||||
|
||||
def apiRecordToJsValue(value: Model.ApiRecord): JsValue =
|
||||
JsObject(
|
||||
propType -> JsString(tagRecord),
|
||||
@ -123,6 +132,7 @@ object ApiCodecVerbose {
|
||||
strField(value, propType, "ApiValue") match {
|
||||
case `tagRecord` => jsValueToApiRecord(value)
|
||||
case `tagVariant` => jsValueToApiVariant(value)
|
||||
case `tagEnum` => jsValueToApiEnum(value)
|
||||
case `tagList` =>
|
||||
Model.ApiList(arrayField(value, propValue, "ApiList").map(jsValueToApiValue))
|
||||
case `tagText` => Model.ApiText(strField(value, propValue, "ApiText"))
|
||||
@ -194,6 +204,21 @@ object ApiCodecVerbose {
|
||||
s"Can't read ${value.prettyPrint} as ApiVariant, type '$t' is not a variant")
|
||||
}
|
||||
|
||||
def jsValueToApiEnum(value: JsValue): Model.ApiEnum =
|
||||
strField(value, propType, "ApiEnum") match {
|
||||
case `tagEnum` =>
|
||||
Model.ApiEnum(
|
||||
asObject(value, "ApiEnum").fields
|
||||
.get(propId)
|
||||
.flatMap(_.convertTo[Option[DamlLfIdentifier]]),
|
||||
strField(value, propConstructor, "ApiEnum")
|
||||
)
|
||||
case t =>
|
||||
deserializationError(
|
||||
s"Can't read ${value.prettyPrint} as ApiEnum, type '$t' is not a enum"
|
||||
)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------------------
|
||||
// Implicits that can be imported for .parseJson and .toJson functions
|
||||
// ------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -4,8 +4,8 @@
|
||||
package com.digitalasset.navigator.json
|
||||
|
||||
import com.digitalasset.daml.lf.data.{Ref => DamlLfRef}
|
||||
import com.digitalasset.navigator.{model => Model}
|
||||
import com.digitalasset.navigator.json.Util._
|
||||
import com.digitalasset.navigator.{model => Model}
|
||||
import spray.json._
|
||||
|
||||
/**
|
||||
@ -27,6 +27,7 @@ object DamlLfCodec {
|
||||
private[this] final val propArgs: String = "args"
|
||||
private[this] final val propVars: String = "vars"
|
||||
private[this] final val propFields: String = "fields"
|
||||
private[this] final val propConstructors: String = "constructors"
|
||||
|
||||
private[this] final val tagTypeCon: String = "typecon"
|
||||
private[this] final val tagTypeVar: String = "typevar"
|
||||
@ -43,6 +44,7 @@ object DamlLfCodec {
|
||||
private[this] final val tagTypeUnit: String = "unit"
|
||||
private[this] final val tagTypeRecord: String = "record"
|
||||
private[this] final val tagTypeVariant: String = "variant"
|
||||
private[this] final val tagTypeEnum: String = "enum"
|
||||
private[this] final val tagTypeOptional: String = "optional"
|
||||
private[this] final val tagTypeMap: String = "map"
|
||||
|
||||
@ -115,8 +117,10 @@ object DamlLfCodec {
|
||||
.toVector)
|
||||
)
|
||||
case e: Model.DamlLfEnum =>
|
||||
// FixMe (RH) https://github.com/digital-asset/daml/issues/105
|
||||
throw new NotImplementedError("Enum types not supported")
|
||||
JsObject(
|
||||
propType -> JsString(tagTypeEnum),
|
||||
propConstructors -> JsArray(e.constructors.map(JsString(_)).toVector)
|
||||
)
|
||||
}
|
||||
|
||||
def damlLfDefDataTypeToJsValue(value: Model.DamlLfDefDataType): JsValue = JsObject(
|
||||
@ -183,6 +187,9 @@ object DamlLfCodec {
|
||||
nameField(f, propName, "DamlLfVariant"),
|
||||
jsValueToDamlLfType(anyField(f, propValue, "DamlLfVariant")))): _*)
|
||||
)
|
||||
case `tagTypeEnum` =>
|
||||
val constructors = arrayField(value, propConstructors, "DamlLfEnum")
|
||||
Model.DamlLfEnum(Model.DamlLfImmArraySeq(constructors: _*).map(asName(_, "DamlLfEnum")))
|
||||
case t =>
|
||||
deserializationError(
|
||||
s"Can't read ${value.prettyPrint} as DamlLfDataType, unknown type '$t'")
|
||||
|
@ -36,6 +36,10 @@ final case class ApiVariant(
|
||||
constructor: String,
|
||||
value: ApiValue)
|
||||
extends ApiValue
|
||||
final case class ApiEnum(
|
||||
enumId: Option[DamlLfIdentifier],
|
||||
constructor: String
|
||||
) extends ApiValue
|
||||
final case class ApiList(elements: List[ApiValue]) extends ApiValue
|
||||
final case class ApiOptional(value: Option[ApiValue]) extends ApiValue
|
||||
final case class ApiMap(value: SortedLookupList[ApiValue]) extends ApiValue
|
||||
|
@ -34,9 +34,9 @@ case class PackageRegistry(
|
||||
)
|
||||
|
||||
def withPackages(interfaces: List[DamlLfIface.Interface]): PackageRegistry = {
|
||||
val newPackages: Map[DamlLfRef.PackageId, DamlLfPackage] = interfaces
|
||||
val newPackages = interfaces
|
||||
.filterNot(p => packages.contains(p.packageId))
|
||||
.map(p => {
|
||||
.map { p =>
|
||||
val typeDefs = p.typeDecls.collect {
|
||||
case (qname, DamlLfIface.reader.InterfaceType.Normal(t)) =>
|
||||
DamlLfIdentifier(p.packageId, qname) -> t
|
||||
@ -48,8 +48,7 @@ case class PackageRegistry(
|
||||
DamlLfIdentifier(p.packageId, qname) -> template(p.packageId, qname, r, t)
|
||||
}
|
||||
p.packageId -> DamlLfPackage(p.packageId, typeDefs, templates)
|
||||
})
|
||||
.toMap
|
||||
}
|
||||
|
||||
val newTemplates = newPackages
|
||||
.map(_._2.templates)
|
||||
@ -159,8 +158,7 @@ case class PackageRegistry(
|
||||
case DamlLfVariant(fields) =>
|
||||
fields.foldLeft(deps)((r, field) => foldType(field._2, r, instantiatesRemaining))
|
||||
case DamlLfEnum(_) =>
|
||||
// FixMe (RH) https://github.com/digital-asset/daml/issues/105
|
||||
throw new NotImplementedError("Enum types not supported")
|
||||
deps
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -365,13 +365,37 @@ case object LedgerApiV1 {
|
||||
}
|
||||
choice <- dt.fields
|
||||
.find(f => f._1 == variant.constructor)
|
||||
.toRight(GenericConversionError(s"Unknown choice ${variant.constructor}"))
|
||||
.toRight(GenericConversionError(s"Unknown enum constructor ${variant.constructor}"))
|
||||
argument <- readArgument(value, choice._2, ctx)
|
||||
} yield {
|
||||
Model.ApiVariant(Some(typeCon.name.identifier), variant.constructor, argument)
|
||||
}
|
||||
}
|
||||
|
||||
private def readEnumArgument(
|
||||
enum: V1.value.Enum,
|
||||
typ: Model.DamlLfType,
|
||||
ctx: Context
|
||||
): Result[Model.ApiEnum] =
|
||||
for {
|
||||
typeCon <- typ match {
|
||||
case t @ Model.DamlLfTypeCon(_, _) => Right(t)
|
||||
case _ => Left(GenericConversionError(s"Cannot read $enum as $typ"))
|
||||
}
|
||||
ddt <- ctx.templates
|
||||
.damlLfDefDataType(typeCon.name.identifier)
|
||||
.toRight(GenericConversionError(s"Unknown type ${typeCon.name.identifier}"))
|
||||
dt <- typeCon.instantiate(ddt) match {
|
||||
case v @ iface.Enum(_) => Right(v)
|
||||
case iface.Record(_) | iface.Variant(_) =>
|
||||
Left(GenericConversionError(s"Enum expected"))
|
||||
}
|
||||
_ <- Either.cond(
|
||||
dt.constructors.contains(enum.constructor),
|
||||
(),
|
||||
GenericConversionError(s"Unknown choice ${enum.constructor}"))
|
||||
} yield Model.ApiEnum(Some(typeCon.name.identifier), enum.constructor)
|
||||
|
||||
private def readArgument(
|
||||
value: V1.value.Value,
|
||||
typ: Model.DamlLfType,
|
||||
@ -393,6 +417,7 @@ case object LedgerApiV1 {
|
||||
case (VS.Map(v), t) => readMapArgument(v, t, ctx)
|
||||
case (VS.Record(v), t) => readRecordArgument(v, t, ctx)
|
||||
case (VS.Variant(v), t) => readVariantArgument(v, t, ctx)
|
||||
case (VS.Enum(v), t) => readEnumArgument(v, t, ctx)
|
||||
case (VS.Empty, _) => Left(GenericConversionError("Argument value is empty"))
|
||||
case (_, _) => Left(GenericConversionError(s"Cannot read argument $value as $typ"))
|
||||
}
|
||||
@ -422,6 +447,8 @@ case object LedgerApiV1 {
|
||||
value match {
|
||||
case arg: Model.ApiRecord => writeRecordArgument(arg).map(a => Value(Value.Sum.Record(a)))
|
||||
case arg: Model.ApiVariant => writeVariantArgument(arg).map(a => Value(Value.Sum.Variant(a)))
|
||||
case Model.ApiEnum(id, cons) =>
|
||||
Right(Value(Value.Sum.Enum(V1.value.Enum(id.map(_.asApi), cons))))
|
||||
case arg: Model.ApiList => writeListArgument(arg).map(a => Value(Value.Sum.List(a)))
|
||||
case Model.ApiBool(v) => Right(Value(Value.Sum.Bool(v)))
|
||||
case Model.ApiInt64(v) => Right(Value(Value.Sum.Int64(v)))
|
||||
|
@ -37,29 +37,32 @@ package object filter {
|
||||
ps: DamlLfTypeLookup): Either[DotNotFailure, Boolean] = {
|
||||
|
||||
@annotation.tailrec
|
||||
def loop(
|
||||
parameter: DamlLfType,
|
||||
cursor: PropertyCursor,
|
||||
ps: DamlLfTypeLookup): Either[DotNotFailure, Boolean] =
|
||||
def loop(parameter: DamlLfType, cursor: PropertyCursor): Either[DotNotFailure, Boolean] =
|
||||
parameter match {
|
||||
case tc: DamlLfTypeCon =>
|
||||
val next = for {
|
||||
ddt <- ps(tc.name.identifier)
|
||||
nextCursor <- cursor.next
|
||||
//nextField <- tc.instantiate(ddt) match {
|
||||
nextField <- damlLfInstantiate(tc, ddt) match {
|
||||
case DamlLfRecord(fields) => fields.find(f => f._1 == nextCursor.current)
|
||||
case DamlLfVariant(fields) => fields.find(f => f._1 == nextCursor.current)
|
||||
case DamlLfEnum(_) =>
|
||||
// FixMe (RH) https://github.com/digital-asset/daml/issues/105
|
||||
throw new NotImplementedError("Enum types not supported")
|
||||
val nextOrResult =
|
||||
(ps(tc.name.identifier).map(damlLfInstantiate(tc, _)), cursor.next) match {
|
||||
case (Some(DamlLfRecord(fields)), Some(nextCursor)) =>
|
||||
fields
|
||||
.collectFirst {
|
||||
case (nextCursor.current, fType) => fType -> nextCursor
|
||||
}
|
||||
.toLeft(false)
|
||||
case (Some(DamlLfVariant(fields)), Some(nextCursor)) =>
|
||||
fields
|
||||
.collectFirst {
|
||||
case (nextCursor.current, fType) => fType -> nextCursor
|
||||
}
|
||||
.toLeft(false)
|
||||
case (Some(DamlLfEnum(constructors)), _) =>
|
||||
Right(constructors.exists(checkContained(_, expectedValue)))
|
||||
case (None, _) | (_, None) =>
|
||||
Right(false)
|
||||
}
|
||||
} yield {
|
||||
(nextField._2, nextCursor)
|
||||
}
|
||||
next match {
|
||||
case Some((nextType, nextCursor)) => loop(nextType, nextCursor, ps)
|
||||
case None => Right(false)
|
||||
|
||||
nextOrResult match {
|
||||
case Right(r) => Right(r)
|
||||
case Left((typ, nextCursor)) => loop(typ, nextCursor)
|
||||
}
|
||||
|
||||
case DamlLfTypeVar(name) => Right(checkContained(name, expectedValue))
|
||||
@ -84,7 +87,7 @@ package object filter {
|
||||
Right(checkContained("map", expectedValue))
|
||||
}
|
||||
|
||||
loop(rootParam, cursor.prev.get, ps)
|
||||
loop(rootParam, cursor.prev.get)
|
||||
}
|
||||
|
||||
def checkArgument(
|
||||
@ -123,6 +126,15 @@ package object filter {
|
||||
case _ => Right(false)
|
||||
}
|
||||
}
|
||||
case ApiEnum(_, constructor) =>
|
||||
cursor.next match {
|
||||
case None => Right(false)
|
||||
case Some(nextCursor) =>
|
||||
nextCursor.current match {
|
||||
case "__constructor" => Right(checkContained(constructor, expectedValue))
|
||||
case _ => Right(false)
|
||||
}
|
||||
}
|
||||
case ApiList(elements) =>
|
||||
cursor.next match {
|
||||
case None => Right(false)
|
||||
|
@ -134,6 +134,15 @@ object project {
|
||||
case _ => Left(UnknownProperty("variant", nextCursor, expectedValue))
|
||||
}
|
||||
}
|
||||
case ApiEnum(_, constructor) =>
|
||||
cursor.next match {
|
||||
case None => Left(MustNotBeLastPart("enum", cursor, expectedValue))
|
||||
case Some(nextCursor) =>
|
||||
nextCursor.current match {
|
||||
case "__constructor" => Right(StringValue(constructor))
|
||||
case _ => Left(UnknownProperty("enum", nextCursor, expectedValue))
|
||||
}
|
||||
}
|
||||
case ApiList(elements) =>
|
||||
cursor.next match {
|
||||
case None => Left(MustNotBeLastPart("list", cursor, expectedValue))
|
||||
|
@ -1,26 +1,20 @@
|
||||
// Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import {
|
||||
ChoicesButton,
|
||||
ContractColumn,
|
||||
} from '@da/ui-core';
|
||||
import { DamlLfDataType, DamlLFFieldWithType } from '@da/ui-core/lib/api/DamlLfType';
|
||||
import { DamlLfValueRecord } from '@da/ui-core/lib/api/DamlLfValue';
|
||||
import {ChoicesButton, ContractColumn} from '@da/ui-core';
|
||||
import {DamlLFFieldWithType, DamlLfRecord} from '@da/ui-core/lib/api/DamlLfType';
|
||||
import * as DamlLfValueF from '@da/ui-core/lib/api/DamlLfValue';
|
||||
import * as React from 'react';
|
||||
import Link from '../../components/Link'
|
||||
import * as Routes from '../../routes'
|
||||
import {
|
||||
Contract,
|
||||
} from './data';
|
||||
import {Contract} from './data';
|
||||
|
||||
function formatField(field: DamlLFFieldWithType, argument: DamlLfValueRecord): string {
|
||||
function formatField(field: DamlLFFieldWithType, argument: DamlLfValueF.DamlLfValueRecord): string {
|
||||
const valueField = argument.fields.filter((f) => f.label === field.name)[0];
|
||||
return valueField ? JSON.stringify(DamlLfValueF.toJSON(valueField.value)) : '???';
|
||||
}
|
||||
|
||||
function makeColumns(param: DamlLfDataType): ContractColumn<Contract>[] {
|
||||
function makeColumns(param: DamlLfRecord): ContractColumn<Contract>[] {
|
||||
return param.fields.map((field) => (
|
||||
{
|
||||
key: `argument.${field.name}`,
|
||||
@ -35,7 +29,7 @@ function makeColumns(param: DamlLfDataType): ContractColumn<Contract>[] {
|
||||
));
|
||||
}
|
||||
|
||||
export default (param: DamlLfDataType): ContractColumn<Contract>[] => [
|
||||
export default (param: DamlLfRecord): ContractColumn<Contract>[] => [
|
||||
{
|
||||
key: 'id',
|
||||
title: 'ID',
|
||||
|
@ -105,7 +105,8 @@ class Component extends React.Component<Props, {}> {
|
||||
|
||||
render() {
|
||||
const { data } = this.props;
|
||||
const columns = data && data.node && data.node.__typename === 'Template' ?
|
||||
const columns =
|
||||
data && data.node && data.node.__typename === 'Template' && data.node.parameterDef.dataType.type === 'record' ?
|
||||
makeColumns(data.node.parameterDef.dataType) : [];
|
||||
return (
|
||||
<ContractTable
|
||||
|
@ -50,6 +50,15 @@ const ArgumentDisplay = (props: Props): JSX.Element => {
|
||||
</NestedForm>
|
||||
);
|
||||
}
|
||||
case 'enum' : {
|
||||
return (
|
||||
<NestedForm level={level}>
|
||||
<LabeledElement key={'type'} label={`Type (${argument.id.name})`} className={className}>
|
||||
<span>{argument.constructor}</span>
|
||||
</LabeledElement>
|
||||
</NestedForm>
|
||||
);
|
||||
}
|
||||
case 'list': {
|
||||
return (
|
||||
<NestedForm level={level}>
|
||||
|
@ -73,8 +73,8 @@ const exampleRecord: DamlLfRecord = {
|
||||
{ name: 'bool parameter', value: DamlLfTypeF.bool() },
|
||||
],
|
||||
};
|
||||
const exampleRecordDef: DamlLfDefDataType = { dataType: exampleRecord, typeVars: []}
|
||||
const exampleRecordTc: DamlLfTypeCon = { type: 'typecon', name: exampleRecordId, args: [] }
|
||||
const exampleRecordDef: DamlLfDefDataType = { dataType: exampleRecord, typeVars: []};
|
||||
const exampleRecordTc: DamlLfTypeCon = { type: 'typecon', name: exampleRecordId, args: [] };
|
||||
|
||||
const typeProvider: TypeProvider = {
|
||||
fetchType(id: DamlLfIdentifier,
|
||||
@ -85,7 +85,7 @@ const typeProvider: TypeProvider = {
|
||||
onResult(id, undefined);
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
export interface State {
|
||||
value: DamlLfValue;
|
||||
|
@ -2,9 +2,11 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import * as React from 'react';
|
||||
import * as DamlLfTypeF from '../api/DamlLfType';
|
||||
import {
|
||||
DamlLfDataType,
|
||||
DamlLfDefDataType,
|
||||
DamlLfEnum,
|
||||
DamlLfIdentifier,
|
||||
DamlLfPrimType,
|
||||
DamlLfRecord,
|
||||
@ -13,31 +15,35 @@ import {
|
||||
DamlLfTypePrim,
|
||||
DamlLfVariant,
|
||||
} from '../api/DamlLfType';
|
||||
import * as DamlLfTypeF from '../api/DamlLfType';
|
||||
import {
|
||||
DamlLfValue,
|
||||
DamlLfValueBool,
|
||||
DamlLfValueDecimal,
|
||||
DamlLfValueEnum,
|
||||
DamlLfValueInt64,
|
||||
DamlLfValueList, DamlLfValueMap,
|
||||
DamlLfValueList,
|
||||
DamlLfValueMap,
|
||||
DamlLfValueOptional,
|
||||
DamlLfValueParty,
|
||||
DamlLfValueRecord,
|
||||
DamlLfValueText,
|
||||
DamlLfValueUnit,
|
||||
DamlLfValueVariant, mapEntry,
|
||||
DamlLfValueVariant,
|
||||
enumCon,
|
||||
mapEntry,
|
||||
} from '../api/DamlLfValue';
|
||||
import * as DamlLfValueF from '../api/DamlLfValue';
|
||||
import Button from '../Button';
|
||||
import { StyledTextInput } from '../Input';
|
||||
import { LabeledElement } from '../Label';
|
||||
import {StyledTextInput} from '../Input';
|
||||
import {LabeledElement} from '../Label';
|
||||
import NestedForm from '../NestedForm';
|
||||
import Select from '../Select';
|
||||
import styled from '../theme';
|
||||
import TimeInput from '../TimeInput';
|
||||
import { NonExhaustiveMatch, TypeErrorElement } from '../util';
|
||||
import {NonExhaustiveMatch, TypeErrorElement} from '../util';
|
||||
import ContractIdInput from './ContractIdInput';
|
||||
|
||||
import * as DamlLfValueF from '@da/ui-core/lib/api/DamlLfValue';
|
||||
|
||||
|
||||
//tslint:disable:no-use-before-declare
|
||||
|
||||
@ -61,7 +67,8 @@ export function matchPrimitiveType(value: DamlLfValue, type: DamlLfTypePrim, nam
|
||||
/** Returns true if both the `value` and the `type` are valid for the given type. */
|
||||
function matchDataType(value: DamlLfValue, type: DamlLfDataType, name: 'record'): value is DamlLfValueRecord;
|
||||
function matchDataType(value: DamlLfValue, type: DamlLfDataType, name: 'variant'): value is DamlLfValueVariant;
|
||||
function matchDataType(value: DamlLfValue, type: DamlLfDataType, name: 'record' | 'variant'): boolean {
|
||||
function matchDataType(value: DamlLfValue, type: DamlLfDataType, name: 'enum'): value is DamlLfValueEnum;
|
||||
function matchDataType(value: DamlLfValue, type: DamlLfDataType, name: 'record' | 'variant' | 'enum'): boolean {
|
||||
return (value.type === name && type.type === name)
|
||||
}
|
||||
|
||||
@ -213,7 +220,7 @@ const UnitInput = (props: InputProps<DamlLfValueUnit>): JSX.Element => {
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
interface VariantTypeInputProps {
|
||||
parameter: DamlLfDataType;
|
||||
parameter: DamlLfVariant;
|
||||
disabled: boolean;
|
||||
onChange(val: string): void;
|
||||
varType: string | undefined;
|
||||
@ -227,8 +234,7 @@ const variantTypeNone = '';
|
||||
|
||||
const VariantTypeInput = (props: VariantTypeInputProps): JSX.Element => {
|
||||
const { parameter, disabled, onChange, varType } = props;
|
||||
const options = parameter.fields
|
||||
.map((f) => ({value: f.name, label: f.name}))
|
||||
const options = parameter.fields.map((f) => ({value: f.name, label: f.name}));
|
||||
return (
|
||||
<Select
|
||||
disabled={disabled}
|
||||
@ -267,7 +273,7 @@ const VariantInput = (props: VariantInputProps): JSX.Element => {
|
||||
const newConstructor = parameter.fields.filter((f) => f.name === val)[0]
|
||||
if (newConstructor === undefined) {
|
||||
// Resetting variant to initial state
|
||||
onChange(DamlLfValueF.initialDataTypeValue(id, parameter))
|
||||
onChange(DamlLfValueF.initialVariantValue(id, parameter))
|
||||
} else if (constructor === undefined) {
|
||||
// Setting a value for the first time
|
||||
onChange(DamlLfValueF.variant(id, newConstructor.name, DamlLfValueF.initialValue(newConstructor.value)))
|
||||
@ -301,7 +307,7 @@ const VariantInput = (props: VariantInputProps): JSX.Element => {
|
||||
} else {
|
||||
return (<TypeErrorElement parameter={parameter} argument={argument} />);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// Record - nested input form
|
||||
@ -347,8 +353,47 @@ const RecordInput = (props: RecordInputProps): JSX.Element => {
|
||||
} else {
|
||||
return (<TypeErrorElement parameter={parameter} argument={argument} />);
|
||||
}
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// Enum - non-nested value
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
interface EnumInputProps {
|
||||
id: DamlLfIdentifier;
|
||||
parameter: DamlLfEnum;
|
||||
disabled: boolean;
|
||||
onChange(val: DamlLfValueEnum): void;
|
||||
argument: DamlLfValue;
|
||||
level: number
|
||||
}
|
||||
|
||||
const EnumInput = (props: EnumInputProps): JSX.Element => {
|
||||
const { id, parameter, level, onChange, argument, disabled } = props;
|
||||
if (matchDataType(argument, parameter, 'enum')) {
|
||||
const options = parameter.constructors.map((c) => ({value: c, label: c}));
|
||||
return (
|
||||
<NestedForm level={level}>
|
||||
<LabeledElement label={'Constructor'} key={'constructor'}>
|
||||
<Select
|
||||
disabled={disabled}
|
||||
value={argument.constructor}
|
||||
onChange={(value) => {
|
||||
if (value === undefined) {
|
||||
onChange(DamlLfValueF.initialEnumValue(id, parameter));
|
||||
} else {
|
||||
onChange(enumCon(id, value));
|
||||
}}}
|
||||
options={options}
|
||||
/>
|
||||
</LabeledElement>
|
||||
</NestedForm>
|
||||
);
|
||||
} else {
|
||||
return (<TypeErrorElement parameter={parameter} argument={argument} />);
|
||||
}
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// Optional - nested value
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
@ -530,14 +575,6 @@ interface ListInputProps extends InputProps<DamlLfValueList> {
|
||||
typeProvider: TypeProvider
|
||||
}
|
||||
|
||||
interface MapInputProps extends InputProps<DamlLfValueMap> {
|
||||
parameter: DamlLfTypePrim;
|
||||
name: string;
|
||||
level: number
|
||||
contractIdProvider?: ContractIdProvider
|
||||
typeProvider: TypeProvider
|
||||
}
|
||||
|
||||
const ListInput = (props: ListInputProps): JSX.Element => {
|
||||
const { argument, parameter, level, name, onChange, disabled, contractIdProvider, typeProvider } = props;
|
||||
if (matchPrimitiveType(argument, parameter, 'list')) {
|
||||
@ -591,6 +628,15 @@ const ListInput = (props: ListInputProps): JSX.Element => {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
interface MapInputProps extends InputProps<DamlLfValueMap> {
|
||||
parameter: DamlLfTypePrim;
|
||||
name: string;
|
||||
level: number
|
||||
contractIdProvider?: ContractIdProvider
|
||||
typeProvider: TypeProvider
|
||||
}
|
||||
|
||||
const MapInput = (props: MapInputProps): JSX.Element => {
|
||||
const { argument, parameter, level, onChange, disabled, contractIdProvider, typeProvider } = props;
|
||||
if (matchPrimitiveType(argument, parameter, 'map')) {
|
||||
@ -694,9 +740,19 @@ class TypeConInput extends React.Component<TypeConInputProps, TypeConInputState>
|
||||
const { parameter, onChange } = this.props;
|
||||
if (ddt) {
|
||||
const dataType = DamlLfTypeF.instantiate(parameter, ddt);
|
||||
const initialValue = DamlLfValueF.initialDataTypeValue(parameter.name, dataType);
|
||||
switch (dataType.type) {
|
||||
case 'record':
|
||||
onChange(DamlLfValueF.initialRecordValue(parameter.name, dataType));
|
||||
break;
|
||||
case 'variant':
|
||||
onChange(DamlLfValueF.initialVariantValue(parameter.name, dataType));
|
||||
break;
|
||||
case 'enum':
|
||||
onChange(DamlLfValueF.initialEnumValue(parameter.name, dataType));
|
||||
break;
|
||||
default: throw new NonExhaustiveMatch(dataType);
|
||||
}
|
||||
this.setState({ dataType });
|
||||
onChange(initialValue);
|
||||
} else {
|
||||
this.setState({ dataType: undefined });
|
||||
onChange(DamlLfValueF.undef());
|
||||
@ -753,6 +809,17 @@ class TypeConInput extends React.Component<TypeConInputProps, TypeConInputState>
|
||||
typeProvider={typeProvider}
|
||||
/>
|
||||
);
|
||||
case 'enum' : return(
|
||||
<EnumInput
|
||||
id={parameter.name}
|
||||
parameter={dataType}
|
||||
disabled={disabled}
|
||||
onChange={onChange}
|
||||
argument={argument}
|
||||
level={level}
|
||||
/>
|
||||
);
|
||||
|
||||
default: throw new NonExhaustiveMatch(dataType);
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,8 @@ export type DamlLFFieldWithType = { name: string, value: DamlLfType }
|
||||
|
||||
export type DamlLfRecord = { type: 'record', fields: DamlLFFieldWithType[] }
|
||||
export type DamlLfVariant = { type: 'variant', fields: DamlLFFieldWithType[] }
|
||||
export type DamlLfDataType = DamlLfRecord | DamlLfVariant
|
||||
export type DamlLfEnum = { type: 'enum', constructors: string[] }
|
||||
export type DamlLfDataType = DamlLfRecord | DamlLfVariant | DamlLfEnum
|
||||
|
||||
export type DamlLfDefDataType = { dataType: DamlLfDataType, typeVars: string[] }
|
||||
|
||||
@ -112,9 +113,10 @@ export function instantiate(tc: DamlLfTypeCon, ddt: DamlLfDefDataType): DamlLfDa
|
||||
|
||||
switch (ddt.dataType.type) {
|
||||
case 'record': return { type: 'record',
|
||||
fields: ddt.dataType.fields.map((f) => ({name: f.name, value: mapTypeVars(f.value, (n) => typeMap[n.name])})) }
|
||||
fields: ddt.dataType.fields.map((f) => ({name: f.name, value: mapTypeVars(f.value, (n) => typeMap[n.name])})) };
|
||||
case 'variant': return { type: 'variant',
|
||||
fields: ddt.dataType.fields.map((f) => ({name: f.name, value: mapTypeVars(f.value, (n) => typeMap[n.name])})) }
|
||||
fields: ddt.dataType.fields.map((f) => ({name: f.name, value: mapTypeVars(f.value, (n) => typeMap[n.name])})) };
|
||||
case 'enum': return {type : 'enum', constructors: ddt.dataType.constructors };
|
||||
default: throw new NonExhaustiveMatch(ddt.dataType)
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
import * as Moment from 'moment';
|
||||
import { NonExhaustiveMatch } from '../util'
|
||||
import { DamlLfDataType, DamlLfIdentifier, DamlLfRecord, DamlLfType, DamlLfVariant } from './DamlLfType';
|
||||
import {DamlLfEnum, DamlLfIdentifier, DamlLfRecord, DamlLfType, DamlLfVariant} from './DamlLfType';
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// Type definitions
|
||||
@ -27,6 +27,7 @@ export type DamlLfValueOptional = { type: 'optional', value: DamlLfValue | nul
|
||||
export type DamlLfValueList = { type: 'list', value: DamlLfValue[] }
|
||||
export type DamlLfValueRecord = { type: 'record', id: DamlLfIdentifier, fields: DamlLfRecordField[] }
|
||||
export type DamlLfValueVariant = { type: 'variant', id: DamlLfIdentifier, constructor: string, value: DamlLfValue }
|
||||
export type DamlLfValueEnum = { type: 'enum', id: DamlLfIdentifier, constructor: string }
|
||||
export type DamlLfValueUndefined = { type: 'undefined' }
|
||||
export type DamlLfValueMap = { type: 'map', value: DamlLfValueMapEntry[] }
|
||||
export type DamlLfValueMapEntry = { key: string, value: DamlLfValue }
|
||||
@ -46,6 +47,7 @@ export type DamlLfValue
|
||||
| DamlLfValueMap
|
||||
| DamlLfValueRecord
|
||||
| DamlLfValueVariant
|
||||
| DamlLfValueEnum
|
||||
| DamlLfValueUndefined
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
@ -74,6 +76,9 @@ export function record(id: DamlLfIdentifier, fields: DamlLfRecordField[]): DamlL
|
||||
export function variant(id: DamlLfIdentifier, constructor: string, value: DamlLfValue): DamlLfValueVariant {
|
||||
return { type: 'variant', id, constructor, value }
|
||||
}
|
||||
export function enumCon(id: DamlLfIdentifier, constructor: string): DamlLfValueEnum {
|
||||
return { type: 'enum', id, constructor }
|
||||
}
|
||||
export function undef(): DamlLfValueUndefined { return valueUndef }
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
@ -141,6 +146,12 @@ export function evalPath(value: DamlLfValue, path: string[], index: number = 0):
|
||||
} else {
|
||||
return notFound;
|
||||
}
|
||||
case 'enum':
|
||||
if (isLast){
|
||||
return value;
|
||||
} else {
|
||||
return notFound;
|
||||
}
|
||||
case 'map':
|
||||
if (isLast) {
|
||||
return value;
|
||||
@ -212,6 +223,8 @@ export function toJSON(value: DamlLfValue): JSON {
|
||||
return r;
|
||||
case 'variant':
|
||||
return {[value.constructor]: toJSON(value.value)};
|
||||
case 'enum' :
|
||||
return value.constructor;
|
||||
case 'map':
|
||||
return value.value.map((e) => ({key: e.key, value: toJSON(e.value)}));
|
||||
case 'undefined': return '???';
|
||||
@ -219,19 +232,14 @@ export function toJSON(value: DamlLfValue): JSON {
|
||||
}
|
||||
}
|
||||
|
||||
export function initialDataTypeValue(id: DamlLfIdentifier, dataType: DamlLfRecord): DamlLfValueRecord;
|
||||
export function initialDataTypeValue(id: DamlLfIdentifier, dataType: DamlLfVariant): DamlLfValueVariant;
|
||||
export function initialDataTypeValue(id: DamlLfIdentifier, dataType: DamlLfDataType):
|
||||
DamlLfValueRecord | DamlLfValueVariant;
|
||||
export function initialDataTypeValue(id: DamlLfIdentifier, dataType: DamlLfDataType):
|
||||
DamlLfValueRecord | DamlLfValueVariant {
|
||||
switch (dataType.type) {
|
||||
case 'record': return record(id,
|
||||
dataType.fields.map((f) => ({label: f.name, value: initialValue(f.value)})));
|
||||
case 'variant': return variant(id,
|
||||
dataType.fields[0].name, initialValue(dataType.fields[0].value));
|
||||
default: throw new NonExhaustiveMatch(dataType);
|
||||
}
|
||||
export function initialRecordValue(id: DamlLfIdentifier, dataType: DamlLfRecord): DamlLfValueRecord {
|
||||
return record(id, dataType.fields.map((f) => ({label: f.name, value: initialValue(f.value)})));
|
||||
}
|
||||
export function initialVariantValue(id: DamlLfIdentifier, dataType: DamlLfVariant): DamlLfValueVariant {
|
||||
return variant(id, dataType.fields[0].name, initialValue(dataType.fields[0].value));
|
||||
}
|
||||
export function initialEnumValue(id: DamlLfIdentifier, dataType: DamlLfEnum): DamlLfValueEnum {
|
||||
return enumCon(id, dataType.constructors[0]);
|
||||
}
|
||||
|
||||
const momentDateFormat = 'YYYY-MM-DD';
|
||||
|
Loading…
Reference in New Issue
Block a user