Shop OBEX P1 Docs P2 Docs Learn Events
FORTH - 2swap — Parallax Forums

FORTH - 2swap

prof_brainoprof_braino Posts: 4,313
edited 2013-12-11 04:14 in General Discussion
If you don't care about FORTH, no need to keep reading or responding.

A question came up about a less commonly used FORTH word - 2swap

SWAP - swtches the top two values on the stack
: swap \ ( n1 n2 - n2 n1 )

2swap - switches the top PAIR of values on the stack
: 2swap \ ( n1 n2 n3 n4 - n3 n4 n1 n2 )

This is not included in the default propforth dictionary. A user found a reference to this word in a thrid party example.
To my knowledge, this is the first time somebody noticed its absence when writing code in propforth.

Should this word be added to the kernel, since it is defined in the ANS forth standard DPANS94?
Should this word be left to the user to add as an extension, since it is seldom used and would consume limited dictionary space?

What do you think? Other reasons for or against?
«1

Comments

  • kwinnkwinn Posts: 8,697
    edited 2013-06-18 08:09
    Ah, the old quandary. 2swap or not 2swap. If it has taken this long to find it is missing then it is indeed rarely used so I would say it is best not2add it to the kernel.
  • mindrobotsmindrobots Posts: 6,506
    edited 2013-06-18 08:33
    I'd vote NOT 2swap in the released PropForth kernel words in respect for kernel size versus frequency of use.

    BUT as non-implemented ANSI words are recognized, I think there needs to be an addendum document that gives you a PropForth ready example to implement the word if you want it. Some folks may run across the use of an ANSI word and not know how to best implement it to get over their current roadblock. If there was a file of ready to go words to add in, it would make stumbling a little less painful.
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-06-18 08:43
    2SWAP can be implemented as ": 2SWAP ROT >R ROT R> ;". Since it's rarely used in PropForth it's probably better to put it in an ANS Forth extras file that could be loaded if needed. You can find the definition for most ANS Forth core words in pfth's init.fth file, or you can see how it's implemented in eForth.
  • LoopyBytelooseLoopyByteloose Posts: 12,537
    edited 2013-06-18 10:55
    Dictionaries have a tendency to perpetually grow larger and larger. And so does documentation.

    I like eForth for a quick reference of anything that needs to be quickly added. The ANSI Forth spec does NOT provide the info to make words from other words and factoring for yourself is really a bit mental for a language that has this maturity.

    I believe that Dave factored his ANS Forth core words independently for the init.fth before discovering eForth was available.
  • Martin_HMartin_H Posts: 4,051
    edited 2013-06-18 16:15
    Reading this thread got me interested in Forth again. I hope you guys are happy with yourselves. :^)
  • prof_brainoprof_braino Posts: 4,313
    edited 2013-06-18 18:53
    mindrobots wrote: »
    BUT as non-implemented ANSI words are recognized, I think there needs to be an addendum document that gives you a PropForth ready example to implement the word if you want it.

    Noted...
    Dave Hein wrote: »
    2SWAP can be implemented as ": 2SWAP ROT >R ROT R> ;". ... You can find the definition for most ANS Forth core words in pfth's init.fth file, or you can see how it's implemented in eForth.

    This is a really good idea. After the "build the bot" sessions at the start of class next fall, I will attempt to create a "programming" class. I think I will have the kids impleiment non-kernel ANS words in propforth, using init.fth and eforth examples. Then the kids can get used to adding to the extensions and documentation.
    Martin_H wrote: »
    Reading this thread got me interested in Forth again. I hope you guys are happy with yourselves. :^)

    Muhuhahah! My evil plan is working!
  • LoopyBytelooseLoopyByteloose Posts: 12,537
    edited 2013-06-19 02:49
    Martin_H wrote: »
    Reading this thread got me interested in Forth again. I hope you guys are happy with yourselves. :^)

    It may be a good time to get started. I think we have finished with the debate of standard versus non-standard. The Propeller really requires BOTH for users to really be able to do their own thing in Forth.

    Of course, some of the legacy and PC supported words will never take hold.... it is an all new world for Forth on the Propeller.
  • prof_brainoprof_braino Posts: 4,313
    edited 2013-06-19 07:42
    I agree. The kids can start building an "extensions for Starting Forth" library. These will take space, but only need to be loaded for doing examples in "Starting Forth"; or individually loaded on a case by case basis. The kids can drive which function need to be added by the examples they choose, choose to ignore any examples that are not useful.

    This might become the plan to finally address the ANS support for standard intro materials.
  • Martin_HMartin_H Posts: 4,051
    edited 2013-06-20 10:36
    OK, I decided to do another CS 101 FORTH project. The first thing that popped into my head was a roman numeral print program. It has input, iteration, conditionals, and output so it covers all the basis. What was interesting was originally I tried writing this using arrays and the program was over 100 lines. It occurred to me that brute force was probably better in this circumstance. So below at 47 lines is what I think is the FORTH way to do it.
    \ prints a single roman digit from array
    : roman_digit_print \ ( n -- )
       case
             1 of  ." i" endof
             4 of ." iv" endof
             5 of  ." v" endof
             9 of ." ix" endof
            10 of  ." x" endof
            40 of ." xl" endof
            50 of  ." l" endof
            90 of ." xc" endof
           100 of  ." c" endof
           400 of ." cd" endof
           500 of  ." d" endof
           900 of ." cm" endof
          1000 of  ." m" endof
       endcase ;
    
    \ iterates on a single digit until all are printed
    : do_single_digit \ (number digit -- remainder)
       begin 2dup >= while
         dup roman_digit_print
         2dup \ number digit number digit
         -    \ number digit remainder
         swap \ number remainder digit
         rot  \ remainder digit number
         drop \ remainder digit
       repeat
       drop ;
    
    \ prints an integer on the stack as roman numeral
    : roman_numeral_print ( number -- )
       1000 do_single_digit
        900 do_single_digit
        500 do_single_digit
        400 do_single_digit
        100 do_single_digit
         90 do_single_digit
         50 do_single_digit
         40 do_single_digit
         10 do_single_digit
          9 do_single_digit
          5 do_single_digit
          4 do_single_digit
          1 do_single_digit
       drop ;
    
  • LoopyBytelooseLoopyByteloose Posts: 12,537
    edited 2013-06-20 13:21
    The Romans never had computers... Just looking at their numeral system seems to indicate to me why. But it is good fun, isn't it.

    In Forth, programs seem to evolve very quickly. I love the rapid deployment.

    It is an excellent example of how to use CASE but PropForth has stolen ( and ) for other purposes... that comment must be removed before Prof Brano will accept this.
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-06-20 13:26
    It looks like it works OK. I tried it in pfth, but I had to add the CASE, OF, ENDOF and ENDCASE words. I created quick and dirty versions of OF and ENDOF by modifying the definitions of the IF and THEN words as shown below. I'm not sure what the best way is to implement the OF - ENDOF words, but at least this works.
    : case ;
    : of [compile] over [compile] = [compile] _jz here 4 allot ; immediate
    : endof here swap ! ; immediate
    : endcase drop ;
    
  • Martin_HMartin_H Posts: 4,051
    edited 2013-06-20 16:39
    Dave, that looks like some expert mode FORTH programming. I'll have to digest that as I suspect that I will learn something.
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-06-20 18:51
    After I posted my comment I looked at how eForth implements it, and it defines OF/ENDOF using embedded nested IF/ELSE/THEN words. My quick and dirty encoding will cause every case to be evaluated. The right way to do it will cause only the cases up to the selected one to be evaluated, and the rest will be skipped. That's the right way to do it, and I might add that to pfth later. It does require generating a bunch of THEN's in the ENDCASE word.
  • prof_brainoprof_braino Posts: 4,313
    edited 2013-06-21 06:08
    Dave Hein wrote: »
    It does require generating a bunch of THEN's in the ENDCASE word.

    There a non DPANS word THENS that might be useful. It resolves all pending IF statements, and makes the code more readable.
  • prof_brainoprof_braino Posts: 4,313
    edited 2013-06-21 06:12
    Martin_H wrote: »
    CS 101 FORTH project. ... a roman numeral print program.

    Hey! That's cool!

    Can I post this? Does it work in propforth? I want to use this in the programming portion of the LittleRobot workshop.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2013-06-21 07:04
    I adapted your roman numeral print routine for Tachyon to try out my CASE structure. It all works as it should and I modified as little as possible but found the brevity of .ROMAN more suitable.
    [FONT=courier new]DECIMAL
    \ prints a single roman digit from array
    : roman_digit_print \ ( n -- )
       SWITCH
             1 CASE  ." i" BREAK
             4 CASE ." iv" BREAK
             5 CASE  ." v" BREAK
             9 CASE ." ix" BREAK
            10 CASE  ." x" BREAK
            40 CASE ." xl" BREAK
            50 CASE  ." l" BREAK
            90 CASE ." xc" BREAK
           100 CASE  ." c" BREAK
           400 CASE ." cd" BREAK
           500 CASE  ." d" BREAK
           900 CASE ." cm" BREAK
          1000 CASE  ." m" BREAK
          ;
    
    \ iterates on a single digit until all are printed
    : do_single_digit \ (number digit -- remainder)
       BEGIN 2DUP => WHILE
         DUP roman_digit_print
         2DUP \ number digit number digit
         -    \ number digit remainder
         SWAP \ number remainder digit
         ROT  \ remainder digit number
         DROP \ remainder digit
       REPEAT
       DROP ;
    
    \ prints an integer on the stack as roman numeral
    : .ROMAN ( number -- )
       SPACE
       1000 do_single_digit
        900 do_single_digit
        500 do_single_digit
        400 do_single_digit
        100 do_single_digit
         90 do_single_digit
         50 do_single_digit
         40 do_single_digit
         10 do_single_digit
          9 do_single_digit
          5 do_single_digit
          4 do_single_digit
          1 do_single_digit
       DROP ;
    [/FONT]
    1043 .ROMAN  mxliii ok
    2012 .ROMAN  mmxii ok
    1996 .ROMAN  mcmxcvi ok[FONT=courier new]
    [/FONT]
    
  • Martin_HMartin_H Posts: 4,051
    edited 2013-06-21 07:13
    Hey! That's cool!

    Can I post this? Does it work in propforth? I want to use this in the programming portion of the LittleRobot workshop.

    Be my guest. I've only tried in in gforth, but I'm willing to try it in propforth over the weekend. It's pretty basic as I avoided most of the areas where I know propforth differs from gforth.

    BTW Here's a line for line translation of the program from FORTH into C++ using MS Visual Studio IDE.
    // RomanNumerals.cpp : Line for line copy of FORTH into C++
    //
    #include "stdafx.h"
    #include <stdlib.h>
    
    // forward declaration of function.
    void roman_numeral_print(int number);
    
    int _tmain(int argc, _TCHAR* argv[]) // don't get me started on TCHAR's.
    {
        if (argc >= 2)
            roman_numeral_print( _ttoi(argv[1]) );
    
        return 0;
    }
    
    // prints a single roman digit from array
    void roman_digit_print (int n)
    {
        switch(n)
        {
        case 1:
            printf("i");
            break;
        case 4:
            printf("iv");
            break;
        case 5:
            printf("v");
            break;
        case 9:
            printf("ix");
            break;
        case 10:
            printf("x");
            break;
        case 40:
            printf("xl");
            break;
        case 50:
            printf("l");
            break;
        case 90:
            printf("xc");
            break;
        case 100:
            printf("c");
            break;
        case 400:
            printf("cd");
            break;
        case 500:
            printf("d");
            break;
        case 900:
            printf("cm");
            break;
        case 1000:
            printf("m");
            break;
        }
    }
    
    // iterates on a single digit until all are printed
    void do_single_digit (int * number, int digit)
    {
        while(*number >= digit)
        {
            roman_digit_print (digit);
            *number -= digit;
        }
    }
    
    // prints an integer on the stack as roman numeral
    void roman_numeral_print(int number)
    {
        do_single_digit(&number, 1000);
        do_single_digit(&number, 900);
        do_single_digit(&number, 500);
        do_single_digit(&number, 400);
        do_single_digit(&number, 100);
        do_single_digit(&number, 90);
        do_single_digit(&number, 50);
        do_single_digit(&number, 40);
        do_single_digit(&number, 10);
        do_single_digit(&number, 9);
        do_single_digit(&number, 5);
        do_single_digit(&number, 4);
        do_single_digit(&number, 1);
        printf("\n");
    }
    

    But that's not how I would write the program in C++. I would use arrays and iteration as follows:
    // RomanNumerals.cpp : This is the way I would write this in C++ and the
    // resulting program is more space efficient that brute force iteration too.
    #include "stdafx.h"
    #include <stdlib.h>
    
    // forward declaration of function.
    void roman_numeral_print(int number);
    
    int _tmain(int argc, _TCHAR* argv[]) // don't get me started on TCHAR's.
    {
        if (argc >= 2)
            roman_numeral_print( _ttoi(argv[1]) );
    
        return 0;
    }
    
    // These coordinated arrays are used to map back and forth from the numeric to text values.
    int   digits[] = {1000,  900, 500,  400, 100,   90,  50,   40,  10,    9,   5,    4,  1};
    char* values[] = { "m", "cm", "d", "cd", "c", "xc", "l", "xl", "x", "ix", "v", "iv", "i"};
    int digitCount = sizeof digits/ sizeof(int);
    
    // prints a single roman digit from array
    void roman_digit_print (int idx)
    {
        printf(values[idx]);
    }
    
    // iterates on a single digit until all are printed
    void do_single_digit (int * number, int idx)
    {
        while(*number >= digits[idx])
        {
            roman_digit_print (idx);
            *number -= digits[idx];
        }
    }
    
    // prints an integer on the stack as roman numeral
    void roman_numeral_print(int number)
    {
        for (int idx = 0; idx < digitCount; idx++)
            do_single_digit(&number, idx);
    
        printf("\n");
    }
    

    I checked the resultant code size and this indeed results in a more compact program. The result might be less clear to a novice programmer. What I may do it translate the second program into FORTH to get a better handle on strings arrays. This will likely bring this post back on topic as I suspect I'll need 2swap at some point.
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-06-21 08:29
    There a non DPANS word THENS that might be useful. It resolves all pending IF statements, and makes the code more readable.
    eForth's definition of ENDCASE is similar to THENS. eForth uses the following code:
    ( CASE structure )
    0 CONSTANT CASE ( -- 0 ) IMMEDIATE
    : OF ( -- sys )
      ['] OVER COMPILE,  ['] = COMPILE,
      [COMPILE] IF  ['] DROP COMPILE, ; IMMEDIATE
    : ENDOF ( sys -- sys ) [COMPILE] ELSE ; IMMEDIATE
    : ESAC ( 0 i*sys -- ) ( a useful factor )
      BEGIN ?DUP WHILE  [COMPILE] THEN  REPEAT ; IMMEDIATE
    : ENDCASE ( 0 i*sys -- ) ['] DROP COMPILE,  [COMPILE] ESAC ; IMMEDIATE
    
    So ESAC does the same thing as THENS. However, it depends on CASE to put a 0 on the stack before for the first OF. THENS must have a similar requirement. Personally, I like the use of explicit THEN words along with indentation to clearly show the scope of imbedded IF-ELSE words. Of course, the CASE/OF/ENDOF/ENDCASE words hide the details of the imbedded IF-ELSE words that it uses.
  • prof_brainoprof_braino Posts: 4,313
    edited 2013-06-21 09:28
    Dave Hein wrote: »
    So ESAC does the same thing as THENS. However, it depends on CASE to put a 0 on the stack before for the first OF. THENS must have a similar requirement.

    I don't know, but I don't think so. As I recall, THENS just closes out any outstanding IF's. If I rermember correctly, there can even be some nested if's that were explicitley resolved by specific then. But I'll have to dig through the code and find the example. Only used it once. Sal uses it often, so he can leave out the case words.
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-06-21 10:32
    I did a little bit of searching, and it looks like THENS was created by Wil Baden. It requires a COND before starting the nested IFs. COND is defined the same as CASE, where it's just a constant with a value of zero, and has the immediate flag set so it puts a 0 on the stack during compile time. THENS can also be used within a CASE structure, but it terminates the nesting of the OF words. Subsequent OFs will execute even if the value for a previous OF matched the CASE value.
  • Martin_HMartin_H Posts: 4,051
    edited 2013-06-21 11:07
    Beating a dead horse, but here's my second C program translated line for line back into FORTH. Two arrays are required for the values because FORTH handles strings differently from C. I also decided to adopt Peter's .roman function name because I got sick of typing my longer one. I don't think this program will work in propforth because the last time I tried it my array function wouldn't work.
    \ Used to allocate an array of cells of the desired size passed on stack
    : array	( n -- addr )
       create
         cells	     \ converts count into size in bytes
         here over erase \ clear the buffer and
         allot           \ allocate space
       Does>
         swap cells  + ; \ run time gives address of cell at index
    
    \ Create and load an array of values
    13 array roman_digits
    1000  0 roman_digits !
     900  1 roman_digits !
     500  2 roman_digits !
     400  3 roman_digits !
     100  4 roman_digits !
      90  5 roman_digits !
      50  6 roman_digits !
      40  7 roman_digits !
      10  8 roman_digits !
       9  9 roman_digits !
       5 10 roman_digits !
       4 11 roman_digits !
       1 12 roman_digits !
    
    \ Create and load an arrays of values and lengths
    13 array roman_values
    13 array roman_values_len
    
    \ helper function to store both the address and length
    : roman_values_store  \ (c-addr u idx -- )
       dup -rot           \  c-addr idx u idx
       roman_values_len ! \ c-addr idx
       roman_values ! ;
    
    s" m"   0 roman_values_store
    s" cm"  1 roman_values_store
    s" d"   2 roman_values_store
    s" cd"  3 roman_values_store
    s" c"   4 roman_values_store
    s" xc"  5 roman_values_store
    s" l"   6 roman_values_store
    s" xl"  7 roman_values_store
    s" x"   8 roman_values_store
    s" ix"  9 roman_values_store
    s" v"  10 roman_values_store
    s" iv" 11 roman_values_store
    s" i"  12 roman_values_store 
    
    \ prints a single roman digit
    : roman_digit_print \ ( n -- )
       dup
       roman_values @
       swap
       roman_values_len @
       type ;
    
    \ iterates on a single digit until all are printed
    : do_single_digit \ (number index -- remainder)
       begin 2dup roman_digits @ >= while
         dup roman_digit_print
         2dup           \ number index number index
         roman_digits @ \ number index number digit
         -              \ number index remainder
         swap           \ number remainder index
         rot            \ remainder index number
         drop           \ remainder index
       repeat
       drop ;
    
    \ prints an integer on the stack as roman numeral
    : .roman ( number -- )
       13 0
       do		     \ from 0 to 13
          i do_single_digit
       loop
       drop ;
    

    There might be a more concise way to construct the arrays and statically initialize them. But reading this program you can see how much detail the C compiler is hiding from you in two lines of code.
  • Martin_HMartin_H Posts: 4,051
    edited 2013-06-21 13:28
    Further beating a dead horse and going off into the programming woods. This version eliminates the array of string pointers and lengths. Instead it uses an array of execution tokens which makes printing trivial compared with the two array technique.
    \ Used to allocate an array of cells of the desired size passed on stack
    : array	( n -- addr )
       create
         cells	     \ converts count into size in bytes
         here over erase \ clear the buffer and
         allot           \ allocate space
       Does>
         swap cells  + ; \ run time gives address of cell at index
    
    \ Create and load an array of digits
    13 array roman_digits
    1000  0 roman_digits !
     900  1 roman_digits !
     500  2 roman_digits !
     400  3 roman_digits !
     100  4 roman_digits !
      90  5 roman_digits !
      50  6 roman_digits !
      40  7 roman_digits !
      10  8 roman_digits !
       9  9 roman_digits !
       5 10 roman_digits !
       4 11 roman_digits !
       1 12 roman_digits !
    
    \ Create a set of functions to print the text values.
    : .m  ." m" ;
    : .cm ." cm" ;
    : .d  ." d" ;
    : .cd ." cd" ;
    : .c  ." c" ;
    : .xc ." xc";
    : .l  ." l";
    : .xl ." xl";
    : .x  ." x";
    : .ix ." ix";
    : .v  ." v";
    : .iv ." iv";
    : .i  ." i";
    
    \ Create and load an array of execution tokens
    13 array roman_values
    
    : roman_values_load
       ['] .m   0 roman_values !
       ['] .cm  1 roman_values !
       ['] .d   2 roman_values !
       ['] .cd  3 roman_values !
       ['] .c   4 roman_values !
       ['] .xc  5 roman_values !
       ['] .l   6 roman_values !
       ['] .xl  7 roman_values !
       ['] .x   8 roman_values !
       ['] .ix  9 roman_values !
       ['] .v  10 roman_values !
       ['] .iv 11 roman_values !
       ['] .i  12 roman_values ! ;
    roman_values_load
    
    \ prints a single roman digit
    : .roman_digit \ ( n -- )
       roman_values @ execute ;
    
    \ iterates on a single digit until all are printed
    : do_single_digit \ (number index -- remainder)
       begin 2dup roman_digits @ >= while
         dup .roman_digit
         2dup           \ number index number index
         roman_digits @ \ number index number digit
         -              \ number index remainder
         swap           \ number remainder index
         rot            \ remainder index number
         drop           \ remainder index
       repeat
       drop ;
    
    \ prints an integer on the stack as roman numeral
    : .roman ( number -- )
       13 0
       do		     \ from 0 to 13
          i do_single_digit
       loop
       drop ;
    
  • Heater.Heater. Posts: 21,230
    edited 2013-06-21 14:58
    Oh my God. How do you guys do that? I think I would have a better chance using th language "Brainf**k":
    http://en.wikipedia.org/wiki/Smile
    or perhaps "Whitespace":
    http://en.wikipedia.org/wiki/Whitespace_(programming_language)


    Wouldn't it be easier to write programs in raw hex or binary like we had to in the old days before we got hold of assemblers?
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-06-21 15:16
    @Heater, did you ever finish doing the FFT in Forth? I don't recall how it ended up.

    Here's my version of the roman numeral program. I haven't tried it yet, so I don't know if it has any errors in it.
    \ create an array of roman digits
    create roman_digits 1000 , 900 , 500 , 400 , 100 , 90 , 50 , 40 , 10 , 9 , 5 , 4 , 1 ,
    
    \ get a roman value based on the index
    : roman_value ( index -- value ) 3 * s" m  cm d  cd c  xc l  xl x  ix v  iv i " drop + ;
    
    \ get a roman digit based on the index
    : roman_digit ( index -- digit ) 4 * roman_digits + @ ;
    
    \ print a single digit
    : print_digit ( value -- )
      dup c@ emit
      1 + c@ dup bl =
      if drop else emit then
      ;
    
    \ iterates on a single digit until all are printed
    : do_single_digit (number index -- remainder)
      swap
      begin
        over roman_digit - dup 0 >=
      while
        over roman_value
        print_digit
      repeat
      swap roman_digit +
      ;
    
    \ prints an integer on the stack as a roman numeral
    : .roman ( number -- )
      13 0 do 
        i do_single_digit
      loop
      drop
      ;
    
  • Heater.Heater. Posts: 21,230
    edited 2013-06-21 15:35
    Dave Hein,
    @Heater, did you ever finish doing the FFT in Forth? I don't recall how it ended up.
    The FFT concept itself gave me a severe headache, getting it running in assembler on the Prop was migraine inducing.

    But that's was nothing compared to trying to get Forth to even do simple arithmetic in a readable manner, that is epilepsy time and total nervous collapse.

    After therapy and counceling I'm OK, as long as keep taking the meds. My shrink warns me not to go near Forth again. I start shaking just reading this thread.

    Basically I have been reduced to a JavaScript monkey....
  • Martin_HMartin_H Posts: 4,051
    edited 2013-06-21 16:08
    @Heater, the stack management is the hardest part. The thing about FORTH is that its interactive nature is the key to dealing with the weirdness. Just type in commands to figure out what they do. But It can pretty easily become write only if you're not careful. I wrote a couple of sort algorithms last year and some of the details are opaque to me now.

    @Dave, I like your approach. But you use the s" operator to allocate a string in a function. Does that allocate it each execution, or at compile time? I'm asking because I've wondered about memory leaks of unreferenced allocations.
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-06-21 18:39
    When s" is encountered in the compile mode the string is compiled into the word. There is also a word compiled in that will load the address and length of the string onto the stack when the word is executed. Most Forth interpreters will let you use s" in the interpret mode, but the ANS Forth standard says its use is undefined in that mode.

    I found an error in my code where I used >=0. I replaced this with "0 >=" and it works correctly.
  • prof_brainoprof_braino Posts: 4,313
    edited 2013-06-27 06:45
    Heater. wrote: »
    The FFT concept itself gave me a severe headache, getting it running in assembler on the Prop was migraine inducing.

    But that's was nothing compared to trying to get Forth to even do simple arithmetic in a readable manner, that is epilepsy time and total nervous collapse.

    After therapy and counceling I'm OK, as long as keep taking the meds. My shrink warns me not to go near Forth again. I start shaking just reading this thread.

    Basically I have been reduced to a JavaScript monkey....

    !@heater: (don't want him to have a relapse)

    Off topic, but there's these two examples to show how its done the easy way. At least it looks easy to me, but I don't really understand it yet. Apparently the Hartley transform derivative of the fourrier is the way to go on the prop.

    http://propforth.googlecode.com/files/FHT11.rtf

    http://propforth.googlecode.com/files/FHT_Examples.f
  • Dave HeinDave Hein Posts: 6,347
    edited 2013-06-27 07:03
    prof_braino, that code is the poster child for programming in something other than Forth. The FHT can be done more compactly and is more readable when programmed in C. Forth is good for some things, but the FHT isn't one of those things.
  • Martin_HMartin_H Posts: 4,051
    edited 2013-06-27 07:25
    The more I play around with FORTH the more it reminds me of using an 80's era assembler monitor/debugger. You could type in assembler and it could interactively compile it. You could then execute that code and when it hit a BRK instruction control would be returned back to the monitor. You could list sections of memory for their contents, alter that code and recompile it. It was great for writing code to run in a vertical blank interrupt handler, but quickly became tedious for other sorts of tasks.

    Basically FORTH feels a bit like an assembly language that prevents access to the JMP instruction, so labels can only be used for subroutine names and variable storage. But makes up for it with one heck of a macro facility (its flow of control structures), so you don't mind.
Sign In or Register to comment.