Skip to content

Instantly share code, notes, and snippets.

@paulp
Last active September 2, 2016 16:20
Show Gist options
  • Save paulp/3610719ad3fa30c5ee076937d796ae83 to your computer and use it in GitHub Desktop.
Save paulp/3610719ad3fa30c5ee076937d796ae83 to your computer and use it in GitHub Desktop.
Indirect compile-time literal types
class MacroBundle(val c: Context) {
/* etc */
/** Typecheck singleton types so as to obtain indirectly
* available known-at-compile-time values.
*/
object Const {
def unapply(tp: Type): Option[Constant] = tp match {
case ConstantType(c) => Some(c)
case SingleType(_, sym) => unapply(c.typecheck(q"$sym").tpe)
case _ => None
}
}
def constInt(tp: Type): Tree = tp match {
case Const(Constant(n: Int)) => q"$n"
case _ => q"-1"
}
def constImpl[A: c.WeakTypeTag](value: c.Expr[A]): Tree = constInt(weakTypeOf[A])
def constTypeImpl[A: c.WeakTypeTag] : Tree = constInt(weakTypeOf[A])
}
package psply.tests
import scala.language.experimental.macros
class ConstTests {
def const[A <: Int with Singleton](value: A): Int = macro psply.trees.PsplyMacros.constImpl[A]
def constType[A <: Int with Singleton] : Int = macro psply.trees.PsplyMacros.constTypeImpl[A]
val one: 1 = 1
val oneA: one.type = one
val oneB: oneA.type = oneA
val oneC = oneB // inferred singleton type
final val oneD = 1 // inferred singleton type
val unknown1: Int = 1
val unknown2 = 1 // non-final means Int is inferred
@Test
def constTest(): Unit = {
assertEqual(const(1))(1)
assertEqual(const(one))(1)
assertEqual(const(oneA))(1)
assertEqual(const(oneB))(1)
assertEqual(const(oneC))(1)
assertEqual(const(oneD))(1)
// doesn't always return 1
assertUnequal(const(unknown1))(1)
assertUnequal(const(unknown2))(1)
}
@Test
def constTypeTest(): Unit = {
assertEqual(constType[1])(1)
assertEqual(constType[one.type])(1)
assertEqual(constType[oneA.type])(1)
assertEqual(constType[oneB.type])(1)
assertEqual(constType[oneC.type])(1)
assertEqual(constType[oneD.type])(1)
// doesn't always return 1
assertUnequal(constType[unknown1.type])(1)
assertUnequal(constType[unknown2.type])(1)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment