Main method invocation in scala nsc - scala

I was trying to go through the code for nsc(new scala compiler). I am a little confused about Main.scala. It is implemented as follows:
/* NSC -- new Scala compiler
* Copyright 2005-2013 LAMP/EPFL
* #author Martin Odersky
*/
package scala.tools
package nsc
import scala.language.postfixOps
/** The main class for NSC, a compiler for the programming
* language Scala.
*/
class MainClass extends Driver with EvalLoop {
def resident(compiler: Global): Unit = loop { line =>
val command = new CompilerCommand(line split "\\s+" toList, new Settings(scalacError))
compiler.reporter.reset()
new compiler.Run() compile command.files
}
override def newCompiler(): Global = Global(settings, reporter)
override def doCompile(compiler: Global) {
if (settings.resident) resident(compiler)
else super.doCompile(compiler)
}
}
object Main extends MainClass { }
My first question is, how is Main being called by the compiler process? When I call something along the lines of:
scalac [ <options> ] <source files>
Somewhere along the lines the newCompiler and doCompile is being called, can somebody help me with tracing through how this is being called and how the compiler is being initialized?
Any pointers will be much appreciated.
Thanks

MainClass extends Driver which has the main method:
def main(args: Array[String]) {
process(args)
sys.exit(if (reporter.hasErrors) 1 else 0)
}
At the same time, object Main extends MainClass which means that there is a Main.class file that contains a public static void main(String[] args) forwarder method that actually invokes aforementioned non-static method on object Main. See for example this question for more details on how object is compiled in Scala.
This means that scala.tools.nsc.Main can be used as a main class when running the scala compiler (this is hardcoded somewhere in the scalac script).
newCompiler and doCompile are called by process.

Related

Is there a per-test non-specific mock reset pattern using Scala+PlaySpec+Mockito?

I'm writing a unit test suite for a Scala Play application and I'm wondering if there's anything analogous to java's
#Mock
private Foo foo;
#Autowired/InjectMocks
private Bar fixture;
#BeforeMethod
public void setUp() {
MockitoAnnotations.initMocks(this);
}
For auto-mocking the annotated class and resetting it after every test
Currently I'm settling for
TestClass extends PlaySpec with BeforeAndAfterEach
private val foo = mock[Foo]
override def fakeApplication(): Application =
new GuiceApplicationBuilder().overrides(bind[Foo].toInstance(foo)).build
override protected def beforeEach(): Unit = {
reset(foo)
}
A cursory attempt at using the java annotations in the scala test was not successful. My current approach works, I just want to make sure there's not a nicer one.
mockito-scala solves this problem from version 0.1.1, as it provides a trait (org.mockito.integrations.scalatest.ResetMocksAfterEachTest) that helps to automatically reset any existent mock after each test is run
The trait has to be mixed after org.mockito.MockitoSugar in order to work, otherwise your test will not compile
So your code would look like this
TestClass extends PlaySpec with MockitoSugar with ResetMocksAfterEachTest
private val foo = mock[Foo]
override def fakeApplication(): Application =
new GuiceApplicationBuilder().overrides(bind[Foo].toInstance(foo)).build
The main advantage being not having to remember to manually reset each one of the mocks...
If for some reason you want to have a mock that is not reset automatically while using this trait, then it should be
created via the companion object of org.mockito.MockitoSugar so is not tracked by this mechanism
Disclaimer: I'm a developer of that library

Scala's delayedInit and Scallop

