Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #65 from MoeOrganization/prakash/repl-enhancement
pretty-printing of AST dumps and a bit of configurability for REPL
  • Loading branch information
Stevan Little committed Mar 2, 2013
2 parents 560ab18 + 9d3358c commit db563a6
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 11 deletions.
41 changes: 33 additions & 8 deletions src/main/scala/org/moe/Moe.scala
Expand Up @@ -77,7 +77,7 @@ object Moe {

if (cmd.hasOption("e")) {
val code: String = cmd.getOptionValue("e")
REPL.evalLine(interpreter, runtime, code, dumpAST)
REPL.evalLine(interpreter, runtime, code, Map("dumpAST" -> dumpAST))
return
}
else {
Expand All @@ -90,9 +90,8 @@ object Moe {
val path = rest(0)

val source = Source.fromFile(path).mkString
val printOutput = false

REPL.evalLine(interpreter, runtime, source, dumpAST, printOutput)
REPL.evalLine(interpreter, runtime, source, Map("printOutput" -> false, "dumpAST" -> dumpAST))
}
}
}
Expand Down Expand Up @@ -126,10 +125,18 @@ object Moe {
val cReader: ConsoleReader = new ConsoleReader
val prompt = "moe> "

var replOptions = Map(
"printOutput" -> true,
"dumpAST" -> dumpAST,
"prettyPrintAST" -> false
)
while (true) {
val line = cReader readLine prompt
if (line != null && line.length > 0 && line != "exit") {
evalLine(interpreter, runtime, line, dumpAST)
if (line(0) == ':')
replOptions = processReplCommand(line, replOptions)
else
evalLine(interpreter, runtime, line, replOptions)
}
else {
if (line != "exit") println()
Expand All @@ -138,23 +145,41 @@ object Moe {
}
}

def evalLine(interpreter: Interpreter, runtime: MoeRuntime, line: String, dumpAST: Boolean = false, printOutput: Boolean = true) = {
def evalLine(interpreter: Interpreter, runtime: MoeRuntime, line: String, options: Map[String, Boolean]) = {
try {
val nodes = MoeParsers.parseFromEntry(line)
val ast = CompilationUnitNode(
ScopeNode(nodes)
)
if (dumpAST) {
println(Serializer.toJSON(ast))
if (options("dumpAST")) {
if (options("prettyPrintAST"))
println(Serializer.toJSONPretty(ast))
else
println(Serializer.toJSON(ast))
}
val result = interpreter.eval(runtime, runtime.getRootEnv, ast)
if( printOutput ) {
if( options("printOutput") ) {
println(result.toString)
}
}
catch {
case e: Exception => System.err.println(e)
}
}

import scala.util.matching.Regex

def processReplCommand(command: String, options: Map[String, Boolean]): Map[String, Boolean] = {
def toBoolean(v: String): Boolean = v == "on" || v == "yes" || v == "1"
val pattern = new Regex(""":set\s+(\w+)\s+(\w+)""", "option", "value")

pattern findFirstIn command match {
case Some(pattern(option, value)) => options updated (option, toBoolean(value))
case None => {
println("Unrecognized command: " + command)
options
}
}
}
}
}
28 changes: 25 additions & 3 deletions src/main/scala/org/moe/ast/Serializer.scala
Expand Up @@ -50,7 +50,7 @@ object Serializer {
)
)
)
)
)

case PostfixUnaryOpNode(lhs, operator) => JSONObject(
Map(
Expand All @@ -61,7 +61,7 @@ object Serializer {
)
)
)
)
)

case BinaryOpNode(lhs, operator, rhs) => JSONObject(
Map(
Expand Down Expand Up @@ -339,5 +339,27 @@ object Serializer {

case _ => "stub"
}
}

// thanks to https://gist.github.com/umitanuki/944839
def pprint(j: Option[Any], l: Int = 0):String = {
val indent = (for(i <- List.range(0, l)) yield " ").mkString
j match{
case Some(o: JSONObject) => {
List("{",
o.obj.keys.map(key => indent + " " + "\"" + key + "\" : " + pprint(o.obj.get(key), l + 1)).mkString(",\n"),
indent + "}").mkString("\n")
}
case Some(a: JSONArray) => {
List("[",
a.list.map(v => indent + " " + pprint(Some(v), l + 1)).mkString(",\n"),
indent + "]").mkString("\n")
}
case Some(s: String) => "\"" + s + "\""
case Some(n: Number) => n.toString
case None => "null"
case _ => "undefined"
}
}

def toJSONPretty(ast: AST): String = pprint(Some(toJSON(ast)))
}

0 comments on commit db563a6

Please sign in to comment.