Skip to content

Commit d488d6b

Browse files
committed
Reified: big refactoring + inject most captured values as function params instead of inlining them (unless forced)
1 parent 3a88391 commit d488d6b

18 files changed

Lines changed: 713 additions & 464 deletions

File tree

Components/src/main/scala/scalaxy/components/CommonScalaNames.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import scala.language.postfixOps
66
import scala.reflect.api.Universe
77
import scala.reflect.NameTransformer
88

9-
trait CommonScalaNames {
9+
private[internal] trait CommonScalaNames {
1010
val global: Universe
1111
import global._
1212
import definitions._
@@ -184,4 +184,4 @@ trait CommonScalaNames {
184184
(sym, C("scala.collection.mutable.ArrayOps." + n))
185185
} toMap
186186

187-
}
187+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package scalaxy.generic
2+
3+
import scala.language.experimental.macros
4+
import scala.reflect.macros.Context
5+
6+
import scala.language.implicitConversions
7+
import scala.language.dynamics
8+
9+
import scala.reflect.ClassTag
10+
import scala.reflect.runtime.universe.TypeTag
11+
12+
// import _root_.scalaxy.generic.{ mkTypeTag => _ }
13+
14+
sealed class Generic[A: TypeTag] {
15+
def typeTag = implicitly[TypeTag[A]]
16+
def numeric: Option[Numeric[A]] = implicitly[Option[Numeric[A]]]
17+
}
18+
19+
object Generic {
20+
implicit def mkGeneric[A: TypeTag]: Generic[A] = new Generic[A]
21+
}

Generic/src/main/scala/scalaxy/generic/GenericOps.scala

Lines changed: 52 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,11 @@ import scala.reflect.runtime.universe._
1111
/**
1212
* A dynamic wrapper for generic values that can be optimized away in reified ASTs, and can verify basic union-style static type constraints.
1313
*/
14-
class GenericOps[+A: Generic](value_ : A, implicitConversions: Any*) extends Dynamic with NumberOps[A] {
15-
import GenericOps._
14+
class GenericOps[+A: Generic](val rawValue: A, implicitConversions: List[Any] = Nil) extends Dynamic with NumberOps[A] {
1615

17-
val value = peel_(value_)
16+
val value: Any = peel_(rawValue)
1817

19-
private lazy val targets_ = value :: implicitConversions.toList ++ (value match {
18+
private lazy val targets_ = value :: implicitConversions ++ (value match {
2019
case (v: java.lang.Byte) => numOps_(v.byteValue)
2120
case (v: java.lang.Short) => numOps_(v.shortValue)
2221
case (v: java.lang.Integer) => numOps_(v.intValue)
@@ -27,66 +26,39 @@ class GenericOps[+A: Generic](value_ : A, implicitConversions: Any*) extends Dyn
2726
case v => Nil
2827
})
2928

30-
private[generic] lazy val targetMirrors_ = targets_.map(implementation => {
29+
private lazy val targetMirrors_ = targets_.map(implementation => {
3130
val mirror = runtimeMirror(Thread.currentThread.getContextClassLoader)
3231
mirror.reflect(implementation)(ClassTag(implementation.getClass))
3332
})
3433

35-
private[generic] def valueClassName_ = {
34+
private def valueClassName_ = {
3635
if (value == null)
3736
null
3837
else
3938
value.getClass.getName
4039
}
4140

42-
def applyDynamic(name: String)(args: Any*): Any = macro internal.applyDynamic[A]
43-
def selectDynamic(name: String): Any = macro internal.selectDynamic[A]
44-
def updateDynamic(name: String)(value: Any): Unit = macro internal.updateDynamic[A]
45-
46-
override def equals(other: Any) = value.equals(other)
47-
override def hashCode() = value.hashCode()
48-
override def toString() = "GenericOps(" + value + ")"
49-
}
50-
51-
trait NumberOps[+A] {
52-
def +(rhs: A): A = macro internal.methodHomogeneous[A, A]
53-
def -(rhs: A): A = macro internal.methodHomogeneous[A, A]
54-
def *(rhs: A): A = macro internal.methodHomogeneous[A, A]
55-
def /(rhs: A): A = macro internal.methodHomogeneous[A, A]
56-
def /%(rhs: A): (A, A) = macro internal.methodHomogeneous[A, (A, A)]
57-
def ==:(rhs: A): Boolean = macro internal.methodHomogeneous[A, Boolean]
58-
def !=:(rhs: A): Boolean = macro internal.methodHomogeneous[A, Boolean]
59-
def <=(rhs: A): Boolean = macro internal.methodHomogeneous[A, Boolean]
60-
def <(rhs: A): Boolean = macro internal.methodHomogeneous[A, Boolean]
61-
def >=(rhs: A): Boolean = macro internal.methodHomogeneous[A, Boolean]
62-
def >(rhs: A): Boolean = macro internal.methodHomogeneous[A, Boolean]
63-
def abs: A = macro internal.method0[A, A]
64-
def signum: Int = macro internal.method0[A, Int]
65-
def toInt: Int = macro internal.method0[A, Int]
66-
def toLong: Long = macro internal.method0[A, Long]
67-
def toFloat: Float = macro internal.method0[A, Float]
68-
def toDouble: Double = macro internal.method0[A, Double]
69-
}
70-
71-
object GenericOps {
72-
73-
private[generic] def numOps_[N: math.Numeric](v: N): Seq[Any] = {
41+
private def numOps_[N: math.Numeric](v: N): Seq[Any] = {
7442
val n = implicitly[math.Numeric[N]]
7543
List(n.mkNumericOps(v), n.mkOrderingOps(v))
7644
}
7745

78-
private[generic] def peel_(value: Any): Any = value match {
79-
case ops: GenericOps[_] => peel_(ops.value)
80-
case _ => value
46+
private def peel_(value: Any): Any = {
47+
if (value.isInstanceOf[GenericOps[_]]) {
48+
value.asInstanceOf[GenericOps[_]].value
49+
} else {
50+
value
51+
}
8152
}
8253

83-
private def findDecl(ops: GenericOps[_])(name: String) = {
54+
private def findDecl(name: String) = {
8455
def sub(mirrors: List[InstanceMirror]): Option[(Symbol, InstanceMirror)] = mirrors match {
8556
case Nil => None
8657
case mirror :: otherMirrors =>
8758
val tpe = mirror.symbol.asType.toType
8859
val symbol =
89-
tpe.member(name: TermName) orElse tpe.member(reflect.NameTransformer.encode(name): TermName)
60+
tpe.member(name: TermName) orElse
61+
tpe.member(reflect.NameTransformer.encode(name): TermName)
9062
if (symbol == NoSymbol) { //} || !(mirror.symbol.asType.toType <:< symbol.owner.asType.toType)) {
9163
// println("No " + name + " or " + reflect.NameTransformer.encode(name) + " in " + mirror.instance.getClass.getName + ": " + tpe + ": " + tpe.members)
9264
sub(otherMirrors)
@@ -96,34 +68,61 @@ object GenericOps {
9668
Some(symbol -> mirror)
9769
}
9870
}
99-
sub(ops.targetMirrors_)
71+
sub(targetMirrors_)
10072
}
101-
def applyDynamicImpl[A](ops: GenericOps[A], name: String, args: Any*): Any = {
102-
findDecl(ops)(name) match {
73+
def applyDynamic(name: String)(args: Any*): Any = {
74+
findDecl(name) match {
10375
case Some((symbol, mirror)) if symbol.isMethod =>
10476
val unwrapped = args.map(peel_(_))
10577
// println("Calling " + name + " on " + mirror.instance)
10678
mirror.reflectMethod(symbol.asMethod)(unwrapped: _*)
10779
case _ =>
108-
throw new NoSuchMethodException("No method '" + name + "' in " + ops.valueClassName_)
80+
throw new NoSuchMethodException("No method '" + name + "' in " + valueClassName_)
10981
}
11082
}
111-
def selectDynamicImpl[A](ops: GenericOps[A], name: String): Any = {
112-
findDecl(ops)(name) match {
83+
def selectDynamic(name: String): Any = {
84+
findDecl(name) match {
11385
case Some((symbol, mirror)) if symbol.isMethod =>
11486
mirror.reflectMethod(symbol.asMethod)()
11587
case Some((symbol, mirror)) if symbol.isTerm =>
11688
mirror.reflectField(symbol.asTerm).get
11789
case _ =>
118-
throw new NoSuchFieldException("No field '" + name + "' in " + ops.valueClassName_)
90+
throw new NoSuchFieldException("No field '" + name + "' in " + valueClassName_)
11991
}
12092
}
121-
def updateDynamicImpl[A](ops: GenericOps[A], name: String, value: Any) {
122-
findDecl(ops)(name) match {
93+
def updateDynamic(name: String)(value: Any) {
94+
findDecl(name) match {
12395
case Some((symbol, mirror)) if symbol.isTerm =>
12496
mirror.reflectField(symbol.asTerm).set(value)
12597
case _ =>
126-
throw new NoSuchFieldException("No field '" + name + "' in " + ops.valueClassName_)
98+
throw new NoSuchFieldException("No field '" + name + "' in " + valueClassName_)
12799
}
128100
}
101+
102+
override def equals(other: Any) = value.equals(other)
103+
override def hashCode() = value.hashCode()
104+
override def toString() = "GenericOps(" + value + ")"
105+
}
106+
107+
trait NumberOps[+A] {
108+
def +(rhs: A): A = macro internal.methodHomogeneous[A, A]
109+
def -(rhs: A): A = macro internal.methodHomogeneous[A, A]
110+
def *(rhs: A): A = macro internal.methodHomogeneous[A, A]
111+
def /(rhs: A): A = macro internal.methodHomogeneous[A, A]
112+
def /%(rhs: A): (A, A) = macro internal.methodHomogeneous[A, (A, A)]
113+
def ==:(rhs: A): Boolean = macro internal.methodHomogeneous[A, Boolean]
114+
def !=:(rhs: A): Boolean = macro internal.methodHomogeneous[A, Boolean]
115+
def <=(rhs: A): Boolean = macro internal.methodHomogeneous[A, Boolean]
116+
def <(rhs: A): Boolean = macro internal.methodHomogeneous[A, Boolean]
117+
def >=(rhs: A): Boolean = macro internal.methodHomogeneous[A, Boolean]
118+
def >(rhs: A): Boolean = macro internal.methodHomogeneous[A, Boolean]
119+
def abs: A = macro internal.method0[A, A]
120+
def signum: Int = macro internal.method0[A, Int]
121+
def toInt: Int = macro internal.method0[A, Int]
122+
def toLong: Long = macro internal.method0[A, Long]
123+
def toFloat: Float = macro internal.method0[A, Float]
124+
def toDouble: Double = macro internal.method0[A, Double]
125+
}
126+
127+
object GenericOps {
129128
}

Generic/src/main/scala/scalaxy/generic/internal/package.scala

Lines changed: 10 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,57 +8,25 @@ import scala.reflect.runtime.universe
88

99
package object internal {
1010

11-
def applyDynamic[A: c.WeakTypeTag](c: Context)(name: c.Expr[String])(args: c.Expr[Any]*): c.Expr[Any] = {
12-
applyDynamicImpl(c)(c.prefix.asInstanceOf[c.Expr[GenericOps[A]]], name, args: _*)
13-
}
14-
15-
private def applyDynamicImpl[A: c.WeakTypeTag](c: Context)(prefix: c.Expr[GenericOps[A]], name: c.Expr[String], args: c.Expr[Any]*): c.Expr[Any] = {
16-
import c.universe._
17-
// TODO: If the type of Generic is concrete, then:
18-
// - check that method exists in A with the static types of these args
19-
// - if prefix is GenericOps.apply[A](value), replace by value, otherwise replace by prefix.value
20-
val pref = c.prefix.asInstanceOf[c.Expr[GenericOps[A]]]
21-
val Apply(target, firstArgs) = c.universe.reify(GenericOps.applyDynamicImpl(pref.splice, name.splice)).tree
22-
c.Expr[Any](
23-
Apply(target, firstArgs ++ args.map(_.tree))
24-
)
25-
}
26-
27-
def selectDynamic[A: c.WeakTypeTag](c: Context)(name: c.Expr[String]): c.Expr[Any] = {
28-
import c.universe._
29-
// TODO: If the type of Generic is concrete, then:
30-
// - check that method exists in A with the static types of these args
31-
// - if prefix is GenericOps.apply[A](value), replace by value, otherwise replace by prefix.value
32-
val pref = c.prefix.asInstanceOf[c.Expr[GenericOps[A]]]
33-
c.universe.reify(
34-
GenericOps.selectDynamicImpl(pref.splice, name.splice)
35-
)
36-
}
37-
38-
def updateDynamic[A: c.WeakTypeTag](c: Context)(name: c.Expr[String])(value: c.Expr[Any]): c.Expr[Unit] = {
39-
import c.universe._
40-
// TODO: If the type of Generic is concrete, then:
41-
// - check that method exists in A with the static types of these args
42-
// - if prefix is GenericOps.apply[A](value), replace by value, otherwise replace by prefix.value
43-
val pref = c.prefix.asInstanceOf[c.Expr[GenericOps[A]]]
44-
c.universe.reify(
45-
GenericOps.updateDynamicImpl(pref.splice, name.splice, value.splice)
46-
)
47-
}
48-
4911
def methodHomogeneous[A: c.WeakTypeTag, B: c.WeakTypeTag](c: Context)(rhs: c.Expr[A]): c.Expr[B] = {
5012
import c.universe._
5113
val Apply(Select(target, name), _) = c.macroApplication
5214

53-
val res = applyDynamicImpl(c)(c.prefix.asInstanceOf[c.Expr[GenericOps[A]]], c.literal(name.toString), rhs)
54-
c.universe.reify(res.splice.asInstanceOf[B])
15+
val nameExpr = c.literal(name.toString)
16+
val prefix = c.prefix.asInstanceOf[c.Expr[GenericOps[A]]]
17+
reify(prefix.splice.applyDynamic(nameExpr.splice)(rhs.splice).asInstanceOf[B])
18+
// val res = applyDynamicImpl(c)(c.prefix.asInstanceOf[c.Expr[GenericOps[A]]], c.literal(name.toString), rhs)
19+
// c.universe.reify(res.splice.asInstanceOf[B])
5520
}
5621

5722
def method0[A: c.WeakTypeTag, B: c.WeakTypeTag](c: Context): c.Expr[B] = {
5823
import c.universe._
5924
val Select(target, name) = c.macroApplication
6025

61-
val res = applyDynamicImpl(c)(c.prefix.asInstanceOf[c.Expr[GenericOps[A]]], c.literal(name.toString))
62-
c.universe.reify(res.splice.asInstanceOf[B])
26+
val nameExpr = c.literal(name.toString)
27+
val prefix = c.prefix.asInstanceOf[c.Expr[GenericOps[A]]]
28+
reify(prefix.splice.selectDynamic(nameExpr.splice).asInstanceOf[B])
29+
// val res = applyDynamicImpl(c)(c.prefix.asInstanceOf[c.Expr[GenericOps[A]]], c.literal(name.toString))
30+
// c.universe.reify(res.splice.asInstanceOf[B])
6331
}
6432
}

0 commit comments

Comments
 (0)