SLS 5.1 says "Delayed Initializaton. The initialization code of an object or class (but not a trait) that follows the superclass constructor invocation and the mixin-evaluation of the template’s base classes is passed to a special hook, which is inaccessible from user code. Normally, that hook simply executes the code that is passed to it. But templates inheriting the scala.DelayedInit trait can override the hook by re-implementing the delayedInit method, which is defined as follows:"
def delayedInit(body: => Unit)
The ScallopConf command-line parser extends DelayedInit and using it according to the docs generates the warning Selecting value apples from class Conf, which extends scala.DelayedInit, is likely to yield an uninitialized value.
How should the following simple example be rewritten so the warning is not generated?
import org.rogach.scallop._
class Conf(arguments: Seq[String]) extends ScallopConf(arguments) {
val help = opt[Boolean](name = "help", short = 'h', descr = "Help me please.")
}
object Gen {
def main(args: Array[String]) {
val conf: Conf = new Conf(args)
if (conf.help()) {
println(s"""Usage: Gen [--help]""")
sys.exit(-1)
}
println("Do some work here")
}
}
Making help a lazy val and calling conf.afterInit() before accessing conf.help should clear the compiler warnings.

scala App class DelayedInit hook

trait App extends DelayedInit {
//...
private val initCode = new ListBuffer[() => Unit]
/** The init hook. This saves all initialization code for execution within `main`.
* This method is normally never called directly from user code.
* Instead it is called as compiler-generated code for those classes and objects
* (but not traits) that inherit from the `DelayedInit` trait and that do not
* themselves define a `delayedInit` method.
* #param body the initialization code to be stored for later execution
*/
override def delayedInit(body: => Unit) {
initCode += (() => body)
}
//...
}
object CircuitMain extends App {
// You can write tests either here, or better in the test class CircuitSuite.
Circuit.andGateExample //line in question ?
}
Related Post why-if-i-extend-the-app-trait-in-scala-i-override-the-main-method
I can see that in the comment it is saying it will be called by compiler generated code.
and from the related post, it is saying that the scala compiler will do special things about DelayedInit, what made this DelayedInit trait so special ? is it language related feature? or we can do similar things to other traits as well ? if yes, how to do that.
Was pondering this myself the other day...
Yes, it's a language specific feature - check Section 5.1 "Delayed Initializaton" in the Scala Language Specification:
http://www.scala-lang.org/docu/files/ScalaReference.pdf
You can also confirm this checking out the compiler source code:
https://github.com/scala/scala/blob/946b76ad8b31b1fd74e2f8e1972c4a9159ac690a/src/reflect/scala/reflect/internal/StdNames.scala
// Compiler utilized names
...
val delayedInit: NameType = "delayedInit"
val delayedInitArg: NameType = "delayedInit$body"
And also:
https://github.com/scala/scala/blob/96df73d994097e3318d003ddef00194b711289a3/src/reflect/scala/reflect/internal/Definitions.scala
// classes with special meanings
lazy val StringAddClass = requiredClass[scala.runtime.StringAdd]
lazy val ScalaNumberClass = requiredClass[scala.math.ScalaNumber]
lazy val TraitSetterAnnotationClass = requiredClass[scala.runtime.TraitSetter]
lazy val DelayedInitClass = requiredClass[scala.DelayedInit]
def delayedInitMethod = getMemberMethod(DelayedInitClass, nme.delayedInit)

using inherited method from Java class in Scala [duplicate]

