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 # memory = +-----------------------+
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
36 # the dictionary. Additionally, all
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 memory = Array{Int64,1}(size_memory)
43 primitives = Array{Function,1}()
48 RSP0 = nextVarAddr; nextVarAddr += 1
49 PSP0 = nextVarAddr; nextVarAddr += 1
50 HERE = nextVarAddr; nextVarAddr += 1
51 LATEST = nextVarAddr; nextVarAddr += 1
53 memory[RSP0] = size_BIVar # bottom of RS
54 memory[PSP0] = memory[RSP0] + size_RS # bottom of PS
55 TIB = memory[PSP0] + size_PS # address of terminal input buffer
56 memory[HERE] = TIB + size_TIB # location of bottom of dictionary
57 memory[LATEST] = 0 # no previous definition
60 # Stack manipulation functions
62 function pushRS(reg::Reg, val::Int64)
63 memory[reg.RSP+=1] = val
66 function popRS(reg::Reg)
72 function pushPS(reg::Reg, val::Int64)
73 memory[reg.PSP += 1] = val
76 function popPS(reg::Reg)
82 # Primitive creation and calling functions
84 function defPrim(name::AbstractString, f::Function)
91 memory[here] = length(name); here += 1
92 memory[here:(here+length(name)-1)] = [Int(c) for c in name]; here += length(name)
95 memory[here] = -length(primitives)
98 return -length(primitives)
101 callPrim(reg::Reg, addr::Int64) = primitives[-addr](reg)
103 function defSysVar(name::AbstractString, varAddr::Int64)
106 memory[here] = latest
110 memory[here] = length(name); here += 1
111 memory[here:(here+length(name)-1)] = [Int(c) for c in name]; here += length(name)
113 push!(primitives, eval(:((reg::Reg) -> begin
114 pushPS(reg, $(varAddr))
117 memory[here] = -length(primitives)
123 defConst(name::AbstractString, val::Int64) = defSysVar(name, val)
125 # Threading Primitives
127 NEXT = defPrim("NEXT", (reg) -> begin
128 reg.W = memory[reg.IP]
134 DOCOL = defPrim("DOCOL", (reg) -> begin
140 EXIT = defPrim("EXIT", (reg) -> begin
146 # Basic forth primitives
148 DROP = defPrim("DROP", (reg) -> begin
153 SWAP = defPrim("SWAP", (reg) -> begin
154 memory[reg.PSP], memory[reg.PSP-1] = memory[reg.PSP-1], memory[reg.PSP]
158 DUP = defPrim("DUP", (reg) -> begin
159 pushPS(reg, memory[reg.PSP])
163 LIT = defPrim("LIT", (reg) -> begin
164 pushPS(reg, memory[reg.IP])
171 STORE = defPrim("!", (reg) -> begin
178 FETCH = defPrim("@", (reg) -> begin
180 pushPS(reg, memory[addr])
184 ADDSTORE = defPrim("+!", (reg) -> begin
187 memory[addr] += toAdd
191 SUBSTORE = defPrim("-!", (reg) -> begin
194 memory[addr] -= toSub
204 defConst("VERSION", 1)
205 defConst("DOCOL", DOCOL)
209 TOR = defPrim(">R", (reg) -> begin
210 pushRS(reg, popPS(reg))
214 FROMR = defPrim("R>", (reg) -> begin
215 pushPS(reg, popRS(reg))
219 RSPFETCH = defPrim("RSP@", (reg) -> begin
224 RSPSTORE = defPrim("RSP!", (reg) -> begin
229 RDROP = defPrim("RDROP", (reg) -> begin
236 PSPFETCH = defPrim("PSP@", (reg) -> begin
241 PSPSTORE = defPrim("PSP!", (reg) -> begin
249 defVar("#TIB", :numtib)
252 KEY = defPrim("KEY", (reg) -> begin
260 EMIT = defPrim("EMIT", (reg) -> begin
265 WORD = defPrim("WORD", (reg) -> begin
270 NUMBER = defPrim("NUMBER", (reg) -> begin
276 function runVM(reg::Reg)
278 while (jmp = callPrim(reg, jmp)) != 0 end