Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] support operator interception for non-literal types #147

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions src/main/scala/singleton/ops/impl/GeneralMacros.scala
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,13 @@ trait GeneralMacros {
////////////////////////////////////////////////////////////////////////

def abort(msg: String, annotatedSym : Option[TypeSymbol] = defaultAnnotatedSym): Nothing = {
val st = java.lang.Thread.currentThread().getStackTrace()
println("\n\nstack trace:")
for { e <- st.filter(_.getClassName().startsWith("singleton")) } {
println(s" $e")
}
println("\n")
//java.lang.Thread.dumpStack()
VerboseTraversal(s"!!!!!!aborted with: $msg at $annotatedSym, $defaultAnnotatedSym")
if (annotatedSym.isDefined) setAnnotation(msg, annotatedSym.get)
c.abort(c.enclosingPosition, msg)
Expand Down Expand Up @@ -719,6 +726,7 @@ trait GeneralMacros {
}

def genOpTreeUnknown(opTpe : Type, calc : CalcUnknown) : Tree = {
println("In genOpTreeUnknown")
val outTpe = calc.tpe
calc.treeOption match {
case Some(valueTree) =>
Expand Down Expand Up @@ -898,10 +906,17 @@ trait GeneralMacros {
lazy val a = aCalc
lazy val b = bCalc
lazy val cArg = cCalc

def unsupported() : Calc = {
(a, b) match {
case (aArg : CalcVal, bArg : CalcVal) => abort(s"Unsupported $funcType[$a, $b, $cArg]")
case _ => CalcUnknown(funcType.toType, None)
val itree = c.typecheck(q"implicitly[_root_.singleton.ops.impl.OpIntercept[${funcType.toType}, ${a.tpe}, ${b.tpe}, ${cArg.tpe}]]", silent = true)
if (itree != EmptyTree) {
println(s"\n\nitree= ${itree.tpe}\n\n")
CalcUnknown(itree.tpe, Some(itree))
} else {
(a, b) match {
case (aArg : CalcVal, bArg : CalcVal) => abort(s"Unsupported $funcType[$a, $b, $cArg]")
case _ => CalcUnknown(funcType.toType, None)
}
}
}

Expand Down Expand Up @@ -1375,6 +1390,9 @@ trait GeneralMacros {
val funcType = opTpe.typeArgs.head.typeSymbol.asType
val opResult = TypeCalc(opTpe)

println(s"usingFuncName: opTpe= $opTpe")
println(s" funcType= $funcType")
println(s" opResult= $opResult")
val genTree = (funcType, opResult) match {
case (funcTypes.ToNat, CalcLit.Int(t)) =>
if (t < 0) abort(s"Nat cannot be a negative literal. Found: $t")
Expand Down
21 changes: 21 additions & 0 deletions src/main/scala/singleton/ops/impl/OpMacros.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
package singleton.ops.impl
import scala.reflect.macros.whitebox


trait OpIntercept[N, S1, S2, S3] extends OpMacro[N, S2, S2, S3] {
import singleton.ops.W

type OutWide = None.type
val valueWide: OutWide = None
val isLiteral: Boolean = false
type OutNat = shapeless.Nat._0
type OutChar = W.`'0'`.T
type OutInt = W.`0`.T
type OutLong = W.`0L`.T
type OutFloat = W.`0f`.T
type OutDouble = W.`0D`.T
type OutString = W.`""`.T
type OutBoolean = W.`false`.T
}

object OpIntercept {
type Aux[N, S1, S2, S3, O] = OpIntercept[N, S1, S2, S3] { type Out = O }
}

/********************************************************************************************************
* Three arguments type function macro
*******************************************************************************************************/
Expand Down
39 changes: 39 additions & 0 deletions src/main/scala/singleton/ops/impl/TestRig.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package singleton.ops.impl

import singleton.ops._

trait Rig[V <: XInt] {
val value: Int
override def toString: String = s"Rig($value)"
}

object Rig {
// get the 'Out' type resulting from resolving an implicit type
object impeval {
trait Out[O]
def apply[I <: { type Out } ](implicit i: I): Out[i.Out] = new Out[i.Out] {}
}

implicit def rigAddition[L <: Rig[_], R <: Rig[_], O <: Rig[_]](implicit
add: Add.Aux[L, R, O]): OpIntercept.Aux[OpId.+, L, R, W.`0`.T, O] =
new OpIntercept[OpId.+, L, R, W.`0`.T] {
type Out = O
val value = add.value
}

trait Add[L, R] {
type Out
val value: Out
}
object Add {
type Aux[L, R, O] = Add[L, R] { type Out = O }

implicit def addRig[LV <: XInt, RV <: XInt, OV <: XInt](implicit
add: OpInt.Aux[LV + RV, OV]): Add.Aux[Rig[LV], Rig[RV], Rig[OV]] =
new Add[Rig[LV], Rig[RV]] {
type Out = Rig[OV]
val value = new Rig[OV] { val value = add.value }
}
}
}