INCLUDED and INCLUDE should now work.
[forth.jl.git] / src / forth.jl
index d911e21..9c62fe6 100644 (file)
@@ -665,6 +665,22 @@ CLOSE_FILES_CFA = defPrimWord("CLOSE-FILES", () -> begin
 end)
 
 READ_LINE_CFA = defPrimWord("READ-LINE", () -> begin
+    fid = popPS()
+    maxSize = popPS()
+    addr = popPS()
+
+    fh = openFiles[fid]
+    line = readline(fh)
+
+    eofFlag = endswith(line, '\n') ? 0 : -1
+    line = chomp(line)
+
+    putString(line, addr, maxSize)
+
+    pushPS(length(line))
+    pushPS(eofFlag)
+    pushPS(0)
+
     return NEXT
 end)
 
@@ -963,6 +979,8 @@ QUERY_CFA = defWord("QUERY",
     LIT_CFA, 0, TOIN_CFA, STORE_CFA,
     EXIT_CFA])
 
+# ( fid -- flag )
+# Flag is false when EOF is reached.
 QUERY_FILE_CFA = defWord("QUERY-FILE",
     [FIB_CFA, LIT_CFA, 160, ROT_CFA, READ_LINE_CFA,
     DROP_CFA, SWAP_CFA,
@@ -1148,7 +1166,7 @@ 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 TIB is exhausted
+        DROP_CFA, EXIT_CFA, # Exit if input buffer is exhausted
 
     STATE_CFA, FETCH_CFA, ZBRANCH_CFA, 24,
         # Compiling
@@ -1193,6 +1211,18 @@ QUIT_CFA = defWord("QUIT",
     INTERPRET_CFA, PROMPT_CFA,
     BRANCH_CFA,-4])
 
+INCLUDED_CFA = defWord("INCLUDED",
+    [SOURCE_ID_CFA, FETCH_CFA, TOR_CFA, # Store current source on return stack
+    FAM_RO_CFA, OPEN_FILE_CFA, DROP_CFA, # Open the file named by this word.
+    DUP_CFA, SOURCE_ID_CFA, STORE_CFA, # Mark this as the current source
+    DUP_CFA, QUERY_FILE_CFA, # Read line from file
+    INTERPRET_CFA,
+    INVERT_CFA, ZBRANCH_CFA, -5,
+    DROP_CFA, EXIT_CFA])
+
+INCLUDE_CFA = defWord("INCLUDE", [LIT_CFA, 32, WORD_CFA, INCLUDED_CFA]);
+
+
 ABORT_CFA = defWord("ABORT",
     [CLOSE_FILES_CFA, PSP0_CFA, PSPSTORE_CFA, QUIT_CFA])
 
@@ -1201,6 +1231,10 @@ BYE_CFA = defPrimWord("BYE", () -> begin
     return 0
 end)
 
+EOF_CFA = defPrimWord("\x04", () -> begin
+    return 0
+end)
+
 #### VM loop ####
 
 initialized = false
@@ -1213,6 +1247,10 @@ end
 
 function run(;initialize=true)
 
+    # Start with IP pointing to first instruction of outer interpreter
+    pushRS(QUIT_CFA+1)
+
+    # Load library files
     global initialized, initFileName
     if !initialized && initialize
         if initFileName != nothing
@@ -1226,12 +1264,10 @@ function run(;initialize=true)
         end
     end
 
-    # Start with IP pointing to first instruction of outer interpreter
-    reg.IP = QUIT_CFA + 1
 
     # Primitive processing loop.
     # Everyting else is simply a consequence of this loop!
-    jmp = NEXT
+    jmp = mem[EXIT_CFA]
     while jmp != 0
         try
             #println("Entering prim $(getPrimName(jmp))")