summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/MainInterpreter.scala
blob: 4727cd8cc9d8f38f98b1497626f68528f392790a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/* NSC -- new scala compiler
 * Copyright 2005 LAMP/EPFL
 * @author emir
 */
// $Id$
package scala.tools.nsc

import java.io._
import scala.tools.nsc.util.{Position}
import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}

/** The main class for the new scala interpreter.
 */
object MainInterpreter {
  val reporter = new ConsoleReporter()

  var interpreter: Interpreter = _

  /** print a friendly help message */
  def printHelp = {
    Console.println("This is an interpreter for Scala.")
    Console.println("Type in expressions to have them evaluated.")
    Console.println("Type :quit to exit the interpreter.")
    Console.println("Type :compile followed by a filename to compile a complete Scala file.")
    Console.println("Type :load followed by a filename to load a sequence of interpreter commands.")
    Console.println("Type :help to repeat this message later.")
  }

  /** A simple, generic read-eval-print loop with a pluggable eval-print function.
      Loop reading lines of input and invoking the eval-print function.
      Stop looping when eval-print returns false.  */
  def repl(evpr: String => Boolean): Unit = {
    val in = new BufferedReader(new InputStreamReader(System.in))

    while(true) {
      Console.print("\nscala> ")
      var line = in.readLine()
			if(line == null)
        return ()  // assumes null means EOF

      val keepGoing = evpr(line)

      if(!keepGoing)
        return ()  // the evpr function said to stop
    }
  }

  /** interpret one line of code submitted by the user */
  def interpretOne(line: String): Unit = {
    try {
      interpreter.interpret(line)
     } catch {
       case e: Exception => {
         reporter.info(null,"Exception occurred: " + e.getMessage(),true)
         //e.printStackTrace()
       }
     }
  }

  /** interpret all lines from a specified file */
  def interpretAllFrom(filename: String): Unit = {
    val fileIn = try {
      new FileReader(filename)
    } catch {
      case _:IOException =>
          Console.println("Error opening file: " + filename)
          null
    }
    if(fileIn == null) return ()
    val in = new BufferedReader(fileIn)
    while(true) {
      val line = in.readLine
      if(line == null) {
        fileIn.close
        return ()
      }
      command(line)
    }
  }

  /** run one command submitted by the user */
  def command(line: String): Boolean = {
    def withFile(command: String)(action: String=>Unit): Unit = {
      val spaceIdx = command.indexOf(' ')
      if(spaceIdx <= 0) {
        Console.println("That command requires a filename to be specified.")
        return ()
      }
      val filename = command.substring(spaceIdx).trim
      action(filename)
    }

    if(line.startsWith(":"))
      line match {
        case ":help" => printHelp
        case ":quit" => return false
        case _ if line.startsWith(":compile") => withFile(line)(f => interpreter.compile(f))
        case _ if line.startsWith(":load") => withFile(line)(f => interpretAllFrom(f))
        case _ => Console.println("Unknown command.  Type :help for help.")
      }
    else
      interpretOne(line)
    true
  }



  /** the main interpreter loop */
  def interpretLoop(compiler: Global): unit = {
    interpreter = new Interpreter(compiler, str=>Console.print(str))
    repl(command)
    interpreter.close
  }



  /** process the command-line arguments and do as they request */
  def process(args: Array[String]): unit = {
    val command = new CompilerCommand(List.fromArray(args), error, false)
    reporter.prompt = command.settings.prompt.value
    if (command.settings.help.value) {
      reporter.info(null, command.usageMsg, true)
    } else {
      printHelp
      interpretLoop(new Global(command.settings, reporter))
    }
  }

  def main(args: Array[String]): unit = {
    process(args)
  }
}