6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Thu Nov 21, 2024 4:13 pm

All times are UTC




Post new topic Reply to topic  [ 3 posts ] 
Author Message
PostPosted: Fri Jan 22, 2021 9:32 pm 
Offline

Joined: Sun May 13, 2018 5:49 pm
Posts: 255
I'm working on Tali Forth 2 (an ANS 2012 STC Forth) and I'm looking for others' thoughts/suggestions on making REFILL extendable. The ANS 2012 is important as DPANS94 (I think) changed how the input is parsed and allows using any string/buffer in memory as the input buffer (eg. strings are often just made the input buffer temporarily to evaluate them rather than copy them into a separate input buffer). I think DPANS94 also added SOURCE-ID to BLK to indicate if the input was a block/screen or a file.

REFILL will be in ROM, and is called by words that are also in ROM ( QUIT and S" ). I'm really only concerned with S", as QUIT will restore input to be from the console and REFILL knows how to handle the console. I'd like S" to be able to handle long strings in files.

My current thought is to introduce a user variable 'USERREFILL (or something like that) where the user can put their routine. This will be called first in the ROM version of REFILL, and the result code on the stack will tell REFILL if the user's version handled things, or if REFILL should run the rest of it's code. That might look something like (untested):
Code:
: REFILL ( -- f)
   'USERREFILL EXECUTE ( Run user's version of REFILL )
   ?DUP 0= IF ( See if user's version of REFILL worked)
      ( * User's refill didn't do it... put rest of code currently in REFILL here *)
   THEN ;
On startup, the user variables that Tali2 starts with are copied to RAM from a table in ROM, so I can just arrange to put the XT for 0 (zero is a word in Tali2) into 'USERREFILL for initialization. That way, when REFILL is called, it will execute 0 and therefore get a 0 on the stack to indicate that the user's refill did not refill the input buffer and perhaps REFILL should try to do it the normal way. When a user adds file support, they can write their own file-aware routine and put its XT into 'USERREFILL. That routine would return TRUE if it handled the request and FALSE if REFILL should attempt to do its normal thing.

I may need to make REFILL a little smarter so it can handle an end-of-file in the middle of an S" string. It will have BLK and SOURCE-ID to look at, so it will be able to tell if the USERREFILL routine *should* have been the one to refill the input buffer.

Are there other methods of making an extendable word in ROM, whereby other ROM words will get the new functionality?


Top
 Profile  
Reply with quote  
PostPosted: Sat Feb 20, 2021 10:36 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 895
SamCoVT wrote:
Are there other methods of making an extendable word in ROM, whereby other ROM words will get the new functionality?


First, I don't have experience building a Forth in ROM, but if I wanted extendable words in ROM this is what I would try.
A version of deferred words in the kernel (everything in ROM) and a version for RAM (any deferred words defined later). Only the RAM version of DEFER would need defined.
Since the number of kernel deferred words would be known, a table in ROM could hold the vectors of the deferred words and be copied to a table in RAM at startup. A kernel deferred word would not hold the address of its vector. It would hold an offset into that table. Any other deferred word defined later in RAM would store its vector in its body.
IS DEFER! and DEFER@ would need written to check which do-defer a deferred word has and behave accordingly.
Just my 2 cents worth.


Top
 Profile  
Reply with quote  
PostPosted: Thu Feb 25, 2021 9:41 pm 
Offline

Joined: Sun May 13, 2018 5:49 pm
Posts: 255
That sounds very similar to how Tali2 handles the input/output words. There are words INPUT and OUTPUT that return the location of the vector (not the vector itself) in RAM. There are also vectors in ram for reading and writing blocks. These vectored words don't work quite the same as a deferred word in Tali, but it has the same overall effect and indeed the vectors for the implementations in ROM are copied into RAM at startup like you describe.

The I/O vectors are currently held in zero page, but zero page was starting to fill up (Tali tries to leave half of zero page for applications to use) so the block read/write vectors ended up in what Tali calls "User variables". This is a spot in the dictionary with 256 bytes (128 cells) alloted and the variables here are indexed from a base pointer which is in zero page. When Tali2 eventually gets tasking, the idea is to have one set of user variables for each task and only the base pointer needs to be swapped in zero page to load that tasks' set of variables.

My original proposed solution was to have some kind of vectored word that REFILL would call, but you seem to be suggesting vectoring REFILL itself and I think that is probably more the "Forth way" as my replacement REFILL can always call the ROM version.

REFILL is only called when the interpreter runs out of text or for very longs strings (Tali2 supports strings longer than 256 bytes), so there's virtually no performance penalty to vector it.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 3 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 8 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: