Jump to content
IGNORED

Beware: Forth in here


Willsy

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 C@ 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
Link to comment
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

Link to comment
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
Link to comment
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 C@ 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
Link to comment
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
Link to comment
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
Link to comment
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

Link to comment
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

Link to comment
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

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...