aboutsummaryrefslogblamecommitdiff
path: root/src/dotty/tools/dotc/Driver.scala
blob: 1627b6e4822dff570618d16289cfd2cc5c4ac212 (plain) (tree)
1
2
3
4
5
6
7
8
9
10



                                           
                    
                  
                                  


                                        
                         


                                       
                                                                 
 









                                                                                                         
                      

                      


                                                      


                                                                               
                                                        



                                                                              






                                                                        

   



                                                                            





                                                                            




                                                                                                      
                                                   
   



                                               
package dotty.tools.dotc

import config.CompilerCommand
import core.Contexts.{Context, ContextBase}
import util.DotClass
import reporting._
import scala.util.control.NonFatal

abstract class Driver extends DotClass {

  val prompt = "\ndotc> "

  protected def newCompiler(): Compiler

  protected def emptyReporter: Reporter = new StoreReporter(null)

  protected def doCompile(compiler: Compiler, fileNames: List[String])(implicit ctx: Context): Reporter =
    if (fileNames.nonEmpty)
      try {
        val run = compiler.newRun
        run.compile(fileNames)
        run.printSummary()
      }
      catch {
        case ex: FatalError  =>
          ctx.error(ex.getMessage) // signals that we should fail compilation.
          ctx.reporter
      }
    else emptyReporter

  protected def initCtx = (new ContextBase).initialCtx

  protected def sourcesRequired = true

  def setup(args: Array[String], rootCtx: Context): (List[String], Context) = {
    val summary = CompilerCommand.distill(args)(rootCtx)
    // FIXME: We should reuse rootCtx instead of creating newCtx, but this
    // makes some tests fail with "denotation module _root_ invalid in run 2."
    val newCtx = initCtx.setCompilerCallback(rootCtx.compilerCallback)
    implicit val ctx: Context = newCtx.fresh.setSettings(summary.sstate)
    val fileNames = CompilerCommand.checkUsage(summary, sourcesRequired)
    (fileNames, ctx)
  }

  def process(args: Array[String], rootCtx: Context): Reporter = {
    val (fileNames, ctx) = setup(args, rootCtx)
    doCompile(newCompiler(), fileNames)(ctx)
  }

  def process(args: Array[String], callback: CompilerCallback): Reporter = {
    process(args, initCtx.setCompilerCallback(callback))
  }

  // We overload `process` instead of using a default argument so that we
  // can easily call this method using reflection from `RawCompiler` in sbt.
  def process(args: Array[String]): Reporter = {
    process(args, initCtx)
  }

  def main(args: Array[String]): Unit = {
    // Preload scala.util.control.NonFatal. Otherwise, when trying to catch a StackOverflowError,
    // we may try to load it but fail with another StackOverflowError and lose the original exception,
    // see <https://groups.google.com/forum/#!topic/scala-user/kte6nak-zPM>.
    val _ = NonFatal
    sys.exit(if (process(args).hasErrors) 1 else 0)
  }
}

class FatalError(msg: String) extends Exception