virtualization-lms-core icon indicating copy to clipboard operation
virtualization-lms-core copied to clipboard

TupledFunctions vs Tuple Function

Open tzbob opened this issue 10 years ago • 0 comments

Imagine a scenario where you want to wrap a third-party higher-order polymorphic function like so:

  trait LambdaMap extends ListOps with TupledFunctions {
    def map[T: Manifest](l: Rep[List[T]], callback: Rep[T => T]): Rep[List[T]]
  }

  trait LambdaMapExp extends LambdaMap with ListOpsExp with TupledFunctionsExp {
    case class LambdaMap[T:Manifest](l: Exp[List[T]], callback: Exp[T => T]) extends Def[List[T]]
    def map[T: Manifest](l: Exp[List[T]], callback: Exp[T => T]): Exp[List[T]] =
      LambdaMap(l, callback)
  }

  trait GenLambdaMap extends ScalaGenListOps with ScalaGenTupledFunctions {
    val IR: LambdaMapExp
    import IR._

    override def emitNode(sym: Sym[Any], rhs: Def[Any]) = rhs match {
      case LambdaMap(l,callback) => emitValDef(sym, src"$l.map($callback)")
      case _ => super.emitNode(sym, rhs)
    }
  }

  trait LambdaMapUse extends LambdaMap {
    def test[T: Manifest](xs: Rep[List[T]]): Rep[List[T]] =
      map(xs, fun { x: Rep[T] => x })
  }

So generating our 'test' function where T == Double gives us the correct functionality:

class Test extends ((scala.collection.immutable.List[Double])=>(scala.collection.immutable.List[Double])) {
def apply(x0:scala.collection.immutable.List[Double]): scala.collection.immutable.List[Double] = {
val x2 = {x1: (Double) => 
x1: Double
}
val x3 = x0.map(x2)
x3
}
}

While generating our 'test' function where T == (Double, Double) gives us the wrong functionality:

class Test extends ((scala.collection.immutable.List[scala.Tuple2[Double, Double]])=>(scala.collection.immutable.List[scala.Tuple2[Double, Double]])) {
def apply(x0:scala.collection.immutable.List[scala.Tuple2[Double, Double]]): scala.collection.immutable.List[scala.Tuple2[Double, Double]] = {
val x3 = {(x1:Double,x2:Double) => 
((x1,x2)): scala.Tuple2[Double, Double]
}
val x4 = x0.map(x3)
x4
}
}

Due to the autoboxing and unboxing going on with tupled functions I'm not sure how this issue would be resolved? It seems that the 'standard library' of LMS avoids these problems by staging at a different scope e.g. Rep[A] => Rep[B] vs Rep[A => B] with more work being done in the expression layer and generation phase.

I'm not sure if this is a bug or just intended behaviour, so how should I go about this problem? Thanks!

tzbob avatar Dec 16 '14 10:12 tzbob