mirror of
https://github.com/unisonweb/unison.git
synced 2024-10-05 22:27:28 +03:00
Merge pull request #189 from unisonweb/topic/move-output-type
move outputType from `Lambda` to primitive `Computation`s
This commit is contained in:
commit
a6aa61fd4f
@ -134,7 +134,7 @@ object BuiltinTypes {
|
||||
}
|
||||
val lam: Computation =
|
||||
if (arity >= 1)
|
||||
new Value.Lambda.ClosureForming(paramNames.toList, body, None, decompile)
|
||||
new Value.Lambda.ClosureForming(paramNames.toList, body, decompile)
|
||||
.toComputation
|
||||
else try {
|
||||
Return(req(Array()))
|
||||
|
@ -1,7 +1,6 @@
|
||||
package org.unisonweb
|
||||
|
||||
import java.util.function.{LongBinaryOperator, LongPredicate, LongUnaryOperator,
|
||||
DoubleBinaryOperator}
|
||||
import java.util.function.{DoubleBinaryOperator, LongBinaryOperator, LongPredicate, LongUnaryOperator}
|
||||
|
||||
import org.unisonweb.Term.{Name, Term}
|
||||
import org.unisonweb.Value.Lambda
|
||||
@ -72,7 +71,7 @@ object Builtins {
|
||||
}
|
||||
val decompiled = Term.Id(name)
|
||||
val lambda =
|
||||
new Value.Lambda.ClosureForming(List(arg1, arg2, arg3), body, None, decompiled)
|
||||
new Value.Lambda.ClosureForming(List(arg1, arg2, arg3), body, decompiled)
|
||||
name -> Return(lambda)
|
||||
}
|
||||
|
||||
@ -384,7 +383,7 @@ object Builtins {
|
||||
(implicit A: Decode[A], B: Encode[B]): (Name, Computation) = {
|
||||
val body: Computation.C1P = (r,x0,x0b) => B.encode(r, f(A.decode(x0, x0b)))
|
||||
val decompile = Term.Id(name)
|
||||
name -> Return(new Lambda1(arg, body, None, decompile))
|
||||
name -> Return(new Lambda1(arg, body, decompile))
|
||||
}
|
||||
|
||||
// Monomorphic one-argument function on unboxed values
|
||||
@ -392,14 +391,11 @@ object Builtins {
|
||||
arg: Name,
|
||||
outputType: UnboxedType,
|
||||
f: LongUnaryOperator): (Name, Computation) = {
|
||||
val body: Computation.C1U = (r,x0) => {
|
||||
// Unintuitively, we store the type of the unboxed value in `boxed`
|
||||
// since that's a field we don't use for unboxed values.
|
||||
r.boxed = outputType
|
||||
f.applyAsLong(x0)
|
||||
val body: Computation.C1U = new Computation.C1U(outputType) {
|
||||
def raw(x0: U): U = f.applyAsLong(x0)
|
||||
}
|
||||
val decompile = Term.Id(name)
|
||||
val computation = Return(new Lambda1(arg, body, Some(outputType), decompile))
|
||||
val computation = Return(new Lambda1(arg, body, decompile))
|
||||
name -> computation
|
||||
}
|
||||
|
||||
@ -431,7 +427,7 @@ object Builtins {
|
||||
val body: Computation.C1P = (r,x0,x0b) => {
|
||||
B.encodeOp(r, f(A.decode(x0, x0b)), name, Value.fromParam(x0, x0b))
|
||||
}
|
||||
val lambda = new Lambda.Lambda1(arg, body, None, Term.Id(name))
|
||||
val lambda = new Lambda.Lambda1(arg, body, Term.Id(name))
|
||||
name -> Return(lambda)
|
||||
}
|
||||
|
||||
@ -443,7 +439,7 @@ object Builtins {
|
||||
(r,x1,x0,x1b,x0b) =>
|
||||
C.encode(r, f(A.decode(x1, x1b), B.decode(x0, x0b)))
|
||||
val decompiled = Term.Id(name)
|
||||
val lambda = new Lambda.ClosureForming(List(arg1, arg2), body, None, decompiled)
|
||||
val lambda = new Lambda.ClosureForming(List(arg1, arg2), body, decompiled)
|
||||
name -> Return(lambda)
|
||||
}
|
||||
|
||||
@ -460,7 +456,7 @@ object Builtins {
|
||||
Value.fromParam(x0, x0b))
|
||||
}
|
||||
val decompiled = Term.Id(name)
|
||||
val lambda = new Lambda.ClosureForming(List(arg1, arg2), body, None, decompiled)
|
||||
val lambda = new Lambda.ClosureForming(List(arg1, arg2), body, decompiled)
|
||||
name -> Return(lambda)
|
||||
}
|
||||
|
||||
@ -475,7 +471,7 @@ object Builtins {
|
||||
val body: Computation.C2P = (r,x1,x0,_,x0b) =>
|
||||
B.encode(r, f(x1, A.decode(x0, x0b)))
|
||||
val decompiled = Term.Id(name)
|
||||
val lambda = new Lambda.ClosureForming(List(arg1, arg2), body, None, decompiled)
|
||||
val lambda = new Lambda.ClosureForming(List(arg1, arg2), body, decompiled)
|
||||
name -> Return(lambda)
|
||||
}
|
||||
|
||||
@ -487,7 +483,7 @@ object Builtins {
|
||||
name,
|
||||
Value.fromParam(x1,x1b),
|
||||
Value.fromParam(x0,x0b))
|
||||
name -> Return(new Value.Lambda.ClosureForming(List(arg1, arg2), body, None, Term.Id(name)))
|
||||
name -> Return(new Value.Lambda.ClosureForming(List(arg1, arg2), body, Term.Id(name)))
|
||||
}
|
||||
|
||||
|
||||
@ -503,7 +499,7 @@ object Builtins {
|
||||
Value.fromParam(x0, x0b))
|
||||
|
||||
val decompiled = Term.Id(name)
|
||||
val lambda = new Lambda.ClosureForming(List(arg1, arg2), body, None, decompiled)
|
||||
val lambda = new Lambda.ClosureForming(List(arg1, arg2), body, decompiled)
|
||||
name -> Return(lambda)
|
||||
}
|
||||
|
||||
@ -522,7 +518,7 @@ object Builtins {
|
||||
f(A.decode(x1, x1b), B.decode(x0, x0b))
|
||||
}
|
||||
val decompiled = Term.Id(name)
|
||||
val lambda = new Lambda.ClosureForming(List(arg1, arg2), body, None, decompiled)
|
||||
val lambda = new Lambda.ClosureForming(List(arg1, arg2), body, decompiled)
|
||||
name -> Return(lambda)
|
||||
}
|
||||
|
||||
@ -553,65 +549,53 @@ object Builtins {
|
||||
arg2: Name,
|
||||
outputType: UnboxedType,
|
||||
f: LongBinaryOperator): (Name, Computation) = {
|
||||
val body: Computation.C2U = (r,x1,x0) => {
|
||||
r.boxed = outputType
|
||||
f.applyAsLong(x1, x0)
|
||||
val body = new Computation.C2U(outputType) {
|
||||
def raw(x1: U, x0: U): U = f.applyAsLong(x1, x0)
|
||||
}
|
||||
|
||||
val decompiled = Term.Id(name)
|
||||
val lam = new Lambda(List(arg1, arg2), body, Some(outputType), decompiled) {
|
||||
val lam = new Lambda(List(arg1, arg2), body, decompiled) {
|
||||
self =>
|
||||
|
||||
override def saturatedNonTailCall(args: List[Computation]) = args match {
|
||||
case List(Return(Value.Unboxed(n1, _)),
|
||||
Return(Value.Unboxed(n2, _))) =>
|
||||
val n3 = f.applyAsLong(n1,n2) // constant fold
|
||||
val c : Computation.C0 = r => { r.boxed = outputType; n3 }
|
||||
c
|
||||
new Computation.C0U(outputType) {
|
||||
def raw: U = n3
|
||||
}
|
||||
case List(CompiledVar0,Return(Value.Unboxed(n, _))) =>
|
||||
val c : Computation.C1U = (r,x0) => {
|
||||
r.boxed = outputType
|
||||
f.applyAsLong(x0, n)
|
||||
new Computation.C1U(outputType) {
|
||||
def raw(x0: U): U = f.applyAsLong(x0, n)
|
||||
}
|
||||
c
|
||||
case List(CompiledVar1,Return(Value.Unboxed(n, _))) =>
|
||||
val c : Computation.C2U = (r,x1,_) => {
|
||||
r.boxed = outputType
|
||||
f.applyAsLong(x1, n)
|
||||
new Computation.C2U(outputType) {
|
||||
def raw(x1: U, x0: U): U = f.applyAsLong(x1, n)
|
||||
}
|
||||
c
|
||||
case List(Return(Value.Unboxed(n, _)), CompiledVar0) =>
|
||||
val c: Computation.C1U = (r,x0) => {
|
||||
r.boxed = outputType
|
||||
f.applyAsLong(n,x0)
|
||||
new Computation.C1U(outputType) {
|
||||
def raw(x0: U): U = f.applyAsLong(n,x0)
|
||||
}
|
||||
c
|
||||
case List(Return(Value.Unboxed(n, _)), CompiledVar1) =>
|
||||
val c: Computation.C2U = (r,x1,_) => {
|
||||
r.boxed = outputType
|
||||
f.applyAsLong(n,x1)
|
||||
new Computation.C2U(outputType) {
|
||||
def raw(x1: U, x0: U): U = f.applyAsLong(n,x1)
|
||||
}
|
||||
c
|
||||
case List(CompiledVar1,CompiledVar0) =>
|
||||
val c: Computation.C2U = (r,x1,x0) => {
|
||||
r.boxed = outputType
|
||||
f.applyAsLong(x1,x0)
|
||||
new Computation.C2U(outputType) {
|
||||
def raw(x1: U, x0: U): U = f.applyAsLong(x1,x0)
|
||||
}
|
||||
c
|
||||
case List(CompiledVar0,CompiledVar1) =>
|
||||
val c: Computation.C2U = (r,x1,x0) => {
|
||||
r.boxed = outputType
|
||||
f.applyAsLong(x0,x1)
|
||||
new Computation.C2U(outputType) {
|
||||
def raw(x1: U, x0: U): U = f.applyAsLong(x0,x1)
|
||||
}
|
||||
c
|
||||
case List(arg1: Computation.C2U, arg2: Computation.C2U) =>
|
||||
val c: Computation.C2U = (r,x1,x0) => {
|
||||
val x1v = arg1(r, x1, x0)
|
||||
val x0v = arg2(r, x1, x0)
|
||||
r.boxed = outputType
|
||||
f.applyAsLong(x1v, x0v)
|
||||
new Computation.C2U(outputType) {
|
||||
def raw(x1: U, x0: U): U = {
|
||||
val x1v = arg1.raw(x1, x0)
|
||||
val x0v = arg2.raw(x1, x0)
|
||||
f.applyAsLong(x1v, x0v)
|
||||
}
|
||||
}
|
||||
c
|
||||
case List(arg1,arg2) => (r,rec,top,stackU,x1,x0,stackB,x1b,x0b) => {
|
||||
val x1v = eval(arg1,r,rec,top,stackU,x1,x0,stackB,x1b,x0b)
|
||||
val x0v = eval(arg2,r,rec,top,stackU,x1,x0,stackB,x1b,x0b)
|
||||
@ -626,16 +610,14 @@ object Builtins {
|
||||
case Term.Compiled(p: Param) =>
|
||||
// cast is okay, because in `fuu_u`, args are Unboxed.
|
||||
val n = p.toValue.asInstanceOf[Value.Unboxed].n
|
||||
val body: Computation =
|
||||
(r,rec,top,stackU,x1,x0,stackB,x1b,x0b) => {
|
||||
r.boxed = outputType
|
||||
f.applyAsLong(n, x0)
|
||||
}
|
||||
new Lambda(self.names drop argCount, body, unboxedType,
|
||||
val body = new Computation.C1U(outputType) {
|
||||
def raw(x0: U): U = f.applyAsLong(n, x0)
|
||||
}
|
||||
new Lambda(self.names drop argCount, body,
|
||||
Term.Apply(decompiled, term))
|
||||
case _ => sys.error("")
|
||||
}
|
||||
case _ => sys.error("unpossible")
|
||||
case _ => sys.error("can't underapply a function of 2 args with anything but 1 arg")
|
||||
}
|
||||
}
|
||||
name -> Return(lam)
|
||||
|
@ -59,7 +59,6 @@ object Value {
|
||||
class Lambda(
|
||||
final val names: List[Name],
|
||||
final val body: Computation,
|
||||
final val unboxedType: Option[UnboxedType],
|
||||
// the lambda decompiled form may have one free var, referring to itself
|
||||
decompileWithPossibleFreeVar: Term) extends Value { self =>
|
||||
|
||||
@ -81,14 +80,25 @@ object Value {
|
||||
|
||||
def compose(f: Lambda): Lambda = {
|
||||
assert(arity == 1)
|
||||
val k: Computation = (r, rec, top, stackU, x1, x0, stackB, x1b, x0b) => {
|
||||
val v = evalLam(f,r,top,stackU,x1,x0,stackB,x1b,x0b)
|
||||
val vb = r.boxed
|
||||
self(r,top,stackU,U0,v,stackB,null,vb)
|
||||
|
||||
val k: Computation = (self.body, f.body) match {
|
||||
case (left: Computation.C1U, right: Computation.C1U) =>
|
||||
new compilation.Computation.C1U(left.outputType) {
|
||||
def raw(x0: U): U = left.raw(right.raw(x0))
|
||||
}
|
||||
case (left: Computation.C1U, right: Computation.C2U) =>
|
||||
new Computation.C2U(left.outputType) {
|
||||
def raw(x1: U, x0: U): U = left.raw(right.raw(x1, x0))
|
||||
}
|
||||
case _ =>
|
||||
(r, rec, top, stackU, x1, x0, stackB, x1b, x0b) => {
|
||||
val v = evalLam(f,r,top,stackU,x1,x0,stackB,x1b,x0b)
|
||||
val vb = r.boxed
|
||||
self(r,top,stackU,U0,v,stackB,null,vb)
|
||||
}
|
||||
}
|
||||
val compose = Term.Lam('f, 'g, 'x)('f.v('g.v('x))) // todo: intern this
|
||||
new Lambda(f.names, k, self.unboxedType,
|
||||
compose(self.decompile, f.decompile))
|
||||
new Lambda(f.names, k, compose(self.decompile, f.decompile))
|
||||
}
|
||||
|
||||
def saturatedNonTailCall(args: List[Computation]): Computation =
|
||||
@ -112,37 +122,33 @@ object Value {
|
||||
object Lambda {
|
||||
final def toValue = this
|
||||
|
||||
def apply(arity: Int, body: Computation, unboxedType: Option[UnboxedType],
|
||||
decompile: Term) = {
|
||||
def apply(arity: Int, body: Computation, decompile: Term) = {
|
||||
new Lambda(names = decompile match { case Term.Lam(names, _) => names },
|
||||
body, unboxedType, decompile)
|
||||
body, decompile)
|
||||
}
|
||||
|
||||
def unapply(l: Lambda): Option[(Int, Computation, Term)] =
|
||||
Some((l.arity, l.body, l.decompile))
|
||||
|
||||
val identity: Lambda1 = {
|
||||
val c: Computation = (r,rec,top,stackU,x1,x0,stackB,x1b,x0b) => {
|
||||
val c: Computation.C1P = (r,x0,x0b) => {
|
||||
r.boxed = x0b.toValue
|
||||
x0
|
||||
}
|
||||
Lambda1("x", c, None, Term.Lam('x)('x))
|
||||
Lambda1("x", c, Term.Lam('x)('x))
|
||||
}
|
||||
|
||||
/** A `Lambda` of arity 1. */
|
||||
// todo: delete this and ClosureForming2 later
|
||||
case class Lambda1(arg1: Name, _body: Computation,
|
||||
outputType: Option[UnboxedType], decompiled: Term)
|
||||
extends Lambda(names = List(arg1),_body,outputType,decompiled) {
|
||||
case class Lambda1(arg1: Name, _body: Computation, decompiled: Term)
|
||||
extends Lambda(names = List(arg1),_body,decompiled) {
|
||||
override def underapply(builtins: Environment)(
|
||||
argCount: Arity, substs: Map[Name, Term]): Lambda =
|
||||
sys.error("a lambda with arity 1 cannot be underapplied")
|
||||
}
|
||||
|
||||
class ClosureForming(names: List[Name], body: Computation,
|
||||
outputType: Option[UnboxedType],
|
||||
decompiled: Term)
|
||||
extends Lambda(names,body,outputType,decompiled) { self =>
|
||||
class ClosureForming(names: List[Name], body: Computation, decompiled: Term)
|
||||
extends Lambda(names,body,decompiled) { self =>
|
||||
val namesArray = names.toArray
|
||||
|
||||
/** Underapply this `Lambda`, passing 1 argument (named `substName`). */
|
||||
@ -157,8 +163,16 @@ object Value {
|
||||
val body2: Computation = arity match {
|
||||
// stack passed to `body2`: [a]
|
||||
// stack passed to `body` : [arg,a]
|
||||
case 2 => (r,rec,top,stackU,x1,x0,stackB,x1b,x0b) =>
|
||||
body(r,rec,top,stackU,argv,x0,stackB,argvb,x0b)
|
||||
case 2 =>
|
||||
body match {
|
||||
case c2u: Computation.C2U => new Computation.C1U(c2u.outputType) {
|
||||
def raw(x0: U): U = c2u.raw(argv,x0)
|
||||
}
|
||||
case _ =>
|
||||
(r,rec,top,stackU,x1,x0,stackB,x1b,x0b) =>
|
||||
body(r,rec,top,stackU,argv,x0,stackB,argvb,x0b)
|
||||
}
|
||||
|
||||
// stack passed to `body2`: [a,b]
|
||||
// stack passed to `body` : [arg,a,b]
|
||||
case 3 => (r,rec,top,stackU,x1,x0,stackB,x1b,x0b) => {
|
||||
@ -181,7 +195,7 @@ object Value {
|
||||
body(r,rec,top.inc,stackU,x1,x0,stackB,x1b,x0b)
|
||||
}
|
||||
}
|
||||
new ClosureForming(names drop 1, body2, outputType, decompiled(substTerm))
|
||||
new ClosureForming(names drop 1, body2, decompiled(substTerm))
|
||||
}
|
||||
|
||||
// todo: try for more efficient implementation of underapply, O(n) vs n^2
|
||||
|
@ -12,23 +12,22 @@ object UnisonToScala {
|
||||
|
||||
def toUnboxed1(f: Value.Lambda): Env => Unboxed.F1[Param,Value] = {
|
||||
require (f.arity == 1)
|
||||
f.unboxedType.map[Env => Unboxed.F1[Param,Value]] {
|
||||
outputType =>
|
||||
env => {
|
||||
f.body match {
|
||||
case body: Computation.C1U =>
|
||||
_env =>
|
||||
new Unboxed.F1[Param, Value] {
|
||||
def apply[x] = kvx => (u1,a,u2,x) => kvx(body.raw(u1), body.outputType, u2, x)
|
||||
}
|
||||
case _body =>
|
||||
env =>
|
||||
val (stackU, stackB, top, r) = env
|
||||
f.body match {
|
||||
case body: Computation.C1U => new Unboxed.F1[Param,Value] {
|
||||
def apply[x] = kvx => (u1,a,u2,x) => kvx(body(r,u1), outputType, u2, x)
|
||||
}
|
||||
case body => new Unboxed.F1[Param,Value] {
|
||||
def apply[x] = kvx => (u1,a,u2,x) => {
|
||||
val out = evalLam(f, r, top, stackU, U0, u1, stackB, null, a)
|
||||
kvx(out, r.boxed, u2, x)
|
||||
}
|
||||
new Unboxed.F1[Param,Value] {
|
||||
def apply[x] = kvx => (u1,a,u2,x) => {
|
||||
val out = evalLam(f, r, top, stackU, U0, u1, stackB, null, a)
|
||||
kvx(out, r.boxed, u2, x)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.getOrElse(sys.error("`f` is expected to have an unboxed output type"))
|
||||
}
|
||||
}
|
||||
|
||||
def toUnboxed2(p: (Term.Name, Computation)): Env => Unboxed.F2[Value,Value,Value] =
|
||||
@ -36,22 +35,22 @@ object UnisonToScala {
|
||||
|
||||
def toUnboxed2(f: Value.Lambda): Env => Unboxed.F2[Value,Value,Value] = {
|
||||
require(f.arity == 2)
|
||||
f.unboxedType.map[Env => Unboxed.F2[Value,Value,Value]] {
|
||||
outputType =>
|
||||
env => {
|
||||
f.body match {
|
||||
case body: Computation.C2U =>
|
||||
_env =>
|
||||
new Unboxed.F2[Param, Param, Value] {
|
||||
def apply[x] = kvx => (u1, a, u2, b, u3, x) => kvx(body.raw(u1, u2), body.outputType, u3, x)
|
||||
}
|
||||
|
||||
case _body =>
|
||||
env =>
|
||||
val (stackU, stackB, top, r) = env
|
||||
f.body match {
|
||||
case body: Computation.C2U => new Unboxed.F2[Param, Param, Value] {
|
||||
def apply[x] = kvx => (u1, a, u2, b, u3, x) => kvx(body(r, u1, u2), outputType, u3, x)
|
||||
}
|
||||
case body => new Unboxed.F2[Param, Param, Value] {
|
||||
def apply[x] = kvx => (u1, a, u2, b, u3, x) => {
|
||||
val out = evalLam(f, r, top, stackU, u1, u2, stackB, a, b)
|
||||
kvx(out, r.boxed, u3, x)
|
||||
}
|
||||
new Unboxed.F2[Param, Param, Value] {
|
||||
def apply[x] = kvx => (u1, a, u2, b, u3, x) => {
|
||||
val out = evalLam(f, r, top, stackU, u1, u2, stackB, a, b)
|
||||
kvx(out, r.boxed, u3, x)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.getOrElse(sys.error("`f` is expected to have an unboxed output type"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -129,18 +129,31 @@ package object compilation {
|
||||
// Special cases for computations that take unboxed arguments and produce unboxed results,
|
||||
// and which are guaranteed not to throw tail call exceptions during evaluation. We check for
|
||||
// these in various places to emit more efficient code for common cases.
|
||||
abstract class C2U extends Computation {
|
||||
def apply(r: R, x1: U, x0: U): U
|
||||
abstract class C2U(val outputType: UnboxedType) extends Computation {
|
||||
def raw(x1: U, x0: U): U
|
||||
|
||||
final def apply(r: R, x1: U, x0: U): U = {
|
||||
r.boxed = outputType
|
||||
raw(x1, x0)
|
||||
}
|
||||
final def apply(r: R, rec: Lambda, top: StackPtr, stackU: Array[U], x1: U, x0: U, stackB: Array[B], x1b: B, x0b: B): U =
|
||||
apply(r, x1, x0)
|
||||
}
|
||||
abstract class C1U extends C2U {
|
||||
def apply(r: R, x0: U): U
|
||||
final def apply(r: R, x1: U, x0: U): U = apply(r, x0)
|
||||
abstract class C1U(outputType: UnboxedType) extends C2U(outputType) {
|
||||
def raw(x0: U): U
|
||||
final def raw(x1: U, x0: U) = raw(x0)
|
||||
final def apply(r: R, x0: U): U = {
|
||||
r.boxed = outputType
|
||||
raw(x0)
|
||||
}
|
||||
}
|
||||
abstract class C0U extends C1U {
|
||||
def apply(r: R): U
|
||||
final def apply(r: R, x0: U): U = apply(r)
|
||||
abstract class C0U(outputType: UnboxedType) extends C1U(outputType) {
|
||||
def raw: U
|
||||
final def raw(x0: U) = raw
|
||||
final def apply(r: R): U = {
|
||||
r.boxed = outputType
|
||||
raw
|
||||
}
|
||||
}
|
||||
abstract class C2P extends Computation {
|
||||
def apply(r: R, x1: U, x0: U, x1b: B, x0b: B): U
|
||||
@ -783,6 +796,9 @@ package object compilation {
|
||||
val needsCopy = names.length > K
|
||||
// inner lambda may throw SelfCall, so we create wrapper Lambda
|
||||
// to process those
|
||||
|
||||
// note: no reason to specialize for Computation.C{2,1,0}U, as these
|
||||
// won't contain a tail-recursive call, thus won't enter here
|
||||
val outerLambdaBody: Computation = (r,rec,top,stackU,x1,x0,stackB,x1b,x0b) => {
|
||||
val stackArgsCount = (innerLambda.arity - K) max 0
|
||||
|
||||
@ -818,7 +834,7 @@ package object compilation {
|
||||
|
||||
go(x1, x0, x1b, x0b)
|
||||
}
|
||||
Lambda(names.length, outerLambdaBody, innerLambda.unboxedType, innerLambda.decompile)
|
||||
Lambda(names.length, outerLambdaBody, innerLambda.decompile)
|
||||
}
|
||||
|
||||
compiledLambda match {
|
||||
@ -877,7 +893,7 @@ package object compilation {
|
||||
val shadowedRec = bodyRec.shadow(names)
|
||||
val cbody = compile(builtins)(body, names.reverse.toVector,
|
||||
shadowedRec, shadowedRec.toRecursiveVars, IsTail)
|
||||
Return(Lambda(names.length, cbody, None, e))
|
||||
Return(Lambda(names.length, cbody, e))
|
||||
}
|
||||
// 2.
|
||||
else {
|
||||
@ -1294,9 +1310,10 @@ package object compilation {
|
||||
// Note: We have to make up a name here. "handler" works.
|
||||
Term.Lam(k.names:_*)(Term.Handle(Term.Compiled(handler))(
|
||||
k.decompile(k.names.map(Term.Var(_)):_*)))
|
||||
// todo: worth it to specialize doIt for k.body: Computation.C{2,1,0}U?
|
||||
val body: Computation = (r,rec,top,stackU,x1,x0,stackB,x1b,x0b) =>
|
||||
doIt(handler, k.body)(r,rec,top,stackU,x1,x0,stackB,x1b,x0b)
|
||||
Lambda(k.arity, body, k.unboxedType, decompiled)
|
||||
Lambda(k.arity, body, decompiled)
|
||||
}
|
||||
def apply(r: R, rec: Lambda, top: StackPtr,
|
||||
stackU: Array[U], x1: U, x0: U,
|
||||
|
@ -157,7 +157,7 @@ object CompilationTests {
|
||||
}
|
||||
|
||||
val lam = Term.Compiled(
|
||||
new ClosureForming(List("a","b","c","d"), body, Some(UnboxedType.Int64), 42))
|
||||
new ClosureForming(List("a","b","c","d"), body, 42))
|
||||
val p = Let('f -> lam(1))('f.v(2,3,4))
|
||||
val p2 = Let('f -> lam(1), 'g -> 'f.v(2))('g.v(3,4))
|
||||
val p3 = Let('f -> lam(1), 'g -> 'f.v(2), 'h -> 'g.v(3))('h.v(4))
|
||||
|
Loading…
Reference in New Issue
Block a user