Shop OBEX P1 Docs P2 Docs Learn Events
The Forth Dimension. — Parallax Forums

The Forth Dimension.

Heater.Heater. Posts: 21,230
edited 2012-12-30 03:52 in Propeller 1
I recently got my knuckles rapped on the forum for criticizing the Forth language and/or it's implementations without having actually tried it. At least not in a few decades. I have to admit my knuckle wrapping was deserved. Given my respect for my peers here and the fact that they are right I decided to have a little look at Forth. Given that I have been tweaking with my FFT again recently I decided to kick off with trying to get some parts of that working in Forth, it seems like a good learning exercise as the FFT contains a good mix of typical arithmetic/logical ops, bit tweaking, conditionals, loops etc found in typical MCU programming.

So here is my first step into the Forth Dimension (cue the Twilight Zone music). Its a routine to reverse the low order bits of an integer.
\ Reverse L low order bits of integer I
: bitreverse ( L I -- RI )
    swap

    dup
    $aaaaaaaa and
    1 rshift
    swap
    $55555555 and
    1 lshift
    or

    dup
    $cccccccc and
    2 rshift
    swap
    $33333333 and
    2 lshift
    or

    dup
    $f0f0f0f0 and
    4 rshift
    swap
    $0f0f0f0f and
    4 lshift
    or

    dup
    $ff00ff00 and
    8 rshift
    swap
    $00ff00ff and
    8 lshift
    or

    dup
    16 rshift
    swap
    16 lshift
    or

    swap
    negate
    32 +
    rshift
;
.( Bit reversal) cr
130 dup .( Initial = ) . cr
8 bitreverse dup .( Reversed = ) . cr
8 bitreverse dup .( And again = ) . cr
bye
"Ah", you say, "There is a PASM instruction to do that in the Propeller". Quite so but that would not be Forth would it. As far as I can tell there is no bit reverse operator in any standard Forth , especially not in the gforth I have been playing with on my PC. I have no Propellers here to try out a Propeller Forth.

"Ah", you say, "Why have you written it out in so many short lines?" Well, this looks like such low level stuff to me a feel better writing out like you would ops in assembler, one by one.

Any comments welcome. Will this actually run on all the Propeller Forths we have?

Next up I need to figure out how to use arrays in Forth any suggestions?
«1345

