Skip to content

Commit

Permalink
Ensure stack-safety during closure-conversion.
Browse files Browse the repository at this point in the history
ClosureConversion -> Suffix with "Old"

CHANGELOG_BEGIN
CHANGELOG_END

ClosureConversion old-vs-new diff check

ClosureConversionNew, first cut. All tests in SBuiltinTest work.

In addition we change some Array --> List in SExpr1 (for human pp).
And we throw away ClosureConversionDup.

adapt AnfTest from Array to List change for SExpr1

all tests pass in daml-lf/interpreter

remove SExpr0.SELet1General

reorder things

testing for stack-safety of closure conversion

file/class renames

improve naming

pass cont as sep arg to commit (move out of Up/Down)

comment stack-safe closure conversion

fix bug: failed to use env1

fix 2x unmoored doc comment

comment stack safety testing

Remove old closure-conversion code & diff-check between old/new.

loose StackSafe suffix on ClosureConversion class/file

rename StackSafetyTest.scala to ClosureConversionTest.scala

prefer "sealed abstract class" to "sealed trait"

fvs.zipWithIndex --> fvs.view.zipWithIndex

(SExpr1) SEAppGeneral -> SEApp; prefer List to Array in SEApp/SECase

prefer xs.toArray to Array(xs: _*)

access SExpr0 via "source."

two more .view

improve comment and fix typo

link to Issue

switch to a continuation stack; avoids nesting in the Cont type
  • Loading branch information
nickchapman-da committed Nov 23, 2021
1 parent 2d60ae8 commit 82223aa
Show file tree
Hide file tree
Showing 10 changed files with 476 additions and 181 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -93,16 +93,16 @@ object PlaySpeedy {

// The trailing numeral is the number of args at the scala level

def decrement1(x: SExpr): SExpr = SEApp(SEBuiltin(SBSubInt64), Array(x, SEValue(SInt64(1))))
def decrement1(x: SExpr): SExpr = SEApp(SEBuiltin(SBSubInt64), List(x, SEValue(SInt64(1))))
val decrement = SEAbs(1, decrement1(SEVar(1)))

def subtract2(x: SExpr, y: SExpr): SExpr = SEApp(SEBuiltin(SBSubInt64), Array(x, y))
def subtract2(x: SExpr, y: SExpr): SExpr = SEApp(SEBuiltin(SBSubInt64), List(x, y))
val subtract = SEAbs(2, subtract2(SEVar(2), SEVar(1)))

def twice2(f: SExpr, x: SExpr): SExpr = SEApp(f, Array(SEApp(f, Array(x))))
def twice2(f: SExpr, x: SExpr): SExpr = SEApp(f, List(SEApp(f, List(x))))
val twice = SEAbs(2, twice2(SEVar(2), SEVar(1)))

def thrice2(f: SExpr, x: SExpr): SExpr = SEApp(f, Array(SEApp(f, Array(SEApp(f, Array(x))))))
def thrice2(f: SExpr, x: SExpr): SExpr = SEApp(f, List(SEApp(f, List(SEApp(f, List(x))))))
val thrice = SEAbs(2, thrice2(SEVar(2), SEVar(1)))

val examples = List(
Expand All @@ -119,30 +119,30 @@ object PlaySpeedy {
(
"subF", //88-55
33,
SEApp(subtract, Array(num(88), num(55))),
SEApp(subtract, List(num(88), num(55))),
),
(
"thrice", // thrice (\x -> x - 1) 0
-3,
SEApp(thrice, Array(decrement, num(0))),
SEApp(thrice, List(decrement, num(0))),
),
(
"thrice-thrice", //thrice thrice (\x -> x - 1) 0
-27,
SEApp(thrice, Array(thrice, decrement, num(0))),
SEApp(thrice, List(thrice, decrement, num(0))),
),
(
"free", // let (a,b,c) = (30,100,21) in twice (\x -> x - (a-c)) b
82,
SELet1General(
num(30),
SELet1General(
num(100),
SELet1General(
num(21),
SELet(
List(num(30)),
SELet(
List(num(100)),
SELet(
List(num(21)),
SEApp(
twice,
Array(SEAbs(1, subtract2(SEVar(1), subtract2(SEVar(4), SEVar(2)))), SEVar(2)),
List(SEAbs(1, subtract2(SEVar(1), subtract2(SEVar(4), SEVar(2)))), SEVar(2)),
),
), //100
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ private[lf] object Anf {

case source.SEVal(x) => Bounce(() => transform(depth, target.SEVal(x), k))

case source.SEAppGeneral(func, args) =>
case source.SEApp(func, args) =>
// It's safe to perform ANF if the func-expression has no effects when evaluated.
val safeFunc =
func match {
Expand All @@ -311,22 +311,22 @@ private[lf] object Anf {
}
// It's also safe to perform ANF for applications of a single argument.
if (safeFunc || args.size == 1) {
transformMultiApp[A](depth, env, func, args, k)(transform)
transformMultiApp[A](depth, env, func, args.toArray, k)(transform)
} else {
transformMultiAppSafely[A](depth, env, func, args, k)(transform)
transformMultiAppSafely[A](depth, env, func, args.toArray, k)(transform)
}

case source.SEMakeClo(fvs0, arity, body0) =>
val fvs = fvs0.map((loc) => makeRelativeL(depth)(makeAbsoluteL(env, loc)))
val body = flattenToAnfInternal(body0).wrapped
Bounce(() => transform(depth, target.SEMakeClo(fvs, arity, body), k))
Bounce(() => transform(depth, target.SEMakeClo(fvs.toArray, arity, body), k))

case source.SECase(scrut, alts0) => {
Bounce(() =>
atomizeExp(depth, env, scrut, k) { (depth, scrut, txK) =>
val scrut1 = makeRelativeA(depth)(scrut)
Bounce(() =>
flattenAlts(depth, env, alts0) { alts =>
flattenAlts(depth, env, alts0.toArray) { alts =>
Bounce(() => transform(depth, target.SECaseAtomic(scrut1, alts), txK))
}
)
Expand Down
Loading

0 comments on commit 82223aa

Please sign in to comment.