+# Outer Interpreter
+
+EXECUTE_CFA = defPrimWord("EXECUTE", () -> begin
+ reg.W = popPS()
+ return mem[reg.W]
+end)
+
+INTERPRET_CFA = defWord("INTERPRET",
+ [LIT_CFA, 32, WORD_CFA, # Read next space-delimited word
+
+ DUP_CFA, FETCH_CFA, ZE_CFA, ZBRANCH_CFA, 3,
+ DROP_CFA, EXIT_CFA, # Exit if input buffer is exhausted
+
+ STATE_CFA, FETCH_CFA, ZBRANCH_CFA, 24,
+ # Compiling
+ FIND_CFA, QDUP_CFA, ZBRANCH_CFA, 13,
+
+ # Found word.
+ LIT_CFA, -1, EQ_CFA, INVERT_CFA, ZBRANCH_CFA, 4,
+
+ # Immediate: Execute!
+ EXECUTE_CFA, BRANCH_CFA, -26,
+
+ # Not immediate: Compile!
+ COMMA_CFA, BRANCH_CFA, -29,
+
+ # No word found, parse number
+ NUMBER_CFA, LIT_CFA, LIT_CFA, COMMA_CFA, COMMA_CFA, BRANCH_CFA, -36,
+
+ # Interpreting
+ FIND_CFA, QDUP_CFA, ZBRANCH_CFA, 5,
+
+ # Found word. Execute!
+ DROP_CFA, EXECUTE_CFA, BRANCH_CFA, -44,
+
+ # No word found, parse number and leave on stack
+ NUMBER_CFA, BRANCH_CFA, -47,
+ EXIT_CFA])
+
+PROMPT_CFA = defPrimWord("PROMPT", () -> begin
+ if mem[STATE] == 0
+ print(" ok")
+ end
+ println()
+
+ return NEXT
+end)
+
+QUIT_CFA = defWord("QUIT",
+ [LIT_CFA, 0, STATE_CFA, STORE_CFA, # Set mode to interpret
+ LIT_CFA, 0, SOURCE_ID_VAR_CFA, STORE_CFA, # Set terminal as input stream
+ LIT_CFA, 0, NUMTIB_CFA, STORE_CFA, # Clear the input buffer
+ RSP0_CFA, RSPSTORE_CFA, # Clear the return stack
+ QUERY_CFA, # Read line of input
+ INTERPRET_CFA, PROMPT_CFA, # Interpret line
+ BRANCH_CFA,-4]) # Loop
+
+INCLUDED_CFA = defWord("INCLUDED",
+ [LIT_CFA, 0, STATE_CFA, STORE_CFA, # Set mode to interpret
+ FAM_RO_CFA, OPEN_FILE_CFA, DROP_CFA, # Open the file
+ SOURCE_ID_VAR_CFA, FETCH_CFA, SWAP_CFA, # Store current source on stack
+ SOURCE_ID_VAR_CFA, STORE_CFA, # Mark this as the current source
+ SOURCE_ID_VAR_CFA, FETCH_CFA, QUERY_FILE_CFA, # Read line from file
+ EOF_FLAG_CFA, FETCH_CFA,
+ NUMFIB_CFA, FETCH_CFA, ZE_CFA, AND_CFA, # Test for EOF and empty line
+ INVERT_CFA, ZBRANCH_CFA, 4, # Break out if EOF
+ INTERPRET_CFA, # Interpret line
+ BRANCH_CFA, -14, # Loop
+ SOURCE_ID_VAR_CFA, FETCH_CFA,
+ CLOSE_FILE_CFA, DROP_CFA, # Close file
+ SOURCE_ID_VAR_CFA, STORE_CFA, # Restore input source
+ LIT_CFA, 0, NUMIB_CFA, STORE_CFA, # Zero #IB
+ LIT_CFA, 0, TOIN_CFA, STORE_CFA, # Zero >IN
+ EXIT_CFA])
+
+INCLUDE_CFA = defWord("INCLUDE", [LIT_CFA, 32, WORD_CFA,
+ DUP_CFA, INCR_CFA,
+ SWAP_CFA, FETCH_CFA,
+ INCLUDED_CFA, EXIT_CFA]);
+
+oldCWD = ""
+SETLIBCWD_CFA = defPrimWord("SETLIBCWD", () -> begin
+ global oldCWD = pwd()
+ if !isfile("lib.4th") # Exception for debugging.
+ cd(Pkg.dir("forth","src"))
+ end
+ return NEXT
+end)
+
+RESTORECWD_CFA = defPrimWord("RESTORECWD", () -> begin
+ cd(oldCWD)
+ return NEXT
+end)
+
+INCLUDED_LIB_CFA = defWord("INCLUDED-LIB",
+ [SETLIBCWD_CFA, INCLUDED_CFA, RESTORECWD_CFA, EXIT_CFA])
+
+INCLUDE_LIB_CFA = defWord("INCLUDE-LIB", [LIT_CFA, 32, WORD_CFA,
+ DUP_CFA, INCR_CFA,
+ SWAP_CFA, FETCH_CFA,
+ INCLUDED_LIB_CFA, EXIT_CFA]);
+
+ABORT_CFA = defWord("ABORT",
+ [CLOSE_FILES_CFA, DROP_CFA, PSP0_CFA, PSPSTORE_CFA, QUIT_CFA])
+
+BYE_CFA = defPrimWord("BYE", () -> begin
+ println("\nBye!")
+ return 0
+end)
+
+EOF_CFA = defPrimWord("\x04", () -> begin
+ return 0
+end)