- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
help with very simple compiler transformation
Sun, 2010-05-30, 05:00
Dear all,
I'm trying to write a very simple compiler transformation, which
will create temporary variables, for the sake of maintaining type
annotations through compilation (since they will not be erased from
symbols). I want to rewrite [for example] "(fcn() : Int @ Range(-31 to
31)) + 2" into "{ val tmp = fcn() : Int @ Range(-31 to 31); tmp; } +
2". I think I'm getting farther and farther from what I want...
The current code goes something like this,
class CreateTmpvarsForTyped() extends Transformer {
def createBlockForTyped(expr:Tree, tpt:Tree) = {
val name = newTermName("__skalch_internal_typed_tmp")
val sym = expr.tpe.typeSymbol.newValue(NoPosition,
name).setInfo(expr.tpe)
val vd = ValDef(Modifiers(LOCAL), name, tpt, expr)
vd.symbol = sym
val ident = Ident(name)
ident.symbol = sym
Block(List(vd), ident)
}
override def transform(tree : Tree) = tree match {
case Typed(expr, tpt) =>
createBlockForTyped(expr, tpt)
case _ => super.transform(tree)
}
}
It's throwing a null pointer exception in a later stage,
Exception in thread "main" java.lang.NullPointerException
at scala.tools.nsc.transform.UnCurry.scala$tools$nsc$transform$UnCurry$$expandAlias(UnCurry.scala:50)
at scala.tools.nsc.transform.UnCurry$$anon$3.apply(UnCurry.scala:59)
at scala.tools.nsc.transform.UnCurry$$anon$3.apply(UnCurry.scala:57)
Any help would be much appreciated.
Thanks very much,
Nicholas — ntung at ntung — https://ntung.com — CS major @ UC Berkeley
Mon, 2010-05-31, 23:27
#2
Re: help with very simple compiler transformation
On Sat, May 29, 2010 at 9:06 PM, Paul Phillips wrote:
>
> On Sat, May 29, 2010 at 08:59:37PM -0700, Nicholas Tung wrote:
> > def createBlockForTyped(expr:Tree, tpt:Tree) = {
> ...
> > Block(List(vd), ident)
>
> That's an untyped tree.
>
> > override def transform(tree : Tree) = tree match {
> > case Typed(expr, tpt) =>
>
> That's a typed tree.
>
> > createBlockForTyped(expr, tpt)
>
> That's you replacing a typed tree with an untyped tree.
>
> > Exception in thread "main" java.lang.NullPointerException
> > at scala.tools.nsc.transform.UnCurry.scala$tools$nsc$transform$UnCurry$$expandAlias(UnCurry.scala:50)
>
> That's the compiler dereferencing the null pointer where it expects the
> tpe to be.
>
> --
> Paul Phillips | It's better to have gloved and tossed than never to
> Apatheist | have played baseball.
> Empiricist |
> up hill, pi pals! |----------* http://www.improving.org/paulp/ *----------
Thanks very much. I have another question -- how can I follow a
TypeRef to get an annotation? Here's some example code:
type Int5 = Int @ Range(-32 to 31)
val x = (fcn() : Int5)
I want the "Range" annotation, so I can map "x -> Range(-32 to 31)",
since the compiler destroys this info later on.
If there is more documentation than the videos listed here, I'd
appreciate a reference.
http://www.scala-lang.org/node/598
Thanks,
Nicholas — ntung at ntung — https://ntung.com — CS major @ UC Berkeley
Tue, 2010-06-01, 01:47
#3
Re: help with very simple compiler transformation
On Mon, May 31, 2010 at 03:23:52PM -0700, Nicholas Tung wrote:
> Thanks very much. I have another question -- how can I follow a
> TypeRef to get an annotation? Here's some example code:
> type Int5 = Int @ Range(-32 to 31)
> val x = (fcn() : Int5)
Do you have reason to believe this can work? I'll be surprised. It'd be
neat if so. I don't think type aliases are sufficiently first class
that you can annotate them and distinguish between the annotated alias
and the underlying type.
Here's a little repl session in my current repl, which I can't resist to
demo the stuff I've been adding. Not sure what if anything this will
tell you -- I know little about the annotations implementation. But it
seems to support my suspicion since I only see the annotation at all if
I normalize.
scala> class Range(x: scala.Range) extends scala.StaticAnnotation
defined class Range
scala> type Int5 = Int @ Range(-32 to 31)
defined type alias Int5
scala> :type Int5
tpe7: global.Type = Int5
scala> tpe7.normalize
res10: global.Type = Int
scala> repl.allPhases( tpe7.normalize.annotations)
parser -> List(Range(scala.this.Predef.intWrapper(-32).to(31)))
namer -> " " "
packageobjects -> " " "
typer -> " " "
superaccessors -> " " "
pickler -> " " "
refchecks -> " " "
selectiveanf -> " " "
liftcode -> " " "
selectivecps -> " " "
uncurry -> " " "
tailcalls -> " " "
specialize -> " " "
explicitouter -> " " "
erasure -> " " "
lazyvals -> List()
lambdalift -> " " "
constructors -> " " "
flatten -> " " "
mixin -> " " "
cleanup -> " " "
icode -> " " "
inliner -> " " "
closelim -> " " "
dce -> " " "
jvm -> " " "
terminal -> " " "
scala> repl.allPhases( tpe7.annotations)
parser -> List()
namer -> " " "
packageobjects -> " " "
typer -> " " "
superaccessors -> " " "
pickler -> " " "
refchecks -> " " "
selectiveanf -> " " "
liftcode -> " " "
selectivecps -> " " "
uncurry -> " " "
tailcalls -> " " "
specialize -> " " "
explicitouter -> " " "
erasure -> " " "
lazyvals -> " " "
lambdalift -> " " "
constructors -> " " "
flatten -> " " "
mixin -> " " "
cleanup -> " " "
icode -> " " "
inliner -> " " "
closelim -> " " "
dce -> " " "
jvm -> " " "
terminal -> " " "
Tue, 2010-06-01, 03:07
#4
Re: help with very simple compiler transformation
Thanks so much, normalize works great!!!
I'm not sure why the annotations are not showing up for you... I see them
after the typer. I'm running Scala 2.8.0 RC2 from Maven; the primary files
in my project are here (plugin, file, and library defining @Range):
http://github.com/gatoatigrado/skalch/blob/564b7e6b97305e62faeee69a321cd...
http://github.com/gatoatigrado/skalch/blob/564b7e6b97305e62faeee69a321cd...
http://github.com/gatoatigrado/skalch/blob/564b7e6b97305e62faeee69a321cd...
regards,
Nicholas — ntung at ntung — https://ntung.com — CS major @ UC Berkeley
On Mon, May 31, 2010 at 5:39 PM, Paul Phillips wrote:
> On Mon, May 31, 2010 at 03:23:52PM -0700, Nicholas Tung wrote:
>> Thanks very much. I have another question -- how can I follow a
>> TypeRef to get an annotation? Here's some example code:
>> type Int5 = Int @ Range(-32 to 31)
>> val x = (fcn() : Int5)
>
> Do you have reason to believe this can work? I'll be surprised. It'd be
> neat if so. I don't think type aliases are sufficiently first class
> that you can annotate them and distinguish between the annotated alias
> and the underlying type.
>
> Here's a little repl session in my current repl, which I can't resist to
> demo the stuff I've been adding. Not sure what if anything this will
> tell you -- I know little about the annotations implementation. But it
> seems to support my suspicion since I only see the annotation at all if
> I normalize.
>
> scala> class Range(x: scala.Range) extends scala.StaticAnnotation
> defined class Range
>
> scala> type Int5 = Int @ Range(-32 to 31)
> defined type alias Int5
>
> scala> :type Int5
> tpe7: global.Type = Int5
>
> scala> tpe7.normalize
> res10: global.Type = Int
>
> scala> repl.allPhases( tpe7.normalize.annotations)
> parser -> List(Range(scala.this.Predef.intWrapper(-32).to(31)))
> namer -> " " "
> packageobjects -> " " "
> typer -> " " "
> superaccessors -> " " "
> pickler -> " " "
> refchecks -> " " "
> selectiveanf -> " " "
> liftcode -> " " "
> selectivecps -> " " "
> uncurry -> " " "
> tailcalls -> " " "
> specialize -> " " "
> explicitouter -> " " "
> erasure -> " " "
> lazyvals -> List()
> lambdalift -> " " "
> constructors -> " " "
> flatten -> " " "
> mixin -> " " "
> cleanup -> " " "
> icode -> " " "
> inliner -> " " "
> closelim -> " " "
> dce -> " " "
> jvm -> " " "
> terminal -> " " "
>
> scala> repl.allPhases( tpe7.annotations)
> parser -> List()
> namer -> " " "
> packageobjects -> " " "
> typer -> " " "
> superaccessors -> " " "
> pickler -> " " "
> refchecks -> " " "
> selectiveanf -> " " "
> liftcode -> " " "
> selectivecps -> " " "
> uncurry -> " " "
> tailcalls -> " " "
> specialize -> " " "
> explicitouter -> " " "
> erasure -> " " "
> lazyvals -> " " "
> lambdalift -> " " "
> constructors -> " " "
> flatten -> " " "
> mixin -> " " "
> cleanup -> " " "
> icode -> " " "
> inliner -> " " "
> closelim -> " " "
> dce -> " " "
> jvm -> " " "
> terminal -> " " "
>
> --
> Paul Phillips | On two occasions, I have been asked, 'Mr. Babbage, if you
> Caged Spirit | put into the machine wrong figures, will the right answers
> Empiricist | come out?' I am not able to rightly apprehend the kind of
> i'll ship a pulp | confusion of ideas that could provoke such a question.
>
Tue, 2010-06-01, 03:37
#5
Re: help with very simple compiler transformation
On Mon, May 31, 2010 at 07:00:37PM -0700, Nicholas Tung wrote:
> I'm not sure why the annotations are not showing up for you... I see
> them after the typer. I'm running Scala 2.8.0 RC2 from Maven; the
> primary files in my project are here (plugin, file, and library
> defining @Range):
I'm going to guess it's because I defined the annotation in the repl.
I've recently found myself unable to recover the scala sig annotation in
repl defined classes so maybe this is serendipitously pointing me in the
right general direction for fixing that.
On Sat, May 29, 2010 at 08:59:37PM -0700, Nicholas Tung wrote:
> def createBlockForTyped(expr:Tree, tpt:Tree) = {
...
> Block(List(vd), ident)
That's an untyped tree.
> override def transform(tree : Tree) = tree match {
> case Typed(expr, tpt) =>
That's a typed tree.
> createBlockForTyped(expr, tpt)
That's you replacing a typed tree with an untyped tree.
> Exception in thread "main" java.lang.NullPointerException
> at scala.tools.nsc.transform.UnCurry.scala$tools$nsc$transform$UnCurry$$expandAlias(UnCurry.scala:50)
That's the compiler dereferencing the null pointer where it expects the
tpe to be.