From b18e42773e45b9d4819cf0e2d2c5965bd34dcb4f Mon Sep 17 00:00:00 2001 From: Tim Vaughan Date: Fri, 27 May 2016 00:03:40 +1200 Subject: [PATCH] Reimplemented EXPECT. Closes #1. --- README.md | 12 +++---- examples/mandelbrot.4th | 4 ++- src/forth.jl | 78 +++++++++++++++++++++++++++++++++++------ src/lib.4th | 3 ++ 4 files changed, 77 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 612de1a..f43eb80 100644 --- a/README.md +++ b/README.md @@ -37,14 +37,8 @@ the julia prompt: The first thing the interpreter will do is compile the core definitions in the library file. Once this is complete you can start entering forth commands: - : star 42 emit ; - ok - star - * ok - -Notice that unlike other forths, forth.jl echos a newline after reading each -line of standard input. This is an unfortunate side-effect of the way that -I've implemented EXPECT. Hopefully I'll be able to fix this in future. + : star 42 emit ; ok + star * ok There's an example Mandelbrot Set drawing program included in the examples directory. To run it, you'll have to locate this directory on your system (its @@ -86,6 +80,8 @@ my system I can run the example in this way: ** ok +To exit, enter ^D on a blank line or use the `bye` word. + ## License This package is free software and is distributed under version 3.0 of the GNU diff --git a/examples/mandelbrot.4th b/examples/mandelbrot.4th index b8af203..9759a39 100644 --- a/examples/mandelbrot.4th +++ b/examples/mandelbrot.4th @@ -76,6 +76,8 @@ ( Draw the Mandelbrot Set!) : mandeldraw ( x1 y1 x2 y2 -- ) + cr + 0 pick 3 pick - ysteps / 1 pick 4 pick do @@ -106,4 +108,4 @@ hide * mandeldraw ; -.( Enter 'mandel' to draw the Mandelbrot Set.) +CR .( Enter 'mandel' to draw the Mandelbrot Set.) diff --git a/src/forth.jl b/src/forth.jl index 04771ea..4b71499 100644 --- a/src/forth.jl +++ b/src/forth.jl @@ -607,8 +607,8 @@ sources = Array{Any,1}() currentSource() = sources[length(sources)] EOF = defPrimWord("\x04", () -> begin - close(pop!(sources)) - if !isempty(sources) + if currentSource() != STDIN + close(pop!(sources)) return NEXT else return 0 @@ -626,27 +626,82 @@ function raw_mode!(mode::Bool) end end -KEY = defPrimWord("KEY", () -> begin +function getKey() raw_mode!(true) - pushPS(Int(readbytes(STDIN, 1)[1])) + byte = readbytes(STDIN, 1)[1] raw_mode!(false) + + if byte == 0x0d + return 0x0a + elseif byte == 127 + return 0x08 + else + return byte + end +end + +KEY = defPrimWord("KEY", () -> begin + pushPS(Int(getKey())) return NEXT end) +function getLineFromSTDIN() + line = "" + while true + key = Char(getKey()) + + if key == '\n' + print(" ") + return ASCIIString(line) + + elseif key == '\x04' + if isempty(line) + return string("\x04") + end + + elseif key == '\b' + if !isempty(line) + line = line[1:length(line)-1] + print("\b \b") + end + + elseif key == '\e' + # Strip ANSI escape sequence + nextKey = Char(getKey()) + if nextKey == '[' + while true + nextKey = Char(getKey()) + if nextKey >= '@' || nextKey <= '~' + break + end + end + end + + else + print(key) + line = string(line, key) + end + end +end + SPAN, SPAN_CFA = defNewVar("SPAN", 0) EXPECT = defPrimWord("EXPECT", () -> begin maxLen = popPS() addr = popPS() - if !eof(currentSource()) - line = chomp(readline(currentSource())) - mem[SPAN] = min(length(line), maxLen) - putString(line[1:mem[SPAN]], addr) + if currentSource() == STDIN + line = getLineFromSTDIN() else - mem[SPAN] = 1 - mem[addr] = 4 # eof + if !eof(currentSource()) + line = chomp(readline(currentSource())) + else + line = "\x04" # eof + end end + mem[SPAN] = min(length(line), maxLen) + putString(line[1:mem[SPAN]], addr) + return NEXT end) @@ -855,7 +910,7 @@ PARSE = defPrimWord("PARSE", () -> begin end) BYE = defPrimWord("BYE", () -> begin - println("Bye!") + println("\nBye!") return 0 end) @@ -1131,6 +1186,7 @@ DUMP = defPrimWord("DUMP", () -> begin count = popPS() addr = popPS() + println() dump(addr, count=count) return NEXT diff --git a/src/lib.4th b/src/lib.4th index 664ff80..8da2fb1 100644 --- a/src/lib.4th +++ b/src/lib.4th @@ -587,6 +587,7 @@ DOES> @ ; : WORDS + CR LATEST @ ( start at LATEST dictionary entry ) BEGIN ?DUP ( while link pointer is not null ) @@ -619,6 +620,8 @@ DOES> @ : SEE BL WORD FIND ( find the dictionary entry to decompile ) + CR + 0= IF ." Word '" COUNT TYPE ." ' not found in dictionary." EXIT -- 2.20.1