From 6ba8cb2514d52255cff8d1a0aa5ac1fe0eb61209 Mon Sep 17 00:00:00 2001 From: Alexey Romanov Date: Thu, 26 Nov 2015 15:21:07 +0300 Subject: [PATCH] Include the type converted to as part of ImplicitConvert --- src/common/ImplicitOps.scala | 16 ++++++++-------- src/internal/ScalaCodegen.scala | 27 +++++++++++++++++++++------ 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/common/ImplicitOps.scala b/src/common/ImplicitOps.scala index 37372160..bfe27639 100644 --- a/src/common/ImplicitOps.scala +++ b/src/common/ImplicitOps.scala @@ -15,14 +15,14 @@ trait ImplicitOps extends Base { } trait ImplicitOpsExp extends ImplicitOps with BaseExp { - case class ImplicitConvert[X,Y](x: Exp[X])(implicit val mX: Manifest[X], val mY: Manifest[Y]) extends Def[Y] + case class ImplicitConvert[X,Y](x: Exp[X], mY: Manifest[Y])(implicit val mX: Manifest[X]) extends Def[Y] def implicit_convert[X,Y](x: Exp[X])(implicit c: X => Y, mX: Manifest[X], mY: Manifest[Y], pos: SourceContext) : Rep[Y] = { - if (mX == mY) x.asInstanceOf[Rep[Y]] else ImplicitConvert[X,Y](x) + if (mX == mY) x.asInstanceOf[Rep[Y]] else ImplicitConvert[X,Y](x, mY) } override def mirror[A:Manifest](e: Def[A], f: Transformer)(implicit pos: SourceContext): Exp[A] = (e match { - case im@ImplicitConvert(x) => toAtom(ImplicitConvert(f(x))(im.mX,im.mY))(mtype(manifest[A]),pos) + case im@ImplicitConvert(x, mY) => toAtom(ImplicitConvert(f(x), mY)(im.mX))(mtype(manifest[A]),pos) case _ => super.mirror(e,f) }).asInstanceOf[Exp[A]] @@ -33,9 +33,9 @@ trait ScalaGenImplicitOps extends ScalaGenBase { import IR._ override def emitNode(sym: Sym[Any], rhs: Def[Any]) = rhs match { - // TODO: this valDef is redundant; we really just want the conversion to be a no-op in the generated code. - // TODO: but we still need to link the defs together - case ImplicitConvert(x) => emitValDef(sym, quote(x)) + // Make sure it's typed to trigger the implicit conversion + // Otherwise we can get type mismatch in generated code + case ImplicitConvert(x, mY) => emitTypedValDef(sym, quote(x)) case _ => super.emitNode(sym, rhs) } } @@ -46,8 +46,8 @@ trait CLikeGenImplicitOps extends CLikeGenBase { override def emitNode(sym: Sym[Any], rhs: Def[Any]) = { rhs match { - case im@ImplicitConvert(x) => - gen"${im.mY} $sym = (${im.mY})$x;" + case ImplicitConvert(x, mY) => + gen"$mY $sym = ($mY)$x;" case _ => super.emitNode(sym, rhs) } } diff --git a/src/internal/ScalaCodegen.scala b/src/internal/ScalaCodegen.scala index 2d108fd0..f34ceb06 100644 --- a/src/internal/ScalaCodegen.scala +++ b/src/internal/ScalaCodegen.scala @@ -90,12 +90,20 @@ trait ScalaCodegen extends GenericCodegen with Config { fileName.substring(i + 1) } - def emitValDef(sym: Sym[Any], rhs: String): Unit = { - val extra = if ((sourceinfo < 2) || sym.pos.isEmpty) "" else { - val context = sym.pos(0) - " // " + relativePath(context.fileName) + ":" + context.line + private def valDefExtra(sym: IR.Sym[Any]): String = { + sym.pos.headOption match { + case Some(context) if sourceinfo >= 2 => + " // " + relativePath(context.fileName) + ":" + context.line + case _ => "" } - stream.println("val " + quote(sym) + " = " + rhs + extra) + } + + def emitValDef(sym: Sym[Any], rhs: String): Unit = { + stream.println("val " + quote(sym) + " = " + rhs + valDefExtra(sym)) + } + + def emitTypedValDef(sym: Sym[Any], rhs: String): Unit = { + stream.println(src"val $sym: ${sym.tp} = $rhs" + valDefExtra(sym)) } def emitVarDef(sym: Sym[Variable[Any]], rhs: String): Unit = { @@ -132,7 +140,14 @@ trait ScalaNestedCodegen extends GenericNestedCodegen with ScalaCodegen { else super.emitValDef(sym,rhs) } - + + // special case for recursive vals + override def emitTypedValDef(sym: Sym[Any], rhs: String): Unit = { + if (recursive contains sym) + stream.println(quote(sym) + " = " + rhs) // we have a forward declaration above. + else + super.emitTypedValDef(sym,rhs) + } }