module forth
-instream = STDIN
-currentLine = ""
-currentPos = 0
+RS = Array{Int64, 1}(1024)
+RSP = 1
-function readPattern(pattern::Regex)
+PS = Array{Int64, 1}(1024)
+PSP = 1
- if currentPos<1 || currentPos>length(currentLine)
- if eof(instream)
- return ""
- else
- global currentLine = readline(instream)
- global currentPos = 1
- end
- end
+IP = 0
+W = 0
+X = 0
- m = match(pattern, currentLine[currentPos:length(currentLine)])
- if m != nothing
- global currentPos += length(m.match)
- return m.match
- else
- return ""
- end
-end
+jmp = nothing
-readSpaces() = readPattern(r"^([ \t]*)")
-readWord() = readPattern(r"^([^\s]+)")
-readNewline() = readPattern(r"^(\n)")
-readRestOfLine() = readPattern(r"^([^\n]*)")
+primitives = Array{Expr,1}()
+memory = Array{Int64,1}()
+headers = Array{Tuple{AbstractString, Int64},1}()
-word = ""
-function getWordOrNewline()
- global word = readWord()
- if word == ""
- global word = readNewline()
- end
+function addPrim(name::AbstractString, expr::Expr)
+ push!(primitives, expr)
+ push!(memory, -length(primitives))
+ push!(headers, (name, length(memory)))
+
+ return expr
end
-modes = Dict{AbstractString,Function}()
-mode = ""
+NEXT = addPrim("next", :(begin
+ W = memory[IP]
+ IP += 1
+ X = memory[W]
+ jmp = primitives[-X]
+end))
-dict = Dict{AbstractString, Function}()
-dict["%J"] = () -> begin
- rol = readRestOfLine()
- println("Evaluating '$rol'")
- eval(parse(rol))
-end
+DOCOL = addPrim("docol", :(begin
+ push!(RS, IP)
+ IP = W + 1
+ jmp = NEXT
+end))
-function interpretPrimitive()
- if haskey(dict, word)
- dict[word]()
- return true
- else
- return false
- end
-end
-interpretNonPrimitive() = false
-interpretNumber() = false
+EXIT = addPrim("exit", :(begin
+ IP = pop!(RS)
+ jmp = NEXT
+end))
-modes["interpret"] = () -> begin
- getWordOrNewline()
- if ! (interpretPrimitive() ||
- interpretNonPrimitive() ||
- interpretNumber())
- println("Error: unknown word '$word'.")
- end
-end
-function repl()
- global mode = "interpret"
- idx = 1
- while mode != "stop"
- modes[mode]()
+# VM loop
+jmp = NEXT
+function runVM()
+ while true
+ eval(jmp)
end
end
-# Bootstrapping interpreter
-
-firstProg = """%J dict["\\n"] = () -> nothing
-%J dict["\\n"] = () -> nothing
-%J dict[""] = () -> global mode = "stop"
-%J global DS = []
-%J global RS = []
-"""
-
-instream = IOBuffer(firstProg)
-repl()
-
end