diff options
Diffstat (limited to 'src/compiler/scala/tools/nsc/MainInterpreter.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/MainInterpreter.scala | 166 |
1 files changed, 112 insertions, 54 deletions
diff --git a/src/compiler/scala/tools/nsc/MainInterpreter.scala b/src/compiler/scala/tools/nsc/MainInterpreter.scala index b1ea38e065..4727cd8cc9 100644 --- a/src/compiler/scala/tools/nsc/MainInterpreter.scala +++ b/src/compiler/scala/tools/nsc/MainInterpreter.scala @@ -3,72 +3,130 @@ * @author emir */ // $Id$ -package scala.tools.nsc; +package scala.tools.nsc -import java.io._; -import scala.tools.nsc.util.{Position}; -import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}; +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 extends Object with EvalLoop { - // lots of stuff duplicated from Main - val PRODUCT: String = - System.getProperty("scala.product", "scalaint"); - val VERSION: String = - System.getProperty("scala.version", "unknown version"); - val versionMsg = PRODUCT + " " + VERSION + " -- (c) 2002-05 LAMP/EPFL"; - val prompt = "\nnsc> "; - - private var reporter: ConsoleReporter = _; - - def error(msg: String): unit = - reporter.error(new Position(PRODUCT), - msg + "\n " + PRODUCT + " -help gives more information"); - - def errors() = reporter.errors; - - def interpret(gCompiler: Global): unit = { - val interpreter = new Interpreter { - val compiler: gCompiler.type = gCompiler - }; - loop(line => try { - interpreter.interpret(line.trim(), reporter) - } catch { - case e: Exception => { - reporter.info(null,e.getMessage(),true); - //e.printStackTrace(); - } +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) + } } - def process(args: Array[String]): unit = { - reporter = new ConsoleReporter(); - val command = new CompilerCommand(List.fromArray(args), error, false); - reporter.prompt = (command.settings.prompt.value); - if (command.settings.version.value) - reporter.info(null, versionMsg, true) - else if (command.settings.help.value) // 2do replace with InterpCommand - reporter.info(null, command.usageMsg, true) + /** 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) + } - else { - try { - val compiler = new Global(command.settings, reporter); - interpret(compiler); - } catch { - case ex @ FatalError(msg) => - if (command.settings.debug.value) - ex.printStackTrace(); - reporter.error(null, "fatal error: " + msg); + 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.") } - reporter.printSummary() + 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); - System.exit(if (reporter.errors > 0) 1 else 0); + process(args) } - } |