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
|
package scala.tools.nsc
package interactive
import scala.concurrent.SyncVar
import scala.tools.nsc.util._
import scala.tools.nsc.symtab._
import scala.tools.nsc.ast._
import scala.tools.nsc.reporters._
import scala.tools.nsc.io._
/** Interface of interactive compiler to a client such as an IDE
*/
object REPL {
val versionMsg = "Scala compiler " +
Properties.versionString + " -- " +
Properties.copyrightString
val prompt = "> "
var reporter: ConsoleReporter = _
def error(msg: String) {
reporter.error(/*new Position */FakePos("scalac"),
msg + "\n scalac -help gives more information")
}
def process(args: Array[String]) {
val settings = new Settings(error)
reporter = new ConsoleReporter(settings)
val command = new CompilerCommand(args.toList, settings)
if (command.settings.version.value)
reporter.info(null, versionMsg, true)
else {
try {
object compiler extends Global(command.settings, reporter) {
// printTypings = true
}
if (reporter.hasErrors) {
reporter.flush()
return
}
if (command.shouldStopWithInfo) {
reporter.info(null, command.getInfoMessage(compiler), true)
} else {
run(compiler)
}
} catch {
case ex @ FatalError(msg) =>
if (true || command.settings.debug.value) // !!!
ex.printStackTrace();
reporter.error(null, "fatal error: " + msg)
}
}
}
def main(args: Array[String]) {
process(args)
exit(if (reporter.hasErrors) 1 else 0)
}
def loop(action: (String) => Unit) {
Console.print(prompt)
try {
val line = Console.readLine
if (line.length() > 0) {
action(line)
}
loop(action)
}
catch {
case _: java.io.EOFException => //nop
}
}
/** Commands:
*
* reload file1 ... fileN
* typeat file off1 off2?
* complete file off1 off2?
*/
def run(comp: Global) {
val reloadResult = new Response[Unit]
val typeatResult = new Response[comp.Tree]
val completeResult = new Response[List[comp.Member]]
def makePos(file: String, off1: String, off2: String) = {
val source = toSourceFile(file)
comp.rangePos(source, off1.toInt, off1.toInt, off2.toInt)
}
def doTypeAt(pos: Position) {
comp.askTypeAt(pos, typeatResult)
show(typeatResult)
}
def doComplete(pos: Position) {
comp.askTypeCompletion(pos, completeResult)
show(completeResult)
}
loop { line =>
(line split " ").toList match {
case "reload" :: args =>
comp.askReload(args map toSourceFile, reloadResult)
show(reloadResult)
case List("typeat", file, off1, off2) =>
doTypeAt(makePos(file, off1, off2))
case List("typeat", file, off1) =>
doTypeAt(makePos(file, off1, off1))
case List("complete", file, off1, off2) =>
doComplete(makePos(file, off1, off2))
case List("complete", file, off1) =>
doComplete(makePos(file, off1, off1))
case List("quit") =>
System.exit(1)
case _ =>
println("unrecongized command")
}
}
}
def toSourceFile(name: String) = new BatchSourceFile(new PlainFile(new java.io.File(name)))
def show[T](svar: Response[T]) {
svar.get match {
case Left(result) => println("==> "+result)
case Right(exc) => exc.printStackTrace; println("ERROR: "+exc)
}
svar.clear()
}
}
|