8 size_RS = 1024 # Return stack size
9 size_PS = 1024 # Parameter stack size
10 size_TIB = 4096 # Terminal input buffer size
12 # The mem array constitutes the memory of the VM. It has the following geography:
14 # mem = +-----------------------+
15 # | Built-in Variables |
16 # +-----------------------+
18 # +-----------------------+
20 # +-----------------------+
21 # | Terminal Input Buffer |
22 # +-----------------------+
24 # +-----------------------+
26 # Note that all words (user-defined, primitive, variables, etc) are included in
29 # Simple linear addressing is used with one exception: references to primitive code
30 # blocks, which are represented as anonymous functions, appear the negative index
31 # into the primitives array which contains only these functions.
33 mem = Array{Int64,1}(size_mem)
34 primitives = Array{Function,1}()
39 RSP0 = nextVarAddr; nextVarAddr += 1
40 PSP0 = nextVarAddr; nextVarAddr += 1
41 HERE = nextVarAddr; nextVarAddr += 1
42 LATEST = nextVarAddr; nextVarAddr += 1
44 mem[RSP0] = size_BIVar # bottom of RS
45 mem[PSP0] = mem[RSP0] + size_RS # bottom of PS
46 TIB = mem[PSP0] + size_PS # address of terminal input buffer
47 mem[HERE] = TIB + size_TIB # location of bottom of dictionary
48 mem[LATEST] = 0 # no previous definition
52 RSP::Int64 # Return stack pointer
53 PSP::Int64 # Parameter/data stack pointer
54 IP::Int64 # Instruction pointer
55 W::Int64 # Working register
56 X::Int64 # Extra register
58 reg = Reg(mem[RSP0], mem[PSP0], 0, 0, 0)
60 # Stack manipulation functions
62 function pushRS(val::Int64)
72 function pushPS(val::Int64)
73 mem[reg.PSP += 1] = val
82 # Primitive creation and calling functions
84 function createHeader(name::AbstractString, flags::Int64)
85 mem[mem[HERE]] = mem[LATEST]
86 mem[LATEST] = mem[HERE]
89 mem[mem[HERE]] = length(name) + flags; 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; flags::Int64=0)
94 createHeader(name, flags)
97 mem[mem[HERE]] = -length(primitives)
100 return -length(primitives)
103 callPrim(addr::Int64) = primitives[-addr]()
105 function defExistingVar(name::AbstractString, varAddr::Int64; flags::Int64=0)
106 defPrim(name, eval(:(() -> begin
112 function defConst(name::AbstractString, val::Int64; flags::Int64=0)
113 defPrim(name, eval(:(() -> begin
119 function defNewVar(name::AbstractString, initial::Int64; flags::Int64=0)
120 createHeader(name, flags)
122 varAddr = mem[HERE] + 1
123 push!(primitives, eval(:(() -> begin
127 mem[mem[HERE]] = -length(primitives); mem[HERE] += 1
129 mem[mem[HERE]] = initial; mem[HERE] += 1
134 # Threading Primitives
136 NEXT = defPrim("NEXT", () -> begin
143 DOCOL = defPrim("DOCOL", () -> begin
149 EXIT = defPrim("EXIT", () -> begin
155 # Basic forth primitives
157 DROP = defPrim("DROP", () -> begin
162 SWAP = defPrim("SWAP", () -> begin
163 mem[reg.PSP], mem[reg.PSP-1] = mem[reg.PSP-1], mem[reg.PSP]
167 DUP = defPrim("DUP", () -> begin
172 LIT = defPrim("LIT", () -> begin
180 STORE = defPrim("!", () -> begin
187 FETCH = defPrim("@", () -> begin
193 ADDSTORE = defPrim("+!", () -> begin
200 SUBSTORE = defPrim("-!", () -> begin
210 defExistingVar("HERE", HERE)
211 defExistingVar("LATEST", LATEST)
212 defExistingVar("PSP0", PSP0)
213 defExistingVar("RSP0", RSP0)
214 defNewVar("STATE", 0)
215 defNewVar("BASE", 10)
219 defConst("VERSION", 1)
220 defConst("DOCOL", DOCOL)
224 TOR = defPrim(">R", () -> begin
229 FROMR = defPrim("R>", () -> begin
234 RSPFETCH = defPrim("RSP@", () -> begin
239 RSPSTORE = defPrim("RSP!", () -> begin
244 RDROP = defPrim("RDROP", () -> begin
251 PSPFETCH = defPrim("PSP@", () -> begin
256 PSPSTORE = defPrim("PSP!", () -> begin
264 NUMTIB = defNewVar("#TIB", 0)
265 TOIN = defNewVar(">IN", TIB)
267 #KEY = defPrim("KEY", (reg) -> begin
275 #EMIT = defPrim("EMIT", (reg) -> begin
280 #WORD = defPrim("WORD", (reg) -> begin
285 #NUMBER = defPrim("NUMBER", (reg) -> begin
291 #function runVM(reg::Reg)
293 # while (jmp = callPrim(reg, jmp)) != 0 end
298 function coredump(startAddr::Int64; count::Int64 = 16, cellsPerLine::Int64 = 8)
299 chars = Array{Char,1}(cellsPerLine)
303 if i%cellsPerLine == 0
307 print("\t$(mem[addr]) ")
309 if (mem[addr]>=32 && mem[addr]<176)
310 chars[i%cellsPerLine + 1] = Char(mem[addr])
312 chars[i%cellsPerLine + 1] = '.'
315 if i%cellsPerLine == cellsPerLine-1
316 println(string("\t", ASCIIString(chars)))
322 count = reg.PSP - mem[PSP0]
326 for i in (mem[PSP0]+1):reg.PSP
331 println("Parameter stack empty")