class file optimization with the scala compiler - scala

I have some class file inside a jar. Now I am searching for a way to optimize that class file using some components(most notably the Inliners) of the scala compiler.
My idea is to :
use the ICodeReader to emit ICode from class file
use an instance of the Inliner class in order to achieve the desired optimization
I am not know if that´s the right way to go
The problem is that
How to use the ICodeReader in order to read a class file and produce the needed ICode. ICodeReader inherits from ClassfileParser. The sole method that is for me more probable to use is parse(file: AbstractFile, root: Symbol) but the problem the root argument.
Any help is welcome

The Scala compiler acts on the source code and on the results of the intermediate step to produce bytecode, and will try to apply, if enabled, several optimisation.
In your case, if I understood right, you do not have the sources but the compiled classes, and I would not expect you being able to use a feature of Scala compiler on compiled classes.
What you should be looking to, in my understanding, is a bytecode optimizer , such as ProGuard, which is able to take existing bytecode and optimize it without having access to the source code
http://proguard.sourceforge.net/#FAQ.html

Related

Compile only one class in a Scala program that contains more than one classes?

I know a Scala file, as in Java, should better define only one class. But now I have someone else's code. The code defines two classes. I 'd like to compile one of them because the other one does not compile. Of course I could have commented out the other one, but I have a large number of such files and I am looking for an automated solution for doing so. Any idea?
The Scala compiler works on whole files. The only way I can imagine doing this is to write a script which comments out all classes you don't want, runs scalac and then removes the comment markers again (well, you could also use Scala compiler as a library to get equivalent results without doing this literally). Needless to say, I don't think it's actually a good idea, but it's possible.

obtaining the source of a case class's automatically generated methods

How can one obtain the code of all automatically generated methods of a case class, to cleanly preserve any of them when refactoring to a regular (non-case) class? is there some compilation flag that reveals the case class's auto-generated methods, or some other way, that ultimately reduce this to a cut & paste?
I have been under the impression that there are compilation flags to reveal automatically expanded definitions....
You can see what the compiler desugars the source code to with the -Xprint:<phase> flags. For your example (seeing which code is generated for case classes), run:
scalac -Xprint:typer YourScala.sca
With -Xshow-phases flag you'll see all the available phases.
But the output you see is not compilable scala source code, but some intermediate representation.
This is maybe not that easy.
The compiler generates byte code, so it isn't possible to copy compiler output and paste into source code.
You could read through the generated byte code and recreate Scala code for analogous methods by hand. This would be a bit laborious, but the methods are relatively simple and understanding byte code is A Good Thing.
If there is a usable Scala decompiler somewhere, then decompiling the compiled case class would reveal the code you want.
Given that the methods are dependent on the fields of the case class, they are not likely to be available in the compiler implementation as anything that could be copied and pasted.
Perhaps the best bet is to look at the language specification and implement the methods as described for case classes.

Generate scala source for a class instance using reflection

Assuming you have an instance of a class.
What is the best approach to generate valid scala source code, which could be written out into a file and compiled, of that instance during runtime?
(Utilizing the scala reflection-api/macros?)
Is it possible to parse the AST representation into source code?
No it's not possible. Class file contains JVM byte-code that has nothing to do with Scala. You can try use Java-decompiler (http://varaneckas.com/jad/ for example), but you wouldn't be able to get something readable.
As I unserstand scala is moving towards new platform (Dotty), and maybe in future it will be possible.

Scala: Difference between file.class and file$.class from scalac

When I use scalac to compile file.scala, I end up with 2 outputs, file.class and file$.class. What is the difference between these files and which is the appropriate one to then run? I get distinctly different error messages between executing "scala file" vs "scala file$".
Scala objects get compiled to classes ending in "$" because you're allowed to have an "ordinary" class with the same name. But the object's methods are also exposed as static methods on the "ordinary" class, so that they can be called under the names you would expect. This is an artifact of trying to represent the scala semantics in a way that make sense to Java / the JVM, and I would encourage you to regard it as an implementation detail rather than something important.
(#MattPutnam's answer is correct that anonymous classes, including closures, are compiled to class files with $es in their name, but that's not what's causing your file$.class in this particular instance)
Use scala file. If you're interested in the implementation details you might also want to try java -cp /path/to/scala-library.jar file.
file$.class is some inner anonymous class. In Java they're very explicit, but they can be easy to miss in Scala. If you use any method that takes a function, there's an implicit anonymous class there. Post the code and I'll point it out.

How do I generate new source code in text form in a Scala compiler plugin?

I have just finished the first version of a Java 6 compiler plugin, that automatically generates wrappers (proxy, adapter, delegate, call it what you like) based on an annotation.
Since I am doing mixed Java/Scala projects, I would like to be able to use the same annotation inside my Scala code, and get the same generated code (except of course in Scala). That basically means starting from scratch.
What I would like to do, and for which I haven't found an example yet, is how do I generate the code inside a Scala compiler plugin in the same way as in the Java compiler plugin. That is, I match/find where my annotation is used, get the AST for the annotated interface, and then ask the API to give me a Stream/Writer in which I output the generated Scala source code, using String manipulation.
That last part is what I could not find. So how do I tell the API to create a new Scala source file, and give me a Stream/Writer/File/Handle, so I can just write in it, and when I'm done, the Scala compiler compiles it, within the same run in which the plugin was invoked?
Why would I want to do that? Firstly, because than both plugins have the same structure, so maintenance is easy. Secondly, I want to open source it, and there is just no way to support every option that anyone would want, so I expect potential users to want to extend the generation with their own code. This will be a lot easier for them if they just have to do some printf(), instead of learning the AST API (this also applies to me).
Short answer:
It can't be done
Long answer:
You could conceivably generate your source file and push that through a parser instance within your plugin. But not in any way that's likely to be of any use to you, because you'd now have a bigger problem to contend with:
In order to grab all the type/name information for generating the delagate/proxy, you'll have to pick up the annotated type's AST after it has run through both the namer and typer phases (which are inseperable). The catch is that any attempts to call your generated code will already have failed typechecking, the compiler will have thrown an error, and any further bets are off.
Method synthesis is possible in limited cases, so long as you can somehow fool the typechecker for just long enough to get your code generated, which is the trick I pulled with my Autoproxy 'lite' plugin. Even then, you're far better off working with TreeDSL to generate code instead of pumping out raw source.
Kevin is entirely correct, but just for completeness it's worth mentioning that there is another alternative - write a compiler plugin that generates source. This is the approach that I've adopted in Borachio. It's not a very satisfactory solution, but it can be made to work.
Edit - I just reread your question and realised that you're actually asking about generating source anyway
So there is no support for this directly, but it's basically just a question of opening a file and writing the relevant "print" statements. There's no way to invoke the compiler "inside" a plugin AFAIK, but I've written an sbt plugin which hides most of the complexity of invoking the compiler twice.