diff options
Diffstat (limited to 'compiler/llstream.nim')
-rw-r--r-- | compiler/llstream.nim | 90 |
1 files changed, 48 insertions, 42 deletions
diff --git a/compiler/llstream.nim b/compiler/llstream.nim index 42bbb7600..cc8148483 100644 --- a/compiler/llstream.nim +++ b/compiler/llstream.nim @@ -10,13 +10,20 @@ ## Low-level streams for high performance. import - strutils + pathutils -# support '-d:useGnuReadline' for backwards compatibility: -when not defined(windows) and (defined(useGnuReadline) or defined(useLinenoise)): - import rdstdin +when defined(nimPreviewSlimSystem): + import std/syncio + +# support `useGnuReadline`, `useLinenoise` for backwards compatibility +const hasRstdin = (defined(nimUseLinenoise) or defined(useLinenoise) or defined(useGnuReadline)) and + not defined(windows) + +when hasRstdin: import std/rdstdin type + TLLRepl* = proc (s: PLLStream, buf: pointer, bufLen: int): int + OnPrompt* = proc() {.closure.} TLLStreamKind* = enum # enum of different stream implementations llsNone, # null stream: reading and writing has no effect llsString, # stream encapsulates a string @@ -28,33 +35,27 @@ type s*: string rd*, wr*: int # for string streams lineOffset*: int # for fake stdin line numbers + repl*: TLLRepl # gives stdin control to clients + onPrompt*: OnPrompt PLLStream* = ref TLLStream -proc llStreamOpen*(data: string): PLLStream = - new(result) - result.s = data - result.kind = llsString +proc llStreamOpen*(data: sink string): PLLStream = + PLLStream(kind: llsString, s: data) proc llStreamOpen*(f: File): PLLStream = - new(result) - result.f = f - result.kind = llsFile + PLLStream(kind: llsFile, f: f) -proc llStreamOpen*(filename: string, mode: FileMode): PLLStream = - new(result) - result.kind = llsFile - if not open(result.f, filename, mode): result = nil +proc llStreamOpen*(filename: AbsoluteFile, mode: FileMode): PLLStream = + result = PLLStream(kind: llsFile) + if not open(result.f, filename.string, mode): result = nil proc llStreamOpen*(): PLLStream = - new(result) - result.kind = llsNone + PLLStream(kind: llsNone) -proc llStreamOpenStdIn*(): PLLStream = - new(result) - result.kind = llsStdIn - result.s = "" - result.lineOffset = -1 +proc llReadFromStdin(s: PLLStream, buf: pointer, bufLen: int): int +proc llStreamOpenStdIn*(r: TLLRepl = llReadFromStdin, onPrompt: OnPrompt = nil): PLLStream = + PLLStream(kind: llsStdIn, s: "", lineOffset: -1, repl: r, onPrompt: onPrompt) proc llStreamClose*(s: PLLStream) = case s.kind @@ -67,6 +68,7 @@ when not declared(readLineFromStdin): # fallback implementation: proc readLineFromStdin(prompt: string, line: var string): bool = stdout.write(prompt) + stdout.flushFile() result = readLine(stdin, line) if not result: stdout.write("\n") @@ -77,6 +79,8 @@ proc endsWith*(x: string, s: set[char]): bool = while i >= 0 and x[i] == ' ': dec(i) if i >= 0 and x[i] in s: result = true + else: + result = false const LineContinuationOprs = {'+', '-', '*', '/', '\\', '<', '>', '!', '?', '^', @@ -87,13 +91,14 @@ proc endsWithOpr*(x: string): bool = result = x.endsWith(LineContinuationOprs) proc continueLine(line: string, inTripleString: bool): bool {.inline.} = - result = inTripleString or - line[0] == ' ' or - line.endsWith(LineContinuationOprs+AdditionalLineContinuationOprs) + result = inTripleString or line.len > 0 and ( + line[0] == ' ' or + line.endsWith(LineContinuationOprs+AdditionalLineContinuationOprs)) proc countTriples(s: string): int = + result = 0 var i = 0 - while i < s.len: + while i+2 < s.len: if s[i] == '"' and s[i+1] == '"' and s[i+2] == '"': inc result inc i, 2 @@ -105,12 +110,12 @@ proc llReadFromStdin(s: PLLStream, buf: pointer, bufLen: int): int = var line = newStringOfCap(120) var triples = 0 while readLineFromStdin(if s.s.len == 0: ">>> " else: "... ", line): - add(s.s, line) - add(s.s, "\n") + s.s.add(line) + s.s.add("\n") inc triples, countTriples(line) if not continueLine(line, (triples and 1) == 1): break inc(s.lineOffset) - result = min(bufLen, len(s.s) - s.rd) + result = min(bufLen, s.s.len - s.rd) if result > 0: copyMem(buf, addr(s.s[s.rd]), result) inc(s.rd, result) @@ -120,14 +125,15 @@ proc llStreamRead*(s: PLLStream, buf: pointer, bufLen: int): int = of llsNone: result = 0 of llsString: - result = min(bufLen, len(s.s) - s.rd) + result = min(bufLen, s.s.len - s.rd) if result > 0: copyMem(buf, addr(s.s[0 + s.rd]), result) inc(s.rd, result) of llsFile: result = readBuffer(s.f, buf, bufLen) of llsStdIn: - result = llReadFromStdin(s, buf, bufLen) + if s.onPrompt!=nil: s.onPrompt() + result = s.repl(s, buf, bufLen) proc llStreamReadLine*(s: PLLStream, line: var string): bool = setLen(line, 0) @@ -135,19 +141,19 @@ proc llStreamReadLine*(s: PLLStream, line: var string): bool = of llsNone: result = true of llsString: - while s.rd < len(s.s): + while s.rd < s.s.len: case s.s[s.rd] - of '\x0D': + of '\r': inc(s.rd) - if s.s[s.rd] == '\x0A': inc(s.rd) + if s.s[s.rd] == '\n': inc(s.rd) break - of '\x0A': + of '\n': inc(s.rd) break else: - add(line, s.s[s.rd]) + line.add(s.s[s.rd]) inc(s.rd) - result = line.len > 0 or s.rd < len(s.s) + result = line.len > 0 or s.rd < s.s.len of llsFile: result = readLine(s.f, line) of llsStdIn: @@ -158,8 +164,8 @@ proc llStreamWrite*(s: PLLStream, data: string) = of llsNone, llsStdIn: discard of llsString: - add(s.s, data) - inc(s.wr, len(data)) + s.s.add(data) + inc(s.wr, data.len) of llsFile: write(s.f, data) @@ -173,7 +179,7 @@ proc llStreamWrite*(s: PLLStream, data: char) = of llsNone, llsStdIn: discard of llsString: - add(s.s, data) + s.s.add(data) inc(s.wr) of llsFile: c = data @@ -185,7 +191,7 @@ proc llStreamWrite*(s: PLLStream, buf: pointer, buflen: int) = discard of llsString: if buflen > 0: - setLen(s.s, len(s.s) + buflen) + setLen(s.s, s.s.len + buflen) copyMem(addr(s.s[0 + s.wr]), buf, buflen) inc(s.wr, buflen) of llsFile: @@ -200,7 +206,7 @@ proc llStreamReadAll*(s: PLLStream): string = of llsString: if s.rd == 0: result = s.s else: result = substr(s.s, s.rd) - s.rd = len(s.s) + s.rd = s.s.len of llsFile: result = newString(bufSize) var bytes = readBuffer(s.f, addr(result[0]), bufSize) |