6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Sep 21, 2024 5:19 pm

All times are UTC




Post new topic Reply to topic  [ 354 posts ]  Go to page Previous  1 ... 6, 7, 8, 9, 10, 11, 12 ... 24  Next
Author Message
PostPosted: Wed Nov 11, 2020 11:09 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 890

I've made a slight change to Fleet Forth's word -NUMBER . I've added about 44 bytes of code to check the beginning of a numeric string for one of the following three characters: # $ % .
For # base is temporarily set to decimal.
For $ base is temporarily set to hexadecimal.
For % base is temporarily set to binary.
After conversion, the value of base is restored to what it was prior to the execution of -NUMBER .
If one of these three characters is not the first character of the numeric string to be converted, the number base is unaltered.
I just build this version of Fleet Forth yesterday, so I don't know how useful this change will be. Does anyone have any experience with this?


Top
 Profile  
Reply with quote  
PostPosted: Thu Nov 12, 2020 12:51 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8510
Location: Southern California
I like the easy base specification. I don't think I've seen it done in Forth. Doing [ DECIMAL ] and [ HEX ] and [ BINARY ] was so common in my code and taking so much space in the source code that I made IMMEDIATE words [D] and [H] and [B]. The I/O in my kind of work is mostly not human-oriented, so I normally keep the base at hex, not decimal; and after going to a non-hex base, I normally try to keep the return-to-hex word either directly to the right or directly below the other word, to make it easy to find. For example:
Code:
: SYNCSERSETUP   ( -- )
   [B]          VIA1ACR  C@
   00010100 OR                      \ Enable SR to shift out under T2 ctrl w/
   11010111 AND VIA1ACR  C!         \ µP resetting T2, and decr at the φ2 rate.
   00100100     VIA1IER  C!         \ Disable SR-empty and T2 IRQs.
   00001000     VIA1T2CL C!         \ Set T2 for about 100kHz shift rate, low
   [H]          VIA1T2CH C_OFF  ;   \ byte 1st. T2 gets reset automatically;
                                    \ so it's not really 1-shot in SR mode.
Here the [H] is directly below the [B]. I try to take maximum advantage of visual factoring (like your column of CONSTANTs above). I do not however put the ; on the margin, because ; and : look too much alike at first glance. I don't put anything on the margin that will be encountered when COMPILER is on. In a sequence of definitions, I try to align the ; for example:
Code:
: ESC     ( -- )  1B  EMIT       ;
: OUT-2   ( -- )   2  OUT -!     ;

: BOLDON  ESC  ." E"  OUT-2      ;    \ Put printer in bold mode.
: BOLDOFF ESC  ." F"  OUT-2      ;    \ Take printer out of bold.
: TINYON  0F EMIT     OUT  DECR  ;    \ Put printer in compressed.
: TINYOFF 12 EMIT     OUT  DECR  ;    \ Take printer out of compressed.
: ITALON  ESC  ." 4"  OUT-2      ;    \ Put printer in italics mode.
: ITALOFF ESC  ." 5"  OUT-2      ;    \ Cancel printer italics mode.
or
Code:
: TYPE      ( addr len -- )
   DUP OUT +!   type    ;

: CR        ( -- )
   0D emit   OUT OFF
   EOLSEQ C@  ?DUP
   IF emit THEN         ;

: SPACE     ( -- )
   BL  EMIT             ;

: SPACES    ( n -- )
   0 MAX    0
   ?DO  SPACE  LOOP     ;

I see Jim mostly does this, but others don't; so I'm just trying to encourage everyone else in the visual-factoring department.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Fri Nov 13, 2020 7:24 pm 
Offline

