Jump to content
IGNORED

TF, camel, FB Forth fun


GDMike

Recommended Posts

I used to read Jeff Fox talking about you can do things in Forth with 10X less code. I didn't believe it because "I" couldn't do it. :) 

 

Over the years I am "starting" to get how you do it but it means really exploring what all these little trivial words do in a Forth system and what else you could use them for.

It seems to be more like an instruction set for a CPU where it takes time to figure out the best way to use the instructions for different situations. 

It's just not obvious what "else" you can do with the wee beasties. 

 

One that made say "WHAT?!"  was using COUNT to index into a stack string. (not a byte counted string)

 

: TYPE   ( addr len -- )  0 DO  COUNT EMIT  LOOP  DROP ; 

:) 

  • Like 3
Link to comment
Share on other sites

Yep. That works too. Though I'll need to study the code to understand why. I'm somewhat rusty! I've never seen COUNT used in a loop like that, so my eyebrows are on the ceiling right now!

image.thumb.png.7d32dd290f11e453cbef4f83aec3720c.png

  • Like 3
Link to comment
Share on other sites

On 8/2/2023 at 9:49 PM, TheBF said:

I just saw something on comp.lang.forth that I would have never thought of but apparently others have used it. It is not guaranteed to work on all Forth systems.  You need the Forth83 style word CREATE so it doesn't work in FbForth without making that word.

 

Let's say you wanted to create a vector table of these actions that you have written up. 

 

: FIZZ  ;
: BUZZ ;
: BLEEP ; 
: HALT ; 

 

In many Forth systems you can do this to make the table of executable "tokens" (addresses) 

 

CREATE TABLE  ] FIZZ BUZZ BLEEP HALT [ 

For the Forth student: How does it work? Because ] turns on the compiler so the token for each word is looked up in the dictionary and is compiled into memory as each word is parsed.

Then [  turns off the compiler ie: turns on the interpreter again

 

And then to run them you might do something like this.

: DOIT  ( n -- ) CELLS TABLE +  @ EXECUTE ; 

\ Usage: 0 DOIT 1 DOIT  etc. 

(no protection on this example so you can blow up the system if you type 4 DOIT. )   ( I will leave it to the reader to implement protection ) (always wanted to say that) :) 

 

More stuff you'll probably never need but now you know. 

 

Yeah... CREATE in Forth83 and beyond is virtually the same as VARIABLE , with the difference that VARIABLE reserves and zeroes one cell for the parameter field. Words created with both of those defining words leave the parameter field address of the defined word on the stack when executed. Whereas, in figForth-based Forths like fbForthCREATE creates the new word with the same kind of header, viz., no parameter field is reserved. The difference is that fbForth’s CREATE stashes the new word’s pfa into its code field, meaning that, upon execution of the new word, its parameter field (nonexistent, unless you defined it separately) will be executed—not usually what you want to happen when trying to use CREATE on the command line. Furthermore, fbForth’s CREATE sets the new word’s smudge bit ( hides the word from -FIND ). The above two functions of fbForth’s CREATE presume CREATE will only be used by other defining words that will modify the contents of the new word’s code field and toggle its smudge bit before concluding the new word’s definition. fbForth’s VARIABLE differs only in that it expects the initial value of the parameter field on the stack instead of automatically zeroing it.

 

For what it’s worth, here is a definition of CREATE83 for fbForth that will function as the CREATE for Forth83 (and beyond):

: CREATE83  <BUILDS DOES> ;

 

 That said, we can kill two birds with one stone by using fbForth’s VARIABLE to store the number of entries in TABLE in the first cell and use that in DOIT for bounds checking (the leave-it-to-the-reader poser):

: CELLS  ( n -- 2n ) 1 SLA ;  \ double n (word not yet in fbForth)

\ Set up TABLE with count as first word in parameter field followed by
\ count cfas to flesh out TABLE.
4 VARIABLE TABLE  ] FIZZ BUZZ BLEEP HALT [ 

: DOIT  ( n -- ) 
   DUP 1 <                    \ n < 1?
   OVER TABLE @ >             \ n > TABLE count?
   OR ABORT" TABLE range!"    \ abort if either test TRUE
   CELLS TABLE +  @ EXECUTE   \ execute nth cfa in TABLE
;

\ Usage: 1 DOIT 2 DOIT  etc. 

 

...lee

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

  • 3 weeks later...

Over on comp.lang.forth I fellow posted a link to this site. 

It is aruably the cleanest source code to describe a Forth kernel I have ever seen.

Primitives are in intel Assembler and then another file shows the high level words as Forth source. 

 

T3XFORTH - T3X.ORG

 

(I may just try to cross-compile it on TI99 if I get some time) 

  • Like 2
Link to comment
Share on other sites

  • 3 weeks later...

Over in another thread @InsaneMultitasker posted some code to detect the presence of a SAMS Card.

I am always curious about comparing Assembly Language to Forth.

 

In this case, at least for Camel99 Forth, a couple of extra words are needed from the SAMS library to do this in Forth. 

 

For the Forth curious, here is what I came up with. (un tested at time of posting)

Edit: Tested and it works. 

       But SAMSINI in the DSK1.SAMS file runs when the file compiles and it burps with an error if SAMS is not present.

 

Again I see the low level semantic power of 9900 Assembly language is about the same as Forth primitives.

The gap widens only when we begin making higher level words that we can concatenate to make yet higher level words. 

 

Original code

H0101  data >0101
SAMSDT DATA PLAYWS,$+2
       clr    @0(R13)
       li    r12,>1E00
       sbo 0
       mov    @>4008,R2      ;save whatever was in the mapper for >4000-4fff
       a      @H0101,@>4008  ;change the value    
       c      r2,@>4008      ;is it still the same? 
       jeq    noams          ;yes. can't be SAMS
       seto   @0(R13)        ;no, assume SAMS
       mov    r2,@>4008      ;restore, for futureproofing
noams  sbz 0 
       rtwp


A Forth version

\ For Camel99 Forth 

NEEDS 'R12 FROM DSK1.SAMS

HEX       
: SAMSDT ( -- ?)       \ returns true FLAG if present      
       1E00 'R12 !     \ set CRU to SAMS card
       0SBO            \ Enable the card
       4008 @ >R       \ save whatever was in the mapper on RETURN stack 
       0101 4008 +!    \ change the value 
       R@ 4008 @ <>    \ is it different? (compared to top Rstack)
       R> 4008 !       \ restore previous value to SAMS card
       0SBZ            \ disable the card
;

 

  • Like 2
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...