Jump to content
Willsy

Beware: Forth in here

Recommended Posts

This version works and seems to give the same results as BASIC.
It uses an old trick that I use to create easy string lists.
It was not as easy as I thought to RPN all those calculations. It really makes the point for the late Julian Noble's "FORmula TRANslator" (FORTRAN)
It was an evaluator that let you input infix equations and it spit out Forth.

This program also points out a sticky situation with Forth. There is no "standard" way to convert text to a number.
Every Forth has one but they seem to all have different names. CAMEL Forth uses ?NUMBER ( c$adr-- n flag) .
But without that , I can't make a truly portable "INPUT" statement to put this in a loop like the BASIC version.
I can do it, but it will probably not compile on other systems without some editing.

This compiles on CAMEL99 and gives correct results according to http://www.calculatorcat.com/date/day-of-week.html

DECIMAL
: ,"          ( -- ) [CHAR] "  WORD [email protected] 1+ ALLOT ALIGNED ;  IMMEDIATE

: [[     0 C,  ;
: ]]     [[ ;

CREATE DAYS [[ ," SUN" ," MON"  ," TUES" ," WEDNES" ," THURS" ," FRI" ," SATUR" ]]

: NTH  ( n adr -- adr') SWAP 0 ?DO  COUNT + LOOP ;
: DAY.  ( n -- $adr ) 1+ DAYS NTH COUNT TYPE ." DAY" ;

VARIABLE D   VARIABLE M   VARIABLE Y

: INPUT       ( d m y -- ) Y ! M ! D ! ;
: (M-2)/12   ( -- n ) M @ 2-  12 / ;               ( factored out of below)
: YR          ( -- )   Y @ (M-2)/12 +  Y ! ;       ( line 130 a)
: MNTH        ( -- )   M @ (M-2)/12 12 * -  M ! ;  ( line 130 b)

: MAGIC       ( -- n )
              YR MNTH
              D @  M @ 2* +
              M @ 1+  6 * 10 / +
              Y @ +
              Y @ 4 / +
              Y @ 100 / -
              Y @ 400 / +
              1+
              DUP 7 / 7 * - ;                       ( line 150)

: DOW   ( D M Y -- )   CR ." That's a " INPUT MAGIC DAY. ;

post-50750-0-77729300-1490275789_thumb.jpg
BUT! the same code on HsForth under Intel DOSBOX gives wrong results. In both cases I am using the machine's native divide instruction.
Is that the problem? No idea.

(I could not get it to compile on TurboForth because I don't know the equivalent to the ANS word ALIGNED)

Edited by TheBF
  • Like 1

Share this post


Link to post
Share on other sites

...This program also points out a sticky situation with Forth. There is no "standard" way to convert text to a number.

Every Forth has one but they seem to all have different names. CAMEL Forth uses ?NUMBER ( c$adr-- n flag) .

But without that , I can't make a truly portable "INPUT" statement to put this in a loop like the BASIC version.

I can do it, but it will probably not compile on other systems without some editing.

 

Yeah...TurboForth uses NUMBER ( addr len -- n|d flag ) the result is in the current radix (number base) and is usually a single number (n) unless the string at addr contains a ‘.’, in which case the result is a double number (d). fbForth and TI Forth use NUMBER ( addr -- d ), which operates on a packed string (string length in first byte) at addr to always produce a double number (d). DPL (“decimal” point location) is updated if a ‘.’ is present in the string at addr. An error message is issued if the string cannot be converted.

 

BUT! the same code on HsForth under Intel DOSBOX gives wrong results. In both cases I am using the machine's native divide instruction.

Is that the problem? No idea.

 

Very likely. The TMS9900’s DIV is unsigned. Other CPUs may be signed (some symmetric, some floored, some ...) unsigned or both (I think).

 

(I could not get it to compile on TurboForth because I don't know the equivalent to the ANS word ALIGNED)

 

ANS ALIGNED ( addr -- a-addr ) is =CELLS ( addr -- a-addr ) in fbForth and TI Forth. (a-addr = aligned address.) It is not present in TurboForth, but the high-level Forth equivalent is

 

: =CELLS ( addr -- a-addr ) <---this can obviously be named ALIGNED
1+ $FFFE AND ;

 

...lee

Share this post


Link to post
Share on other sites

Thank you for the translation kind sir.

 

I have to do some work and stop playing here. :-)

 

B

Share this post


Link to post
Share on other sites

Here's a super compact one for TurboForth, using VALUEs (I prefer them as you don't get the "noise" of ! and @)

 

 

0 value day   0 value month   0 value year
: dow ( d m y )
    to year  to month  to day 
    month 2- 12 / year + to year
    month month 2- 12 / 12 * - to month
    month 2* day +  month 1+ 6 * 10 / +  year +  year 4 / +  year 100 / -  
    year 400 / +  1+  7 mod  case 
    0 of ." Sunday " endof     1 of ." Monday " endof
    2 of ." Tuesday " endof    3 of ." Wednesday " endof
    4 of ." Thursday " endof   5 of ." Friday " endof
    6 of ." Saturday " endof
    endcase ;
  • Like 2

Share this post


Link to post
Share on other sites

Here it is exactly translated to fbForth 2.0 (well, as near as I could manage it):

 

 

 

DECIMAL
: ," ( -- ) ASCII " WORD HERE [email protected] 1+ ALLOT ; IMMEDIATE
: [[ 0 C, ;
: ]] [[ ;
: CREATE_HDR <BUILDS DOES> ;
CREATE_HDR DAYS
[[ ," SUN" ," MON" ," TUES" ," WEDNES" ," THURS" ," FRI" ," SATUR" ]]
: NTH ( n adr -- adr') SWAP 0 DO COUNT + LOOP ;
: DAY. ( n -- $adr ) 1+ DAYS NTH COUNT TYPE ." DAY" ;
0 VARIABLE D 0 VARIABLE M 0 VARIABLE Y
: INPUT ( d m y -- ) Y ! M ! D ! ;
: (M-2)/12 ( -- n ) M @ 2- 12 / ; ( factored out of below)
: YR ( -- ) Y @ (M-2)/12 + Y ! ; ( line 130 a)
: MNTH ( -- ) M @ (M-2)/12 12 * - M ! ; ( line 130 b)
: MAGIC ( -- n )
YR MNTH
D @ M @ 2 * +
M @ 1+ 6 * 10 / +
Y @ +
Y @ 4 / +
Y @ 100 / -
Y @ 400 / +
1+
DUP 7 / 7 * - ; ( line 150)
: DOW ( D M Y -- ) CR ." That's a " INPUT MAGIC DAY. ;

Changes necessary for fbForth 2.0:
  • ASCII for [CHAR]
  • Added HERE because WORD does not leave anything on the stack, but always puts parsed string at HERE .
  • Removed ALIGNED (not sure what it is doing there because alignment screws up loop in NTH—no alignment necessary until next definition, which aligns itself)
  • Created CREATE_HDR because CREATE in fbForth 2.0 is different (same as figForth)
  • DO for ?DO
  • VARIABLE definitions need initial values on the stack
  • 2 * for 2*

...lee

  • Like 2

Share this post


Link to post
Share on other sites

Bruce/Lee (Ha!!!! Bruce Lee! Bruce Fucking Lee!!!!!!)

Minimal changes required for TurboForth:

: ," ( -- ) ASCII "  WORD  dup c, dup >r  here swap cmove r> allot ; immediate
CREATE DAYS
    ," SUN" ," MON"  ," TUES" ," WEDNES" ," THURS" ," FRI" ," SATUR" 
: NTH  ( n adr -- adr') SWAP 0 ?DO  COUNT + LOOP ;
: DAY.  ( n -- $adr ) DAYS NTH COUNT TYPE ." DAY" ;
 
VARIABLE D   VARIABLE M   VARIABLE Y
 
: INPUT       ( d m y -- ) Y ! M ! D ! ;
: (M-2)/12   ( -- n ) M @ 2-  12 / ;               ( factored out of below)
: YR          ( -- )   Y @ (M-2)/12 +  Y ! ;       ( line 130 a)
: MNTH        ( -- )   M @ (M-2)/12 12 * -  M ! ;  ( line 130 b)
 
: MAGIC       ( -- n )
              YR MNTH
              D @  M @ 2* +
              M @ 1+  6 * 10 / +
              Y @ +
              Y @ 4 / +
              Y @ 100 / -
              Y @ 400 / +
              1+
              DUP 7 / 7 * - ;                       ( line 150)
 
: DOW   ( D M Y -- )   CR ." That's a " INPUT MAGIC DAY. ;
  • ," modified - needs to move the string that WORD *points to* to here.
  • [[ removed (not required)
  • ]] removed (not required)

Note: ?DO isn't in memory at startup, but it's on block 41, hence retained.

  • Like 2

Share this post


Link to post
Share on other sites

Re [[ and ]] , I thought to do that as well, but thought Bruce might have had a reason for using them, if only for aesthetics. I am sure he will chime in ere long to shed light on the matter.

 

...lee

Share this post


Link to post
Share on other sites

Bruce Lee...

 

Son of a bitch, if you guys write a Forth implementation together, there is no doubt what it should be called....

  • Like 2

Share this post


Link to post
Share on other sites

Re [[ and ]] , I thought to do that as well, but thought Bruce might have had a reason for using them, if only for aesthetics. I am sure he will chime in ere long to shed light on the matter.

 

...lee

 

I stole the Nth concept from HsForth and it required a 0 leading and a 0 ending the lists. Never bothered to change it.

So creating the [[ ]] just made some syntax candy.

 

Ending the list with 0 means Nth can't go past the end of the list.

 

My lists don't work correctly if I remove the leading 0 byte... hmmm...

 

By the way although Bruce is a very good name, mine is Brian. :-)

 

BF

 

But I was a big Bruce Lee fan!

Edited by TheBF
  • Like 1

Share this post


Link to post
Share on other sites
Changes necessary for fbForth 2.0:
  • Removed ALIGNED (not sure what it is doing there because alignment screws up loop in NTH—no alignment necessary until next definition, which aligns itself

...lee

 

I put aligned in the string definition to cope with odd length strings. You have challenged my assumptions to the core.

 

Thanks!

 

BF

Share this post


Link to post
Share on other sites

My lists don't work correctly if I remove the leading 0 byte... hmmm...

 

You also need to remove the “1+” from DAY. .

 

By the way although Bruce is a very good name, mine is Brian. :-)

 

Oops! Wonder where Mark got that idea?

 

...lee

Share this post


Link to post
Share on other sites

 

By the way although Bruce is a very good name, mine is Brian. :-)

 

 

"I'm Brian and so's my wife!"

Share this post


Link to post
Share on other sites

 

Oops! Wonder where Mark got that idea?

 

...lee

 

It's just bit-rot. With apologies to Bruce Brian :D

Share this post


Link to post
Share on other sites

Ending the list with 0 means Nth can't go past the end of the list.

 

Not true. COUNT always increments the string address by 1, even when the character count = 0. At least, that is how it works up through Forth-83. I could find nothing in the ANS-Forth standard that says COUNT must not increment the address if the character count = 0. If the number you pass to NTH is more than one past the last element, it will fail miserably.

 

...lee

Share this post


Link to post
Share on other sites

 

Not true. COUNT always increments the string address by 1, even when the character count = 0. At least, that is how it works up through Forth-83. I could find nothing in the ANS-Forth standard that says COUNT must not increment the address if the character count = 0. If the number you pass to NTH is more than one past the last element, it will fail miserably.

 

...lee

 

You are correct again. I had never tested it.

 

B

Share this post


Link to post
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...