3 import Base.REPLCompletions
6 size_mem = 1000000 # 1 mega-int
9 size_RS = 1000 # Return stack size
10 size_PS = 1000 # Parameter stack size
11 size_TIB = 1000 # Terminal input buffer size
12 size_FIB = 1000 # File input buffer size
15 mem = Array{Int64,1}(size_mem)
16 primitives = Array{Function,1}()
17 primNames = Array{AbstractString,1}()
19 # Memory geography and built-in variables
22 H = nextVarAddr; nextVarAddr += 1 # Next free memory address
23 FORTH_LATEST = nextVarAddr; nextVarAddr += 1 # FORTH dict latest
24 CURRENT = nextVarAddr; nextVarAddr += 1 # Current compilation dict
26 RSP0 = nextVarAddr # bottom of RS
27 PSP0 = RSP0 + size_RS # bottom of PS
28 TIB = PSP0 + size_PS # address of terminal input buffer
29 FIB = TIB + size_TIB # address of terminal input buffer
30 mem[H] = FIB + size_FIB # location of bottom of dictionary
31 mem[FORTH_LATEST] = 0 # zero FORTH dict latest (no previous def)
32 mem[CURRENT] = FORTH_LATEST-1 # Compile words to system dict initially
34 DICT = mem[H] # Save bottom of dictionary as constant
38 RSP::Int64 # Return stack pointer
39 PSP::Int64 # Parameter/data stack pointer
40 IP::Int64 # Instruction pointer
41 W::Int64 # Working register
43 reg = Reg(RSP0, PSP0, 0, 0)
45 # Stack manipulation functions
47 function ensurePSDepth(depth::Int64)
48 if reg.PSP - PSP0 < depth
49 error("Parameter stack underflow.")
53 function ensurePSCapacity(toAdd::Int64)
54 if reg.PSP + toAdd >= PSP0 + size_PS
55 error("Parameter stack overflow.")
59 function ensureRSDepth(depth::Int64)
60 if reg.RSP - RSP0 < depth
61 error("Return stack underflow.")
65 function ensureRSCapacity(toAdd::Int64)
66 if reg.RSP + toAdd >= RSP0 + size_RS
67 error("Return stack overflow.")
71 function pushRS(val::Int64)
84 function pushPS(val::Int64)
87 mem[reg.PSP += 1] = val
98 # Handy functions for adding/retrieving strings to/from memory.
100 getString(addr::Int64, len::Int64) = AbstractString([Char(c) for c in mem[addr:(addr+len-1)]])
102 function putString(str::AbstractString, addr::Int64, maxLen::Int64)
103 len = min(length(str), maxLen)
104 mem[addr:(addr+len-1)] = [Int64(c) for c in str]
107 stringAsInts(str::AbstractString) = [Int(c) for c in collect(str)]
109 # Primitive creation and calling functions
111 function defPrim(f::Function; name="nameless")
113 push!(primNames, replace(name, "\004", "EOF"))
115 return -length(primitives)
118 function callPrim(addr::Int64)
119 if addr >=0 || -addr>length(primitives)
120 error("Attempted to execute non-existent primitive at address $addr.")
125 getPrimName(addr::Int64) = primNames[-addr]
127 # Word creation functions
134 function dictWrite(ints::Array{Int64,1})
135 mem[mem[H]:(mem[H]+length(ints)-1)] = ints
136 mem[H] += length(ints)
138 dictWrite(int::Int64) = dictWrite([int])
139 dictWriteString(string::AbstractString) = dictWrite([Int64(c) for c in string])
141 function createHeader(name::AbstractString, flags::Int64)
142 mem[mem[H]] = mem[mem[CURRENT]+1]
143 mem[mem[CURRENT]+1] = mem[H]
146 dictWrite(length(name) | flags | NFA_MARK)
147 dictWriteString(name)
150 function defPrimWord(name::AbstractString, f::Function; flags::Int64=0)
151 createHeader(name, flags)
153 codeWordAddr = mem[H]
154 dictWrite(defPrim(f, name=name))
159 function defWord(name::AbstractString, wordAddrs::Array{Int64,1}; flags::Int64=0)
160 createHeader(name, flags)
170 # Variable creation functions
172 function defExistingVar(name::AbstractString, varAddr::Int64; flags::Int64=0)
174 defPrimWord(name, eval(:(() -> begin
180 function defNewVar(name::AbstractString, initial::Array{Int64,1}; flags::Int64=0)
181 createHeader(name, flags)
183 codeWordAddr = mem[H]
189 return varAddr, codeWordAddr
192 defNewVar(name::AbstractString, initial::Int64; flags::Int64=0) =
193 defNewVar(name, [initial]; flags=flags)
195 function defConst(name::AbstractString, val::Int64; flags::Int64=0)
196 createHeader(name, flags)
198 codeWordAddr = mem[H]
206 # Threading Primitives (inner interpreter)
208 NEXT = defPrim(() -> begin
214 DOCOL = defPrim(() -> begin
220 DOVAR = defPrim(() -> begin
225 DOCON = defPrim(() -> begin
226 pushPS(mem[reg.W + 1])
230 EXIT_CFA = defPrimWord("EXIT", () -> begin
235 # Dictionary entries for core built-in variables, constants
237 H_CFA = defExistingVar("H", H)
239 PSP0_CFA = defConst("PSP0", PSP0)
240 RSP0_CFA = defConst("RSP0", RSP0)
242 defConst("DOCOL", DOCOL)
243 defConst("DOCON", DOCON)
244 defConst("DOVAR", DOVAR)
246 defConst("DICT", DICT)
247 defConst("MEMSIZE", size_mem)
249 F_IMMED_CFA = defConst("F_IMMED", F_IMMED)
250 F_HIDDEN_CFA = defConst("F_HIDDEN", F_HIDDEN)
251 F_LENMASK_CFA = defConst("F_LENMASK", F_LENMASK)
252 NFA_MARK_CFA = defConst("NFA_MARK", NFA_MARK)
254 # Basic forth primitives
256 DROP_CFA = defPrimWord("DROP", () -> begin
261 SWAP_CFA = defPrimWord("SWAP", () -> begin
269 DUP_CFA = defPrimWord("DUP", () -> begin
275 OVER_CFA = defPrimWord("OVER", () -> begin
277 pushPS(mem[reg.PSP-1])
281 ROT_CFA = defPrimWord("ROT", () -> begin
291 NROT_CFA = defPrimWord("-ROT", () -> begin
302 TWODROP_CFA = defPrimWord("2DROP", () -> begin
308 TWODUP_CFA = defPrimWord("2DUP", () -> begin
317 TWOSWAP_CFA = defPrimWord("2SWAP", () -> begin
329 TWOOVER_CFA = defPrimWord("2OVER", () -> begin
338 QDUP_CFA = defPrimWord("?DUP", () -> begin
347 INCR_CFA = defPrimWord("1+", () -> begin
353 DECR_CFA = defPrimWord("1-", () -> begin
359 INCR2_CFA = defPrimWord("2+", () -> begin
365 DECR2_CFA = defPrimWord("2-", () -> begin
371 ADD_CFA = defPrimWord("+", () -> begin
378 SUB_CFA = defPrimWord("-", () -> begin
385 MUL_CFA = defPrimWord("*", () -> begin
392 DIVMOD_CFA = defPrimWord("/MOD", () -> begin
401 TWOMUL_CFA = defPrimWord("2*", () -> begin
406 TWODIV_CFA = defPrimWord("2/", () -> begin
411 EQ_CFA = defPrimWord("=", () -> begin
414 pushPS(a==b ? -1 : 0)
418 NE_CFA = defPrimWord("<>", () -> begin
421 pushPS(a!=b ? -1 : 0)
425 LT_CFA = defPrimWord("<", () -> begin
432 GT_CFA = defPrimWord(">", () -> begin
439 LE_CFA = defPrimWord("<=", () -> begin
442 pushPS(a<=b ? -1 : 0)
446 GE_CFA = defPrimWord(">=", () -> begin
449 pushPS(a>=b ? -1 : 0)
453 ZE_CFA = defPrimWord("0=", () -> begin
454 pushPS(popPS() == 0 ? -1 : 0)
458 ZNE_CFA = defPrimWord("0<>", () -> begin
459 pushPS(popPS() != 0 ? -1 : 0)
463 ZLT_CFA = defPrimWord("0<", () -> begin
464 pushPS(popPS() < 0 ? -1 : 0)
468 ZGT_CFA = defPrimWord("0>", () -> begin
469 pushPS(popPS() > 0 ? -1 : 0)
473 ZLE_CFA = defPrimWord("0<=", () -> begin
474 pushPS(popPS() <= 0 ? -1 : 0)
478 ZGE_CFA = defPrimWord("0>=", () -> begin
479 pushPS(popPS() >= 0 ? -1 : 0)
483 AND_CFA = defPrimWord("AND", () -> begin
490 OR_CFA = defPrimWord("OR", () -> begin
497 XOR_CFA = defPrimWord("XOR", () -> begin
504 INVERT_CFA = defPrimWord("INVERT", () -> begin
511 LIT_CFA = defPrimWord("LIT", () -> begin
519 STORE_CFA = defPrimWord("!", () -> begin
526 FETCH_CFA = defPrimWord("@", () -> begin
532 ADDSTORE_CFA = defPrimWord("+!", () -> begin
539 SUBSTORE_CFA = defPrimWord("-!", () -> begin
549 TOR_CFA = defPrimWord(">R", () -> begin
554 FROMR_CFA = defPrimWord("R>", () -> begin
559 RFETCH_CFA = defPrimWord("R@", () -> begin
564 RSPFETCH_CFA = defPrimWord("RSP@", () -> begin
569 RSPSTORE_CFA = defPrimWord("RSP!", () -> begin
574 RDROP_CFA = defPrimWord("RDROP", () -> begin
581 PSPFETCH_CFA = defPrimWord("PSP@", () -> begin
586 PSPSTORE_CFA = defPrimWord("PSP!", () -> begin
593 WFETCH_CFA = defPrimWord("W@", () -> begin
598 WSTORE_CFA = defPrimWord("W!", () -> begin
605 openFiles = Dict{Int64,IOStream}()
612 FAM_RO_CFA = defConst("R/O", FAM_RO)
613 FAM_WO_CFA = defConst("W/O", FAM_WO)
615 function fileOpener(create::Bool)
620 fname = getString(fnameAddr, fnameLen)
622 if create && !isfile(fname)
634 openFiles[nextFileID] = open(fname, mode)
641 OPEN_FILE_CFA = defPrimWord("OPEN-FILE", () -> begin
646 CREATE_FILE_CFA = defPrimWord("CREATE-FILE", () -> begin
651 CLOSE_FILE_CFA = defPrimWord("CLOSE-FILE", () -> begin
653 close(openFiles[fid])
654 delete!(openFiles, fid)
658 CLOSE_FILES_CFA = defPrimWord("CLOSE-FILES", () -> begin
659 for fh in values(openFiles)
667 READ_LINE_CFA = defPrimWord("READ-LINE", () -> begin
675 eofFlag = endswith(line, '\n') ? 0 : -1
678 putString(line, addr, maxSize)
688 EMIT_CFA = defPrimWord("EMIT", () -> begin
693 function raw_mode!(mode::Bool)
694 if ccall(:jl_tty_set_mode, Int32, (Ptr{Void}, Int32), STDIN.handle, mode) != 0
695 throw("FATAL: Terminal unable to enter raw mode.")
701 byte = readbytes(STDIN, 1)[1]
713 KEY_CFA = defPrimWord("KEY", () -> begin
714 pushPS(Int(getKey()))
718 function getLineFromSTDIN()
722 slashIdx = findlast(chars, '\\')
725 return join(chars[slashIdx:length(chars)])
731 function backspaceStr(s, bsCount)
733 newLen = max(0, oldLen - bsCount)
734 return join(collect(s)[1:newLen])
743 return AbstractString(line)
747 return string("\x04")
753 line = backspaceStr(line, 1)
757 # Strip ANSI escape sequence
758 nextKey = Char(getKey())
761 nextKey = Char(getKey())
762 if nextKey >= '@' || nextKey <= '~'
769 # Currently do nothing
773 if haskey(REPLCompletions.latex_symbols, frag)
774 print(repeat("\b", length(frag)))
776 comp = REPLCompletions.latex_symbols[frag]
777 line = string(backspaceStr(line, length(frag)), comp)
784 line = string(line, key)
789 SPAN, SPAN_CFA = defNewVar("SPAN", 0)
790 EXPECT_CFA = defPrimWord("EXPECT", () -> begin
794 line = getLineFromSTDIN()
796 mem[SPAN] = min(length(line), maxLen)
797 putString(line, addr, maxLen)
802 BASE, BASE_CFA = defNewVar("BASE", 10)
803 NUMBER_CFA = defPrimWord("NUMBER", () -> begin
805 wordLen = mem[wordAddr-1]
807 s = getString(wordAddr, wordLen)
809 pushPS(parse(Int64, s, mem[BASE]))
814 # Dictionary searches
816 FROMLINK_CFA = defPrimWord("LINK>", () -> begin
819 lenAndFlags = mem[addr+1]
820 len = lenAndFlags & F_LENMASK
822 pushPS(addr + 2 + len)
827 NUMCONTEXT, NUMCONTEXT_CFA = defNewVar("#CONTEXT", 1)
829 createHeader("FORTH", 0)
831 dictWrite(defPrim(() -> begin
832 mem[CONTEXT + mem[NUMCONTEXT] - 1] = reg.W
835 dictWrite(0) # cell for latest
837 CURRENT_CFA = defExistingVar("CURRENT", CURRENT)
839 # Switch to new FORTH vocabulary cfa
840 mem[FORTH_CFA+1] = mem[mem[CURRENT]+1]
841 mem[CURRENT] = FORTH_CFA
843 CONTEXT, CONTEXT_CFA = defNewVar("CONTEXT", zeros(Int64, 10))
844 mem[CONTEXT] = FORTH_CFA
846 FINDVOCAB_CFA = defPrimWord("FINDVOCAB", () -> begin
848 countedAddr = popPS()
850 wordAddr = countedAddr + 1
851 wordLen = mem[countedAddr]
852 word = lowercase(getString(wordAddr, wordLen))
857 while (lfa = mem[lfa]) > 0
859 lenAndFlags = mem[lfa+1]
860 len = lenAndFlags & F_LENMASK
861 hidden = (lenAndFlags & F_HIDDEN) == F_HIDDEN
863 if hidden || len != wordLen
867 thisWord = lowercase(getString(lfa+2, len))
876 callPrim(mem[FROMLINK_CFA])
877 if (lenAndFlags & F_IMMED) == F_IMMED
890 FIND_CFA = defPrimWord("FIND", () -> begin
892 countedAddr = popPS()
893 context = mem[CONTEXT:(CONTEXT+mem[NUMCONTEXT]-1)]
895 for vocabCFA in reverse(context)
898 callPrim(mem[FINDVOCAB_CFA])
900 callPrim(mem[DUP_CFA])
918 BRANCH_CFA = defPrimWord("BRANCH", () -> begin
919 reg.IP += mem[reg.IP]
923 ZBRANCH_CFA = defPrimWord("0BRANCH", () -> begin
925 reg.IP += mem[reg.IP]
935 LITSTRING_CFA = defPrimWord("LITSTRING", () -> begin
945 TYPE_CFA = defPrimWord("TYPE", () -> begin
948 str = getString(addr, len)
953 # Interpreter/Compiler-specific I/O
955 TIB_CFA = defConst("TIB", TIB)
956 NUMTIB, NUMTIB_CFA = defNewVar("#TIB", 0)
958 FIB_CFA = defConst("FIB", TIB)
959 NUMFIB, NUMFIB_CFA = defNewVar("#FIB", 0)
961 TOIN, TOIN_CFA = defNewVar(">IN", 0)
963 SOURCE_ID, SOURCE_ID_CFA = defNewVar("SOURCE-ID", 0)
965 SOURCE_CFA = defPrimWord("SOURCE", () -> begin
966 if mem[SOURCE_ID] == 0
976 QUERY_CFA = defWord("QUERY",
977 [TIB_CFA, LIT_CFA, 160, EXPECT_CFA,
978 SPAN_CFA, FETCH_CFA, NUMTIB_CFA, STORE_CFA,
979 LIT_CFA, 0, TOIN_CFA, STORE_CFA,
982 QUERY_FILE_CFA = defWord("QUERY-FILE",
983 [FIB_CFA, LIT_CFA, 160, ROT_CFA, READ_LINE_CFA,
985 NUMFIB_CFA, STORE_CFA,
988 WORD_CFA = defPrimWord("WORD", () -> begin
991 callPrim(mem[SOURCE_CFA])
995 # Chew up initial occurrences of delim
996 while (mem[TOIN]<mem[sizeAddr] && mem[bufferAddr+mem[TOIN]] == delim)
1003 # Start reading in word
1005 while (mem[TOIN]<mem[sizeAddr])
1006 mem[addr] = mem[bufferAddr+mem[TOIN]]
1009 if (mem[addr] == delim)
1018 mem[countAddr] = count
1026 STATE, STATE_CFA = defNewVar("STATE", 0)
1028 COMMA_CFA = defPrimWord(",", () -> begin
1029 mem[mem[H]] = popPS()
1035 HERE_CFA = defWord("HERE",
1036 [H_CFA, FETCH_CFA, EXIT_CFA])
1038 HEADER_CFA = defPrimWord("HEADER", () -> begin
1039 wordAddr = popPS()+1
1040 wordLen = mem[wordAddr-1]
1041 word = getString(wordAddr, wordLen)
1043 createHeader(word, 0)
1048 CREATE_CFA = defWord("CREATE",
1049 [LIT_CFA, 32, WORD_CFA, HEADER_CFA,
1050 LIT_CFA, DOVAR, COMMA_CFA,
1053 DODOES = defPrim(() -> begin
1060 DOES_HELPER_CFA = defPrimWord("(DOES>)", () -> begin
1062 pushPS(mem[mem[CURRENT]+1])
1063 callPrim(mem[FROMLINK_CFA])
1066 runtimeAddr = popPS()
1068 mem[cfa] = defPrim(eval(:(() -> begin
1069 pushPS($(runtimeAddr))
1071 end)), name="doesPrim")
1074 end, flags=F_IMMED | F_HIDDEN)
1076 DOES_CFA = defWord("DOES>",
1077 [LIT_CFA, LIT_CFA, COMMA_CFA, HERE_CFA, LIT_CFA, 3, ADD_CFA, COMMA_CFA,
1078 LIT_CFA, DOES_HELPER_CFA, COMMA_CFA, LIT_CFA, EXIT_CFA, COMMA_CFA, EXIT_CFA],
1081 LBRAC_CFA = defPrimWord("[", () -> begin
1086 RBRAC_CFA = defPrimWord("]", () -> begin
1091 HIDDEN_CFA = defPrimWord("HIDDEN", () -> begin
1092 lenAndFlagsAddr = mem[mem[CURRENT]+1] + 1
1093 mem[lenAndFlagsAddr] = mem[lenAndFlagsAddr] $ F_HIDDEN
1097 COLON_CFA = defWord(":",
1098 [LIT_CFA, 32, WORD_CFA,
1100 LIT_CFA, DOCOL, COMMA_CFA,
1105 SEMICOLON_CFA = defWord(";",
1106 [LIT_CFA, EXIT_CFA, COMMA_CFA,
1109 EXIT_CFA], flags=F_IMMED)
1111 IMMEDIATE_CFA = defPrimWord("IMMEDIATE", () -> begin
1112 lenAndFlagsAddr = mem[mem[CURRENT]+1] + 1
1113 mem[lenAndFlagsAddr] = mem[lenAndFlagsAddr] $ F_IMMED
1117 CODE_CFA = defPrimWord("CODE", () -> begin
1119 callPrim(mem[WORD_CFA])
1120 callPrim(mem[HEADER_CFA])
1122 exprString = "() -> begin\n"
1124 if mem[TOIN] >= mem[NUMTIB]
1125 exprString = string(exprString, "\n")
1126 if currentSource() == STDIN
1132 callPrim(mem[EXPECT_CFA])
1133 mem[NUMTIB] = mem[SPAN]
1138 callPrim(mem[WORD_CFA])
1140 thisWord = getString(cAddr+1, mem[cAddr])
1142 if uppercase(thisWord) == "END-CODE"
1146 exprString = string(exprString, " ", thisWord)
1148 exprString = string(exprString, "\nreturn NEXT\nend")
1150 func = eval(parse(exprString))
1151 dictWrite(defPrim(func))
1158 EXECUTE_CFA = defPrimWord("EXECUTE", () -> begin
1163 INTERPRET_CFA = defWord("INTERPRET",
1164 [LIT_CFA, 32, WORD_CFA, # Read next space-delimited word
1166 DUP_CFA, FETCH_CFA, ZE_CFA, ZBRANCH_CFA, 3,
1167 DROP_CFA, EXIT_CFA, # Exit if input buffer is exhausted
1169 STATE_CFA, FETCH_CFA, ZBRANCH_CFA, 24,
1171 FIND_CFA, QDUP_CFA, ZBRANCH_CFA, 13,
1174 LIT_CFA, -1, EQ_CFA, INVERT_CFA, ZBRANCH_CFA, 4,
1176 # Immediate: Execute!
1177 EXECUTE_CFA, BRANCH_CFA, -26,
1179 # Not immediate: Compile!
1180 COMMA_CFA, BRANCH_CFA, -29,
1182 # No word found, parse number
1183 NUMBER_CFA, LIT_CFA, LIT_CFA, COMMA_CFA, COMMA_CFA, BRANCH_CFA, -36,
1186 FIND_CFA, QDUP_CFA, ZBRANCH_CFA, 5,
1188 # Found word. Execute!
1189 DROP_CFA, EXECUTE_CFA, BRANCH_CFA, -44,
1191 # No word found, parse number and leave on stack
1192 NUMBER_CFA, BRANCH_CFA, -47,
1195 PROMPT_CFA = defPrimWord("PROMPT", () -> begin
1204 QUIT_CFA = defWord("QUIT",
1205 [LIT_CFA, 0, STATE_CFA, STORE_CFA,
1206 LIT_CFA, 0, NUMTIB_CFA, STORE_CFA,
1207 RSP0_CFA, RSPSTORE_CFA,
1209 INTERPRET_CFA, PROMPT_CFA,
1212 INTERPRET_CFA = defWord("INTERPRET",
1213 [SOURCE_ID_CFA, FETCH_CFA, TOR_CFA, # Store current source on return stack
1215 LIT_CFA, 32, WORD_CFA, # Read next word from current input source
1217 FAM_RO_CFA, OPEN_FILE_CFA, DROP_CFA, # Open the file named by this word.
1219 DUP_CFA, SOURCE_ID_CFA, STORE_CFA, # Mark this as the current source
1221 DUP_CFA, QUERY_FILE_CFA, # Read line from file
1228 ABORT_CFA = defWord("ABORT",
1229 [CLOSE_FILES_CFA, PSP0_CFA, PSPSTORE_CFA, QUIT_CFA])
1231 BYE_CFA = defPrimWord("BYE", () -> begin
1236 EOF_CFA = defPrimWord("\x04", () -> begin
1243 initFileName = nothing
1244 if isfile("lib.4th")
1245 initFileName = "lib.4th"
1246 elseif isfile(Pkg.dir("forth","src", "lib.4th"))
1247 initFileName = Pkg.dir("forth","src","lib.4th")
1250 function run(;initialize=true)
1252 # Start with IP pointing to first instruction of outer interpreter
1255 # Load library files
1256 global initialized, initFileName
1257 if !initialized && initialize
1258 if initFileName != nothing
1259 print("Including definitions from $initFileName...")
1265 println("No library file found. Only primitive words available.")
1270 # Primitive processing loop.
1271 # Everyting else is simply a consequence of this loop!
1275 #println("Entering prim $(getPrimName(jmp))")
1279 showerror(STDOUT, ex)
1283 reg.IP = ABORT_CFA + 1
1291 TRACE_CFA = defPrimWord("TRACE", () -> begin
1292 println("reg.W: $(reg.W) reg.IP: $(reg.IP)")
1293 print("PS: "); printPS()
1294 print("RS: "); printRS()
1301 function dump(startAddr::Int64; count::Int64 = 100, cellsPerLine::Int64 = 10)
1302 chars = Array{Char,1}(cellsPerLine)
1304 lineStartAddr = cellsPerLine*div((startAddr-1),cellsPerLine) + 1
1305 endAddr = startAddr + count - 1
1307 q, r = divrem((endAddr-lineStartAddr+1), cellsPerLine)
1308 numLines = q + (r > 0 ? 1 : 0)
1314 for c in 1:cellsPerLine
1315 if i >= startAddr && i <= endAddr
1317 if mem[i]>=32 && mem[i]<128
1318 chars[c] = Char(mem[i])
1330 println("\t", AbstractString(chars))
1335 count = reg.PSP - PSP0
1339 for i in (PSP0+1):reg.PSP
1344 println("Parameter stack empty")
1349 count = reg.RSP - RSP0
1353 for i in (RSP0+1):reg.RSP
1358 println("Return stack empty")
1362 DUMP = defPrimWord("DUMP", () -> begin
1367 dump(addr, count=count)