Reimplemented EXPECT. Closes #1.
authorTim Vaughan <tgvaughan@gmail.com>
Thu, 26 May 2016 12:03:40 +0000 (00:03 +1200)
committerTim Vaughan <tgvaughan@gmail.com>
Thu, 26 May 2016 12:03:40 +0000 (00:03 +1200)
README.md
examples/mandelbrot.4th
src/forth.jl
src/lib.4th

index 612de1a..f43eb80 100644 (file)
--- 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:
 
 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
 
 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
 
                                                                            **                       
     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
 ## License
 
 This package is free software and is distributed under version 3.0 of the GNU
index b8af203..9759a39 100644 (file)
@@ -76,6 +76,8 @@
 ( Draw the Mandelbrot Set!)
 : mandeldraw ( x1 y1 x2 y2 -- )
 
 ( Draw the Mandelbrot Set!)
 : mandeldraw ( x1 y1 x2 y2 -- )
 
+    cr
+
     0 pick 3 pick - ysteps /
     1 pick 4 pick do
 
     0 pick 3 pick - ysteps /
     1 pick 4 pick do
 
@@ -106,4 +108,4 @@ hide *
         mandeldraw
 ;
 
         mandeldraw
 ;
 
-.( Enter 'mandel' to draw the Mandelbrot Set.)
+CR .( Enter 'mandel' to draw the Mandelbrot Set.)
index 04771ea..4b71499 100644 (file)
@@ -607,8 +607,8 @@ sources = Array{Any,1}()
 currentSource() = sources[length(sources)]
 
 EOF = defPrimWord("\x04", () -> begin
 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
         return NEXT
     else
         return 0
@@ -626,27 +626,82 @@ function raw_mode!(mode::Bool)
     end
 end
 
     end
 end
 
-KEY = defPrimWord("KEY", () -> begin
+function getKey()
     raw_mode!(true)
     raw_mode!(true)
-    pushPS(Int(readbytes(STDIN, 1)[1]))
+    byte = readbytes(STDIN, 1)[1]
     raw_mode!(false)
     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)
 
     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()
 
 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
     else
-        mem[SPAN] = 1
-        mem[addr] = 4 # eof
+        if !eof(currentSource())
+            line = chomp(readline(currentSource()))
+        else
+            line = "\x04" # eof
+        end
     end
 
     end
 
+    mem[SPAN] = min(length(line), maxLen)
+    putString(line[1:mem[SPAN]], addr)
+
     return NEXT
 end)
 
     return NEXT
 end)
 
@@ -855,7 +910,7 @@ PARSE = defPrimWord("PARSE", () -> begin
 end)
 
 BYE = defPrimWord("BYE", () -> begin
 end)
 
 BYE = defPrimWord("BYE", () -> begin
-    println("Bye!")
+    println("\nBye!")
     return 0
 end)
 
     return 0
 end)
 
@@ -1131,6 +1186,7 @@ DUMP = defPrimWord("DUMP", () -> begin
     count = popPS()
     addr = popPS()
 
     count = popPS()
     addr = popPS()
 
+    println()
     dump(addr, count=count)
 
     return NEXT
     dump(addr, count=count)
 
     return NEXT
index 664ff80..8da2fb1 100644 (file)
@@ -587,6 +587,7 @@ DOES>   @
 ;
 
 : WORDS
 ;
 
 : WORDS
+        CR
         LATEST @        ( start at LATEST dictionary entry )
         BEGIN
                 ?DUP            ( while link pointer is not null )
         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 )
 
 : SEE
         BL WORD FIND    ( find the dictionary entry to decompile )
 
+        CR
+
         0= IF
                 ." Word '" COUNT TYPE ." ' not found in dictionary."
                 EXIT
         0= IF
                 ." Word '" COUNT TYPE ." ' not found in dictionary."
                 EXIT