ForthNet@willett.UUCP (ForthNet articles from GEnie) (08/01/90)
Category 2, Topic 13 Message 4 Mon Jul 30, 1990 W.BADEN1 [Wil] at 19:23 PDT Every Forth programmer believes his code is readable. Other programmers, even other Forth programmers, seldom agree with him. I'm looking for short but non-trivial examples of code that you believe is readable. No one can make Forth code absolutely readable, but I believe I can make most code more readable. I want to test my method and verify it or find a better method. This is a daring challenge on my part and I may convince no one but myself but I am confident enough to try. If no one submits anything I will take it as a personal confession that you do not write readable Forth code. Procedamus in pace. ----- This message came from GEnie via willett through a semi-automated process. Report problems to: uunet!willett!dwp or willett!dwp@hobbes.cert.sei.cmu.edu
wmb@MITCH.ENG.SUN.COM (Mitch Bradley) (08/01/90)
Wil Baden> I'm looking for short but non-trivial examples of code that you Wil Baden> believe is readable. I hereby submit the following implementation of CATCH/THROW. Go to it, Wil! \ CATCH/THROW Error Handling Wordset \ by Mitch Bradley \ \ This implementation uses the non-standard words SP@ , SP! , RP@ , and \ RP! . These words, or their equivalents, are present in most systems. \ Another implementation which does not use those non-standard words \ follows this implementation. \ Thanks to Don Colburn and Dean Sanderson for implementation suggestions. VARIABLE HANDLER \ Most recent error handler (should be a USER variable) : CATCH ( cfa -- error# | 0 ) ( cfa ) \ Return address is already on the stack SP@ >R ( cfa ) \ Save data stack pointer EXCEPTION @ >R ( cfa ) \ Previous handler RP@ HANDLER ! ( cfa ) \ Set current handler to this one EXECUTE ( ) \ Execute the word passed in on the stack R> HANDLER ! ( ) \ Restore previous handler R> DROP ( ) \ Discard saved stack pointer 0 ( 0 ) \ Signify normal completion ; : THROW ( ??? error# -- ??? error# ) \ Returns in saved context ?DUP IF HANDLER @ RP! ( err# ) \ Return to saved return stack context R> HANDLER ! ( err# ) \ Restore previous handler \ Remember error# on return stack before changing data stack pointer R> SWAP >R ( saved-sp ) \ err# is on return stack SP! R> ( err# ) \ Change stack pointer \ This return will return to the caller of catch, because the return \ stack has been restored to the state that existed when CATCH began \ execution . THEN ;
wmb@MITCH.ENG.SUN.COM (Mitch Bradley) (08/01/90)
Wil Baden> I'm looking for short but non-trivial examples of code that you
Wil Baden> believe is readable.
Another "readable code" submission:
\ LEFT-PARSE-STRING ( adr len char -- adra lena adrb lenb )
\ Splits a string into two halves around a delimiter character.
\ If the delimiter character is present in the string, adra lena is the
\ substring after the first occurrence of the character, adrb lenb
\ is the substring before it.
\ Both substrings exclude the character itself.
\
\ If the character is not present in the string, the original string
\ adr len is returned, and the flag on top of the stack is false.
\ Removes max(n,len) characters from the beginning of the string "adr len"
: /string ( adr len n -- adr+len adr-len )
over min >r swap r@ + swap r> -
;
: +string ( adr len -- adr len+1 ) 1+ ;
: -string ( adr len -- adr+1 len-1 ) swap 1+ swap 1- ;
\ adra,lena is the string after the delimiter
\ adrb,lenb is the string before the delimiter
\ lena = 0 if there was no delimiter
: left-parse-string ( adr len char -- adra lena adrb lenb )
>r over 0 2swap ( adrb 0 adra lena )
\ Throughout the loop, we maintain both substrings. Each time through,
\ we add a character to the first string and remove it from the second.
\ The loop terminates when either the second string is empty or the
\ desired character is found
begin dup while ( adr0 len0 adr1 len1 )
over c@ r@ = if \ Found it; exchange strings
r> drop -string 2swap exit ( adra lena adrb lenb )
then
2swap +string 2swap -string ( adr0 len0 adr1 len1 )
repeat ( adr0 len0 adr1 len1 )
\ Character not found. len1 is 0.
2swap ( adra lena adrb lenb )
r> drop
;
ForthNet@willett.pgh.pa.us (ForthNet articles from GEnie) (01/12/91)
Category 2, Topic 13 Message 9 Thu Jan 10, 1991 B.RODRIGUEZ2 [Brad] at 07:32 EST Well, maybe I'm missing something here, but I've had no trouble producing standalone/turnkey applications for my PC using LOVE- 83Forth and PC PowerForth. And that's not even counting TCOM, which I have but don't (yet) use. Now, if your gripe is that there's no _standard_ way to do this, you have a valid (although perhaps trivial) point. - Brad ----- This message came from GEnie via willett. You cannot Reply to the author using email. Please post a follow-up article, or use any instructions the author may have included (USMail addresses, telephone #, whatever). Report problems to: dwp@willett.pgh.pa.us or uunet!willett!dwp
ForthNet@willett.pgh.pa.us (ForthNet articles from GEnie) (03/30/91)
Category 2, Topic 13 Message 18 Mon Mar 25, 1991 ATFURMAN [Alan F.] at 23:50 PST Mitch Bradley writes: > Those languages tend to start out with a relatively straightforward > syntactic structure...After awhile it degenerates into a massive kludge. Syntactic diabetes. ----- This message came from GEnie via willett. You *cannot* reply to the author using e-mail. Please post a follow-up article, or use any instructions the author may have included (USMail addresses, telephone #, etc.). Report problems to: dwp@willett.pgh.pa.us _or_ uunet!willett!dwp
ForthNet@willett.pgh.pa.us (ForthNet articles from GEnie) (05/13/91)
Category 2, Topic 13
Message 19 Wed May 08, 1991
R.CAVANAUGH [BobC] at 23:38 MDT
In keeping with the spirit, here is my prefered way of formatting:
( F - PC dialect )
\ Modified query to select maximum number of input
: nquery ( n -- )
tib swap expect \ get digits from in stream
span @ #tib ! \ store number of inputs
>in off \ reset input pointer
;
\ General purpose routine to
\ input a number from the user
: get-num ( #digits base -- dnum flag ) \ flag - true for valid
base @ >r ! \ save current base, load new
." ?" \ prompt for input
nquery \ get <= #digits from input
bl word \ convert to counted str
?uppercase \ if hex, make sure upper
number? \ convert string to number
r> base ! \ restore old base
;
- Notes
1. If my words require detailed stack diagrams at each line,
I feel I need to rethink how I am doing it. Input stack condition
and output I feel should be sufficient
2. Each line should be functionally related, i.e. I would put
" 1 junk +! " as one line as incrementing a variable
is really one action, whereas
" something-to-test n =
if
do-if-true
else
do-if-false
then
"
is the way I like to structure conditionals. I can take a ruler
(or the col indicator on my editor) and see the subdivisions
of the algorithm.
3. I am a strong proponent of line-by-line comments, as to what you
are trying to do. I find this helps me a great deal when I come
back to code (in any language) n years later and try to reuse
or modify it. The flow of how I thought out what I was doing
rings bells, and I have found aids my collegues in understanding
and maintaining the code. I find the effort required pays later.
- Bobc
-----
This message came from GEnie via willett. You *cannot* reply to the author
using e-mail. Please post a follow-up article, or use any instructions
the author may have included (USMail addresses, telephone #, etc.).
Report problems to: dwp@willett.pgh.pa.us _or_ uunet!willett!dwp
ForthNet@willett.pgh.pa.us (ForthNet articles from GEnie) (05/13/91)
Category 2, Topic 13 Message 20 Fri May 10, 1991 D.RUFFER [Dennis] at 01:31 EDT Bob, just a couple of comments on your formatting style (:since you opened yourself up to it:) Lower case: I've seen many people adopt this before, and I can understand how someone who has a background in other languages (that aren't case sensitive) might prefer it. However, in my opinion, those people and languages are throwing away half the alphabet. I prefer to work with Forth's that _are_ case sensitive, and I tend to use lower case for low level words. That way, I have a built in indication of user interface words, with easy to remember sublayers. Comment/phrase: I used to work (some 12 years ago) on RPG programs written by IBM programmers. They tend to comment everything and in some cases it got to the point that could not even find the "real" source code lines. Personally, I can read the code much better than I can read the comments, that is why I work in a given language. At the most, all I care about is a brief description of _why_ a given module is needed. I _do not_ need a comment that tells me that the phrase: >IN OFF resets the input stream. Something like that just "gets in the way" when I'm trying to figure a section of code out. My personal opinion is that you should be able to _read_ Forth source code. The names should be choosen carefully so that the resulting modules "say" what they do. Some of this comes from internal naming conventions (i.e. "/" means initialize, ">" means pointer to..., etc.), but most comes from imaginitive vocabularies (i.e. a thesaurus). Vertical coding: Maybe this comes from my long time work with BLOCK files, but putting only a few things on a line seems to be wasteful to me. For me, 2 spaces is enough to seperate phases within Forth. I want to get as much of a given concept as I can on 1 page. As far as lining up structures goes, I sometimes find that useful, but again, I will only use it if the vertical space is not overused. Stack diagrams: Absolutely essential at the beginning of the word, but I agree with you about line by line analysis. If it is that hard to understand what is happening on the stack, then the word should be refactored. Comments in general: Not to belabor the point, but I feel that it is important. A comment that tells me _what_ something does is not near as useful as a comment that tells me _why_ it does it. What can be determined by examining the code, but why is often buried within the designer's mind. As a manager, a programmer's time if very valuable. I do not want him/her spending that time duplicating efforts by restating what the code does. Rather, I value the time invested in recording the reasons why the program is organized that way it is. It is much harder to write (as a programmer) but much more valuable years later when the original programmer may not even be available for consultation. Just some thoughts. :) DaR ----- This message came from GEnie via willett. You *cannot* reply to the author using e-mail. Please post a follow-up article, or use any instructions the author may have included (USMail addresses, telephone #, etc.). Report problems to: dwp@willett.pgh.pa.us _or_ uunet!willett!dwp
ForthNet@willett.pgh.pa.us (ForthNet articles from GEnie) (05/13/91)
Category 2, Topic 13 Message 21 Fri May 10, 1991 G.LEFAVE [Gene] at 14:18 CDT I've spent many years trying to decide this question. I have come to favor Dennis's style for the following reasons. 1. Block oriented text generally gets a couple of entire definitons on the screen at once. 2. Shadow blocks and the simple forth index are the easiest way I've found to understand a program. One can read the shadow's to find the point in a program that is of interest, then read the source. 3. Empty shadow blocks are painfully obvious on a listing and encourage programmers to fill them in. My own style is to try to terminate the lines with branching words. But I have to confess to having been taught by Kim Harris. A proponent of that style, the idea being that Forth using RPN notation should actually be indented from the right. ....... IF ............... ........ ELSE ............... ........ THEN I try not to get in these discussions, they're just as bad as the {} debates in another language. ----- This message came from GEnie via willett. You *cannot* reply to the author using e-mail. Please post a follow-up article, or use any instructions the author may have included (USMail addresses, telephone #, etc.). Report problems to: dwp@willett.pgh.pa.us _or_ uunet!willett!dwp
ForthNet@willett.pgh.pa.us (ForthNet articles from GEnie) (05/13/91)
Category 2, Topic 13 Message 22 Fri May 10, 1991 D.RUFFER [Dennis] at 22:30 EDT Gene, I also have been influenced by Kim Harris' coding conventions. For those who have never seen it, find the 1985 FORML Conference Proceedings. Pages 143- 74 contain his paper on "Forth Coding Conventions". It is worth reading by anyone who is concerned about programming style. Gene, you also mentioned "shadow" blocks. For those not familar with them, they are a mapping of source blocks to documentation blocks in a 1 to 1 relationship. In some cases, the second half of the file is reserved for them, in others a whole nother block file is created to hold them. They allow a simple facility to be created to manage them (i.e. one word to switch back and forth). However, although I use them, I've found that a block is even more limiting for documentation than it is for source. I'm always running out of room and then I have to leave something out. While they do accomplish the goal of getting the documentation both out of the way of the source and connected to it at the same time, they are not the panacea that I have been searching for. DaR ----- This message came from GEnie via willett. You *cannot* reply to the author using e-mail. Please post a follow-up article, or use any instructions the author may have included (USMail addresses, telephone #, etc.). Report problems to: dwp@willett.pgh.pa.us _or_ uunet!willett!dwp
ForthNet@willett.pgh.pa.us (ForthNet articles from GEnie) (05/13/91)
Category 2, Topic 13 Message 24 Sat May 11, 1991 R.CAVANAUGH [BobC] at 00:10 MDT Dennis, Thanks for the thoughts! I have used lower case in C, using caps for user definitions (such as #define MYTHING) and the habit has stuck. For some reason, small case seems more "friendly", but you raise a good point. As far as comments form vs function, I usually try to highlight items of a particular language that someone who does not know the syntax intimately can follow what's happening. As the example I used was getting into some of the inner workings of that forth, I was much more detailed than I would be for say 10 0 i . loop, which is one reasonably encapsulated and obvious. Since I work with a text-oriented forth, vertical and logical block spacing is again natural to me from the C world. By the way, re the post on eForth, how do I find out more about polyForth ? Thanks -- Bobc ----- This message came from GEnie via willett. You *cannot* reply to the author using e-mail. Please post a follow-up article, or use any instructions the author may have included (USMail addresses, telephone #, etc.). Report problems to: dwp@willett.pgh.pa.us _or_ uunet!willett!dwp