This question already has an answer here:
Calling a protected static Java method from Scala
(1 answer)
Closed 8 years ago.
I'm trying to compile a Scala class file that extends a Java class. Here is the class definition, it's as basic as it gets. On load, in the host application, the object should write "Hello from Scala" to the host's output window, using the superclass's method 'post'.
import com.cycling74.max.MaxObject;
public class FirstClass extends MaxObject{
public FirstClass{
post("Hello From Java");
}
}
This compiles and runs fine in the application.
Here is my translation to Scala (to be honest I'm not 100% sure I completely understand constructors in Scala):
import com.cycling74.max._
class FirstClass() extends MaxObject {
super.post("Hello from Scala")
}
But, when I try to compile with scalac, I receive the following error:
dm$ scalac -cp max.jar FirstClass.scala
FirstClass.scala:3: error: value post is not a member of com.cycling74.max.MaxObject with ScalaObject
super.post("Hello from Scala")
^
one error found
I'm not sure why the compiler is telling me that 'post' is not a member function, I'm certain that I've botched the Scala syntax, but cannot determine what is wrong.
Thanks!
EDIT
here's the output from the Max window, in addition to changing the code as prescribed below, i just added the Scala libs to Max's dynamic loadpath. This is exciting
MXJ System CLASSPATH:
/Applications/Max 6.1/Cycling '74/java/lib/jitter.jar
/Applications/Max 6.1/Cycling '74/java/lib/jode-1.1.2-pre-embedded.jar
/Applications/Max 6.1/Cycling '74/java/lib/max.jar
MXJClassloader CLASSPATH:
/Applications/Max 6.1/Cycling '74/java/classes/
/Users/dm/maxmsp/classes
/Users/dm/maxmsp/jars/jline.jar
/Users/dm/maxmsp/jars/scala-compiler.jar
/Users/dm/maxmsp/jars/scala-dbc.jar
/Users/dm/maxmsp/jars/scala-library.jar
/Users/dm/maxmsp/jars/scala-partest.jar
/Users/dm/maxmsp/jars/scala-swing.jar
/Users/dm/maxmsp/jars/scalacheck.jar
/Users/dm/maxmsp/jars/scalap.jar
Jitter initialized
Jitter Java support installed
Hello from Scala
Assuming the definitioin of post method in MaxObject as..
public class MaxObject {
public static void post(java.lang.String message){
System.out.println("printing from MaxObject.post :: " + message);
}
}
you can directly call the post method in scala as -
class FirstClass extends MaxObject {
MaxObject.post("Hello from Scala")
}
Infact, if you are not compelled to extend the MaxObject.. you can also use it as..
class FirstClass{
MaxObject.post("Hello from Scala")
}
Consuming it as :
val fc = new FirstClass //> printing from MaxObject.post :: Hello from Scala

Compiling Scala scripts. How works a Scala script?

Groovy
Groovy comes with a compiler called groovyc. For each script, groovyc generates a class that extends groovy.lang.Script, which contains a main method so that Java can execute it. The name of the compiled class matches the name of the script being compiled.
For example, with this HelloWorld.groovy script:
println "Hello World"
That becomes something like this code:
class HelloWorld extends Script {
public static void main(String[] args) {
println "Hello World"
}
}
Scala
Scala comes with a compiler called scalac.
For example, with the same HelloWorld.scala script:
println("Hello World")
The code is not valid for scalac, because the compiler expected class or object definition, but works in the Scala REPL Interpreter. How is possible? Is it wrapped in a class before the execution?
The code in a Scala-Script is first placed in a Scala object, then compiled to JVM-Bytecode and at last executed. You can see the generated Scala object by writing scala -Xprint:parser my_file.scala:
package <empty> {
object Main extends scala.ScalaObject {
def <init>() = {
super.<init>();
()
};
def main(argv: Array[String]): scala.Unit = {
val args = argv;
{
final class $anon extends scala.AnyRef {
def <init>() = {
super.<init>();
()
};
println("hello world")
};
new $anon()
}
}
}
}
scalac will compile your code to java bytecode. println("Hello World") is not by itself a valid scala program, so scalac will not compile it.
You can do:
object Test extends App {
println("Hello World")
}
or
object Test {
def main(args: Array[String]) {
println("Hello World")
}
}
You can then run the output with scala Test.
Running the scala "interpreter" on a file that only contains the println("Hello World") line will basically wrap it in an object (transforming it into the first form we've seen above), compile it and run it for you under the hood.
Note that (even though the code looks very similar to a Hello World console application in java) the resulting compiled program is not the same thing that would result from the compilation of this java
/* note: this is Java code */
/* this does NOT compile to the same bytecode as the previous scala example*/
public class Test {
public static void main (String args[]) {
System.out.println ("Hello World");
}
}
Once you successfully compile a file with scalac, you can use javap, the java class file disassembler, to view the generated class and method signatures (Edit: thanks to #Luigi for pointing out that it is generated signatures, not code). That is, scalac HelloWorld.scala followed by javap HelloWorld.