Add history to REPL.

This commit is contained in:
Bob Nystrom
2016-05-21 10:05:28 -07:00
parent bc7f1de758
commit 2ba264bc29
2 changed files with 83 additions and 33 deletions

View File

@ -12,6 +12,9 @@ class Repl {
construct new() {
_cursor = 0
_line = ""
_history = []
_historyIndex = 0
}
run() {
@ -27,7 +30,7 @@ class Repl {
return
} else if (byte == Chars.ctrlD) {
// If the line is empty, Ctrl_D exits.
if (_line == "") {
if (!_line.isEmpty) {
System.print()
return
}
@ -83,11 +86,9 @@ class Repl {
if (escapeType == Chars.leftBracket) {
// ESC [ sequence.
if (value == EscapeBracket.up) {
// TODO: Handle this.
System.print("up")
previousHistory()
} else if (value == EscapeBracket.down) {
// TODO: Handle this.
System.print("down")
nextHistory()
} else if (value == EscapeBracket.left) {
// Move the cursor left one.
if (_cursor > 0) _cursor = _cursor - 1
@ -101,22 +102,46 @@ class Repl {
}
}
previousHistory() {
if (_historyIndex == 0) return
_historyIndex = _historyIndex - 1
_line = _history[_historyIndex]
_cursor = _line.count
}
nextHistory() {
if (_historyIndex >= _history.count) return
_historyIndex = _historyIndex + 1
if (_historyIndex < _history.count) {
_line = _history[_historyIndex]
_cursor = _line.count
} else {
_line = ""
_cursor = 0
}
}
executeInput() {
System.print()
// Add it to the history.
_history.add(_line)
_historyIndex = _history.count
// Reset the current line.
var input = _line
_line = ""
_cursor = 0
System.print()
// Guess if it looks like a statement or expression. Statements need to be
// evaluated at the top level in case they declare variables, but they
// don't return a value. Expressions need to have their result displayed.
var tokens = lex(input, false)
if (tokens.isEmpty) {
// No code, so do nothing.
// TODO: Temp.
System.print("empty")
return
}
// No code, so do nothing.
if (tokens.isEmpty) return
var first = tokens[0]
var isStatement =
@ -148,6 +173,7 @@ class Repl {
// TODO: Handle error in result.toString.
System.print("%(Color.brightWhite)%(result)%(Color.none)")
return
}
}
System.print("%(Color.red)Runtime error: %(result)%(Color.none)")

View File

@ -14,6 +14,9 @@ static const char* replModuleSource =
" construct new() {\n"
" _cursor = 0\n"
" _line = \"\"\n"
"\n"
" _history = []\n"
" _historyIndex = 0\n"
" }\n"
"\n"
" run() {\n"
@ -29,7 +32,7 @@ static const char* replModuleSource =
" return\n"
" } else if (byte == Chars.ctrlD) {\n"
" // If the line is empty, Ctrl_D exits.\n"
" if (_line == \"\") {\n"
" if (!_line.isEmpty) {\n"
" System.print()\n"
" return\n"
" }\n"
@ -85,11 +88,9 @@ static const char* replModuleSource =
" if (escapeType == Chars.leftBracket) {\n"
" // ESC [ sequence.\n"
" if (value == EscapeBracket.up) {\n"
" // TODO: Handle this.\n"
" System.print(\"up\")\n"
" previousHistory()\n"
" } else if (value == EscapeBracket.down) {\n"
" // TODO: Handle this.\n"
" System.print(\"down\")\n"
" nextHistory()\n"
" } else if (value == EscapeBracket.left) {\n"
" // Move the cursor left one.\n"
" if (_cursor > 0) _cursor = _cursor - 1\n"
@ -103,22 +104,46 @@ static const char* replModuleSource =
" }\n"
" }\n"
"\n"
" previousHistory() {\n"
" if (_historyIndex == 0) return\n"
"\n"
" _historyIndex = _historyIndex - 1\n"
" _line = _history[_historyIndex]\n"
" _cursor = _line.count\n"
" }\n"
"\n"
" nextHistory() {\n"
" if (_historyIndex >= _history.count) return\n"
"\n"
" _historyIndex = _historyIndex + 1\n"
" if (_historyIndex < _history.count) {\n"
" _line = _history[_historyIndex]\n"
" _cursor = _line.count\n"
" } else {\n"
" _line = \"\"\n"
" _cursor = 0\n"
" }\n"
" }\n"
"\n"
" executeInput() {\n"
" System.print()\n"
" // Add it to the history.\n"
" _history.add(_line)\n"
" _historyIndex = _history.count\n"
"\n"
" // Reset the current line.\n"
" var input = _line\n"
" _line = \"\"\n"
" _cursor = 0\n"
"\n"
" System.print()\n"
"\n"
" // Guess if it looks like a statement or expression. Statements need to be\n"
" // evaluated at the top level in case they declare variables, but they\n"
" // don't return a value. Expressions need to have their result displayed.\n"
" var tokens = lex(input, false)\n"
" if (tokens.isEmpty) {\n"
" // No code, so do nothing.\n"
" // TODO: Temp.\n"
" System.print(\"empty\")\n"
" return\n"
" }\n"
"\n"
" // No code, so do nothing.\n"
" if (tokens.isEmpty) return\n"
"\n"
" var first = tokens[0]\n"
" var isStatement =\n"
@ -132,30 +157,29 @@ static const char* replModuleSource =
" first.type == Token.varKeyword ||\n"
" first.type == Token.whileKeyword\n"
"\n"
" var fiber\n"
" if (isStatement) {\n"
" var fiber = Fiber.new {\n"
" fiber = Fiber.new {\n"
" Meta.eval(input)\n"
" }\n"
"\n"
" var result = fiber.try()\n"
" if (fiber.error != null) {\n"
" System.print(\"%(Color.red)Runtime error: %(result)%(Color.none)\")\n"
" // TODO: Print entire stack.\n"
" }\n"
" if (fiber.error == null) return\n"
" } else {\n"
" var function = Meta.compileExpression(input)\n"
" if (function == null) return\n"
"\n"
" var fiber = Fiber.new(function)\n"
" fiber = Fiber.new(function)\n"
" var result = fiber.try()\n"
" if (fiber.error == null) {\n"
" // TODO: Handle error in result.toString.\n"
" System.print(\"%(Color.brightWhite)%(result)%(Color.none)\")\n"
" } else {\n"
" System.print(\"%(Color.red)Runtime error: %(result)%(Color.none)\")\n"
" // TODO: Print entire stack.\n"
" return\n"
" }\n"
" }\n"
"\n"
" System.print(\"%(Color.red)Runtime error: %(result)%(Color.none)\")\n"
" // TODO: Print entire stack.\n"
" }\n"
"\n"
" lex(line, includeWhitespace) {\n"