- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
@conditional annotation now implemented
Wed, 2010-11-03, 18:19
I didn't fully appreciate the goodness of the idea at the time, but it
was a very good idea.
Here is what I have working. One thing I was thinking is that it might
be nice to be able to define what an elided method is replaced with from
the annotation. Right now with @conditional you get a zero based on the
return type of the removed method (which means (), false, 0, or null
pretty much.) But to specify a value in the same annotation I'd have to
add a type parameter and a field which is not appealing as it's nice and
clean as is. Another annotation? What do you think?
And how's this look otherwise?
// include at Info level; exclude Symbol and Tree
% scalac -Xinclude cond.Info -Xexclude cond.Symbol,cond.Tree -d /tmp test/files/run/conditional-ann.scala
// running program
% scala -cp /tmp Test
[types] fatal: oh noes
[types] warning: kind of important
[types] info: hello
// generated bytecode - 15 calls become 3
public void main(java.lang.String[]);
Code:
Stack=2, Locals=2, Args_size=2
0: aload_0
1: invokevirtual #35; //Method typeLogger:()LTest$CategoryLogger;
4: ldc #37; //String oh noes
6: invokevirtual #43; //Method Test$CategoryLogger.fatal:(Ljava/lang/String;)V
9: aload_0
10: invokevirtual #35; //Method typeLogger:()LTest$CategoryLogger;
13: ldc #45; //String kind of important
15: invokevirtual #48; //Method Test$CategoryLogger.warning:(Ljava/lang/String;)V
18: aload_0
19: invokevirtual #35; //Method typeLogger:()LTest$CategoryLogger;
22: ldc #50; //String hello
24: invokevirtual #53; //Method Test$CategoryLogger.info:(Ljava/lang/String;)V
27: return
// full test case
import annotation._
package cond {
trait Trace
trait Debug extends Trace
trait Info extends Debug
trait Warning extends Info
trait Fatal extends Warning
trait Symbol
trait Type
trait Tree
}
object Test {
import cond._
class CategoryLogger[T](categoryName: String) {
@conditional[Fatal with T] def fatal(msg: String) = println("[" + categoryName + "] fatal: " + msg)
@conditional[Warning with T] def warning(msg: String) = println("[" + categoryName + "] warning: " + msg)
@conditional[Info with T] def info(msg: String) = println("[" + categoryName + "] info: " + msg)
@conditional[Debug with T] def debug(msg: String) = println("[" + categoryName + "] debug: " + msg)
@conditional[Trace with T] def trace(msg: String) = println("[" + categoryName + "] trace: " + msg)
}
val typeLogger = new CategoryLogger[Type]("types")
val symbolLogger = new CategoryLogger[Symbol]("symbols")
val treeLogger = new CategoryLogger[Tree]("trees")
def main(args: Array[String]): Unit = {
typeLogger.fatal("oh noes")
typeLogger.warning("kind of important")
typeLogger.info("hello")
typeLogger.debug("relevant info")
typeLogger.trace("extraneous info")
symbolLogger.fatal("oh noes")
symbolLogger.warning("kind of important")
symbolLogger.info("hello")
symbolLogger.debug("relevant info")
symbolLogger.trace("extraneous info")
treeLogger.fatal("oh noes")
treeLogger.warning("kind of important")
treeLogger.info("hello")
treeLogger.debug("relevant info")
treeLogger.trace("extraneous info")
}
}