diff --git a/src/main/scala/singleton/ops/impl/GeneralMacros.scala b/src/main/scala/singleton/ops/impl/GeneralMacros.scala index 6679139b..b868aea3 100644 --- a/src/main/scala/singleton/ops/impl/GeneralMacros.scala +++ b/src/main/scala/singleton/ops/impl/GeneralMacros.scala @@ -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) @@ -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) => @@ -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) + } } } @@ -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") diff --git a/src/main/scala/singleton/ops/impl/OpMacros.scala b/src/main/scala/singleton/ops/impl/OpMacros.scala index 3d8bb5c4..6a9c7413 100644 --- a/src/main/scala/singleton/ops/impl/OpMacros.scala +++ b/src/main/scala/singleton/ops/impl/OpMacros.scala @@ -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 *******************************************************************************************************/ diff --git a/src/main/scala/singleton/ops/impl/TestRig.scala b/src/main/scala/singleton/ops/impl/TestRig.scala new file mode 100644 index 00000000..809c215e --- /dev/null +++ b/src/main/scala/singleton/ops/impl/TestRig.scala @@ -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 } + } + } +} +