X-Git-Url: https://thelambdalab.xyz/gitweb/index.cgi?p=forth.jl.git;a=blobdiff_plain;f=src%2Fforth.jl;h=63e7d576e70e3af8d8855ccb5f9cb932bb0fb81a;hp=9439dead46913871d9255834a9272713cad19433;hb=19d08aee45587ac2b84f6c413fc53542d50c52cc;hpb=6cb12b03e2a154214fc60d7c437e650e79fb42e5 diff --git a/src/forth.jl b/src/forth.jl index 9439dea..63e7d57 100644 --- a/src/forth.jl +++ b/src/forth.jl @@ -16,14 +16,16 @@ primNames = Array{ASCIIString,1}() # Built-in variables nextVarAddr = 1 -H = nextVarAddr; nextVarAddr += 1 -LATEST = nextVarAddr; nextVarAddr += 1 +H = nextVarAddr; nextVarAddr += 1 # Next free memory address +FORTH_LATEST = nextVarAddr; nextVarAddr += 1 # LFA of latest word in system dict +CURRENT = nextVarAddr; nextVarAddr += 1 # Current compilation dict RSP0 = nextVarAddr # bottom of RS PSP0 = RSP0 + size_RS # bottom of PS TIB = PSP0 + size_PS # address of terminal input buffer -mem[H] = TIB + size_TIB # location of bottom of dictionary -mem[LATEST] = 0 # no previous definition +mem[H] = TIB + size_TIB # location of bottom of dictionary +mem[FORTH_LATEST] = 0 # no previous definition +mem[CURRENT] = FORTH_LATEST # Compile words to system dict initially DICT = mem[H] # Save bottom of dictionary as constant @@ -107,21 +109,27 @@ F_IMMED = 32 F_HIDDEN = 64 NFA_MARK = 128 +function dictWrite(ints::Array{Int64,1}) + mem[mem[H]:(mem[H]+length(ints)-1)] = ints + mem[H] += length(ints) +end +dictWrite(int::Int64) = dictWrite([int]) +dictWriteString(string::ASCIIString) = dictWrite([Int64(c) for c in string]) + function createHeader(name::AbstractString, flags::Int64) - mem[mem[H]] = mem[LATEST] - mem[LATEST] = mem[H] + mem[mem[H]] = mem[mem[CURRENT]] + mem[mem[CURRENT]] = mem[H] mem[H] += 1 - mem[mem[H]] = length(name) | flags | NFA_MARK; mem[H] += 1 - putString(name, mem[H]); mem[H] += length(name) + dictWrite(length(name) | flags | NFA_MARK) + dictWriteString(name) end function defPrimWord(name::AbstractString, f::Function; flags::Int64=0) createHeader(name, flags) codeWordAddr = mem[H] - mem[codeWordAddr] = defPrim(f, name=name) - mem[H] += 1 + dictWrite(defPrim(f, name=name)) return codeWordAddr end @@ -130,13 +138,9 @@ function defWord(name::AbstractString, wordAddrs::Array{Int64,1}; flags::Int64=0 createHeader(name, flags) addr = mem[H] - mem[mem[H]] = DOCOL - mem[H] += 1 + dictWrite(DOCOL) - for wordAddr in wordAddrs - mem[mem[H]] = wordAddr - mem[H] += 1 - end + dictWrite(wordAddrs) return addr end @@ -151,25 +155,28 @@ function defExistingVar(name::AbstractString, varAddr::Int64; flags::Int64=0) end))) end -function defNewVar(name::AbstractString, initial::Int64; flags::Int64=0) +function defNewVar(name::AbstractString, initial::Array{Int64,1}; flags::Int64=0) createHeader(name, flags) codeWordAddr = mem[H] varAddr = mem[H] + 1 - mem[mem[H]] = DOVAR; mem[H] += 1 - mem[mem[H]] = initial; mem[H] += 1 + dictWrite(DOVAR) + dictWrite(initial) return varAddr, codeWordAddr end +defNewVar(name::AbstractString, initial::Int64; flags::Int64=0) = + defNewVar(name, [initial]; flags=flags) + function defConst(name::AbstractString, val::Int64; flags::Int64=0) createHeader(name, flags) codeWordAddr = mem[H] - mem[mem[H]] = DOCON; mem[H] += 1 - mem[mem[H]] = val; mem[H] += 1 + dictWrite(DOCON) + dictWrite(val) return codeWordAddr end @@ -206,7 +213,7 @@ end) # Dictionary entries for core built-in variables, constants H_CFA = defExistingVar("H", H) -LATEST_CFA = defExistingVar("LATEST", LATEST) +CURRENT_CFA = defExistingVar("CURRENT", CURRENT) PSP0_CFA = defConst("PSP0", PSP0) RSP0_CFA = defConst("RSP0", RSP0) @@ -690,7 +697,7 @@ end) # Dictionary searches -TOCFA_CFA = defPrimWord(">CFA", () -> begin +FROMLINK_CFA = defPrimWord("LINK>", () -> begin addr = popPS() lenAndFlags = mem[addr+1] @@ -701,7 +708,17 @@ TOCFA_CFA = defPrimWord(">CFA", () -> begin return NEXT end) -TOBODY_CFA = defWord(">BODY", [INCR_CFA, EXIT_CFA]) +createHeader("FORTH", 0) +FORTH_CFA = mem[H] +dictWrite(defPrim(() -> begin + mem[CONTEXT] = reg.W + return NEXT +end, name="FORTH")) +dictWrite(FORTH_LATEST) + +CONTEXT, CONTEXT_CFA = defNewVar("CONTEXT", zeros(Int64, 100)) +mem[CONTEXT] = FORTH_CFA +NUMCONTEXT, NUMCONTEXT_CFA = defNewVar("#CONTEXT", 1) FIND_CFA = defPrimWord("FIND", () -> begin @@ -710,30 +727,39 @@ FIND_CFA = defPrimWord("FIND", () -> begin wordLen = mem[countedAddr] word = lowercase(getString(wordAddr, wordLen)) - latest = LATEST + context = mem[CONTEXT:(CONTEXT+mem[NUMCONTEXT]-1)] + lenAndFlags = 0 - - i = 0 - while (latest = mem[latest]) > 0 - lenAndFlags = mem[latest+1] - len = lenAndFlags & F_LENMASK - hidden = (lenAndFlags & F_HIDDEN) == F_HIDDEN - - if hidden || len != wordLen - continue + lfa = 0 + + for vocabCFA in reverse(context) + lfa = mem[vocabCFA+1] + + while (lfa = mem[lfa]) > 0 + + lenAndFlags = mem[lfa+1] + len = lenAndFlags & F_LENMASK + hidden = (lenAndFlags & F_HIDDEN) == F_HIDDEN + + if hidden || len != wordLen + continue + end + + thisWord = lowercase(getString(lfa+2, len)) + + if thisWord == word + break + end end - - thisAddr = latest+2 - thisWord = lowercase(getString(thisAddr, len)) - if lowercase(thisWord) == lowercase(word) + if lfa>0 break end end - if latest > 0 - pushPS(latest) - callPrim(mem[TOCFA_CFA]) + if lfa > 0 + pushPS(lfa) + callPrim(mem[FROMLINK_CFA]) if (lenAndFlags & F_IMMED) == F_IMMED pushPS(1) else @@ -867,8 +893,8 @@ end, name="DODOES") DOES_HELPER_CFA = defPrimWord("(DOES>)", () -> begin - pushPS(mem[LATEST]) - callPrim(mem[TOCFA_CFA]) + pushPS(mem[mem[CURRENT]]) + callPrim(mem[FROMLINK_CFA]) cfa = popPS() runtimeAddr = popPS() @@ -879,7 +905,7 @@ DOES_HELPER_CFA = defPrimWord("(DOES>)", () -> begin end)), name="doesPrim") return NEXT -end, flags=F_IMMED) +end, flags=F_IMMED | F_HIDDEN) DOES_CFA = defWord("DOES>", [LIT_CFA, LIT_CFA, COMMA_CFA, HERE_CFA, LIT_CFA, 3, ADD_CFA, COMMA_CFA, @@ -897,7 +923,7 @@ RBRAC_CFA = defPrimWord("]", () -> begin end, flags=F_IMMED) HIDDEN_CFA = defPrimWord("HIDDEN", () -> begin - lenAndFlagsAddr = mem[LATEST] + 1 + lenAndFlagsAddr = mem[mem[CURRENT]] + 1 mem[lenAndFlagsAddr] = mem[lenAndFlagsAddr] $ F_HIDDEN return NEXT end) @@ -917,7 +943,7 @@ SEMICOLON_CFA = defWord(";", EXIT_CFA], flags=F_IMMED) IMMEDIATE_CFA = defPrimWord("IMMEDIATE", () -> begin - lenAndFlagsAddr = mem[LATEST] + 1 + lenAndFlagsAddr = mem[mem[CURRENT]] + 1 mem[lenAndFlagsAddr] = mem[lenAndFlagsAddr] $ F_IMMED return NEXT end, flags=F_IMMED) @@ -994,7 +1020,14 @@ INCLUDE_CFA = defPrimWord("INCLUDE", () -> begin wordLen = mem[wordAddr-1] word = getString(wordAddr, wordLen) - push!(sources, open(word, "r")) + fname = word + if !isfile(fname) + fname = Pkg.dir("forth","src",word) + if !isfile(fname) + error("No file named $word found in current directory or package source directory.") + end + end + push!(sources, open(fname, "r")) # Clear input buffer mem[NUMTIB] = 0 @@ -1009,8 +1042,8 @@ initialized = false initFileName = nothing if isfile("lib.4th") initFileName = "lib.4th" -elseif isfile(Pkg.dir("forth/src/lib.4th")) - initFileName = Pkg.dir("forth/src/lib.4th") +elseif isfile(Pkg.dir("forth","src", "lib.4th")) + initFileName = Pkg.dir("forth","src","lib.4th") end function run(;initialize=true)