Reverted to old style REPL and added note in the README

This commit is contained in:
Mattia Giambirtone 2022-11-05 12:38:05 +01:00
parent 3dead5a555
commit 26e16e7f8e
3 changed files with 45 additions and 34 deletions

View File

@ -42,6 +42,13 @@ Peon is a simple, functional, async-first programming language with a focus on c
**Disclaimer**: The project is still in its very early days: lots of stuff is not implemented, a work in progress or
otherwise outright broken. Feel free to report bugs!
**Disclaimer 2**: Currently the REPL is very basic (it incrementally joins your lines with a newline, as if it was compiling a new file every time),
because incremental compilation is designed for modules and it doesn't play well with the interactive nature of a REPL session. To show the current state
of the REPL, type `#show` (this will print all the code that has been typed so far), while to reset everything (will un-import modules and stuff), type
`#reset`. You can also type `#clear` if you want a clean slate to type in, but note that it won't reset the REPL state.
Also, yes: peon is yet another programming language inspired by Bob's book, but it is also **very**
different from Lox, which is an object-oriented, dynamically typed and very high level programming language, whereas
peon is a statically-typed, functional language which aims to allow low-level interfacing with C and Nim code while

View File

@ -55,10 +55,11 @@ $ peon file.pbc Runs the given Peon bytecode file
Command-line options
--------------------
-h, --help Shows this help text and exits
-v, --version Prints the peon version number and exits
-s, --string Executes the passed string as if it was a file
-i, --interactive Enables interactive mode: a REPL session is opened after execution
-d, --nodump Disables dumping the result of bytecode compilation to files
-b, --breakpoints Pauses execution of the peon virtual machine and runs the debugger at specific bytecode offsets
-h, --help Show this help text and exits
-v, --version Print the peon version number and exits
-s, --string Execute the passed string as if it was a file
-n, --nodump Don't dump the result of compilation to a *.pbc file
-b, --breakpoints Run the debugger at specific bytecode offsets (comma-separated).
Only available when compiled with -d:debugVM
-d, --disassemble Disassemble the given bytecode file instead of executing it
"""

View File

@ -55,21 +55,19 @@ proc repl =
compiled: Chunk = newChunk()
serialized: Serialized
tokenizer = newLexer()
parser = newParser()
compiler = newCompiler(replMode=true)
vm = newPeonVM()
debugger = newDebugger()
serializer = newSerializer()
editor = getLineEditor()
input: string
current: string
incremental: bool = false
tokenizer.fillSymbolTable()
editor.bindEvent(jeQuit):
stdout.styledWriteLine(fgGreen, "Goodbye!")
editor.prompt = "=> "
keep = false
input = ""
current = ""
editor.bindKey("ctrl+a"):
editor.content.home()
editor.bindKey("ctrl+e"):
@ -77,18 +75,20 @@ proc repl =
while keep:
try:
input = editor.read()
if input.len() == 0:
continue
elif input == "#reset":
if input == "#reset":
compiled = newChunk()
compiler = newCompiler()
parser = newParser()
incremental = false
current = ""
continue
elif input == "#show":
echo current
elif input == "#clear":
stdout.write("\x1Bc")
continue
tokens = tokenizer.lex(input, "stdin")
else:
current &= input & "\n"
if current.len() == 0:
continue
tokens = tokenizer.lex(current, "stdin")
if tokens.len() == 0:
continue
when debugLexer:
@ -99,7 +99,7 @@ proc repl =
break
styledEcho fgGreen, "\t", $token
echo ""
tree = parser.parse(tokens, "stdin", tokenizer.getLines(), input, persist=true)
tree = newParser().parse(tokens, "stdin", tokenizer.getLines(), current)
if tree.len() == 0:
continue
when debugParser:
@ -107,8 +107,7 @@ proc repl =
for node in tree:
styledEcho fgGreen, "\t", $node
echo ""
discard compiler.compile(tree, "stdin", tokenizer.getLines(), input, chunk=compiled, incremental=incremental)
incremental = true
compiled = newCompiler(replMode=true).compile(tree, "stdin", tokenizer.getLines(), current)
when debugCompiler:
styledEcho fgCyan, "Compilation step:\n"
debugger.disassembleChunk(compiled, "stdin")
@ -141,7 +140,6 @@ proc repl =
styledEcho fgRed, "Corrupted"
vm.run(serialized.chunk)
except LexingError:
input = ""
var exc = LexingError(getCurrentException())
let relPos = exc.lexer.getRelPos(exc.line)
let line = exc.lexer.getSource().splitLines()[exc.line - 1].strip(chars={'\n'})
@ -151,13 +149,14 @@ proc repl =
styledEcho fgBlue, "Source line: " , fgDefault, line
styledEcho fgCyan, " ".repeat(len("Source line: ") + line.find(exc.lexeme)) & "^".repeat(abs(relPos.stop - relPos.start - line.find(exc.lexeme)))
except ParseError:
input = ""
let exc = ParseError(getCurrentException())
let lexeme = exc.token.lexeme
var lineNo = exc.token.line
if exc.token.kind == EndOfFile:
dec(lineNo)
let relPos = exc.parser.getRelPos(lineNo)
let fn = parser.getCurrentFunction()
let line = exc.parser.getSource().splitLines()[lineNo - 1].strip(chars={'\n'})
let fn = exc.parser.getCurrentFunction()
let line = exc.parser.getSource().splitLines()[lineNo - 1].strip()
var fnMsg = ""
if fn != nil and fn.kind == funDecl:
fnMsg &= &"in function '{FunDecl(fn).name.token.lexeme}'"
@ -187,7 +186,7 @@ proc repl =
quit(0)
proc runFile(f: string, interactive: bool = false, fromString: bool = false, dump: bool = true, breakpoints: seq[uint64] = @[]) =
proc runFile(f: string, fromString: bool = false, dump: bool = true, breakpoints: seq[uint64] = @[], dis: bool = false) =
var
tokens: seq[Token] = @[]
tree: seq[Declaration] = @[]
@ -204,8 +203,11 @@ proc runFile(f: string, interactive: bool = false, fromString: bool = false, dum
try:
var f = f
if not fromString:
if not f.endsWith(".pn"):
if not f.endsWith(".pn") and not f.endsWith(".pbc"):
f &= ".pn"
if dis:
debugger.disassembleChunk(serializer.loadFile(f).chunk, f)
return
input = readFile(f)
else:
input = f
@ -238,7 +240,7 @@ proc runFile(f: string, interactive: bool = false, fromString: bool = false, dum
if path.len() > 0:
path &= "/"
path &= splitFile(f).name & ".pbc"
if dump or not fromString:
if dump and not fromString:
serializer.dumpFile(compiled, f, path)
serialized = serializer.loadFile(path)
else:
@ -281,6 +283,8 @@ proc runFile(f: string, interactive: bool = false, fromString: bool = false, dum
let exc = ParseError(getCurrentException())
let lexeme = exc.token.lexeme
var lineNo = exc.token.line
if exc.token.kind == EndOfFile:
dec(lineNo)
let relPos = exc.parser.getRelPos(lineNo)
let fn = parser.getCurrentFunction()
let line = exc.parser.getSource().splitLines()[lineNo - 1].strip(chars={'\n'})
@ -322,9 +326,9 @@ when isMainModule:
var optParser = initOptParser(commandLineParams())
var file: string = ""
var fromString: bool = false
var interactive: bool = false
var dump: bool = true
var breaks: seq[uint64] = @[]
var dis: bool = false
for kind, key, value in optParser.getopt():
case kind:
of cmdArgument:
@ -340,8 +344,6 @@ when isMainModule:
of "string":
file = key
fromString = true
of "interactive":
interactive = true
of "no-dump":
dump = false
of "breakpoints":
@ -354,6 +356,8 @@ when isMainModule:
except ValueError:
echo &"error: invalid breakpoint value '{point}'"
quit()
of "disassemble":
dis = true
else:
echo &"error: unkown option '{key}'"
quit()
@ -368,9 +372,7 @@ when isMainModule:
of "s":
file = key
fromString = true
of "i":
interactive = true
of "d":
of "n":
dump = false
of "b":
when not debugVM:
@ -382,17 +384,18 @@ when isMainModule:
except ValueError:
echo &"error: invalid breakpoint value '{point}'"
quit()
of "d":
dis = true
else:
echo &"error: unkown option '{key}'"
quit()
else:
echo "usage: peon [options] [filename.pn]"
quit()
# TODO: Use interactive
if file == "":
repl()
else:
runFile(file, interactive, fromString, dump, breaks)
runFile(file, fromString, dump, breaks, dis)