Joined: Sun May 13, 2018 5:49 pm
Posts: 251
JimBoyd wrote:
For # base is temporarily set to decimal.
For $ base is temporarily set to hexadecimal.
For % base is temporarily set to binary.
After conversion, the value of base is restored to what it was prior to the execution of -NUMBER .
If one of these three characters is not the first character of the numeric string to be converted, the number base is unaltered.
This is part of the ANS-2012 standard (I checked the 94 and 83 versions and didn't see it mentioned there) in section 3.4.1.3. ANS-2012 also specifies the form 'c' which is for constant characters (rather than using CHAR or [CHAR]). I actually just stumbled onto this last week and realized that Tali doesn't have support for this so I opened an issue on github (and will probably end up submitting a patch for it, eventually).

Seeing as I might be the one to write it, I'm curious where you ended up temporarily putting the BASE value (return stack?) and how you signaled that BASE needed to be restored at the end?


Top
 Profile  
Reply with quote  
PostPosted: Fri Nov 13, 2020 10:56 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 890
SamCoVT wrote:
This is part of the ANS-2012 standard (I checked the 94 and 83 versions and didn't see it mentioned there) in section 3.4.1.3. ANS-2012 also specifies the form 'c' which is for constant characters (rather than using CHAR or [CHAR]).


Fleet Forth conforms to the Forth-83 Standard, which seems more appropriate considering when the C64 came out, and I like the Forth-83 Standard better. Since Fleet Forth conforms to the Forth-83 Standard, I didn't include the form 'c'. I didn't want to add that much extra code. I use ASCII , the immediate state smart word replaced by CHAR and [CHAR] in the new standard.
Since Fleet Forth conforms to the Forth-83 Standard, there are some differences in how numeric strings are handled. The leading count is ignored and the numeric string must have a trailing space.
Quote:
Seeing as I might be the one to write it, I'm curious where you ended up temporarily putting the BASE value (return stack?) and how you signaled that BASE needed to be restored at the end?

Yes, I put the value of BASE on the return stack, or rather, I used a word that did. Fleet Forth has the word RB (restore base). When RB is used in a word, whatever the base was prior to executing RB is restored when that word exits, unless it aborts. -NUMBER never aborts. It passes a flag, FALSE for successful conversion, TRUE if it failed.
RB uses the word CO (coroutine).
Code:
// COROUTINES
: CO   2R> SWAP 2>R ;
// RESTORE BASE AT END OF WORD
// CALLING RB
: RB  ( -- )
   BASE @ R> 2>R  CO
   R> BASE ! ;

Here is the original version of -NUMBER
Code:
: -NUMBER  ( ADR -- D FLAG )
   DPL ON  0 0 ROT
   DUP 1+ C@ ASCII - =
   DUP>R -  DUP>R
   BEGIN
      CONVERT DUP C@ VALID?
   WHILE
      DUP 1+ C@ VALID? 0=
   WHILE
      DPL OFF
   REPEAT
   THEN
   DUP C@ BL <> SWAP
   2-  DPL @ 0< - R> = OR
   R>  0EXIT  >R DNEGATE R> ;

Here is the modified version of -NUMBER
Code:
HEX
NH
CREATE BASE.TABLE
   0A C, 10 C, 2 C,

: -NUMBER  ( ADR -- D FLAG )
   RB
   DUP 1+ C@ ASCII # - DUP 3 U<
   IF
      BASE.TABLE + C@ BASE !
      1+ DUP
   THEN
   DROP
   DPL ON  0 0 ROT
   DUP 1+ C@ ASCII - =
   DUP>R -  DUP>R
   BEGIN
      CONVERT DUP C@ VALID?
   WHILE
      DUP 1+ C@ VALID? 0=
   WHILE
      DPL OFF
   REPEAT
   THEN
   DUP C@ BL <> SWAP
   2-  DPL @ 0< - R> = OR
   R>  0EXIT  >R DNEGATE R> ;

NH is a metacompiler word that causes the following word to be compiled without a header.
VALID? is a word that takes a character and returns a true flag if it is valid punctuation for a number. It is a deferred word and the default is to only accept a period as valid.
For completeness, here is the source for CONVERT
Code:
: CONVERT  ( D1 ADR1 -- D2 ADR2 )
   1+
   BEGIN
      COUNT BASE @ DIGIT
   WHILE
      2SWAP BASE @ *
      SWAP BASE @ UM* D+
      ROT
      DPL @ 0< 1+ DPL +!
   REPEAT
   1- ;

DIGIT takes the character to be converted and the number base to use. It returns the digit as a single cell number and a true flag or just a false flag if the character is not a digit in the specified base.
( CHR #BASE -- N TF )
( CHR #BASE -- FF )


Top
 Profile  
Reply with quote  
PostPosted: Sat Nov 14, 2020 1:51 am 
Offline

Joined: Sun May 13, 2018 5:49 pm
Posts: 251
JimBoyd wrote:
Fleet Forth conforms to the Forth-83 Standard, which seems more appropriate considering when the C64 came out, and I like the Forth-83 Standard better. Since Fleet Forth conforms to the Forth-83 Standard, I didn't include the form 'c'.
Are the # $ and % forms in the 83 standard? I couldn't find them. I guess what I meant to say is that I've only seen those forms mentioned in the 2012 standard. It does seem useful to me, though, to be able to specify constants in regular Forth code without having to switch the base. I've definitely been bit several times when my 10 was 16 and #10 could have been useful!
JimBoyd wrote:
Yes, I put the value of BASE on the return stack, or rather, I used a word that did. Fleet Forth has the word RB (restore base). When RB is used in a word, whatever the base was prior to executing RB is restored when that word exits, unless it aborts. -NUMBER never aborts. It passes a flag, FALSE for successful conversion, TRUE if it failed.
RB uses the word CO (coroutine).
Code:
// COROUTINES
: CO   2R> SWAP 2>R ;
// RESTORE BASE AT END OF WORD
// CALLING RB
: RB  ( -- )
   BASE @ R> 2>R  CO
   R> BASE ! ;
... because of course your forth has coroutines! That's pretty nifty, and I may have to play around with that.

I will probably just toss the BASE on the return stack because the number processing is written in assembly in Tali2. I think your method of just always tossing the original BASE on the return stack and restoring it regardless of what happened is the way to go. That way I won't need a flag to remember if I need to restore it later or not.

Your trick with the BASE.TABLE is pretty slick. I did not notice before that #, $, and % are all right next to each other in the ASCII table. I was looking through your code trying to see where you compared to those characters and I only saw #. Then I saw you looking up in the table with an index and I had to go pull up an ASCII table. Very nice.

Thanks for the detailed response. It's neat to see how other people tackle a problem. The other neat thing (for me) is that I was able to read/understand your Forth code. When I first starting playing around with Forth, reading other people's code was quite difficult for me. I'll also give a shout out to Garth's suggestions for making things visually clear with indentation and spacing.


Top
 Profile  
Reply with quote  
PostPosted: Sat Nov 14, 2020 3:31 am 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 890
SamCoVT wrote:
Are the # $ and % forms in the 83 standard?


No. I guess you could say I added them as a non standard extension.
Quote:
It does seem useful to me, though, to be able to specify constants in regular Forth code without having to switch the base. I've definitely been bit several times when my 10 was 16 and #10 could have been useful!

Exactly. It's a convenience that shouldn't have much impact on portability with, in my case, other Forth-83 systems.
Quote:
Your trick with the BASE.TABLE is pretty slick. I did not notice before that #, $, and % are all right next to each other in the ASCII table. I was looking through your code trying to see where you compared to those characters and I only saw #. Then I saw you looking up in the table with an index and I had to go pull up an ASCII table. Very nice.

Thank you. I didn't notice that #, $, and % are next to each other either, until I looked at their values in binary. I was trying to find a way to manipulate the numbers that would yield a small solution before settling on using the table.
Quote:
Thanks for the detailed response. It's neat to see how other people tackle a problem. The other neat thing (for me) is that I was able to read/understand your Forth code. When I first starting playing around with Forth, reading other people's code was quite difficult for me. I'll also give a shout out to Garth's suggestions for making things visually clear with indentation and spacing.

Poorly formatted source only contributes to Forth's write only reputation. The following is a sample of source code for another Forth for the C64. It's not for the multitasker (this Forth didn't have one), it does the same thing as Fleet Forth's DONE? .
Code:
: PAUSE   ?KEY ?DUP IF 3 <> IF KEY 3 = ELSE TRUE THEN
                    ELSE FALSE THEN ;

?KEY returns a zero if no key was pressed or the value of the key that was pressed.
KEY waits for a keypress and returns the value of that press. It calls ?KEY in a loop.
I don't care that this was from source that was in Forth blocks, it's not worth saving blocks if the control flow is difficult to follow.
Code:
: PAUSE  ( -- F )
   ?KEY ?DUP
   IF
      3 <>
      IF  KEY 3 =  ELSE  TRUE  THEN
   ELSE
      FALSE
   THEN ;

This version of formatting is easier to follow and, I think, easier to improve (hint: TRUE , FALSE , and both ELSEs are not needed in the improved version).


Top
 Profile  
Reply with quote  
PostPosted: Sat Nov 14, 2020 5:00 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8510
Location: Southern California
JimBoyd wrote:
No. I guess you could say I added them as a non standard extension.

As long as things don't conflict, it's nice when you can accommodate multiple standards. The only drawback is that it takes more memory.

Quote:
Your trick with the BASE.TABLE is pretty slick. I did not notice before that #, $, and % are all right next to each other in the ASCII table.

I hadn't noticed that either.

Quote:
The other neat thing (for me) is that I was able to read/understand your Forth code. When I first starting playing around with Forth, reading other people's code was quite difficult for me. I'll also give a shout out to Garth's suggestions for making things visually clear with indentation and spacing.

Forth has been called a write-only language, ie, that it's unreadable. I blame that on the programmer though, not the language. I had an article in Forth dimensions in the early 90's on making Forth more readable. Hopefully my own programming has further improved since then. My article-writing definitely has. To be frank, most people's assembly language on 6502.org is also very difficult to read, and I often have to copy it to my text editor and massage it some to figure out what they're trying to do.

Quote:
The following is a sample <snip>

The first sample follows what so many Forthers are dogmatic about, that definitions should be limited to two lines. This kind of dogma hurts readability. It tends to result in over-factoring too, taking more memory for all the unnecessary headers for factors that are only used once, more time to run because of the extra nesting, and it can be hard sometimes to come up with a descriptive name for the factor that is any shorter than the code it replaces! There was a regular contributor to Forth Dimensions magazine who defended this strongly, and said screens should be viewed as 3x5 cards. He kept pushing this as a plus, yet I just saw it as inadequate room to make things clear and add adequate comments. Then in a private mail exchange (which today we would do by email, but back then it was on paper), he sent me his code for something we were discussing, and he had a definition that was over 100 lines long! I didn't call out his hypocrisy.

Quote:
(hint: TRUE , FALSE , and both ELSEs are not needed in the improved version).

In the two-line version it's particularly easy to miss the fact that those could be eliminated to improve both readability and efficiency.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Sat Nov 14, 2020 5:37 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1948
Location: Sacramento, CA, USA
Here's my clumsy stab at it:
Code:
: PAUSE  ( -- F )
   ?KEY DUP IF
      DUP 3 <> IF
         DROP KEY THEN
      3 = THEN
;
Am I in the right ballpark?
[Edited to try to balance the stack, probably while Garth was reading my first attempt ...]

P.S. eFORTH has the stack comment for ?KEY as ( -- c T | F ) , so in that case I would get rid of my second DUP ... at least I think that's what I'd try ... eh, I'm all messed up! I'll try again when my head's screwed on the right way!

P.P.S. I think I would have to DROP the T, like so:
Code:
: PAUSE  ( -- F )
   ?KEY DUP IF
      DROP DUP 3 <> IF
         DROP KEY THEN
      3 = THEN
;
... but that doesn't seem any better than the original! Back to the drawing board!

_________________
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)


Top
 Profile  
Reply with quote  
PostPosted: Sun Nov 15, 2020 8:29 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 890
barrym95838 wrote:
Here's my clumsy stab at it:
Code:
: PAUSE  ( -- F )
   ?KEY DUP IF
      DUP 3 <> IF
         DROP KEY THEN
      3 = THEN
;
Am I in the right ballpark?


Yes, but I like the factoring where both THEN's are one after the other followed by the semicolon. I'll show why.
Quote:
P.S. eFORTH has the stack comment for ?KEY as ( -- c T | F )

In Fleet Forth it's ( -- c | 0 ) because that is what the C64 kernal supports.
PAUSE is the name of Fleet Forth's task switcher (which is set to a no-op when not multitasking), so I'm just going to call this word DONE? , which is what it is called in Fleet Forth.
Code:
: DONE?  ( -- F )
   ?KEY ?DUP
   IF
      3 <>
      IF  KEY 3 =  ELSE  TRUE  THEN
   ELSE
      FALSE
   THEN ;

Notice the ELSE clause at the end of the word?
Code:
ELSE
   FALSE
THEN ;

If ?DUP is replaced with DUP , that clause is no longer needed.
Code:
: DONE?  ( -- F )
   ?KEY DUP
   IF
      3 <>
      IF  KEY 3 =  ELSE  TRUE  THEN
   THEN ;

In my ITC Forth, this saves 3 cells.
The next improvement is a little harder to see.
3 <> is equivalent to 3 = 0=
At first glance, this doesn't seem to save memory. if ?DUP is inserted between = and 0= the final ELSE clause is no longer needed.
Code:
: DONE?  ( -- F )
   ?KEY DUP
   IF
      3 = ?DUP 0=
      IF  KEY 3 =  THEN
   THEN ;

A savings of another cell.
Fleet Forth also has the primitives ?EXIT and 0EXIT .
Both consume the top stack item.
?EXIT exits the word if the top stack item is TRUE (any non-zero value).
0EXIT exits the word if the top stack item is zero.
Using these two words, some more memory savings can be had, as well as a performance boost. Both IF's branch to the exit at the end of the word. They can both be replaced with 0EXIT and the THEN's removed.
Code:
: DONE?  ( -- F )
   ?KEY DUP
   0EXIT
      3 = ?DUP 0=
      0EXIT  KEY 3 = ;

A little reformatting.
Code:
: DONE?  ( -- F )
   ?KEY DUP 0EXIT
   3 = ?DUP 0= 0EXIT
   KEY 3 = ;

Finally, 0= 0EXIT can be replaced with ?EXIT
Code:
: DONE?  ( -- F )
   ?KEY DUP 0EXIT
   3 = ?DUP ?EXIT
   KEY 3 = ;



Top
 Profile  
Reply with quote  
PostPosted: Mon Nov 16, 2020 4:31 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1948
Location: Sacramento, CA, USA
My way of thinking FORTH is brutally incomplete, but I did think of ?EXIT briefly. It's kind of like a conditionally executed RTS in the middle of a subroutine, efficient but a bit lacking in what I perceive to be "structured" technique. Come to think of it, I often break those techniques when I'm doing my own thing, so ...

My (probably flawed) reasoning on the subject of where to place my IFs and ELSEs and THENs is that I feel weird needlessly inserting line breaks between the data or code and the word immediately responsible for consuming or executing it. In my example, the 3 <> is immediately consumed by the following IF, and the DROP KEY is within the execution scope of the following THEN ... kind of an "object verb verb" "noun noun verb" thing, like Yoda tends to use in his sentences. As my understanding hopefully improves, I may start to see things more the way you and Garth format your code, but many miles to go still have I ... :lol:

_________________
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)


Top
 Profile  
Reply with quote  
PostPosted: Mon Nov 16, 2020 5:16 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8510
Location: Southern California
Nothin' wrong with ?EXIT, as there's nothing pending on either stack like there would be with DO...LOOP (where you can remove the exit address, loop limit, and loop index with UNLOOP). Any of the structures will have stuff on the stack during compilation, but not necessarily at run time.

Putting the condition and flow-control words this way makes if very clear, and there's no visual searching:
Code:
: FOOBAR    ( n1 -- n2 f )
   <do stuff>
   <condition?>
   IF    ┌─────────────────┐
         │ <do this stuff> │
         └─────────────────┘
   ELSE  ┌─────────────────┐
         │ <do this stuff> │
         └─────────────────┘
   THEN
   <do more stuff>    ;

But if you want the IF on the same line with the condition so the line is more stack-autonomous, you can re-arrange it this way:
Code:
: FOOBAR    ( n1 -- n2 f )
   <do stuff>
   <condition?>          IF
   ┌─────────────────┐
   │ <do this stuff> │
   └─────────────────┘   ELSE
   ┌─────────────────┐
   │ <do this stuff> │
   └─────────────────┘   THEN
   <do more stuff>     ;

The latter works out really well if you have a lot of nested IF's, and no visual searching is necessary. (Color syntax highlighting is not only unnecessary when you do this, but totally undesirable, IMO.) Then you can put them one above the other instead of indenting and indenting and indenting way over to ridiculous extremes. You might end with a line of
Code:
   THEN  THEN  THEN  THEN  THEN

Some may turn up their nose at this and say if you're having to do that, then you're taking the wrong approach; but then their "fix" usually ends up overfactoring or doing something else that's just as undesirable.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Mon Nov 16, 2020 7:49 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8510
Location: Southern California
I seem to remember the humorous book "Starting Forth" had the following logic example as part of a getting-dressed word, to show Forth's differing approach.

Are you lacking socks?
IF so, socks-install
THEN shoes-install

(The "shoes install" object-noun word order is natural for native Korean speakers.) The THEN is not part of the IF, but instead meas "After you've taken care of that, do this." It makes perfect sense this way, even though it's different from other programming languages which would take the approach,

process dress_feet:
IF your are lacking socks, THEN put on socks. ENDIF
Now put on shoes.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Tue Nov 17, 2020 10:48 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 890
GARTHWILSON wrote:

The first sample follows what so many Forthers are dogmatic about, that definitions should be limited to two lines. This kind of dogma hurts readability. It tends to result in over-factoring too, taking more memory for all the unnecessary headers for factors that are only used once, more time to run because of the extra nesting, and it can be hard sometimes to come up with a descriptive name for the factor that is any shorter than the code it replaces! There was a regular contributor to Forth Dimensions magazine who defended this strongly, and said screens should be viewed as 3x5 cards. He kept pushing this as a plus, yet I just saw it as inadequate room to make things clear and add adequate comments. Then in a private mail exchange (which today we would do by email, but back then it was on paper), he sent me his code for something we were discussing, and he had a definition that was over 100 lines long! I didn't call out his hypocrisy.


I tend to view screens as a consequence of the limitations of the technology of the day, although blocks on the C64 can also be used as a form of virtual memory. On my Linux box, I use plain text files for source.
If I have a definition on the C64 that will not fit on a single block, I just let it span however many I need. -NUMBER takes two blocks but I load something like that with THRU rather than LOAD , so it's not a problem.
I think some of the over zealous factoring came about because some Forth programmers tried to minimize what they perceived as wasted space in a source screen. I hope this example makes it evident that the "wasted space" in a source screen is not so valuable a resource as the understanding that comes from well formatted source.
I made a copy of the source for -NUMBER and reformatted it to pack it into as few lines as possible. The only rules where:
1) Three space indentation for every line in a definition after the name.
2) two spaces around each control flow word unless it is the first or last word on a line.
To say it is highly unreadable is an understatement. When I deleted the white space, I may have accidentally deleted a word or two. From the compacted form it is not easy to tell.
Code:
: -NUMBER  ( ADR -- D FLAG )  RB DUP 1+ C@ ASCII # - DUP 3 U<
   IF  BASE.TABLE + C@ BASE ! 1+ DUP  THEN  DROP DPL ON  0 0 ROT
   DUP 1+ C@ ASCII - = DUP>R - DUP>R  BEGIN  CONVERT DUP C@
   VALID?  WHILE  DUP 1+ C@ VALID? 0=  WHILE  DPL OFF  REPEAT
   THEN  DUP C@ BL <> SWAP 2- DPL @ 0< - R> = OR R> 0EXIT >R
   DNEGATE R> ;

If this was somebody's ideal, I can see why they would want to aggressively factor it (over factor it). Personally, this form looks like software that went through a virtual trash compactor.
In this case, there is no need to refactor this word, just don't format the source like this.
Even if there are any useful factors in the definition of -NUMBER , it is not easy to find them in this mess.


Top
 Profile  
Reply with quote  
PostPosted: Tue Nov 24, 2020 12:42 am 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 890

I was just reading "Real Time Forth" by Dr. Tim Hendtlass and becoming reacquainted with some of F-PC's words. I had forgotten that F-PC has a word called NUMBER? which is similar to Fleet Forth's -NUMBER . The only apparent difference is NUMBER? returns a TRUE flag if successful. I use the word 'apparent' because without a copy of F-PC (which I had at one time, but it's been a while) I do not know what F-PC's NUMBER? rejects as an invalid number. Fleet Forth's -NUMBER requires a numeric string to:
1) Have at least one valid digit in the current base (or the temporary base specified by a leading # , $ , or % )
2) Have no more than one occurrence of valid punctuation in a row.
3) Have a trailing blank. When interpreting, this is automatically supplied by WORD .
For example, the following are valid numbers:
1.2
1.
.1
.1.
.1.2.3.4.
-1.
$-FF
$-DEAD.BEEF
the following are not:
1..2
.
..
...
.1..2
..1
123...
-.
-
Since there is already a word that does what -NUMBER does, but with a different return flag and a slightly different name, I changed -NUMBER to NUMBER? and changed the return flag.
-NUMBER had the following test to determine if the result was valid:
Code:
   DUP C@ BL <> SWAP
   2-  DPL @ 0< - R> = OR

FALSE = valid
Thanks to De Morgan’s laws, I know I can change this test to reverse the flag without just tacking a 0= on the end to flip the flag.
Code:
   DUP C@ BL = SWAP
   2-  DPL @ 0< - R> <> AND

TRUE = valid
I also had to change a few (very few) things in the kernel and saved two bytes overall.


Top
 Profile  
Reply with quote  
PostPosted: Fri Nov 27, 2020 10:51 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 890
GARTHWILSON wrote:

As long as things don't conflict, it's nice when you can accommodate multiple standards. The only drawback is that it takes more memory.


I wasn't trying to accommodate multiple standards. I thought it would be useful if I could specify a number as hexadecimal, decimal, or binary regardless of the current number base. The Ansi Forth Standard specified that behaviour so I appropriated that part of it.
It's still early days, but for 44 extra bytes in the kernel, I think it will be worth it.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 354 posts ]  Go to page Previous  1 ... 6, 7, 8, 9, 10, 11, 12 ... 24  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 12 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: