+RSPSTORE = defPrim("RSP!", () -> begin
+ RSP = popPS()
+ return NEXT
+end)
+
+RDROP = defPrim("RDROP", () -> begin
+ popRS()
+ return NEXT
+end)
+
+# Parameter Stack
+
+PSPFETCH = defPrim("PSP@", () -> begin
+ pushPS(reg.PSP)
+ return NEXT
+end)
+
+PSPSTORE = defPrim("PSP!", () -> begin
+ PSP = popPS()
+ return NEXT
+end)
+
+# I/O
+
+defConst("TIB", TIB)
+NUMTIB = defNewVar("#TIB", 0)
+TOIN = defNewVar(">IN", 0)
+
+KEY = defPrim("KEY", () -> begin
+ if mem[TOIN] >= mem[NUMTIB]
+ mem[TOIN] = 0
+ line = readline()
+ mem[NUMTIB] = length(line)
+ mem[TIB:(TIB+mem[NUMTIB]-1)] = [Int64(c) for c in collect(line)]
+ end
+
+ pushPS(mem[TIB + mem[TOIN]])
+ mem[TOIN] += 1
+
+ return NEXT
+end)
+
+EMIT = defPrim("EMIT", () -> begin
+ print(Char(popPS()))
+ return NEXT
+end)
+
+WORD = defPrim("WORD", () -> begin
+
+ c = -1
+
+ skip_to_end = false
+ while true
+
+ callPrim(KEY)
+ c = Char(popPS())
+
+ if c == '\\'
+ skip_to_end = true
+ continue
+ end
+
+ if skip_to_end
+ if c == '\n'
+ skip_to_end = false
+ end
+ continue
+ end
+
+ if c == ' ' || c == '\t'
+ continue
+ end
+
+ break
+ end
+
+ wordAddr = mem[HERE]
+ offset = 0
+
+ while true
+ mem[wordAddr + offset] = Int64(c)
+ offset += 1
+
+ callPrim(KEY)
+ c = Char(popPS())
+
+ if c == ' ' || c == '\t' || c == '\n'
+ break
+ end
+ end
+
+ wordLen = offset
+
+ pushPS(wordAddr)
+ pushPS(wordLen)
+
+ return NEXT
+end)
+
+NUMBER = defPrim("NUMBER", () -> begin
+
+ wordLen = popPS()
+ wordAddr = popPS()
+
+ s = ASCIIString([Char(c) for c in mem[wordAddr:(wordAddr+wordLen-1)]])
+
+ try
+ pushPS(parse(Int64, s, mem[BASE]))
+ pushPS(0)
+ catch
+ pushPS(1) # Error indication
+ end
+
+ return NEXT
+end)
+
+# Dictionary searches
+
+FIND = defPrim("FIND", () -> begin
+
+ wordLen = popPS()
+ wordAddr = popPS()
+ word = ASCIIString([Char(c) for c in mem[wordAddr:(wordAddr+wordLen-1)]])
+
+ latest = mem[LATEST]
+
+ while latest>0
+ lenAndFlags = mem[latest+1]
+ len = lenAndFlags & F_LENMASK
+ hidden = (lenAndFlags & F_HIDDEN) == F_HIDDEN
+
+ if hidden || len != wordLen
+ latest = mem[latest]
+ continue
+ end
+
+ thisAddr = latest+2
+ thisWord = ASCIIString([Char(c) for c in mem[thisAddr:(thisAddr+len-1)]])
+
+ if thisWord == word
+ break
+ end
+ end
+
+ pushPS(latest)
+
+ return NEXT
+end)
+
+TOCFA = defPrim(">CFA", () -> begin
+
+ addr = popPS()
+ lenAndFlags = mem[addr+1]
+ len = lenAndFlags & F_LENMASK
+
+ pushPS(addr + 2 + len)
+
+ return NEXT
+end)
+
+TODFA = defWord(">DFA", [TOCFA, INCR1, EXIT])
+
+#### VM loop ####
+#function runVM(reg::Reg)
+# jmp = NEXT
+# while (jmp = callPrim(reg, jmp)) != 0 end
+#end
+
+# Debugging tools
+
+function coredump(startAddr::Int64; count::Int64 = 16, cellsPerLine::Int64 = 8)
+ chars = Array{Char,1}(cellsPerLine)
+
+ for i in 0:(count-1)
+ addr = startAddr + i
+ if i%cellsPerLine == 0
+ print("$addr:")
+ end
+
+ print("\t$(mem[addr]) ")
+
+ if (mem[addr]>=32 && mem[addr]<176)
+ chars[i%cellsPerLine + 1] = Char(mem[addr])
+ else
+ chars[i%cellsPerLine + 1] = '.'
+ end
+
+ if i%cellsPerLine == cellsPerLine-1
+ println(string("\t", ASCIIString(chars)))
+ end
+ end
+end
+
+function printPS()
+ count = reg.PSP - mem[PSP0]
+
+ if count > 0
+ print("<$count>")
+ for i in (mem[PSP0]+1):reg.PSP
+ print(" $(mem[i])")
+ end
+ println()
+ else
+ println("Parameter stack empty")
+ end
+end