X-Git-Url: https://thelambdalab.xyz/gitweb/index.cgi?a=blobdiff_plain;f=src%2Fforth.jl;h=f35d2129b3d5e6be4057c485fbe83c616b9c410a;hb=3332b073f68c5afb68e8ac230c2970b549382108;hp=46c3c9c055935a0e2deb45b634c76b2a55e28e40;hpb=e7ffe0f277ef1d2b9b9005e01e2149b4d34190f7;p=forth.jl.git diff --git a/src/forth.jl b/src/forth.jl index 46c3c9c..f35d212 100644 --- a/src/forth.jl +++ b/src/forth.jl @@ -1,52 +1,163 @@ module forth -currentLine = "" -currentPos = 0 - -function nextLine() - if eof(STDIN) - return false - else - currentLine = readLine() - currentPos = 1 - return true - end +RS = Array{Int64, 1}(1024) +RSP = 0 + +PS = Array{Int64, 1}(1024) +PSP =0 + +IP = 0 +W = 0 +X = 0 + +jmp = 0 + +primitives = Array{Expr,1}() +memory = Array{Int64,1}(64*1024) +LATEST = 0 +HERE = 1 + +# Intperpreter state + +STATE = 0 + +# Current radix + +BASE = 10 + +# Stack manipulation macros + +function pushRS(val::Int64) + global RSP + RS[RSP += 1] = val end -function readPattern(pattern::Regex) - m = match(pattern, currentLine) - pos += length(m.match) - return m.match +function popRS() + global RSP + val = RS[RSP] + RSP -= 1 + return val end -modes = Dict{AbstractString,Function}() -mode = "" +function pushPS(val::Int64) + global PSP + PS[PSP += 1] = val +end -function interpretPrimitive() - if haskey(dict, word) - dict[word]() - return true - else - return false +function popPS() + global PSP + val = PS[PSP] + PSP -= 1 + return val end -interpretNonPrimitive() = false -interpretNumber() = false -modes["interpret"] = () -> begin - getWord() - - if ! (interpretPrimitive() || - interpretNonPrimitive() || - interpretNumber()) - println("Error: unknown word '$word'.") - end +# Primitive creation functions + +function defPrim(name::AbstractString, expr::Expr) + global HERE, LATEST + + memory[HERE] = LATEST + LATEST = HERE + HERE += 1 + + memory[HERE] = length(name); HERE += 1 + memory[HERE:(HERE+length(name)-1)] = [Int(c) for c in name]; HERE += length(name) + + push!(primitives, expr) + memory[HERE] = -length(primitives) + codeword = HERE + HERE += 1 + + return codeword +end + +function defVar(name::AbstractString, var::Expr) + defPrim(name, Expr(:call, :pushPS, var)) end -function repl() +# Threading Primitives + +NEXT = defPrim("NEXT", :(begin + W = memory[IP] + IP += 1 + X = memory[W] + jmp = X +end)) + +DOCOL = defPrim("DOCOL", :(begin + pushRS(IP) + IP = W + 1 + jmp = NEXT +end)) + +EXIT = defPrim("EXIT", :(begin + IP = popRS() + jmp = NEXT +end)) + + +# Basic forth primitives + +DROP = defPrim("DROP", :(begin + popPS() +end)) + +SWAP = defPrim("SWAP", :(begin + PS[PSP], PS[PSP-1] = PS[PSP-1], PS[PS] +end)) + +DUP = defPrim("DUP", :(begin + pushPS(PS[PSP]) +end)) + +LIT = defPrim("LIT", :(begin + pushPS(memory[IP]) + IP += 1 +end)) + +# Memory primitives + +STORE = defPrim("!", :(begin + addr = popPS() + dat = popPS() + memory[addr] = dat +end)) + +FETCH = defPrim("@", :(begin + addr = popPS() + pushPS(memory[addr]) +end)) + +ADDSTORE = defPrim("+!", :(begin + addr = popPS() + toAdd = popPS() + memory[addr] += toAdd +end)) + +SUBSTORE = defPrim("-!", :(begin + addr = popPS() + toSub = popPS() + memory[addr] -= toSub +end)) + + +# Built-in variables + +defVar("STATE", :STATE) +defVar("HERE", :HERE) +defVar("LATEST", :LATEST) +defVAR("PSP", :PSP) +defVAR("BASE", :BASE) + +# Constants + + - mode = "interpret" - while mode != "stop" - modes[mode]() +# VM loop +jmp = NEXT +function runVM() + while true + eval(primitives[-memory[jmp]]) end end