X-Git-Url: https://thelambdalab.xyz/gitweb/index.cgi?p=forth.jl.git;a=blobdiff_plain;f=src%2Fforth.jl;h=63e7d576e70e3af8d8855ccb5f9cb932bb0fb81a;hp=89c4c0db15ca3ac12e6e5f35d54ce88897adaa3b;hb=19d08aee45587ac2b84f6c413fc53542d50c52cc;hpb=a8d323108d89b2438677598d1b1b592191e72a0b diff --git a/src/forth.jl b/src/forth.jl index 89c4c0d..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 # Next free memory address -LATEST = nextVarAddr; nextVarAddr += 1 # LFA of latest word in systetm dict +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[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 @@ -157,8 +161,8 @@ function defNewVar(name::AbstractString, initial::Array{Int64,1}; flags::Int64=0 codeWordAddr = mem[H] varAddr = mem[H] + 1 - mem[mem[H]] = DOVAR; mem[H] += 1 - mem[mem[H]:(mem[H]+length(initial)-1)] = initial; mem[H] += length(initial) + dictWrite(DOVAR) + dictWrite(initial) return varAddr, codeWordAddr end @@ -171,8 +175,8 @@ function defConst(name::AbstractString, val::Int64; flags::Int64=0) codeWordAddr = mem[H] - mem[mem[H]] = DOCON; mem[H] += 1 - mem[mem[H]] = val; mem[H] += 1 + dictWrite(DOCON) + dictWrite(val) return codeWordAddr end @@ -209,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) @@ -693,7 +697,7 @@ end) # Dictionary searches -TOCFA_CFA = defPrimWord(">CFA", () -> begin +FROMLINK_CFA = defPrimWord("LINK>", () -> begin addr = popPS() lenAndFlags = mem[addr+1] @@ -704,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 @@ -713,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 @@ -870,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() @@ -882,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, @@ -900,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) @@ -920,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)