Comments

  • Duane C. JohnsonDuane C. Johnson Posts: 955
    edited 2012-12-06 17:31
    Try this on PropForth:
    \ converted to propforth
    \ fl ( -- ) buffer the input and route to a free cog
    fl 
    decimal
    \ Reverse L low order bits of integer I
    : bitreverse \ ( L I -- RI )
        swap
    
        dup
        hAAAAAAAA and
        d1 rshift
        swap
        h55555555 and
        d1 lshift
        or
    
        dup
        hCCCCCCCC and
        d2 rshift
        swap
        h33333333 and
        d2 lshift
        or
    
        dup
        hF0F0F0F0 and
        d4 rshift
        swap
        h0F0F0F0F and
        d4 lshift
        or
    
        dup
        hFF00FF00 and
        d8 rshift
        swap
        h00FF00FF and
        d8 lshift
        or
    
        dup
        d16 rshift
        swap
        d16 lshift
        or
    
        swap
        negate
        d32 +
        rshift
    ;
    \ test ( -- )
    : test              c" Bit reversal" .cstr cr
      d130          dup c" Initial   = " .cstr . cr
      d8 bitreverse dup c" Reversed  = " .cstr . cr
      d8 bitreverse dup c" And again = " .cstr . cr 
      drop ;
    test
    
    or do it this way
    \ propforth version
    \ fl ( -- ) buffer the input and route to a free cog
    fl 
    \ Reverse L low order bits of integer I
    \ ( L I -- RI ) 
    : bitreverse
    \   rev ( n1 n2 -- n3 ) n3 is n1 with the lower 32-n2 bits reversed and the upper bite cleared
        rev    \ <------ I assume it uses the spin function only forthisly
    ;
    decimal
    \ test ( -- )
    : test                         c" Bit reversal" .cstr cr
      d130                     dup c" Initial   = " .cstr . cr
      d8 d32 swap - bitreverse dup c" Reversed  = " .cstr . cr
      d8 d32 swap - bitreverse dup c" And again = " .cstr . cr 
      drop ;
    test
    

    Duane J
  • Heater.Heater. Posts: 21,230
    edited 2012-12-06 17:48
    Are you saying that my effort won't run on Prop Forth as is?
    That's not very encouraging as I though I had used the simplest most common Forth possible.
    What's with all the "h0F0F0F0F" and "d8" stuff? Doesn't that lead to conflicts between numbers and words?
    I take it "rev" is a special Prop word.
  • Duane C. JohnsonDuane C. Johnson Posts: 955
    edited 2012-12-06 18:31
    Hi Heater;
    Heater. wrote: »
    Are you saying that my effort won't run on Prop Forth as is?
    It did mostly except for the:
    .(  (  )
    
    I replaced these with:
    c"  "  .cstr
    
    The rest worked OK.
    That's not very encouraging as I thought I had used the simplest most common Forth possible.
    These are the variations in the dialects. I never see these things as a particular problem.
    What's with all the "h0F0F0F0F" and "d8" stuff? Doesn't that lead to conflicts between numbers and words?
    Actually no. PropForth, unlike many other forths is case sensitive. I.e.:
    The b, lowercase, forces it to be binary.
    The d, lowercase, forces it to be decimal.
    The h, lowercase, forces it to be hexadecimal, and the rest must be uppercase.
    Actually any alpha character in arbitrary number bases must be upper case, there is just no defining character for them. ( Unless you define one.)

    I find it good practice, for me anyway, to make numbers unambiguous.
    [/QUOTE]I take it "rev" is a special Prop word.[/QUOTE]
    I assume so, at least in PropForth, since the hardware has it. There's really no need for the reverse command which would be slower.
    Actually you could have the word if you need it
    \ reverse ( L  I  -- RI )
    : reverse d32 swap - rev ;
    
    I hope that's right %^)
    Others are much better at the fine details than me.

    Duane J
  • David BetzDavid Betz Posts: 14,516
    edited 2012-12-06 18:44
    The state of Forth reminds me of the state of Lisp before Common Lisp and Scheme. Everyone had their own slightly different syntax. Some still do but most have converted on either Common Lisp or Scheme possibly with extensions. It's too bad there isn't a core word set that Forth implementations all agree to use. They could still add machine-specific words but there is really no reason to have different syntaxes for things as common as integers or literal strings. At least the ": ... ;" syntax seems to be universal.
  • prof_brainoprof_braino Posts: 4,313
    edited 2012-12-06 18:48
    What Duane said, with this addition:

    Propforth supports arbitrary number base, we prefix with lower case d, h, b for decimal, hex and binary (I didn't know we had binary, please verify),
    and ALSO we can prefix with lowercase z to use radix 64.

    [The choice of d, h, and b are my fault; I convinced Sal these are more intuitive to new users than %, $, # and whatever, as those are never consistent across languages. Sorry for the inconvenience]

    RADIX 64 is handy for text encoding long strings of assembler. SO it actually WOULD be forth to optimize your routine in assembler, and propforth has an easy way to to this. Although I've not done it, Sal, Caskaz, Brian and Nick are the ones to ask. AND Nick is the Fast Hartley guy, it not cheating to cheat of of him. Anything is fine as long as we get an FFT that passes the heater test.

    There are other cool things with assembler in propforth but I have not mastered them and therefore have not documented them yet. But, if you get to the point you want to use it, we can focus on that part of the docs for you. But first you should "get it working in forth" before you "get it fast with assembler", as this is the recommended development path.
  • Duane C. JohnsonDuane C. Johnson Posts: 955
    edited 2012-12-06 19:10
    BTW do you have PropForth running yet? I highly recommend it.

    For debugging my code I have added my own extensions:
    fl
    decimal
    \ --------------- words added to PropForth -----------------
    \ fence ( -- )
    : fence ;
    0 wvariable baseold
    \ binary ( -- ) switch to binary
    : binary h2 base W! ;
    \ .hex ( n -- ) emit a single hex digit
    : .hex hF and d48 + dup d57 > if d7 + then emit ;
    \ .x   ( n -- ) emit a single digit in the current base
    : .x base W@ u/mod drop d48 + dup d57 > if d7 + then dup d93 > if d3 + then emit ;
    
    \ Display formated number functions
    \ .bn ( n1 n2 -- ) emit n1 as an n2 (1 to 32) place binary number
    : .bn dup 0 do 2dup d32 swap - rev 1 i lshift and if ." 1" else ." 0" then loop 2drop ;
    \ .dn ( n1 n2 -- ) emit n1 as an n2 place decimal number
    : .dn dup >r 0 do   d10 u/mod loop drop r> 0 do .hex loop ;
    \ .hn ( n1 n2 -- ) emit n1 as an n2 place hex number
    : .hn dup >r 0 do   d16 u/mod loop drop r> 0 do .hex loop ;
    \ .xn ( n1 n2 -- ) emit n1 as an n2 place number in the current base
    : .xn dup >r 0 do base W@ u/mod loop drop r> 0 do .x loop ;
    
    \ ------------------- ascii escape sequences ------------------
    \ ascii escape sequences start with ESC
    \ Clearly Plagerized from "prof_braino"
    : esc     d27 emit ; \ ESCAPE
    : csi esc d91 emit ; \ [
    : capK       ." K" ; \ capital K
    : smallm     ." m" ; \ small m
    \ .digits ( n -- ." emit as decimal characters" ) for by the "at" command to convert 0-99 for emit
    : .digits dup d9 > if d2 else 1 then .dn  ;
    \ at ( column line -- ) put cursor at x y,  column line, from upper left corner
    : at csi .digits ." ;" .digits ." f" ;
    : home       csi ." 1;1f" ;
    : clear      csi ." 2J"   ;
    : preclear   csi ." 1J"   ;
    : postclear  csi ." 0J"   ;
    : cls home clear ;
    : clear-eol  csi d0 .digits capK ;
    : clear-bol  csi d1 .digits capK ;
    : clear-line csi d2 .digits capK ;
    \ attributes esc[d#;d#m  = csi d#;d#m
    : atoff      csi d48 emit smallm ; \ 0 off
    : bold       csi d49 emit smallm ; \ 1 bold
    \ : faint    csi d50 emit smallm ; \ 2 faint ?
    \ : italic   csi d51 emit smallm ; \ 3 italic ?
    : underscore csi d52 emit smallm ; \ 4 underscore (mono) ?
    \ : sblink   csi d53 emit smallm ; \ 5 slow blink PINK
    \ : fblink   csi d54 emit smallm ; \ 6 fast blink
    : reverse    csi d55 emit smallm ; \ 7 reverse
    \ : conceal  csi d56 emit smallm ; \ 8 conceal ?
    \ : crossout csi d57 emit smallm ; \ 9 crossed out ?
    \ there are lots more...
    \ ( n -- ) Curser movements
    : cup        csi    .digits ." A" ; \ up
    : cdown      csi    .digits ." B" ; \ down
    : cforward   csi    .digits ." C" ; \ forward
    : cback      csi    .digits ." D" ; \ backward
    : csave      csi            ." s" ; \ save    position
    : crestore   csi            ." u" ; \ restore position
    \ ( -- ) graphics mode Color attributes Forground/Background
    : black      csi d30 .digits smallm ;
    : onblack    csi d40 .digits smallm ;
    : red        csi d31 .digits smallm ;
    : onred      csi d41 .digits smallm ;
    : green      csi d32 .digits smallm ;
    : ongreen    csi d42 .digits smallm ;
    : yellow     csi d33 .digits smallm ;
    : onyellow   csi d43 .digits smallm ;
    : blue       csi d34 .digits smallm ;
    : onblue     csi d44 .digits smallm ;
    : magenta    csi d35 .digits smallm ;
    : onmagenta  csi d45 .digits smallm ;
    : cyan       csi d36 .digits smallm ;
    : oncyan     csi d46 .digits smallm ;
    : white      csi d37 .digits smallm ;
    : onwhite    csi d47 .digits smallm ;
    \ ----------------- end ascii escape sequences ----------------
    
    \ .sx ( -- ) prints out the stack with a letter tag on the end Non-Destructivly
    : .sx ." ST: " $C_stPtr COG@ 2+ dup $C_stTop < if $C_stTop swap - 0 do $C_stTop 2- i - COG@
      .long space loop else drop then ;            \ removed cr from end of the word st?
    : .s0 .sx ." <0" cr ; : .s1 .sx ." <1" cr ; : .s2 .sx ." <2" cr ; : .s3 .sx ." <3" cr ;
    : .s4 .sx ." <4" cr ; : .s5 .sx ." <5" cr ; : .s6 .sx ." <6" cr ; : .s7 .sx ." <7" cr ;
    : .s8 .sx ." <8" cr ; : .s9 .sx ." <9" cr ; : .sA .sx ." <A" cr ; : .sB .sx ." <B" cr ;
    : .sC .sx ." <C" cr ; : .sD .sx ." <D" cr ; : .sE .sx ." <E" cr ; : .sF .sx ." <F" cr ;
    : .sG .sx ." <G" cr ; : .sH .sx ." <H" cr ; : .sI .sx ." <I" cr ; : .sJ .sx ." <J" cr ;
    : .sK .sx ." <K" cr ; : .sL .sx ." <L" cr ; : .sM .sx ." <M" cr ; : .sN .sx ." <N" cr ;
    : .sO .sx ." <O" cr ; : .sP .sx ." <P" cr ; : .sQ .sx ." <Q" cr ; : .sR .sx ." <R" cr ;
    : .sS .sx ." <S" cr ; : .sT .sx ." <T" cr ; : .sU .sx ." <U" cr ; : .sV .sx ." <V" cr ;
    : .sW .sx ." <W" cr ; : .sX .sx ." <X" cr ; : .sY .sx ." <Y" cr ; : .sZ .sx ." <Z" cr ;
    \ ------------------------------------------------------------- 
    \ .sd ( -- ) prints out the stack as 10 place decimal numbers Non-Destructivly
    : .sd ." STD:" $C_stPtr COG@ 2+ dup $C_stTop < if $C_stTop
      swap - 0 do $C_stTop 2- i - COG@ d10 .dn space loop else drop then cr ;
    \ .sh ( -- ) prints out the stack in hex Non-Destructivly
    : .sh ." STH:" base W@ baseold W! hex .sx cr baseold W@ base W! ;
    
    \ cb ( -- ) clear TeraTerm scroll buffer assuming TeraTerm is set to 512 lines
    : cb d509 0 do cr loop bold blue 0 0 at clear ;
    
    \ pins? ( -- ) samples the current status of all the io pins and prints them to the terminal
    : pins?
      d32 0 do ."  "   i d2 .dn loop cr
      d32 0 do i px? if ."  HI" else ."  LO" then loop cr
      d32 0 do dira COG@ i rshift 1 and if ."  OT" else ."  IN" then loop cr ;
    \ Alternate method
    \ pins? ( -- ) samples the current status of all the io pins and prints them to the terminal
    \ : pins?
    \   d32 0 do ."  "   i d2 .dn loop cr
    \   d32 0 do i px? if ."   ^" else ."   v" then loop cr
    \   d32 0 do dira COG@ i rshift 1 and if ."   <" else ."   >" then loop cr ;
    \ fence ( -- )
    : fence ;
    \ -------------- end words added to PropForth -----------------
    
    One of the most useful set of words are the .sx family of stack display words.
    Extremely useful for decoding complicated stack manipulations.
    fl
    \ test ( n1 n2 n3 n4 --- n1 ) example
    : test
    .s0 dup .s1 over .s2 * .s4 * .s5 *  .s6 / .s7 + .s8 - .s9 ;
    sc
    cb
    10 20 30 40 test
    
    the .s words non-destructivly display the stack.
    Once it works just remove them.
    Cool huh!!

    Duane
  • Duane C. JohnsonDuane C. Johnson Posts: 955
    edited 2012-12-06 19:25
    Hi Professor;
    (I didn't know we had binary, please verify)
    decimal
    Prop0 Cog6 ok
    b1010100101010
    Prop0 Cog6 ok
    . cr
    5418
    Prop0 Cog6 ok
    
    Seems to work fine.

    Duane J
  • Heater.Heater. Posts: 21,230
    edited 2012-12-06 19:39
    Hmm...Early days yet but I'm gunning for a lowest common denominator that will run on as many Forths as possible. As a minimum everything has to work on gforth as I often don't have any Props around and that is what I have in Linux. If that means, for example, not using strings because everyone has a different idea about string syntax then there won't be any strings.

    I'm really not into optimizing this with some weird Forth assembler. The idea here is for me to learn some Forth. I already have a PASM version of the FFT all be it called from Spin. In C the propgcc compiler compiles it into COG code that runs nearly as fast. Anyway someone has already done that optimization in a Forth version of fft_bench. Sorry I forget who now. If anyone want's to point out that my Forth is crappy and can be optimized that would be great.

    The fact that I have kicked off with FFT code is not of any consequence. It's just an exercise for this beginner and could have been anything. However we do have the FFT in a bunch of languages now so at the end of the exercise I can look back at them all and see which one I feel most comfortable with.

    What is the "heater test"?

    Next up I want to tackle the integer square root function. For that I really have the urge to use local variables. Do the various Propeller Forths support local variables as in {a b c} ?
  • Heater.Heater. Posts: 21,230
    edited 2012-12-06 19:52
    Duane,

    Thanks.

    Does Prop Forth accept decimal numbers without the d ?

    if so I'm quite willing to change all the hex literals to decimal as it wold make the code more portable.
  • Duane C. JohnsonDuane C. Johnson Posts: 955
    edited 2012-12-06 20:10
    Heater. wrote: »
    Does Prop Forth accept decimal numbers without the d ?
    Yes, just make sure the base is set to decimal, or other base as needed.
    I just like to formally set the number type so I don't make mistakes.

    Technically, the internal number system is usually 32 bit binary, sometimes 16 bit or 8bit.

    The base is really meant as a convention for human input and output.
    It doesn't cost any time to formally set the number to decimal, hex, or anything else as they are converted to binary at compile time anyway,(when words are entered into the dictionary).

    Note, once the word is entered the base can be changed at will and there will be no effect on the entered word.
    if so I'm quite willing to change all the hex literals to decimal as it wold make the code more portable.
    You can still sprinkle numbers of different basses by changing the base before the number is entered.
    This can be done 2 ways:
    1. use the hex , or decimal , or binary word.
    2. or formally store the radix in the base variable.
    These general words are in all forths I know about.

    Duane J
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-12-06 20:20
    Heater, your code works fine under pfth with some modifications. I had to add a HEX command before defining the BITREVERSE word, and then added a DECIMAL command after it. I also had to remove the $ characters, and change 16 and 32 to the hex equivalents of 10 and 20. I had to make the same changes that were made for PropForth to run the tests. pfth doesn't support strings in the interpreter mode, nor does it support the .( word. I hope to resolve all of these issue in a future update of pfth, but instead of using $ for hex numbers I'll probably use H#, which is the more common way of specifying hex in Forth.

    At some point I also plan on adding a COGX2 word, which will allow me to execute Prop-specific instructions such as REV. pfth already has a COGX1 word that allows it to execute the Prop's hubops.

    Arrays can be implemented in Forth using CREATE and DOES>. "Starting Forth" contains the following example of an array definition:
    : ARRAY ( #rows #cols -- )
           CREATE DUP , * ALLOT
           DOES> ( member: row col -- addr )
                ROT OVER @ * + +  CELL+ ;
    
    A 4x5 array can then be create by typing "4 5 array x". The array element of x at (2, 3) can then be read by typing "2 3 x c@". The magic is performed by the DOES> word. Basically, the words between CREATE and DOES> will create the variable "x", store the number of columns in the first cell and allocate 2*3 = 6 bytes for the array. The words between DOES> and ; will be executed whenever x is accessed. It computes the appropriate offset for the specified row and col, and adds it to the address of the first cell of x.

    Check out "Starting Forth" and "A Beginners Guide to Forth" for more information on what DOES> does.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2012-12-06 23:24
    Dave Hein wrote: »
    I'll probably use H#, which is the more common way of specifying hex in Forth.
    Not quite sure about that, I have never seen it used. I know PropForth likes to put the h before the number contrary to accepted use which always has it after the number of a $ sign before the number. Tachyon accepts either the $ prefix or the h suffix as acceptable and furthermore allows symbols to be mixed with the digits. The rule is symbols are allowed but in which case 2 or more digits are needed so that you can say $801F-0000 or using a # prefix for decimal #80,000,000 is also acceptable. Spin and PASM, the default language for the Propeller also uses the $ and % prefixes so even more reason to use that.


    BTW, why can't you just add a REV word to the kernel as Tachyon does:
    [B][COLOR=#000000][FONT=Ubuntu Mono]
    [FONT=courier new] ' REV ( n1 bits -- n2 ) Reverse LSBs of n1 and zero-extend[/FONT][/FONT][/COLOR][FONT=courier new]
    [COLOR=#FFFFFF][B]_REV[/B][/COLOR][COLOR=#000000]              rev    tos+1,tos[/COLOR]
              [COLOR=#000000]        jmp    #DROP[/COLOR]
    [/FONT][/B]
    
  • Ron SutcliffeRon Sutcliffe Posts: 420
    edited 2012-12-07 03:07
    $ for base 16, % base 2 , oherwise decimal, but base set to 16 on boot
  • prof_brainoprof_braino Posts: 4,313
    edited 2012-12-07 04:31
    Heater. wrote: »
    Does Prop Forth accept decimal numbers without the d ?

    if so I'm quite willing to change all the hex literals to decimal as it wold make the code more portable.
    Heater. wrote: »
    Does Prop Forth accept decimal numbers without the d ?
    if so I'm quite willing to change all the hex literals to decimal as it wold make the code more portable.

    What Duane said with this addition:

    Propforth buffers an incoming datastream for example via the
    fl
    
    word by running a separate interpreter in another cog. This means your development cog (cog6) is free to continue doing work while the text is being interpreted (some steps of the compilation and dictionary insert do take noticeable effort and therefore time).

    Each cog can have a different base, which we can set on the fly. This is very powerful and useful, but we found it gets to be a pain in the brain to manage this manually, and so it is easier to explicitly state the base in the code. It actually makes things MUCH clearer and cleaner, although it is different from what we've grown accustomed to struggling with. Please give explicit base declaration for number literals a change, although once you see its usefulness you may be forever tainted and not tolerant of its absence in other environments.

    Also, don't worry about portability, it not like C where its a big deal. These are mostly small programs that you or we are personally intimate with, and well written code is a snap to port or return to. (If your code is NOT easy to understand when you come back to it, it is a sign of weak programming technique. This goes away after a short while).
  • prof_brainoprof_braino Posts: 4,313
    edited 2012-12-07 04:44
    One thing: If you are going to start by following every exercise in Brodie's "Starting Forth" book, you might want to start with pfth. Remember that this is still bleeding edge and a work in progress. If you intend to focus on fastest and smallest, you should try Tachyon. This is older but still in a very dynamic development phase. If you wish to take advantage of a more mature item, consider propforth. Propforth implements very well though out solutions to the issues Dave and Peter are discovering. All three provide slightly different approaches to any given issue, and all are valid. But there may be an advantage to building on a thoroughly developed, complete project, rather than the experimental ones. So the key question is, do you wish to influence the creation of the kernel, or do you wish to simply use forth on the prop?

    Propforth is tailored to the prop architecture, Tachyon is tailored for speed and minimal size, and pfth is tailed for ANSII compatibility.
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-12-07 04:48
    Also, don't worry about portability, it not like C where its a big deal.
    Yes, it you want to write portable code you should use some other language. Doug, I can't believe you said that! Of course you can write portable Forth code. You just need a standard Forth interpreter.
  • Heater.Heater. Posts: 21,230
    edited 2012-12-07 06:07
    OK guys,

    I can't believe I'm having such a rough start over such a simple thing. Is there one way to specify hexadecimal literals that works in all Propeller Forths? Or should I switch bases with "hexadecimal" and "decimal" as and when required? Or should I just do everything in decimal ?

    Braino,
    Also, don't worry about portability...
    I am exactly going to worry about portability.

    As I said whatever I do has to work under gforth as that will be my playground when I don't have any Propellers around. There is nothing in the FFT that requires any specific Propeller features. It's only calculating a lot of stuff after all. At least not until you want to get into speeding it up. Besides there may be other Forths on other MCUs I want to play on. It has to work on as many Propeller Forths as possible.
    If your code is NOT easy to understand when you come back to it, it is a sign of weak programming technique.
    I totally agree. Especially as the FFT itself, in this case, is hard enough to understand when spelled out in the most simple way. That's also why I don't want any non-standard, non-portable constructs in there. Anything specific to a Forth implementation is an extra little complication to have to remember.

    I have been flicking back and forth between Brodie's book of which I have fond memories from the 1980's and the gforth tutorials which seems to be lacking in some areas.
    But there may be an advantage to building on a thoroughly developed, complete project, rather than the experimental ones.
    I consider the fft_bench to be a complete project, it's not exactly trivial, it works, it has know results, it just needs doing in Forth. That is my chosen exercise and it has many interesting little sub-exercises.

    Please, please, does any Prop Forth support local variables?

    Actually I guess according to my portability criteria if even one Prop Forth does not support local variables then I won't use them.
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-12-07 06:11
    BTW, why can't you just add a REV word to the kernel as Tachyon does:
    [B][COLOR=#000000][FONT=Ubuntu Mono]
    [FONT=courier new] ' REV ( n1 bits -- n2 ) Reverse LSBs of n1 and zero-extend[/FONT][/FONT][/COLOR][FONT=courier new]
    [COLOR=#FFFFFF][B]_REV[/B][/COLOR][COLOR=#000000]              rev    tos+1,tos[/COLOR]
              [COLOR=#000000]        jmp    #DROP[/COLOR]
    [/FONT][/B]
    
    Peter, that looks great. So this get's compiled directly into cog RAM, correct? The only drawback would be that one could quickly use up the remaining cog RAM by implementing all of the Prop's special operators. I suppose a special cog word would only be implemented when needed. Does Tachyon support some other way to execute a Prop instruction, or is this the only way to do it?

    BTW, Doug and Peter, you haven't answered Heater's question about implementing arrays. How do you implement arrays in PropForth and Tachyon?
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2012-12-07 06:21
    Dave Hein wrote: »
    Peter, that looks great. So this get's compiled directly into cog RAM, correct? The only drawback would be that one could quickly use up the remaining cog RAM by implementing all of the Prop's special operators. I suppose a special cog word would only be implemented when needed. Does Tachyon support some other way to execute a Prop instruction, or is this the only way to do it?

    BTW, Doug and Peter, you haven't answered Heater's question about implementing arrays. How do you implement arrays in PropForth and Tachyon?
    Because REV is such an awkward operation otherwise it just makes sense to use the Prop's instruction and this coupled with the way Tachyon addresses the stack means it's a no-brainer, just two instructions. Some other operations might have a mix of a bytecode instruction (PASM) and bytecode (HUB). There is an instruction to allow a PASM instruction to be loaded and executed but I mainly use those for the hubops.
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-12-07 06:22
    Heater, I think the only method for specifying numbers that works on all Forths is to switch bases. It's going to be challenging to write a Forth program that works on gForth/pfth, PropForth and Tachyon. gForth and pfth should have a lot of words in common. I have ported a few programs written for gForth to pfth. However, I usually encounter a few gForth-specific words that I have to convert to ANS Forth. You will need to implement several words to port this from gForth to PropForth or Tachyon. I would suggest keeping the vocabulary as small as possible, and try to use a common set of words. Loopy has documented the standard words that PropForth supports. I don't think anybody has done this for Tachyon yet.
  • Heater.Heater. Posts: 21,230
    edited 2012-12-07 06:38
    No news on local variables yet then.
    I also would appreciate the lowest common denominator way to set use arrays and look up tables.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2012-12-07 06:40
    Heater. wrote: »
    OK guys,

    I can't believe I'm having such a rough start over such a simple thing. Is there one way to specify hexadecimal literals that works in all Propeller Forths? Or should I switch bases with "hexadecimal" and "decimal" as and when required? Or should I just do everything in decimal ?

    Forth doesn't normally handle number base prefix or suffix but it can be added on if the Forth supports a fall-through when a word cannot be found nor converted to a number. Even though I have all the special processing built in there is still a vector called "unum"
    unum res 2 ' User number processing routine - executed if number failed and UNUM <> 0
    and
    unknown byte REG,unum,WFETCH,QDUP,_IF,03,ACALL,_AGAIN,@un01-@chkeol

    I have always preferred having a $ sign for hex numbers or alternatively the "h" for a suffix. This has been standard on so many assemblers that I have worked with but I have never liked the 0x prefix that somehow crept into C.

    Please, please, does any Prop Forth support local variables?

    Actually I guess according to my portability criteria if even one Prop Forth does not support local variables then I won't use them.

    Well, I aim to have them fully implemented but at present I have this:
    [COLOR=#000000][FONT=Ubuntu Mono]pri [/FONT][/COLOR][COLOR=#000000][FONT=Ubuntu Mono][B](RECT)[/B][/FONT][/COLOR]
    [COLOR=#000000][FONT=Ubuntu Mono]	X4 X3 X2 HLINE[/FONT][/COLOR]
    [COLOR=#000000][FONT=Ubuntu Mono]	X4 X3 X1 1- + X2 1- HLINE[/FONT][/COLOR]
    [COLOR=#000000][FONT=Ubuntu Mono]	X4 X2 + 1- X3 X1 VLINE[/FONT][/COLOR]
    [COLOR=#000000][FONT=Ubuntu Mono]	X4 X3 X1 VLINE[/FONT][/COLOR]
    [COLOR=#000000][FONT=Ubuntu Mono]	;[/FONT][/COLOR]
    [COLOR=#000000][FONT=Ubuntu Mono]\ Draw a rectangle[/FONT][/COLOR]
    [COLOR=#000000][FONT=Ubuntu Mono]pub [/FONT][/COLOR][COLOR=#000000][FONT=Ubuntu Mono][B]RECT[/B][/FONT][/COLOR][COLOR=#000000][FONT=Ubuntu Mono] ( x1 y1 width height -- )[/FONT][/COLOR]
    [COLOR=#000000][FONT=Ubuntu Mono]         ( X4 X3 X2    X1 )[/FONT][/COLOR]
    [COLOR=#000000][FONT=Ubuntu Mono]	4 LOCAL (RECT) 4 RELEASE[/FONT][/COLOR]
    [COLOR=#000000][FONT=Ubuntu Mono]	;
    
    [/FONT][/COLOR]So 4 LOCAL will grab 4 parameters from the stack and store them in a local variables stack. X1 X2 X3 X4 implicitly fetch those variables with minimal overhead. I do not try to create local results though, I just work the stack as usual but all the headache stuff is taken care of. Eventually the symbol names enclosed in the stack comment will be used instead and so the LOCAL and RELEASE operator will not be required either.
  • Heater.Heater. Posts: 21,230
    edited 2012-12-07 07:45
    Peter,

    Hmm..I did not understand any of that. None of it looks like "book forth". What is with the pri and pub?
    Are you saying that the stuff in comments will start to have meaning to the compiler?!!

    Sounds like locals are off the table as I it looks like there is not going to be any common ground here.
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-12-07 07:49
    pfth doesn't have local variables yet. It's something on the TODO list. Local variables are nice, but I would avoid them if you want to write code that runs under different Forth interpreters. In my opinion, one of biggest problems with programming in Forth is having to keep track of what's on the stack. Most other languages manage the stack for you, so you don't have to worry about the low-level details. The standard practice for Forth is to break large programs up into very small words that only work with the top 4 or 5 elements on the stack.

    As far as arrays are concerned, I think you will have to break the ARRAY definition that I presented earlier into two words. The first word creates the array, and contains the code before DOES>. The second word would be use to get the address of an element in the array, and contains the code after DOES>.
  • mindrobotsmindrobots Posts: 6,506
    edited 2012-12-07 07:59
    Dave Hein wrote: »
    pfth doesn't have local variables yet. It's something on the TODO list. Local variables are nice, but I would avoid them if you want to write code that runs under different Forth interpreters. In my opinion, one of biggest problems with programming in Forth is having to keep track of what's on the stack. Most other languages manage the stack for you, so you don't have to worry about the low-level details. The standard practice for Forth is to break large programs up into very small words that only work with the top 4 or 5 elements on the stack.

    As far as arrays are concerned, I think you will have to break the ARRAY definition that I presented earlier into two words. The first word creates the array, and contains the code before DOES>. The second word would be use to get the address of an element in the array, and contains the code after DOES>.

    Dave's right on with both these comments.

    Any Forth practitioner will frown on local variables and say you need to refactor your words if the stack becomes unmanageable. Any word should keep stack elements down to a small set that can be kept straight in the authors brain.

    I think is pfth is the only implementation with the DOES> word which mean it is the only one that can have an ARRAY word that does one thing at compile time and another at implementation time. Others will need an array creation word and an array accessor word.

    Factor, a Forth derivative for PCs can use the stack effects documentation, ( x y -- z) for creation of local variables if you want, much like Peter intends for Tachyon.
  • Heater.Heater. Posts: 21,230
    edited 2012-12-07 08:51
    Dave,
    ...one of biggest problems with programming in Forth is having to keep track of what's on the stack.
    Seems to be so.
    ...standard practice for Forth is to break large programs up into very small words that only work with the top 4 or 5 elements on the stack.
    So I gather. Which means your nicely laid out pseudo code of an algorithm which is clear and concise gets chopped in to mess unintelligible snippets.

    Chuck Moore,
    I remain adamant that local variables are not only useless, they are harmful.
    Chuck was clearly insane.

    OK, undeterred, local variables are out and we boldly go forth where no man has gone forth before...
  • Heater.Heater. Posts: 21,230
    edited 2012-12-07 09:03
    mindrobots,

    As far as I can tell I don't need a DOES> word to get my arrays going. Which is nice as I have no idea what DOES> does.
    Factor, a Forth derivative for PCs can use the stack effects documentation, ( x y -- z) for creation of local variables if you want,
    No way, I want lowest common denominator constructs for this exercise. Factor is not even Forth any more.

    I'm kind of thinking it would be an idea to tweak my version of a TINY compiler to emit Forth source code instead of x86 or Propeller instructions and then cast the FFT in TINY and generate Forth from it. Might be quicker than writing Forth by hand:)
  • David BetzDavid Betz Posts: 14,516
    edited 2012-12-07 09:04
    Heater. wrote: »
    I'm kind of thinking it would be an idea to tweak my version of a TINY compiler to emit Forth source code instead of x86 or Propeller instructions and then cast the FFT in TINY and generate Forth from it. Might be quicker than writing Forth by hand:)
    What does Tiny look like?
  • Heater.Heater. Posts: 21,230
    edited 2012-12-07 09:28
    David,

    PropTiny was the result of my working through Jack Crenshaw's "Let's build a Compiler" articles years ago. I did my versions of Jack's Pascal experiments in C and ended up generating x86 assembler output. I revived it to generate Prop LMM code some years later. It's not at all efficient, no optimization, I was just so amazed that I had managed to build a compiler at all, a task that had fascinated me for a long time before and which I never understood from picking up books on the subject.
    I don't even remember what features I put in it now, variables, statements, expressions, conditionals, loops, signed and unsigned bytes words and longs, global and local variables. No arrays, structures or strings. Block structured like Pascal or C. Half way from Jacks TINY language to the bigger KISS.

    I keep wanting to revisit it but there is never enough time. I suspect today it is now possible to build PropTiny with propgcc and actually have a C like compiler running on the Prop itself! That idea could spur me into action again. (needs a PASM assembler that runs on the Prop though)

    PropTiny is here: http://forums.parallax.com/showthread.php?113228-PropTiny-Jack-Crenshaw-s-TINY-language-for-the-Prop

    Turns out my LMM generation is not so hot, I didn't do jumps the proper way.
  • prof_brainoprof_braino Posts: 4,313
    edited 2012-12-07 09:33
    Dave Hein wrote: »
    Yes, it you want to write portable code you should use some other language. Doug, I can't believe you said that! Of course you can write portable Forth code. You just need a standard Forth interpreter.

    Ok guys. Define what you mean by portability.

    Do you write assembler on one hardware, (x86) and expect it to be directly portable to another hardware (68k)? No

    Are you going to write code on the prop, and expect it to be directly portable on an ATEMGA? In ANY language? No.

    Are you going to write a BASIC program for the prop, and expect it to be directly portable to another BASIC on the prop? No. There will all ways be at least something different.

    IF you write in FORTH, is any one going to require you to run you program on all three current incarnation of forth with no changes. Possibly, but its still kind of silly.

    Please look at the ANSII terminal control support for propforth.

    http://propforth.googlecode.com/files/ANSI%20Escape%20Sequences20120704-1652.f

    This should pretty much run on ANY forth, as I developed it on the PC and ported it to propforth. Some stuff is different, but its the same for the most part. The things that make it different on the prop or the PC are so small that you don't even notice them. The effort is similar to when you notice spell "the" as "teh". You fix it and move on.

    So you have to change 1B to h1B. Or change h1B to $1B. How much is that going to kill you? Sheesh!

    Ok this numeric litteral thing is tough on your established habits, sorry about that. It is my fault.
Sign In or Register to comment.