X-Git-Url: https://thelambdalab.xyz/gitweb/index.cgi?a=blobdiff_plain;f=src%2Fforth.jl;h=b1d782ce1d11a0e6d291083315532922ea43c51c;hb=d2b2b3e5b33f882c18c9e7cf8c6623f4e863c2dd;hp=0b4871f89c2674359f32259e35ede298614cba5f;hpb=5328ad90af9699b87b0beee70aa7a7ee6a98e8a9;p=forth.jl.git diff --git a/src/forth.jl b/src/forth.jl index 0b4871f..b1d782c 100644 --- a/src/forth.jl +++ b/src/forth.jl @@ -1,12 +1,12 @@ module forth # VM mem size -size_mem = 640*1024 +size_mem = 1000000 # 1 mega-int # Buffer sizes -size_RS = 1024 # Return stack size -size_PS = 1024 # Parameter stack size -size_TIB = 1096 # Terminal input buffer size +size_RS = 1000 # Return stack size +size_PS = 1000 # Parameter stack size +size_TIB = 1000 # Terminal input buffer size # The mem array constitutes the memory of the VM. It has the following geography: # @@ -123,7 +123,7 @@ end callPrim(addr::Int64) = primitives[-addr]() -# Word creation +# Word creation functions function createHeader(name::AbstractString, flags::Int64) mem[mem[HERE]] = mem[LATEST] @@ -159,7 +159,7 @@ function defWord(name::AbstractString, wordAddrs::Array{Int64,1}; flags::Int64=0 return addr end -# Variable creation +# Variable creation functions function defExistingVar(name::AbstractString, varAddr::Int64; flags::Int64=0) @@ -175,22 +175,17 @@ function defNewVar(name::AbstractString, initial::Int64; flags::Int64=0) codeWordAddr = mem[HERE] varAddr = mem[HERE] + 1 - f = eval(:(() -> begin - pushPS($(varAddr)) - return NEXT - end)) - - mem[mem[HERE]] = defPrim(f, name=name); mem[HERE] += 1 + mem[mem[HERE]] = DOVAR; mem[HERE] += 1 mem[mem[HERE]] = initial; mem[HERE] += 1 return varAddr, codeWordAddr end function defConst(name::AbstractString, val::Int64; flags::Int64=0) - defPrimWord(name, eval(:(() -> begin - pushPS($(val)) - return NEXT - end))) + createHeader(name, flags) + + mem[mem[HERE]] = DOCON; mem[HERE] += 1 + mem[mem[HERE]] = val; mem[HERE] += 1 return val end @@ -209,11 +204,39 @@ DOCOL = defPrim(() -> begin return NEXT end, name="DOCOL") +DOVAR = defPrim(() -> begin + pushPS(reg.W + 1) + return NEXT +end, name="DOVAR") + +DOCON = defPrim(() -> begin + pushPS(mem[reg.W + 1]) + return NEXT +end, name="DOVAR") + EXIT = defPrimWord("EXIT", () -> begin reg.IP = popRS() return NEXT end) +# Dictionary entries for core built-in variables, constants + +HERE_CFA = defExistingVar("HERE", HERE) +LATEST_CFA = defExistingVar("LATEST", LATEST) +PSP0_CFA = defExistingVar("PSP0", PSP0) +RSP0_CFA = defExistingVar("RSP0", RSP0) + +defConst("DOCOL", DOCOL) +defConst("DOCON", DOCON) +defConst("DOVAR", DOVAR) + +defConst("DICT", DICT) +defConst("MEMSIZE", size_mem) + +F_IMMED = defConst("F_IMMED", 128) +F_HIDDEN = defConst("F_HIDDEN", 256) +F_LENMASK = defConst("F_LENMASK", 127) + # Basic forth primitives DROP = defPrimWord("DROP", () -> begin @@ -241,7 +264,7 @@ OVER = defPrimWord("OVER", () -> begin return NEXT end) -NROT = defPrimWord("-ROT", () -> begin +ROT = defPrimWord("ROT", () -> begin a = popPS() b = popPS() c = popPS() @@ -251,7 +274,7 @@ NROT = defPrimWord("-ROT", () -> begin return NEXT end) -ROT = defPrimWord("ROT", () -> begin +NROT = defPrimWord("-ROT", () -> begin a = popPS() b = popPS() c = popPS() @@ -284,8 +307,17 @@ TWOSWAP = defPrimWord("2SWAP", () -> begin d = popPS() pushPS(b) pushPS(a) - pushPS(c) pushPS(d) + pushPS(c) + return NEXT +end) + +TWOOVER = defPrimWord("2OVER", () -> begin + ensurePSDepth(4) + a = mem[reg.PSP-3] + b = mem[reg.PSP-2] + pushPS(a) + pushPS(b) return NEXT end) @@ -498,24 +530,6 @@ SUBSTORE = defPrimWord("-!", () -> begin end) -# Built-in variables - -HERE_CFA = defExistingVar("HERE", HERE) -LATEST_CFA = defExistingVar("LATEST", LATEST) -PSP0_CFA = defExistingVar("PSP0", PSP0) -RSP0_CFA = defExistingVar("RSP0", RSP0) -STATE, STATE_CFA = defNewVar("STATE", 0) -BASE, BASE_CFA = defNewVar("BASE", 10) - -# Constants - -defConst("VERSION", 1) -defConst("DOCOL", DOCOL) -defConst("DICT", DICT) -F_IMMED = defConst("F_IMMED", 128) -F_HIDDEN = defConst("F_HIDDEN", 256) -F_LENMASK = defConst("F_LENMASK", 127) - # Return Stack TOR = defPrimWord(">R", () -> begin @@ -612,24 +626,10 @@ WORD = defPrimWord("WORD", () -> begin eof_char = Char(EOF) c = eof_char - skip_to_end = false while true - callPrim(mem[KEY]) c = Char(popPS()) - if c == '\\' - skip_to_end = true - continue - end - - if skip_to_end - if c == '\n' || c == eof_char - skip_to_end = false - end - continue - end - if c == ' ' || c == '\t' continue end @@ -671,6 +671,7 @@ WORD = defPrimWord("WORD", () -> begin return NEXT end) +BASE, BASE_CFA = defNewVar("BASE", 10) NUMBER = defPrimWord("NUMBER", () -> begin wordLen = popPS() @@ -753,7 +754,9 @@ end) # Compilation -CREATE = defPrimWord("CREATE", () -> begin +STATE, STATE_CFA = defNewVar("STATE", 0) + +HEADER = defPrimWord("HEADER", () -> begin wordLen = popPS() wordAddr = popPS() @@ -795,7 +798,7 @@ HIDE = defWord("HIDE", COLON = defWord(":", [WORD, - CREATE, + HEADER, LIT, DOCOL, COMMA, LATEST_CFA, FETCH, HIDDEN, RBRAC, @@ -814,9 +817,33 @@ IMMEDIATE = defPrimWord("IMMEDIATE", () -> begin end, flags=F_IMMED) TICK = defWord("'", - [STATE_CFA, FETCH, ZBRANCH, 7, - FROMR, DUP, INCR, TOR, FETCH, EXIT, - WORD, FIND, TOCFA, EXIT]) + [WORD, FIND, TOCFA, EXIT]) + +BTICK = defWord("[']", + [FROMR, DUP, INCR, TOR, FETCH, EXIT]) + +# CREATE and DOES> + +CREATE = defWord("CREATE", + [WORD, + HEADER, + LIT, DOVAR, COMMA, EXIT]); + +DODOES = defPrim(() -> begin + pushRS(reg.IP) + reg.IP = reg.W + 1 + return NEXT +end, name="DOCOL") + +defConst("DODOES", DODOES) + +FROMDOES_PAREN = defWord("(DOES>)", + [DODOES, LATEST, FETCH, TOCFA, STORE, EXIT]) + +FROMDOES = defWord("DOES>", + [BTICK, FROMDOES_PAREN, COMMA, BTICK, EXIT, COMMA, + BTICK, LIT, COMMA, LATEST, FETCH, TODFA, COMMA], flags=F_IMMED) + # Strings @@ -872,7 +899,7 @@ INTERPRET = defPrimWord("INTERPRET", () -> begin isImmediate = (mem[wordAddr+1] & F_IMMED) != 0 callPrim(mem[TOCFA]) - callPrim(mem[ROT]) # get rid of extra copy of word string details + callPrim(mem[NROT]) # get rid of extra copy of word string details popPS() popPS() @@ -1020,6 +1047,8 @@ function run(;initialize=true) mem[STATE] = 0 mem[NUMTIB] = 0 + reg.PSP = mem[PSP0] + reg.RSP = mem[RSP0] reg.IP = QUIT + 1 jmp = NEXT end