New BASIC compiler for Prop1 and Prop2

17891012

Comments

  • yetiyeti Posts: 453
    edited November 17 Vote Up0Vote Down
    jmg wrote: »
    Will this ultimately have a linker ? If so, any plan should be linker compatible ?

    With a linker, a header file can declare names, and then the linked .OBJ file can come from any language source at all.
    +1

    If there will be an object format and linker, no nonstandard C extensions need to be invented.
    ◁ FastSpin ▷ ◁ Stay OmmmmmmPtimistic! ▷ ◁ No Source – No Go! ▷ ◁ Please help: http://rosettacode.org/wiki/Category:Spin ▷ ◁ Why Asimov's Laws of Robotics Don't Work - Computerphile ▷ ◁ DNA is a four letter word. ▷
  • yeti wrote: »
    jmg wrote: »
    Will this ultimately have a linker ? If so, any plan should be linker compatible ?

    With a linker, a header file can declare names, and then the linked .OBJ file can come from any language source at all.
    +1

    If there will be an object format and linker, no nonstandard C extensions need to be invented.

    I think even if there was a linker, we still need a way to declare objects. It would be convenient to directly be able to use Spin or BASIC objects from C, with a C++ like notation:
    struct extern "FullDuplexSerial.spin" ser; // create a fullduplexserial object named "ser"
    ser.init(31, 30, 0, 115200);
    ser.str("hello, world!\n");
    

    Otherwise how would you define "ser"?

    In any case, I don't currently have a linker for fastspin, nor do I have plans for one. If a P1 and P2 compatible linker is created (e.g. if someone ports binutils to P2) then I might change that. But not having a linker actually has some significant advantages -- it means, for example, that the compiler can always inline all functions, and eliminate unused functions.
  • yetiyeti Posts: 453
    edited November 17 Vote Up0Vote Down
    Otherwise how would you define "ser"?
    ...by a header like:
    uint32_t ser_init(uint32_t rxPin, uint32_t txPin, uint32_t mode, uint32_t baudrate);
    uint32_t ser_str(char *stringaddress); // if Spin can embed hints for the header generator about types
    // otherwise most items would be guessed to be unsigned 32bitish... I guess... ;-)
    ...
    
    ◁ FastSpin ▷ ◁ Stay OmmmmmmPtimistic! ▷ ◁ No Source – No Go! ▷ ◁ Please help: http://rosettacode.org/wiki/Category:Spin ▷ ◁ Why Asimov's Laws of Robotics Don't Work - Computerphile ▷ ◁ DNA is a four letter word. ▷
  • potatohead wrote: »
    [Weird, I did not mean to post]
    What! Another potatohead short post!
    My Prop boards: P8XBlade2, RamBlade, CpuBlade, TriBlade
    Prop OS (also see Sphinx, PropDos, PropCmd, Spinix)
    Website: www.clusos.com
    Prop Tools (Index) , Emulators (Index) , ZiCog (Z80)
  • yeti wrote: »
    Otherwise how would you define "ser"?
    ...by a header like:
    uint32_t ser_init(uint32_t rxPin, uint32_t txPin, uint32_t mode, uint32_t baudrate);
    uint32_t ser_str(char *stringaddress); // if Spin can embed hints for the header generator about types
    // otherwise most items would be guessed to be unsigned 32bitish... I guess... ;-)
    ...
    

    Actually you need the member variables too, so there has to be a struct, and that has to be passed to the functions. And an instance of the struct needs to be defined. And you need to separately convert FullDuplexSerial.spin to FullDuplexSerial.c and compile that, and remember to link it.

    I think it's much simpler if the C code can just declare "ser" as an external object of type FullDuplexSerial.spin and let the compiler handle the rest.
  • I think
    struct extern "FullDuplexSerial.spin" ser;
    
    is way better than
    uint32_t ser_init(uint32_t rxPin, uint32_t txPin, uint32_t mode, uint32_t baudrate);
    uint32_t ser_str(char *stringaddress); // if Spin can embed hints for the header generator about types
    

    but maybe it's just me,

    Mike
    I am just another Code Monkey.
    A determined coder can write COBOL programs in any language. -- Author unknown.
    Press any key to continue, any other key to quit

    The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this post are to be interpreted as described in RFC 2119.
  • yetiyeti Posts: 453
    edited November 18 Vote Up0Vote Down
    struct extern "FullDuplexSerial.spin" ser;
    
    This looks way to harmless!

    I think such a non standard extension should be added in a way that can be identified as non standard at first sight without needing years of C experiences.
    E.g. using the "preprocessor look" with something like
    #!interface "FullDuplexSerial.spin" as ser
    // or something similar like ...
    #!interface ser from "FullDuplexSerial.spin"
    

    If it has to be something based on "struct", the add on should stick out optically. GCC adds extensions written like "__attribute__(something)".
    struct ser __from_file__("FullDuplexSerial.spin");
    
    may be ok in this sense because "__from_file__(...)" sticks out enough.
    ◁ FastSpin ▷ ◁ Stay OmmmmmmPtimistic! ▷ ◁ No Source – No Go! ▷ ◁ Please help: http://rosettacode.org/wiki/Category:Spin ▷ ◁ Why Asimov's Laws of Robotics Don't Work - Computerphile ▷ ◁ DNA is a four letter word. ▷
  • Rayman wrote: »
    ...
    Actually, I think I changed my mind...
    I like your:
    extern "SimpleSerial.spin" ser;
    
    better...

    I prefer this form as well.

  • lostcauz wrote: »
    Rayman wrote: »
    ...
    Actually, I think I changed my mind...
    I like your:
    extern "SimpleSerial.spin" ser;
    
    better...

    I prefer this form as well.

    +1
    In science there is no authority. There is only experiment.
    Life is unpredictable. Eat dessert first.
  • RaymanRayman Posts: 8,891
    edited November 20 Vote Up0Vote Down
    Are there line numbers in this kind of BASIC?

    I see there is a GOTO command, but don't think I've seen it used in any examples yet...

    I think I remember that GOTO is one of the things that structured language purists don't like...
    Prop Info and Apps: http://www.rayslogic.com/
  • yetiyeti Posts: 453
    edited November 20 Vote Up0Vote Down
    Rayman wrote: »
    I see there is a GOTO command, but don't think I've seen it used in any examples yet...
    https://github.com/totalspectrum/spin2cpp/blob/194b19f52a7288edfd9bd870fe1a3a3c4733f7d7/Test/basexec05.bas#L38-L47

    At the time of writing that program, there was no "BREAK" or "EXIT" to leave loops.
    Rayman wrote: »
    I think I remember that GOTO is one of the things that structured language purists don't like...
    In newer versions of that program, I merged the exit condition with the test in the "WHILE" statement. Did that really improve readability? I heavily doubt it.

    Sporadic use of "GOTO"s is ok. A "GOTO" on every tenth line like in 8bit-BASIC's early days sure is a readability killer.

    "The dose makes the poison" — Paracelsus.
    ◁ FastSpin ▷ ◁ Stay OmmmmmmPtimistic! ▷ ◁ No Source – No Go! ▷ ◁ Please help: http://rosettacode.org/wiki/Category:Spin ▷ ◁ Why Asimov's Laws of Robotics Don't Work - Computerphile ▷ ◁ DNA is a four letter word. ▷
  • Rayman wrote: »
    Are there line numbers in this kind of BASIC?

    I see there is a GOTO command, but don't think I've seen it used in any examples yet...

    No, no line numbers. As the GOTO documentation says, labels are just plain identifiers followed by a colon:
      if x=y goto xyequal
      print "x differs from y"
      goto done
    xyequal:
      print "x and y are equal"
    done:
    
    That particular example would read better as an if/then/else, of course, and indeed there's not a lot of times when goto is useful. But there are a few times when just doing a direct goto is easier than having a big nested set of ifs.
  • yeti wrote: »
    At the time of writing that program, there was no "BREAK" or "EXIT" to leave loops.
    Whoops, I still haven't implemented those. Thanks for reminding me. FreeBASIC has "exit while", "exit for", and "exit do", as well as "continue while", "continue for", and "continue do". But Spin doesn't keep track of which kind of loop is which (exit just exits from the most recent enclosing loop), so I need to change the code around to keep track. Or, maybe I'll just punt and make all the exits the same as Spin's.

  • ersmith wrote: »
    yeti wrote: »
    At the time of writing that program, there was no "BREAK" or "EXIT" to leave loops.
    ......
    Or, maybe I'll just punt and make all the exits the same as Spin's.

    Good idea. I would consider such simplification an improvement over the redundancy of having to specify the type of loop one is exiting from.
    In science there is no authority. There is only experiment.
    Life is unpredictable. Eat dessert first.
  • jmgjmg Posts: 12,616
    edited November 20 Vote Up0Vote Down
    kwinn wrote: »
    Good idea. I would consider such simplification an improvement over the redundancy of having to specify the type of loop one is exiting from.

    Not such a good idea, given :
    a) When you do need to exit a specific loop, how do you specify that ?
    b) How does FreeBASIC like the Spin syntax ?

    One of the key pivots of using Basic, is to try to be compatible with other mainstream basics, (to allow test wrappers and PC tests, plus you can use many of their examples and documents !) and thus far fastspin basic has been tracking FreeBASIC

    That's exactly the same reason it tries to be compatible with C.
    ersmith wrote: »
    Whoops, I still haven't implemented those. Thanks for reminding me. FreeBASIC has "exit while", "exit for", and "exit do", as well as "continue while", "continue for", and "continue do". But Spin doesn't keep track of which kind of loop is which (exit just exits from the most recent enclosing loop), so I need to change the code around to keep track. Or, maybe I'll just punt and make all the exits the same as Spin's.
    See above, please track whatever FreeBASIC does, to keep compatibility as much as practical.

  • jmg wrote: »
    See above, please track whatever FreeBASIC does, to keep compatibility as much as practical.
    👍
    ◁ FastSpin ▷ ◁ Stay OmmmmmmPtimistic! ▷ ◁ No Source – No Go! ▷ ◁ Please help: http://rosettacode.org/wiki/Category:Spin ▷ ◁ Why Asimov's Laws of Robotics Don't Work - Computerphile ▷ ◁ DNA is a four letter word. ▷
  • I think what I'll do is support the FreeBASIC syntax, but only for breaking out of or continuing the innermost enclosing loop. That is, you can say:
      exit for
    
    inside a for loop, but if you do that inside a while loop (even if that while loop is itself inside a for loop) you'll get an error. So it'll support a subset of the FreeBASIC functionality. Evenutally it would be nice to allow the full FreeBASIC exit, like:
    while (1)
      for i = 1 to n
        if somecondition(i) then
          exit while ' same as a "goto done"
        end if
      next
    wend
    done:
    
    but it'll take a bit of work, and probably isn't used all that often.

    I'll also allow just plain "exit" to exit from whatever loop you're in, but if you do that then you (may?) lose FreeBASIC compatibility. It'll be up to the programmer.
  • I personally never liked the exit/break to leave loops, they are just GOTOs with another name and make code harder to follow.

    This comes from decades of COBOL programming, early COBOL did not had the concept of calling procedures so no subroutines at all, later on added perform (alike GOSUB but way weirder) and restructuring old and large COBOL programs is not a task one wish to do.

    I am not in the camp that GOTOs are evil, but for the sake of structured programming they should be used as seldom as possible.

    As far as I know even SPIN has a Byte Code for GOTO, but it was never used by the language.

    @ersmith shows jumping out of multiple loops is possible with a label and a GOTO, but I also do understand the importance of compatibility with FreeBASIC.

    Anyways Eric you are doing a wonderful job here, the ability to mix SPIN, BASIC and C in one program is just fantastic.

    Thanks,

    Mike
    I am just another Code Monkey.
    A determined coder can write COBOL programs in any language. -- Author unknown.
    Press any key to continue, any other key to quit

    The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this post are to be interpreted as described in RFC 2119.
  • ersmith wrote: »
    I think what I'll do is support the FreeBASIC syntax, but only for breaking out of or continuing the innermost enclosing loop. That is, you can say:
      exit for
    
    inside a for loop, but if you do that inside a while loop (even if that while loop is itself inside a for loop) you'll get an error. So it'll support a subset of the FreeBASIC functionality. Evenutally it would be nice to allow the full FreeBASIC exit, like:
    while (1)
      for i = 1 to n
        if somecondition(i) then
          exit while ' same as a "goto done"
        end if
      next
    wend
    done:
    
    but it'll take a bit of work, and probably isn't used all that often.

    I'll also allow just plain "exit" to exit from whatever loop you're in, but if you do that then you (may?) lose FreeBASIC compatibility. It'll be up to the programmer.

    That sounds a reasonable middle ground.
    What about Exit Sub/ Exit Function - can those go anywhere and return as expected ?
  • jmg wrote: »
    kwinn wrote: »
    Good idea. I would consider such simplification an improvement over the redundancy of having to specify the type of loop one is exiting from.

    Not such a good idea, given :
    a) When you do need to exit a specific loop, how do you specify that ?
    b) How does FreeBASIC like the Spin syntax ?

    One of the key pivots of using Basic, is to try to be compatible with other mainstream basics, (to allow test wrappers and PC tests, plus you can use many of their examples and documents !) and thus far fastspin basic has been tracking FreeBASIC

    That's exactly the same reason it tries to be compatible with C.

    How often and under what circumstances would one want to exit a loop when they are not in that loop? Only circumstance I can think of is when one is in a nested loop. Any other circumstances?
    In science there is no authority. There is only experiment.
    Life is unpredictable. Eat dessert first.
  • I have not checked the thread for a few weeks, but I got back today.
    It looks like these keys words are broken.
    do while x =not y
    ,,,,
    loop
    
    and
    do
    ,,,,
    loop until x=y
    


    Ron
  • rsut wrote: »
    I have not checked the thread for a few weeks, but I got back today.
    It looks like these keys words are broken.
    do while x =not y
    ,,,,
    loop
    
    and
    do
    ,,,,
    loop until x=y
    

    In what way are they broken? The "=not" syntax is a bit dodgy (it'll be parsed as "x = (not y)"; did you expect it to be the same as "x <> y"?). But otherwise I'm able to run loops like that and they seem to work, at least the simple examples I tried.

    Thanks,
    Eric
  • Eric,

    Duh, my bad, should have been x<>y.
    Works fine in the three nested loops of my parser function.

    I thing there is a better way to do this by using a pointer rather than a index like this
    do while tib(nextword) <> 0x20            'space delimited
    ,,,,
    ,,,,
    inc(nextword)                   ' sub to increment nextword which is an inex to the next ubyte in the array tib
    loop
    


    Thanks
    Ron

  • I've updated fastspin and spin2gui with a new version (fastspin version 3.9.12). In the BASIC I've added plain EXIT and CONTINUE to exit or resume loops. You can also use the "EXIT FOR" and "EXIT DO" style (and similarly for CONTINUE) but it only works on the innermost containing loop. If you say "EXIT FOR" inside a DO loop you'll get an error, even if there is a FOR loop further out. As long as you stick to only trying to exit from the inner loop the code should be compatible with FreeBasic.

    EXIT FUNCTION and EXIT SUB work the same as RETURN. I've also added the FreeBasic feature where you can assign a value to the name of the function to set a return value:
    function sumif(a, b, c)
      sumif = 0
      if a = 0 then
        exit function
      end if
      sumif = b + c
    end function
    
    will return 0 if a is 0, otherwise it will return b+c.

    Are there any other BASIC features that you'd like to see in fastspin (aka FlexBasic)?

    Eric
  • Do we have ON TIMER/RESUME?
    Failure is not an option...it's bundled with the software.
  • Mickster wrote: »
    Do we have ON TIMER/RESUME?

    FreeBasic doesn't have that, so we don't either. I just looked briefly at it, and it doesn't seem quite appropriate for the Propeller. I think on the Prop if you want to run a subroutine periodically in the background you'd want to start up a COG for that, wouldn't you?
  • I've updated fastspin and spin2gui with a new version (fastspin version 3.9.12).
    At some point I will have to get into testing some more things. Does this new version still use LMM, and are the converted spin programs still running on the large size? I have this suspicion that I might have to wait for the P2 to become available, for the general audience, before I can do what I want to do.

    I am also thinking about moving over to Linux to do some more serious work. Do you have any plans, or is their a strategy that I could apply to have fastspin and FlexBasic run on a Linux system? Probably developing the FlexBasic program would be the easy part, as compared to maybe trying to load the program to the EEPROM. I remember even with SimpleIDE Linux version, there was some things that you had to do in order to use the TTY port.

    Ray
  • Rsadeika wrote: »
    I've updated fastspin and spin2gui with a new version (fastspin version 3.9.12).
    At some point I will have to get into testing some more things. Does this new version still use LMM, and are the converted spin programs still running on the large size?
    Yes.
    I am also thinking about moving over to Linux to do some more serious work. Do you have any plans, or is their a strategy that I could apply to have fastspin and FlexBasic run on a Linux system?
    fastspin builds and runs fine on a Linux system -- in fact that's where it is developed (I have a Debian Linux system that I use for everyday work). spin2gui also runs on Linux, but I don't have it pre-packaged -- you have to build it yourself.

  • ersmith wrote: »
    Mickster wrote: »
    Do we have ON TIMER/RESUME?

    FreeBasic doesn't have that, so we don't either. I just looked briefly at it, and it doesn't seem quite appropriate for the Propeller. I think on the Prop if you want to run a subroutine periodically in the background you'd want to start up a COG for that, wouldn't you?

    I don't think it's quite the same thing. I've had it in many flavors of BASIC but never used it, mainly because it only had a resolution of 55ms on the PC.
    The reason I just brought it up is because I'm playing with it in Android and finding it useful.

    It would be similar to creating a separate task in PASM, using jmpret.
    Failure is not an option...it's bundled with the software.
  • Mickster wrote: »
    ersmith wrote: »
    Mickster wrote: »
    Do we have ON TIMER/RESUME?

    FreeBasic doesn't have that, so we don't either. I just looked briefly at it, and it doesn't seem quite appropriate for the Propeller. I think on the Prop if you want to run a subroutine periodically in the background you'd want to start up a COG for that, wouldn't you?

    I don't think it's quite the same thing. I've had it in many flavors of BASIC but never used it, mainly because it only had a resolution of 55ms on the PC.
    The reason I just brought it up is because I'm playing with it in Android and finding it useful.

    It would be similar to creating a separate task in PASM, using jmpret.

    I think it's more like responding to a timer interrupt. That is, "ON TIMER(N) GOSUB routine" schedules an interrupt to happen in N seconds, and when that interrupt happens the subroutine is called. The Prop1 doesn't have interrupts, so this would have to be simulated somehow. I think the cleaner way to do this on the Prop1 is to start a routine on another cog that sleeps for N seconds then calls "routine".

    (On Prop2 there are interrupts, so at least in theory it could be done there, but that opens up a bit of a can of worms :).)

    So I would suggest that you could write an "ontimer" function like:
    ' run f once every n seconds
    sub runtimed(n as integer, f as sub() ) 
      var nexttick = getcnt()
      do
          nexttick = nexttick + CLKFREQ*n
          waitcnt(nexttick)
          f
      loop
    end sub
    
    ' ontimer(n, f): perform runtimed(n, f) in another CPU
    ' returns the CPU id of the new CPU, or -1 on failure
    const TIMER_STACKSIZE = 8
    
    function ontimer(n as integer, timerfunc as sub() ) as integer
      var stack = new ulong(TIMER_STACKSIZE)
      if (stack) then
        return cpu(runtimed(n, timerfunc), @stack(1))
      end if
      return -1
    end function
    
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''
    '' here's a demo of using ontimer to blink an LED and
    '' increment a counter
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''
    dim shared total_ticks = 0
    
    const pin = 26
    sub tick
      direction(pin) = output
      output(pin) = not output(pin)
      total_ticks = total_ticks + 1
    end sub
    
    var x = ontimer(1, @tick)
    print "launched tick subroutine on cog #"; x
    for i = 1 to 1000
      print "total_ticks = "; total_ticks
      pausems 1000
    next i
    
Sign In or Register to comment.