8 size_RS = 1024 # Return stack size
9 size_PS = 1024 # Parameter stack size
10 size_TIB = 4096 # Terminal input buffer size
14 RSP::Int64 # Return stack pointer
15 PSP::Int64 # Parameter/data stack pointer
16 IP::Int64 # Instruction pointer
17 W::Int64 # Working register
18 X::Int64 # Extra register
21 # The following array constitutes the memory of the VM. It has the following geography:
23 # mem = +-----------------------+
24 # | Built-in Variables |
25 # +-----------------------+
27 # +-----------------------+
29 # +-----------------------+
30 # | Terminal Input Buffer |
31 # +-----------------------+
33 # +-----------------------+
35 # Note that all words (user-defined, primitive, variables, etc) are included in
38 # Simple linear addressing is used with one exception: references to primitive code
39 # blocks, which are represented as anonymous functions, appear the negative index
40 # into the primitives array which contains only these functions.
42 mem = Array{Int64,1}(size_mem)
43 primitives = Array{Function,1}()
48 RSP0 = nextVarAddr; nextVarAddr += 1
49 PSP0 = nextVarAddr; nextVarAddr += 1
50 TIB = nextVarAddr; nextVarAddr += 1
51 HERE = nextVarAddr; nextVarAddr += 1
52 LATEST = nextVarAddr; nextVarAddr += 1
54 mem[RSP0] = size_BIVar # bottom of RS
55 mem[PSP0] = mem[RSP0] + size_RS # bottom of PS
56 mem[TIB] = mem[PSP0] + size_PS # address of terminal input buffer
57 mem[HERE] = mem[TIB] + size_TIB # location of bottom of dictionary
58 mem[LATEST] = 0 # no previous definition
60 # Stack manipulation functions
62 function pushRS(reg::Reg, val::Int64)
66 function popRS(reg::Reg)
72 function pushPS(reg::Reg, val::Int64)
73 mem[reg.PSP += 1] = val
76 function popPS(reg::Reg)
82 # Primitive creation and calling functions
84 function createHeader(name::AbstractString)
85 mem[mem[HERE]] = mem[LATEST]
86 mem[LATEST] = mem[HERE]
89 mem[mem[HERE]] = length(name); mem[HERE] += 1
90 mem[mem[HERE]:(mem[HERE]+length(name)-1)] = [Int(c) for c in name]; mem[HERE] += length(name)
93 function defPrim(name::AbstractString, f::Function)
97 mem[mem[HERE]] = -length(primitives)
100 return -length(primitives)
103 callPrim(reg::Reg, addr::Int64) = primitives[-addr](reg)
105 defExistingVar(name::AbstractString, varAddr::Int64) = defPrim(name, eval(:((reg) -> begin
106 pushPS(reg, $(varAddr))
110 defConst(name::AbstractString, val::Int64) = defPrim(name, eval(:((reg) -> begin
115 function defNewVar(name::AbstractString, initial::Int64)
118 varAddr = mem[HERE] + 1
119 push!(primitives, eval(:((reg) -> begin
120 pushPS(reg, $(varAddr))
123 mem[mem[HERE]] = -length(primitives); mem[HERE] += 1
125 mem[mem[HERE]] = inital; mem[HERE] += 1
130 # Threading Primitives
132 NEXT = defPrim("NEXT", (reg) -> begin
139 DOCOL = defPrim("DOCOL", (reg) -> begin
145 EXIT = defPrim("EXIT", (reg) -> begin
151 # Basic forth primitives
153 DROP = defPrim("DROP", (reg) -> begin
158 SWAP = defPrim("SWAP", (reg) -> begin
159 mem[reg.PSP], mem[reg.PSP-1] = mem[reg.PSP-1], mem[reg.PSP]
163 DUP = defPrim("DUP", (reg) -> begin
164 pushPS(reg, mem[reg.PSP])
168 LIT = defPrim("LIT", (reg) -> begin
169 pushPS(reg, mem[reg.IP])
176 STORE = defPrim("!", (reg) -> begin
183 FETCH = defPrim("@", (reg) -> begin
185 pushPS(reg, mem[addr])
189 ADDSTORE = defPrim("+!", (reg) -> begin
196 SUBSTORE = defPrim("-!", (reg) -> begin
206 defExistingVar("HERE", HERE)
207 defExistingVar("LATEST", LATEST)
208 defExistingVar("PSP0", PSP0)
209 defExistingVar("RSP0", RSP0)
210 defNewVar("STATE", 0)
211 defNewVar("BASE", 10)
215 defConst("VERSION", 1)
216 defConst("DOCOL", DOCOL)
220 TOR = defPrim(">R", (reg) -> begin
221 pushRS(reg, popPS(reg))
225 FROMR = defPrim("R>", (reg) -> begin
226 pushPS(reg, popRS(reg))
230 RSPFETCH = defPrim("RSP@", (reg) -> begin
235 RSPSTORE = defPrim("RSP!", (reg) -> begin
240 RDROP = defPrim("RDROP", (reg) -> begin
247 PSPFETCH = defPrim("PSP@", (reg) -> begin
252 PSPSTORE = defPrim("PSP!", (reg) -> begin
259 #defConst("TIB", tib)
260 #defVar("#TIB", :numtib)
261 #defVar(">IN", :toin)
263 #KEY = defPrim("KEY", (reg) -> begin
271 #EMIT = defPrim("EMIT", (reg) -> begin
276 #WORD = defPrim("WORD", (reg) -> begin
281 #NUMBER = defPrim("NUMBER", (reg) -> begin
287 #function runVM(reg::Reg)
289 # while (jmp = callPrim(reg, jmp)) != 0 end
294 function coredump(startAddr::Int64; count::Int64 = 16, cellsPerLine::Int64 = 8)
295 chars = Array{Char,1}(cellsPerLine)
299 if i%cellsPerLine == 0
303 print("\t$(mem[addr]) ")
305 if (mem[addr]>=32 && mem[addr]<176)
306 chars[i%cellsPerLine + 1] = Char(mem[addr])
308 chars[i%cellsPerLine + 1] = '.'
311 if i%cellsPerLine == cellsPerLine-1
312 println(string("\t", ASCIIString(chars)))