X-Git-Url: https://thelambdalab.xyz/gitweb/index.cgi?a=blobdiff_plain;f=src%2Fforth.jl;h=a233743809fa806017a4ce0313d8d454fc51114d;hb=366db53c2e77d243c744c11f68b8bdeb575c86e6;hp=16791158bba44e90991b2339db55d7f2ab7e69bf;hpb=4aaffe598cbf92821d47324d80ba8a8044572aaa;p=forth.jl.git diff --git a/src/forth.jl b/src/forth.jl index 1679115..a233743 100644 --- a/src/forth.jl +++ b/src/forth.jl @@ -108,6 +108,7 @@ end # Handy functions for adding/retrieving strings to/from memory. getString(addr::Int64, len::Int64) = ASCIIString([Char(c) for c in mem[addr:(addr+len-1)]]) + function putString(str::ASCIIString, addr::Int64) mem[addr:(addr+length(str)-1)] = [Int64(c) for c in str] end @@ -116,12 +117,18 @@ end function defPrim(f::Function; name="nameless") push!(primitives, f) - push!(primNames, replace(replace(name, "\004", "EOF"), "\n", "\\n")) + push!(primNames, replace(name, "\004", "EOF")) return -length(primitives) end -callPrim(addr::Int64) = primitives[-addr]() +function callPrim(addr::Int64) + if addr >=0 || -addr>length(primitives) + error("Attempted to execute non-existent primitive at address $addr.") + else + primitives[-addr]() + end +end getPrimName(addr::Int64) = primNames[-addr] # Word creation functions @@ -598,7 +605,14 @@ end) sources = Array{Any,1}() currentSource() = sources[length(sources)] -EOF_CFA = defConst("EOF", 4) +EOF = defPrimWord("\x04", () -> begin + close(pop!(sources)) + if !isempty(sources) + return NEXT + else + return 0 + end +end) EMIT = defPrimWord("EMIT", () -> begin print(Char(popPS())) @@ -616,7 +630,7 @@ EXPECT = defPrimWord("EXPECT", () -> begin putString(line[1:mem[SPAN]], addr) else mem[SPAN] = 1 - mem[addr] = EOF + mem[addr] = 4 # eof end return NEXT @@ -679,7 +693,7 @@ TOCFA = defPrimWord(">CFA", () -> begin return NEXT end) -TODFA = defWord(">DFA", [TOCFA, INCR, EXIT]) +TOPFA = defWord(">PFA", [TOCFA, INCR, EXIT]) # Branching @@ -721,8 +735,9 @@ end) # Outer interpreter TRACE = defPrimWord("TRACE", () -> begin - print("RS: "); printRS() + println("reg.W: $(reg.W) reg.IP: $(reg.IP)") print("PS: "); printPS() + print("RS: "); printRS() print("[paused]") readline() @@ -767,11 +782,16 @@ WORD = defPrimWord("WORD", () -> begin # Start reading in word count = 0 - while (mem[TOIN] begin return NEXT end) +PARSE = defPrimWord("PARSE", () -> begin + delim = popPS() + + # Chew up initial occurrences of delim + addr = mem[HERE] + + # Start reading input stream + count = 0 + while (mem[TOIN] begin + println("Bye!") + return 0 +end) + STATE, STATE_CFA = defNewVar("STATE", 0) INTERPRET = defWord("INTERPRET", @@ -789,29 +840,30 @@ INTERPRET = defWord("INTERPRET", DUP, FETCH, ZE, ZBRANCH, 3, DROP, EXIT, # Exit if TIB is exhausted - STATE_CFA, FETCH, ZBRANCH, 27, + STATE_CFA, FETCH, ZBRANCH, 31, # Compiling - DUP, FIND, ZBRANCH, 17, + DUP, FIND, QDUP, ZBRANCH, 19, # Found word. + SWAP, DROP, DUP, TOCFA, SWAP, INCR, FETCH, LIT, F_IMMED, AND, ZBRANCH, 4, # Immediate: Execute! - EXECUTE, BRANCH, -30, + EXECUTE, BRANCH, -33, # Not immediate: Compile! - COMMA, BRANCH, -33, + COMMA, BRANCH, -36, # No word found, parse number - NUMBER, BTICK, LIT, COMMA, BRANCH, -39, + NUMBER, BTICK, LIT, COMMA, COMMA, BRANCH, -43, # Interpreting DUP, FIND, QDUP, ZBRANCH, 7, # Found word. Execute! - SWAP, DROP, TOCFA, EXECUTE, BRANCH, -50, + SWAP, DROP, TOCFA, EXECUTE, BRANCH, -54, # No word found, parse number and leave on stack - NUMBER, BRANCH, -53, + NUMBER, BRANCH, -57, EXIT] ) @@ -829,15 +881,11 @@ QUIT = defWord("QUIT", INTERPRET, PROMPT, BRANCH,-4]) -BYE = defPrimWord("BYE", () -> begin - println("Bye!") - return 0 -end) - INCLUDE = defPrimWord("INCLUDE", () -> begin + pushPS(32) callPrim(mem[WORD]) - wordLen = popPS() - wordAddr = popPS() + wordAddr = popPS()+1 + wordLen = mem[wordAddr-1] word = getString(wordAddr, wordLen) push!(sources, open(word, "r")) @@ -851,7 +899,6 @@ end) # Compilation HEADER = defPrimWord("HEADER", () -> begin - wordAddr = popPS()+1 wordLen = mem[wordAddr-1] word = getString(wordAddr, wordLen) @@ -878,13 +925,13 @@ HIDDEN = defPrimWord("HIDDEN", () -> begin end) HIDE = defWord("HIDE", - [WORD, + [LIT, 32, WORD, FIND, HIDDEN, EXIT]) COLON = defWord(":", - [WORD, + [LIT, 32, WORD, HEADER, LIT, DOCOL, COMMA, LATEST_CFA, FETCH, HIDDEN, @@ -903,9 +950,6 @@ IMMEDIATE = defPrimWord("IMMEDIATE", () -> begin return NEXT end, flags=F_IMMED) -TICK = defWord("'", - [WORD, FIND, TOCFA, EXIT]) - #### VM loop #### @@ -917,7 +961,7 @@ elseif isfile(Pkg.dir("forth/src/lib.4th")) initFileName = Pkg.dir("forth/src/lib.4th") end -function run(;initialize=false) +function run(;initialize=true) # Begin with STDIN as source push!(sources, STDIN) @@ -940,7 +984,7 @@ function run(;initialize=false) jmp = NEXT while jmp != 0 try - #println("Entering prim $(getPrimName(jmp))") +# println("Entering prim $(getPrimName(jmp))") jmp = callPrim(jmp) catch ex @@ -951,6 +995,11 @@ function run(;initialize=false) close(pop!(sources)) end + # Want backtrace in here eventually + println("reg.W: $(reg.W) reg.IP: $(reg.IP)") + print("PS: "); printPS() + print("RS: "); printRS() + mem[STATE] = 0 mem[NUMTIB] = 0 reg.PSP = mem[PSP0]