+# VM mem size
+size_mem = 1000000 # 1 mega-int
+
+# Buffer sizes
+size_RS = 1000 # Return stack size
+size_PS = 1000 # Parameter stack size
+size_TIB = 1000 # Terminal input buffer size
+
+# Memory arrays
+mem = Array{Int64,1}(size_mem)
+primitives = Array{Function,1}()
+primNames = Array{ASCIIString,1}()
+
+# Built-in variables
+
+nextVarAddr = 1
+H = nextVarAddr; nextVarAddr += 1
+LATEST = nextVarAddr; nextVarAddr += 1
+
+RSP0 = nextVarAddr # bottom of RS
+PSP0 = RSP0 + size_RS # bottom of PS
+TIB = PSP0 + size_PS # address of terminal input buffer
+mem[H] = TIB + size_TIB # location of bottom of dictionary
+mem[LATEST] = 0 # no previous definition
+
+DICT = mem[H] # Save bottom of dictionary as constant
+
+# VM registers
+type Reg
+ RSP::Int64 # Return stack pointer
+ PSP::Int64 # Parameter/data stack pointer
+ IP::Int64 # Instruction pointer
+ W::Int64 # Working register
+end
+reg = Reg(RSP0, PSP0, 0, 0)
+
+# Stack manipulation functions
+
+function ensurePSDepth(depth::Int64)
+ if reg.PSP - PSP0 < depth
+ error("Parameter stack underflow.")
+ end
+end
+
+function ensureRSDepth(depth::Int64)
+ if reg.RSP - RSP0 < depth
+ error("Return stack underflow.")
+ end
+end
+
+function pushRS(val::Int64)
+ mem[reg.RSP+=1] = val
+end
+
+function popRS()
+ ensureRSDepth(1)
+
+ val = mem[reg.RSP]
+ reg.RSP -= 1
+ return val
+end
+
+function pushPS(val::Int64)
+ mem[reg.PSP += 1] = val
+end
+
+function popPS()
+ ensurePSDepth(1)
+
+ val = mem[reg.PSP]
+ reg.PSP -= 1
+ return val
+end
+
+# Handy functions for adding/retrieving strings to/from memory.
+
+getString(addr::Int64, len::Int64) = ASCIIString([Char(c) for c in mem[addr:(addr+len-1)]])
+
+function putString(str::ASCIIString, addr::Int64)
+ mem[addr:(addr+length(str)-1)] = [Int64(c) for c in str]
+end
+
+# Primitive creation and calling functions
+
+function defPrim(f::Function; name="nameless")
+ push!(primitives, f)
+ push!(primNames, replace(name, "\004", "EOF"))
+
+ return -length(primitives)
+end
+
+function callPrim(addr::Int64)
+ if addr >=0 || -addr>length(primitives)
+ error("Attempted to execute non-existent primitive at address $addr.")
+ else
+ primitives[-addr]()
+ end
+end
+getPrimName(addr::Int64) = primNames[-addr]
+
+# Word creation functions
+
+F_LENMASK = 31
+F_IMMED = 32
+F_HIDDEN = 64
+NFA_MARK = 128
+
+function createHeader(name::AbstractString, flags::Int64)
+ mem[mem[H]] = mem[LATEST]
+ mem[LATEST] = mem[H]
+ mem[H] += 1
+
+ mem[mem[H]] = length(name) | flags | NFA_MARK; mem[H] += 1
+ putString(name, mem[H]); mem[H] += length(name)
+end
+
+function defPrimWord(name::AbstractString, f::Function; flags::Int64=0)
+ createHeader(name, flags)
+
+ codeWordAddr = mem[H]
+ mem[codeWordAddr] = defPrim(f, name=name)
+ mem[H] += 1
+
+ return codeWordAddr
+end
+
+function defWord(name::AbstractString, wordAddrs::Array{Int64,1}; flags::Int64=0)
+ createHeader(name, flags)
+
+ addr = mem[H]
+ mem[mem[H]] = DOCOL
+ mem[H] += 1
+
+ for wordAddr in wordAddrs
+ mem[mem[H]] = wordAddr
+ mem[H] += 1
+ end
+
+ return addr
+end
+
+# Variable creation functions
+
+function defExistingVar(name::AbstractString, varAddr::Int64; flags::Int64=0)
+
+ defPrimWord(name, eval(:(() -> begin
+ pushPS($(varAddr))
+ return NEXT
+ end)))
+end
+
+function defNewVar(name::AbstractString, initial::Int64; flags::Int64=0)
+ createHeader(name, flags)
+
+ codeWordAddr = mem[H]
+ varAddr = mem[H] + 1
+
+ mem[mem[H]] = DOVAR; mem[H] += 1
+ mem[mem[H]] = initial; mem[H] += 1
+
+ return varAddr, codeWordAddr
+end
+
+function defConst(name::AbstractString, val::Int64; flags::Int64=0)
+ createHeader(name, flags)
+
+ codeWordAddr = mem[H]
+
+ mem[mem[H]] = DOCON; mem[H] += 1
+ mem[mem[H]] = val; mem[H] += 1
+
+ return codeWordAddr
+end
+
+# Threading Primitives (inner interpreter)
+
+NEXT = defPrim(() -> begin
+ reg.W = mem[reg.IP]
+ reg.IP += 1
+ return mem[reg.W]
+end, name="NEXT")
+
+DOCOL = defPrim(() -> begin
+ pushRS(reg.IP)
+ reg.IP = reg.W + 1
+ return NEXT
+end, name="DOCOL")
+
+DOVAR = defPrim(() -> begin
+ pushPS(reg.W + 1)
+ return NEXT
+end, name="DOVAR")
+
+DOCON = defPrim(() -> begin
+ pushPS(mem[reg.W + 1])
+ return NEXT
+end, name="DOVAR")
+
+EXIT_CFA = defPrimWord("EXIT", () -> begin
+ reg.IP = popRS()
+ return NEXT
+end)
+
+# Dictionary entries for core built-in variables, constants
+
+H_CFA = defExistingVar("H", H)
+LATEST_CFA = defExistingVar("LATEST", LATEST)
+
+PSP0_CFA = defConst("PSP0", PSP0)
+RSP0_CFA = defConst("RSP0", RSP0)
+
+defConst("DOCOL", DOCOL)
+defConst("DOCON", DOCON)
+defConst("DOVAR", DOVAR)
+
+defConst("DICT", DICT)
+defConst("MEMSIZE", size_mem)
+
+F_IMMED_CFA = defConst("F_IMMED", F_IMMED)
+F_HIDDEN_CFA = defConst("F_HIDDEN", F_HIDDEN)
+F_LENMASK_CFA = defConst("F_LENMASK", F_LENMASK)
+NFA_MARK_CFA = defConst("NFA_MARK", NFA_MARK)
+
+# Basic forth primitives
+
+DROP_CFA = defPrimWord("DROP", () -> begin
+ popPS()
+ return NEXT
+end)
+
+SWAP_CFA = defPrimWord("SWAP", () -> begin
+ a = popPS()
+ b = popPS()
+ pushPS(a)
+ pushPS(b)
+ return NEXT
+end)
+
+DUP_CFA = defPrimWord("DUP", () -> begin
+ ensurePSDepth(1)
+ pushPS(mem[reg.PSP])
+ return NEXT
+end)
+
+OVER_CFA = defPrimWord("OVER", () -> begin
+ ensurePSDepth(2)
+ pushPS(mem[reg.PSP-1])
+ return NEXT
+end)
+
+ROT_CFA = defPrimWord("ROT", () -> begin
+ a = popPS()
+ b = popPS()
+ c = popPS()
+ pushPS(b)
+ pushPS(a)
+ pushPS(c)
+ return NEXT
+end)
+
+NROT_CFA = defPrimWord("-ROT", () -> begin
+ a = popPS()
+ b = popPS()
+ c = popPS()
+ pushPS(a)
+ pushPS(c)
+ pushPS(b)
+ return NEXT
+end)
+
+
+TWODROP_CFA = defPrimWord("2DROP", () -> begin
+ popPS()
+ popPS()
+ return NEXT
+end)
+
+TWODUP_CFA = defPrimWord("2DUP", () -> begin
+ ensurePSDepth(2)
+ a = mem[reg.PSP-1]
+ b = mem[reg.PSP]
+ pushPS(a)
+ pushPS(b)
+ return NEXT
+end)
+
+TWOSWAP_CFA = defPrimWord("2SWAP", () -> begin
+ a = popPS()
+ b = popPS()
+ c = popPS()
+ d = popPS()
+ pushPS(b)
+ pushPS(a)
+ pushPS(d)
+ pushPS(c)
+ return NEXT
+end)
+
+TWOOVER_CFA = defPrimWord("2OVER", () -> begin
+ ensurePSDepth(4)
+ a = mem[reg.PSP-3]
+ b = mem[reg.PSP-2]
+ pushPS(a)
+ pushPS(b)
+ return NEXT
+end)
+
+QDUP_CFA = defPrimWord("?DUP", () -> begin
+ ensurePSDepth(1)
+ val = mem[reg.PSP]
+ if val != 0
+ pushPS(val)
+ end
+ return NEXT
+end)
+
+INCR_CFA = defPrimWord("1+", () -> begin
+ ensurePSDepth(1)
+ mem[reg.PSP] += 1
+ return NEXT
+end)
+
+DECR_CFA = defPrimWord("1-", () -> begin
+ ensurePSDepth(1)
+ mem[reg.PSP] -= 1
+ return NEXT
+end)
+
+INCR2_CFA = defPrimWord("2+", () -> begin
+ ensurePSDepth(1)
+ mem[reg.PSP] += 2
+ return NEXT
+end)
+
+DECR2_CFA = defPrimWord("2-", () -> begin
+ ensurePSDepth(1)
+ mem[reg.PSP] -= 2
+ return NEXT
+end)
+
+ADD_CFA = defPrimWord("+", () -> begin
+ b = popPS()
+ a = popPS()
+ pushPS(a+b)
+ return NEXT
+end)
+
+SUB_CFA = defPrimWord("-", () -> begin
+ b = popPS()
+ a = popPS()
+ pushPS(a-b)
+ return NEXT
+end)
+
+MUL_CFA = defPrimWord("*", () -> begin
+ b = popPS()
+ a = popPS()
+ pushPS(a*b)
+ return NEXT
+end)
+
+DIVMOD_CFA = defPrimWord("/MOD", () -> begin
+ b = popPS()
+ a = popPS()
+ q,r = divrem(a,b)
+ pushPS(r)
+ pushPS(q)
+ return NEXT
+end)
+
+TWOMUL_CFA = defPrimWord("2*", () -> begin
+ pushPS(popPS() << 1)
+ return NEXT
+end)
+
+TWODIV_CFA = defPrimWord("2/", () -> begin
+ pushPS(popPS() >> 1)
+ return NEXT
+end)
+
+EQ_CFA = defPrimWord("=", () -> begin
+ b = popPS()
+ a = popPS()
+ pushPS(a==b ? -1 : 0)
+ return NEXT
+end)
+
+NE_CFA = defPrimWord("<>", () -> begin
+ b = popPS()
+ a = popPS()
+ pushPS(a!=b ? -1 : 0)
+ return NEXT
+end)
+
+LT_CFA = defPrimWord("<", () -> begin
+ b = popPS()
+ a = popPS()
+ pushPS(a<b ? -1 : 0)
+ return NEXT
+end)
+
+GT_CFA = defPrimWord(">", () -> begin
+ b = popPS()
+ a = popPS()
+ pushPS(a>b ? -1 : 0)
+ return NEXT
+end)
+
+LE_CFA = defPrimWord("<=", () -> begin
+ b = popPS()
+ a = popPS()
+ pushPS(a<=b ? -1 : 0)
+ return NEXT
+end)
+
+GE_CFA = defPrimWord(">=", () -> begin
+ b = popPS()
+ a = popPS()
+ pushPS(a>=b ? -1 : 0)
+ return NEXT
+end)
+
+ZE_CFA = defPrimWord("0=", () -> begin
+ pushPS(popPS() == 0 ? -1 : 0)
+ return NEXT
+end)
+
+ZNE_CFA = defPrimWord("0<>", () -> begin
+ pushPS(popPS() != 0 ? -1 : 0)
+ return NEXT
+end)
+
+ZLT_CFA = defPrimWord("0<", () -> begin
+ pushPS(popPS() < 0 ? -1 : 0)
+ return NEXT
+end)
+
+ZGT_CFA = defPrimWord("0>", () -> begin
+ pushPS(popPS() > 0 ? -1 : 0)
+ return NEXT
+end)
+
+ZLE_CFA = defPrimWord("0<=", () -> begin
+ pushPS(popPS() <= 0 ? -1 : 0)
+ return NEXT
+end)
+
+ZGE_CFA = defPrimWord("0>=", () -> begin
+ pushPS(popPS() >= 0 ? -1 : 0)
+ return NEXT
+end)
+
+AND_CFA = defPrimWord("AND", () -> begin
+ b = popPS()
+ a = popPS()
+ pushPS(a & b)
+ return NEXT
+end)
+
+OR_CFA = defPrimWord("OR", () -> begin
+ b = popPS()
+ a = popPS()
+ pushPS(a | b)
+ return NEXT
+end)
+
+XOR_CFA = defPrimWord("XOR", () -> begin
+ b = popPS()
+ a = popPS()
+ pushPS(a $ b)
+ return NEXT
+end)
+
+INVERT_CFA = defPrimWord("INVERT", () -> begin
+ pushPS(~popPS())
+ return NEXT
+end)
+
+# Literals
+
+LIT_CFA = defPrimWord("LIT", () -> begin
+ pushPS(mem[reg.IP])
+ reg.IP += 1
+ return NEXT
+end)
+
+# Memory primitives
+
+STORE_CFA = defPrimWord("!", () -> begin
+ addr = popPS()
+ dat = popPS()
+ mem[addr] = dat
+ return NEXT
+end)
+
+FETCH_CFA = defPrimWord("@", () -> begin
+ addr = popPS()
+ pushPS(mem[addr])
+ return NEXT
+end)
+
+ADDSTORE_CFA = defPrimWord("+!", () -> begin
+ addr = popPS()
+ toAdd = popPS()
+ mem[addr] += toAdd
+ return NEXT
+end)
+
+SUBSTORE_CFA = defPrimWord("-!", () -> begin
+ addr = popPS()
+ toSub = popPS()
+ mem[addr] -= toSub
+ return NEXT
+end)
+
+
+# Return Stack
+
+TOR_CFA = defPrimWord(">R", () -> begin
+ pushRS(popPS())
+ return NEXT
+end)
+
+FROMR_CFA = defPrimWord("R>", () -> begin
+ pushPS(popRS())
+ return NEXT
+end)
+
+RFETCH_CFA = defPrimWord("R@", () -> begin
+ pushPS(mem[reg.RSP])
+ return NEXT
+end)
+
+RSPFETCH_CFA = defPrimWord("RSP@", () -> begin
+ pushPS(reg.RSP)
+ return NEXT
+end)
+
+RSPSTORE_CFA = defPrimWord("RSP!", () -> begin
+ reg.RSP = popPS()
+ return NEXT
+end)
+
+RDROP_CFA = defPrimWord("RDROP", () -> begin
+ popRS()
+ return NEXT
+end)
+
+# Parameter Stack
+
+PSPFETCH_CFA = defPrimWord("PSP@", () -> begin
+ pushPS(reg.PSP)
+ return NEXT
+end)
+
+PSPSTORE_CFA = defPrimWord("PSP!", () -> begin
+ reg.PSP = popPS()
+ return NEXT
+end)
+
+# Working Register
+
+WFETCH_CFA = defPrimWord("W@", () -> begin
+ pushPS(reg.W)
+ return NEXT
+end)
+
+WSTORE_CFA = defPrimWord("W!", () -> begin
+ reg.W = popPS()
+ return NEXT
+end)
+
+# I/O
+
+sources = Array{Any,1}()
+currentSource() = sources[length(sources)]
+
+EOF_CFA = defPrimWord("\x04", () -> begin
+ if currentSource() != STDIN
+ close(pop!(sources))
+ return NEXT
+ else
+ return 0
+ end
+end)
+
+EMIT_CFA = defPrimWord("EMIT", () -> begin
+ print(Char(popPS()))
+ return NEXT
+end)
+
+function raw_mode!(mode::Bool)
+ if ccall(:jl_tty_set_mode, Int32, (Ptr{Void}, Int32), STDIN.handle, mode) != 0
+ throw("FATAL: Terminal unable to enter raw mode.")
+ end