From 30300fdac629a41b8b98b29b5e2b1e6a2a7e388d Mon Sep 17 00:00:00 2001 From: Remy Date: Tue, 11 Jan 2022 16:53:10 +0100 Subject: [PATCH] LF: Revert #7742 (#12354) Following #12338 which merges the two implementations of the structural record projection introduced by #7740, this PR merges the two implementations of the structural record introduced by #7742. However, this PR does not try to cache the field index as it is done 1- unlike what it is suggested by commit message of #7742, the update has a linear complexity anyway, as it has to copy the whole struct. 2- the compiler does not produce any structural record updates As result the PR is basically a revert of #7742. CHANGELOG_BEGIN CHANGELOG_END --- .../daml/lf/speedy/Compiler.scala | 12 ++--------- .../daml/lf/speedy/SBuiltin.scala | 20 ++++--------------- .../digitalasset/daml/lf/language/Ast.scala | 7 ++----- .../daml/lf/validation/Typing.scala | 16 +++++++-------- 4 files changed, 15 insertions(+), 40 deletions(-) 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 08e9c6b7fc4c..6a8a800c9a22 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 @@ -499,16 +499,8 @@ private[lf] final class Compiler( ) case EStructProj(field, struct) => SBStructProj(field)(compile(env, struct)) - case structUpd: EStructUpd => - structUpd.fieldIndex match { - case None => - SBStructUpdByName(structUpd.field)( - compile(env, structUpd.struct), - compile(env, structUpd.update), - ) - case Some(index) => - SBStructUpd(index)(compile(env, structUpd.struct), compile(env, structUpd.update)) - } + case EStructUpd(field, struct, update) => + SBStructUpd(field)(compile(env, struct), compile(env, update)) case ECase(scrut, alts) => compileECase(env, scrut, alts) case ENil(_) => diff --git a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/SBuiltin.scala b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/SBuiltin.scala index 99b0e4e1d63c..690f656aed69 100644 --- a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/SBuiltin.scala +++ b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/SBuiltin.scala @@ -779,25 +779,13 @@ private[lf] object SBuiltin { } } - /** $tupd[fieldIndex] :: Struct -> a -> Struct */ - final case class SBStructUpd(fieldIndex: Int) extends SBuiltinPure(2) { - override private[speedy] def executePure(args: util.ArrayList[SValue]): SStruct = { - val struct = getSStruct(args, 0) - val values2 = struct.values.clone.asInstanceOf[util.ArrayList[SValue]] - discard(values2.set(fieldIndex, args.get(1))) - struct.copy(values = values2) - } - } - /** $tupd[field] :: Struct -> a -> Struct */ - // This is a slower version of `SBStructUpd` for the case when we didn't run - // the Daml-LF type checker and hence didn't infer the field index. - final case class SBStructUpdByName(field: Ast.FieldName) extends SBuiltinPure(2) { + final case class SBStructUpd(field: Ast.FieldName) extends SBuiltinPure(2) { override private[speedy] def executePure(args: util.ArrayList[SValue]): SStruct = { val struct = getSStruct(args, 0) - val values2 = struct.values.clone.asInstanceOf[util.ArrayList[SValue]] - discard(values2.set(struct.fieldNames.indexOf(field), args.get(1))) - struct.copy(values = values2) + val values = struct.values.clone.asInstanceOf[util.ArrayList[SValue]] + discard(values.set(struct.fieldNames.indexOf(field), args.get(1))) + struct.copy(values = values) } } 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 c8a6511f5890..3923d72f0495 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 @@ -87,11 +87,8 @@ object Ast { /** Struct projection. */ final case class EStructProj(field: FieldName, struct: Expr) extends Expr - /** Non-destructive struct update. */ - final case class EStructUpd(field: FieldName, struct: Expr, update: Expr) extends Expr { - // The actual index is filled in by the type checker. - private[lf] var fieldIndex: Option[Int] = None - } + /** Struct update. */ + final case class EStructUpd(field: FieldName, struct: Expr, update: Expr) extends Expr /** Expression application. Function can be an abstraction or a builtin function. */ final case class EApp(fun: Expr, arg: Expr) extends Expr 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 6babbc0cdf01..af01192b99b8 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 @@ -650,19 +650,17 @@ private[validation] object Typing { private def typeOfStructProj(proj: EStructProj): Type = toStruct(typeOf(proj.struct)).fields.get(proj.field) match { - case Some(value) => value + case Some(typ) => typ case None => throw EUnknownField(ctx, proj.field) } private def typeOfStructUpd(upd: EStructUpd): Type = { - val typ @ TStruct(structType) = toStruct(typeOf(upd.struct)) - val index = structType.indexOf(upd.field) - if (index < 0) - throw EUnknownField(ctx, upd.field) - else { - upd.fieldIndex = Some(index) - checkExpr(upd.update, structType.toImmArray(index)._2) - typ + val structType = toStruct(typeOf(upd.struct)) + structType.fields.get(upd.field) match { + case Some(updateType) => + checkExpr(upd.update, updateType) + structType + case None => throw EUnknownField(ctx, upd.field) } }