Shop OBEX P1 Docs P2 Docs Learn Events
New BASIC compiler for Prop1 and Prop2 - Page 12 — Parallax Forums

New BASIC compiler for Prop1 and Prop2

191012141520

Comments

  • yetiyeti Posts: 818
    edited 2018-11-17 19:22
    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.
  • 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: 818
    edited 2018-11-17 22:30
    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... ;-)
    ...
    
  • Cluso99Cluso99 Posts: 18,066
    potatohead wrote: »
    [Weird, I did not mean to post]
    What! Another potatohead short post!
  • 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
  • yetiyeti Posts: 818
    edited 2018-11-18 12:26
    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.
  • Rayman wrote: »
    ...
    Actually, I think I changed my mind...
    I like your:
    extern "SimpleSerial.spin" ser;
    
    better...

    I prefer this form as well.

  • kwinnkwinn Posts: 8,697
    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
  • RaymanRayman Posts: 13,797
    edited 2018-11-20 01:15
    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...
  • yetiyeti Posts: 818
    edited 2018-11-20 04:06
    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.
  • 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.

  • kwinnkwinn Posts: 8,697
    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.
  • jmgjmg Posts: 15,140
    edited 2018-11-20 18:51
    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.
    👍
  • 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
  • jmgjmg Posts: 15,140
    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 ?
  • kwinnkwinn Posts: 8,697
    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?
  • 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?
  • 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.
  • 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.