Simplify handling for EqualList builtin. (#11676)

Step 1: SEBuiltinRecursiveDefinition(_) -> SEBuiltinEqualList

CHANGELOG_BEGIN
CHANGELOG_END

Step2: Replace SEBuiltinEqualList with SBuiltin.SBEqualList

update comment
This commit is contained in:
nickchapman-da 2021-11-15 17:49:07 +00:00 committed by GitHub
parent 90ad968d39
commit a1fc5c6a25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 82 additions and 136 deletions

View File

@ -189,7 +189,6 @@ private[lf] object Anf {
case loc: source.SELoc => convertLoc(loc)
case source.SEValue(x) => target.SEValue(x)
case source.SEBuiltin(x) => target.SEBuiltin(x)
case source.SEBuiltinRecursiveDefinition(x) => target.SEBuiltinRecursiveDefinition(x)
}
}

View File

@ -5,11 +5,7 @@ package com.daml.lf.speedy
/** Closure Conversion (Phase of the speedy compiler pipeline)
*
* This compilation phase transforms from SExpr0 to SExpr0.
* SExpr0 contains expression forms which exist during the speedy compilation pipeline.
*
* TODO: introduces new expression type (SExpr1) for the result of this phase, and input to the
* following ANF transformation phase.
* This compilation phase transforms from SExpr0 to SExpr1.
*/
import com.daml.lf.speedy.{SExpr0 => source}
@ -62,7 +58,6 @@ private[speedy] object ClosureConversion {
case source.SEVal(ref) => target.SEVal(ref)
case source.SEBuiltin(b) => target.SEBuiltin(b)
case source.SEValue(v) => target.SEValue(v)
case source.SEBuiltinRecursiveDefinition(f) => target.SEBuiltinRecursiveDefinition(f)
case source.SELocation(loc, body) =>
target.SELocation(loc, closureConvert(remaps, body))
@ -158,7 +153,6 @@ private[speedy] object ClosureConversion {
case _: source.SEVal => free
case _: source.SEBuiltin => free
case _: source.SEValue => free
case _: source.SEBuiltinRecursiveDefinition => free
case source.SELocation(_, body) =>
go(body, bound, free)
case source.SEAppGeneral(fun, args) =>

View File

@ -570,12 +570,6 @@ private[lf] final class Compiler(
@inline
private[this] def compileBuiltin(bf: BuiltinFunction): s.SExpr =
bf match {
case BEqualList =>
val ref: t.SEBuiltinRecursiveDefinition.Reference =
t.SEBuiltinRecursiveDefinition.Reference.EqualList
val exp: s.SExpr = s.SEBuiltinRecursiveDefinition(ref)
withLabelS(ref, exp)
case BCoerceContractId => s.SEAbs.identity
// Numeric Comparisons
case BLessNumeric => SBLessNumeric
@ -639,6 +633,7 @@ private[lf] final class Compiler(
// List functions
case BFoldl => SBFoldl
case BFoldr => SBFoldr
case BEqualList => SBEqualList
// Errors
case BError => SBError
@ -690,8 +685,8 @@ private[lf] final class Compiler(
case BTextIntercalate => SBTextIntercalate
// Implemented using normal SExpr
case BFoldl | BFoldr | BCoerceContractId | BEqual | BEqualList | BLessEq |
BLess | BGreaterEq | BGreater | BLessNumeric | BLessEqNumeric | BGreaterNumeric |
case BCoerceContractId | BLessNumeric | BLessEqNumeric | BGreaterNumeric |
BGreaterEqNumeric | BEqualNumeric | BNumericToText | BTextMapEmpty | BGenMapEmpty =>
throw CompilationError(s"unexpected $bf")

View File

@ -513,7 +513,6 @@ private[lf] object Pretty {
case SEScopeExercise(body) =>
text("exercise") + char('(') + prettySExpr(index)(body) + text(")")
case x: SEBuiltinRecursiveDefinition => str(x)
case x: SEImportValue => str(x)
case x: SELabelClosure => str(x)
case x: SEDamlException => str(x)

View File

@ -251,7 +251,6 @@ object Profile {
implicit val lookupByKeyDefRef: Allowed[LookupByKeyDefRef] = allowAll
implicit val createAndExerciseLabel: Allowed[CreateAndExerciseLabel] = allowAll
implicit val exceptionMessageDefRef: Allowed[ExceptionMessageDefRef] = allowAll
implicit val sebrdr: Allowed[SEBuiltinRecursiveDefinition.Reference] = allowAll
implicit val scenarioLabel: Allowed[ScenarioLabel] = allowAll
implicit val exprVarName: Allowed[Ast.ExprVarName] = allowAll
@ -281,7 +280,6 @@ object Profile {
case CreateAndExerciseLabel(tmplRef, name) =>
s"createAndExercise @${tmplRef.qualifiedName} ${name}"
case ExceptionMessageDefRef(typeId) => s"message @${typeId.qualifiedName}"
case ref: SEBuiltinRecursiveDefinition.Reference => ref.toString().toLowerCase()
case SubmitLabel => "submit"
case SubmitMustFailLabel => "submitMustFail"
case PassLabel => "pass"

View File

@ -1706,6 +1706,82 @@ private[lf] object SBuiltin {
}
}
/** EQUAL_LIST :: (a -> a -> Bool) -> [a] -> [a] -> Bool */
final case object SBEqualList extends SBuiltin(3) {
private val equalListBody: SExpr =
SECaseAtomic( // case xs of
SELocA(1),
Array(
SCaseAlt(
SCPNil, // nil ->
SECaseAtomic( // case ys of
SELocA(2),
Array(
SCaseAlt(SCPNil, SEValue.True), // nil -> True
SCaseAlt(SCPDefault, SEValue.False),
),
), // default -> False
),
SCaseAlt( // cons x xss ->
SCPCons,
SECaseAtomic( // case ys of
SELocA(2),
Array(
SCaseAlt(SCPNil, SEValue.False), // nil -> False
SCaseAlt( // cons y yss ->
SCPCons,
SELet1( // let sub = (f y x) in
SEAppAtomicGeneral(
SELocA(0), // f
Array(
SELocS(2), // y
SELocS(4),
),
), // x
SECaseAtomic( // case (f y x) of
SELocS(1),
Array(
SCaseAlt(
SCPPrimCon(Ast.PCTrue), // True ->
SEAppAtomicGeneral(
SEBuiltin(SBEqualList), //single recursive occurrence
Array(
SELocA(0), // f
SELocS(2), // yss
SELocS(4),
),
), // xss
),
SCaseAlt(SCPPrimCon(Ast.PCFalse), SEValue.False), // False -> False
),
),
),
),
),
),
),
),
)
private val closure: SValue = {
val frame = Array.ofDim[SValue](0) // no free vars
val arity = 3
SPAP(PClosure(Profile.LabelUnset, equalListBody, frame), new util.ArrayList[SValue](), arity)
}
override private[speedy] def execute(args: util.ArrayList[SValue], machine: Machine) = {
val f = args.get(0)
val xs = args.get(1)
val ys = args.get(2)
machine.enterApplication(
closure,
Array(SEValue(f), SEValue(xs), SEValue(ys)),
)
}
}
object SBExperimental {
private object SBExperimentalAnswer extends SBuiltin(1) {

View File

@ -443,102 +443,6 @@ object SExpr {
methodName: MethodName,
) extends SDefinitionRef
//
// List builtins (equalList) are implemented as recursive
// definition to save java stack
//
final case class SEBuiltinRecursiveDefinition(ref: SEBuiltinRecursiveDefinition.Reference)
extends SExprAtomic {
import SEBuiltinRecursiveDefinition._
private val frame = Array.ofDim[SValue](0) // no free vars
val arity = 3
private def body: SExpr = ref match {
case Reference.EqualList => equalListBody
}
private def closure: SValue =
SPAP(PClosure(Profile.LabelUnset, body, frame), new util.ArrayList[SValue](), arity)
def lookupValue(machine: Machine): SValue = closure
}
// TODO: simplify here: There is only kind of SEBuiltinRecursiveDefinition! - EqualList
final object SEBuiltinRecursiveDefinition {
sealed abstract class Reference
final object Reference {
final case object EqualList extends Reference
}
private val EqualList: SEBuiltinRecursiveDefinition = SEBuiltinRecursiveDefinition(
Reference.EqualList
)
// The body of an expanded recursive-builtin will always be in ANF form.
// The comments show where variables are to be found at runtime.
private def equalListBody: SExpr =
SECaseAtomic( // case xs of
SELocA(1),
Array(
SCaseAlt(
SCPNil, // nil ->
SECaseAtomic( // case ys of
SELocA(2),
Array(
SCaseAlt(SCPNil, SEValue.True), // nil -> True
SCaseAlt(SCPDefault, SEValue.False),
),
), // default -> False
),
SCaseAlt( // cons x xss ->
SCPCons,
SECaseAtomic( // case ys of
SELocA(2),
Array(
SCaseAlt(SCPNil, SEValue.False), // nil -> False
SCaseAlt( // cons y yss ->
SCPCons,
SELet1( // let sub = (f y x) in
SEAppAtomicGeneral(
SELocA(0), // f
Array(
SELocS(2), // y
SELocS(4),
),
), // x
SECaseAtomic( // case (f y x) of
SELocS(1),
Array(
SCaseAlt(
SCPPrimCon(PCTrue), // True ->
SEAppAtomicGeneral(
EqualList,
Array(
SELocA(0), // f
SELocS(2), // yss
SELocS(4),
),
), // xss
),
SCaseAlt(SCPPrimCon(PCFalse), SEValue.False), // False -> False
),
),
),
),
),
),
),
),
)
}
final case object AnonymousClosure
private def prettyPrint(x: Any): String =

View File

@ -30,9 +30,8 @@ package speedy
*
* Summary of which constructors are contained by: SExp0, SExpr1 and SExpr:
*
* - In SExpr{0,1,} (everywhere): SEAppGeneral, SEBuiltin, SEBuiltinRecursiveDefinition,
* SELabelClosure, SELet1General, SELocation,
* SEScopeExercise, SETryCatch, SEVal, SEValue,
* - In SExpr{0,1,} (everywhere): SEAppGeneral, SEBuiltin, SELabelClosure, SELet1General,
* SELocation, SEScopeExercise, SETryCatch, SEVal, SEValue,
*
* - In SExpr0: SEAbs, SEVar
*
@ -49,7 +48,6 @@ package speedy
import com.daml.lf.data.Ref._
import com.daml.lf.speedy.SValue._
import com.daml.lf.speedy.SExpr.{SDefinitionRef, SCasePat}
import com.daml.lf.speedy.{SExpr => runTime}
@SuppressWarnings(Array("org.wartremover.warts.Any"))
private[speedy] object SExpr0 {
@ -139,14 +137,4 @@ private[speedy] object SExpr0 {
* extended and 'body' is evaluated.
*/
final case class SCaseAlt(pattern: SCasePat, body: SExpr)
//
// List builtins (equalList) are implemented as recursive
// definition to save java stack
//
// TODO: simplify here: There is only kind of SEBuiltinRecursiveDefinition! - EqualList
final case class SEBuiltinRecursiveDefinition(ref: runTime.SEBuiltinRecursiveDefinition.Reference)
extends SExpr
}

View File

@ -12,7 +12,6 @@ package speedy
import com.daml.lf.data.Ref._
import com.daml.lf.speedy.SValue._
import com.daml.lf.speedy.SExpr.{SDefinitionRef, SCasePat}
import com.daml.lf.speedy.{SExpr => runTime}
private[speedy] object SExpr1 {
@ -109,8 +108,4 @@ private[speedy] object SExpr1 {
* extended and 'body' is evaluated.
*/
final case class SCaseAlt(pattern: SCasePat, body: SExpr)
final case class SEBuiltinRecursiveDefinition(ref: runTime.SEBuiltinRecursiveDefinition.Reference)
extends SExprAtomic
}

View File

@ -55,7 +55,6 @@ private[lf] object ValidateCompilation {
case loc: SELoc => goLoc(loc)
case _: SEVal => ()
case _: SEBuiltin => ()
case _: SEBuiltinRecursiveDefinition => ()
case SEValue(v) => goV(v)
case SEAppAtomicGeneral(fun, args) =>
go(fun)

View File

@ -29,7 +29,6 @@ private[speedy] object SExprIterable {
case SExpr.SETryCatch(body, handler) => Iterator(body, handler)
case SExpr.SEScopeExercise(body) => Iterator(body)
case SExpr.SEBuiltin(_) => Iterator.empty
case SExpr.SEBuiltinRecursiveDefinition(_) => Iterator.empty
case SExpr.SELocA(_) => Iterator.empty
case SExpr.SELocS(_) => Iterator.empty
case SExpr.SEValue(v) => iterator(v)