New BASIC compiler for Prop1 and Prop2

145791013

Comments

  • Another approach for Basic is to always trap aborts from Spin programs. The caller would have to look at the return code to determine if there was an error.
  • As far as I understand the Spin abort, it cancels all instruction after the abort was called and pops the stack correctly until it finds a '\'. then it returns the long value give when calling abort.

    What I sort of miss is a flag telling me that the result is a abort and not a normal return.

    @ersmith syntax with try..catch...end could maybe provide this.

    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.
  • msrobots said

    As far as I understand the Spin abort, it cancels all instruction after the abort was called and pops the stack correctly until it finds a '\'. then it returns the long value give when calling abort.

    That was my understanding, so I just assumed we would loose the mission! The last thing we would want is to have to re work spin methods so that we can use them in a class. We will have see how Eric deals with it.

    I think the issue, for a user of fastspin(basic) will be is to learn how to keep the code size down.

    Ron
  • I think the issue, for a user of fastspin(basic) will be is to learn how to keep the code size down.
    Interesting, does that mean that you will have to re-write Spin Objects? For somebody like myself, I have not used Spin, in a very long time, I would find it very difficult to deal with fsrw26.spin, in terms of code reduction.

    It will also be very interesting to see how far Eric can reduce the size of Spin Objects. Or, the other option, writing the driver code in fastspin(BASIC), not sure if that was the intent of fastspin(BASIC).

    Ray
  • msrobots wrote: »
    The abort mechanism in Spin has a flaw I always struggle with, and that is the problem to distinguish between a regular return code and a abort situation.
    Yes, that is an annoyance with abort. One way around this in Spin is to "bury" the functions that might abort in a non-aborting function, like:
    pri dofile
      x := popen(xxx)
      y := pwrite(xxx)
      z := pclose(xxx)
      return $eae1e0ff
    
    pub main
      r := \dofile
      if (r == $eae1e0ff)
        '' everything OK
      else
        '' r contains the abort code
    
    That was how I initially planned to implement try/catch in BASIC (having the compiler automatically doing this transformation). But that still means you need one magic value that can't be returned, and I think there's another approach I can use that would avoid this.
    the try catch syntax would allow to separate this (if possible?)
    try
      x = fsrw.popen(xxx)
    catch err
      print "got error code", err
    end
    

    so that x just get changed if NO abort happened?

    Mike

    Right that's definitely an advantage of try/catch, and I'm going to try to implement it.

    The one catch is that we'll only be able to return integers from abort (no strings or floats). Or rather, if you do want to return a string or float you'll have to use explicit casts. Spin doesn't have types so it's never an issue there.
  • Rsadeika wrote: »
    I think the issue, for a user of fastspin(basic) will be is to learn how to keep the code size down.
    Interesting, does that mean that you will have to re-write Spin Objects?
    No. For now it just means that we can't use large functions with large Spin objects, and/or have to use tricks like disabling fcache to get things to fit.

    The root of the problem is the LMM code that fastspin generates, which can be 4 times larger than Spin bytecodes. I think the long term solution is to have a mode where fastspin can generate compressed instructions (like PropGCC CMM) or perhaps even Spin bytecodes. That's going to take a while to get going though.

  • Eric

    The following function compiles Ok.
    I can live with the abort issue for now, if need be I can modify the fsrw.spin file so that I can
    continue testing fastspin(basic)

    '''
    function wrfile(file_name$, text$,  len)         'TODO Use ser  class for input in leu of INPUT$ so that I can count  string length at the  input stage
        dim x as long
         mode= asc("w")
         x = sd.popen(file_name,mode)
         if ( x= -1) then
           print( "error..cannot open file")
         else
          sd.pwrite(text,LEN)
          sd.pclose()
        end if
     end function
    ''' 
    

    Ron

  • ersmith wrote: »
    msrobots wrote: »
    The abort mechanism in Spin has a flaw I always struggle with, and that is the problem to distinguish between a regular return code and a abort situation.
    Yes, that is an annoyance with abort. One way around this in Spin is to "bury" the functions that might abort in a non-aborting function, like:
    pri dofile
      x := popen(xxx)
      y := pwrite(xxx)
      z := pclose(xxx)
      return $eae1e0ff
    
    pub main
      r := \dofile
      if (r == $eae1e0ff)
        '' everything OK
      else
        '' r contains the abort code
    
    That was how I initially planned to implement try/catch in BASIC (having the compiler automatically doing this transformation). But that still means you need one magic value that can't be returned, and I think there's another approach I can use that would avoid this.
    the try catch syntax would allow to separate this (if possible?)
    try
      x = fsrw.popen(xxx)
    catch err
      print "got error code", err
    end
    

    so that x just get changed if NO abort happened?

    Mike

    Right that's definitely an advantage of try/catch, and I'm going to try to implement it.

    The one catch is that we'll only be able to return integers from abort (no strings or floats). Or rather, if you do want to return a string or float you'll have to use explicit casts. Spin doesn't have types so it's never an issue there.

    My usual way there is to abort with a negated string address, so return of less then zero is a error and its abs value is the address of the error-string.

    I guess your integer is long enough to hold a address of a string?

    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.
  • msrobots wrote: »
    The one catch is that we'll only be able to return integers from abort (no strings or floats). Or rather, if you do want to return a string or float you'll have to use explicit casts. Spin doesn't have types so it's never an issue there.

    My usual way there is to abort with a negated string address, so return of less then zero is a error and its abs value is the address of the error-string.

    I guess your integer is long enough to hold a address of a string?

    Yes, integers can hold addresses.

    I could also make throw/catch work with type ANY, which you'd then assign to an appropriately typed variable (integer, string, float, or whatever). This would let you throw string messages. You'll have to be very careful when working with other people's objects though to know what kind of error value they are throwing!

  • Are there major differences in keywords between Propbasic and this basic?
    Prop Info and Apps: http://www.rayslogic.com/
  • Rayman wrote: »
    Are there major differences in keywords between Propbasic and this basic?
    Yes. :-D

    ◁ 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. ▷
  • ersmithersmith Posts: 2,454
    edited October 18 Vote Up0Vote Down
    Rayman wrote: »
    Are there major differences in keywords between Propbasic and this basic?

    Yes. This BASIC is more like Visual BASIC or FreeBASIC. An LED blink program in fastspin BASIC looks like:
    ' pin for the LED
    const LED = 16
    
    ' set the LED pin as an output
    direction(LED) = output
    
    ' put a message on the serial port
    print "Blinking LED on pin "; LED
    
    do
      high LED
      pausems 500
      low LED
      pausems 500
    loop
    
    sub high(pin)
      output(pin) = 1
    end sub
    
    sub low(pin)
      output(pin) = 0
    end sub
    
  • I see you've implemented try/catch. Are you planning on adding "finally" as well? I did try/catch with advsys2 but haven't done "finally" yet.
  • David Betz wrote: »
    I see you've implemented try/catch. Are you planning on adding "finally" as well?
    You won! :-D
    I have the same question but you were faster.
    ◁ 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. ▷
  • In general I don't want to make any breaking changes to fastspin now (just adding new features) but there is one thing that I think needs to change. Right now variables in for loops are declared automatically, which is convenient; but they are made as member variables of the object containing the for loop, which is quite inefficient and not usually what you want. I'm planning to change this so that the default is to create a local variable.

    This shouldn't make any difference if you always explicitly declare all variables with "dim" or "var", but it will make things better for lazy programmers like me :).

    Eric
  • David Betz wrote: »
    I see you've implemented try/catch. Are you planning on adding "finally" as well? I did try/catch with advsys2 but haven't done "finally" yet.

    With the primitive exceptions that fastspin BASIC has right now I think "finally" is redundant. The catch block always catches exceptions, so the code after the try block will always execute. So "finally" would be a dummy like "if (1)". If we had more sophisticated exception handlers that automatically passed exceptions they didn't handle up to the parent then "finally" would be useful.

    Or am I missing something?

    Eric
  • ersmith wrote: »
    David Betz wrote: »
    I see you've implemented try/catch. Are you planning on adding "finally" as well? I did try/catch with advsys2 but haven't done "finally" yet.

    With the primitive exceptions that fastspin BASIC has right now I think "finally" is redundant. The catch block always catches exceptions, so the code after the try block will always execute. So "finally" would be a dummy like "if (1)". If we had more sophisticated exception handlers that automatically passed exceptions they didn't handle up to the parent then "finally" would be useful.

    Or am I missing something?

    Eric
    Ah, that's an interesting point. I started out expecting to implement a more sophisticated "catch" but ended up having it always every exception. In that case, as you suggest, "finally" is not necessary. I guess I can take that off my TODO list!

  • @Eric

    I think users (like me) would like to see a built in function *len*

    So instead of …...........sd.pwrite(file name, text$, len)

    Then I can then do .............sd.pwrite(file_name, text$) and then add the line
    lx= len(text$) inside the function.

    Is it on your TODO list ?

    BTW Thanks for the update on the try/catch

    Ron
  • rsut wrote: »
    I think users (like me) would like to see a built in function *len*

    Oh, definitely! That should have been in there already, and I'll make sure it's added to the next release.

    In the meantime you actually can call the Spin "strsize" function from BASIC. I'd say that's a temporary work-around (I'm not sure all the Spin function names will always be available from BASIC) but it'll get you going until "len" is there (both functions do the same thing).
  • I've updated the compiler to 3.9.6, and new releases of fastspin and spin2gui are available now. The main new features are improvements to COG memory usage, try/catch, LEN, and anonymous functions (lambdas). You shouldn't need to use --fcache=0 any more to compile even fairly complicated programs.

    Also, although the open/print/close code has been in for a while it's been difficult to use with large programs because of the COG memory issue. Since that's fixed, you can now hook up Spin objects to the BASIC I/O functions. For example I have a program below for reading and writing files on an SD card using "print" and "input$". The only caveat is that writing data and then immediately reading it back doesn't seem to work right. The data is being written to the card (if I run a "read only" version of the program it prints it, and I can see it on my PC) but something about opening a file for write, closing it, and then opening the same file for read is not working right. I don't know if that's a fastspin bug, an fsrw bug, or just a misunderstanding on my part of how fsrw works.

    The "open SendRecvDevice as #n" notation works for any object; you just need to provide 3 pointers to the "send a character", "receive a character", and "close" functions. The basic.md file has a bit more information under OPEN.
    ' for some reason doing both a read and a write fails??
    ' but doing just one or the other is OK
    #define TRY_WRITE
    '#define TRY_READ
    
    const HEAPSIZE=2048  ' may not be necessary, but we're doing a lot of memory allocation under the hood
    
    ' the Spin SD card class
    dim fsrw as class using "fsrw.spin"
    
    ' our pin usage
    const D0=22, CLK=23, DI=24, CS=25
    
    ' open a file on the SD card
    sub openfile(n as integer, name as string, mode as string)
      dim r
      r = fsrw.popen(name, asc(mode))
      if r < 0 then
        throw r
      end if
      open SendRecvDevice(@fsrw.pputc, @fsrw.pgetc, @fsrw.pclose) as #n
    end sub
    
    dim err
    dim s$
    dim cycles as uinteger
    
    try
    
      fsrw.mount_explicit(D0, CLK, DI, CS)
      print "done mount"
    
    #ifdef TRY_WRITE
      pausems 500
      print "testing write"
      openfile(2, "hello.txt", "w")
      print #2, "Hello from the propeller"
      cycles = getcnt()
      print #2, "When this was written, cycles = "; cycles
      print #2, "See you!"
      close #2
    #endif
    #ifdef TRY_READ
      pausems 500
      ' try reading it back
      print "testing read"
      openfile(3, "hello.txt", "r")
      s$ = input$(80, 3)
      if s$ then
        print "read back:"
        print s$
      else
        print "got end of file"
      endif
      close #3
    #endif
      print "all done"
    
    catch err
    
      print "caught error: "; err
    
    end try
    
  • Have you done any performance comparisons with PropBASIC?
  • David Betz wrote: »
    Have you done any performance comparisons with PropBASIC?

    Not directly, no -- the two have very different syntaxes so any code for one has to be ported to the other. I have tested fft-bench with fastspin (as Spin code) and since the compiler is the same the benchmark numbers should be very close. On that test fastspin does the FFT in 68 ms, PropBASIC LMM does it in 690 ms, and regular Spin in 1465 ms
  • David BetzDavid Betz Posts: 12,915
    edited October 19 Vote Up0Vote Down
    ersmith wrote: »
    David Betz wrote: »
    Have you done any performance comparisons with PropBASIC?

    Not directly, no -- the two have very different syntaxes so any code for one has to be ported to the other. I have tested fft-bench with fastspin (as Spin code) and since the compiler is the same the benchmark numbers should be very close. On that test fastspin does the FFT in 68 ms, PropBASIC LMM does it in 690 ms, and regular Spin in 1465 ms
    Yeah, I know the syntax is different. That's good since PropBASIC will appeal to BASIC Stamp users since it is similar to pBASIC and fastBASIC will appeal to people familiar with PC-based BASIC dialects like FreeBASIC.

  • Mike GreenMike Green Posts: 22,828
    edited October 19 Vote Up0Vote Down
    Is there a compiled version for the MacOS (of fastspin and spin2gui)? I know I should be able to compile it from source, but I just get a variety of errors and it's taking too much time and effort.
  • I downloaded the new spin2gui, and I tried the program below. Now, it seems to be coming up with some errors. On the previous versions of spin2gui the program below seemed to have run as expected.

    The error refers to an unknown symbol Dhtnn_object_dhtnn_read_tmp003, not sure where this is located. Is this something that fastspin(BASIC) is doing?

    Ray
    rem test_temp.bas
    ' October 13, 2018
    ' Test of the CM2302 module on the WX Activity Board
    
    dim cm2302 as class using "DHTnn_Object.spin"
    
    
    let mscycles = clkfreq / 1000
    sub pausems(ms)
    	waitcnt(getcnt() + ms * mscycles)
    end sub
    
    dim temp#,humid#,misc#
    
    cm2302.StartDHTnn(8,22,@temp#,@humid#,@misc#)
    
    do
    	cm2302.DHTnn_Read()
    	print "Temp ";(9.0/5.0)*temp# + 32.0;"  Humid  ";humid#
    	pausems 3000
    
    loop
    
    
    test_temp.bas
    |-DHTnn_Object.spin
    |-|-FloatMath.spin
    test_temp.pasm
    Done.
    G:/fastspin/programs/test_temp/test_temp.pasm(719) error: Unknown symbol Dhtnn_object_dhtnn_read_tmp003_
    G:/fastspin/programs/test_temp/test_temp.pasm(771) error: Unknown symbol Dhtnn_object_dhtnn_read_tmp003_
    child process exited abnormally
  • David BetzDavid Betz Posts: 12,915
    edited October 19 Vote Up0Vote Down
    Mike Green wrote: »
    Is there a compiled version for the MacOS (of fastspin and spin2gui)? I know I should be able to compile it from source, but I just get a variety of errors and it's taking too much time and effort.
    Here is spin2cpp compiled to run on the Mac. It sounds like you don't have to compile spin2gui. You just have to get the source code from GitHub, open a command prompt, and cd to the top-level directory and type "wish spin2gui.tcl".


  • Rsadeika wrote: »
    I downloaded the new spin2gui, and I tried the program below. Now, it seems to be coming up with some errors. On the previous versions of spin2gui the program below seemed to have run as expected.

    The error refers to an unknown symbol Dhtnn_object_dhtnn_read_tmp003, not sure where this is located. Is this something that fastspin(BASIC) is doing?

    Yes, it sounds like some of the new code for removing unused COG variables is broken. I'll try to track that down. Thanks for the bug report.

  • Here is a zip file that I believe contains everything you need to run spin2gui on the Mac. You should start the GUI from a command line prompt by setting your current directory to "spin2gui" and typing "wish spin2gui.tcl".
    unzip spin2gui
    cd spin2gui
    wish spin2gui.tcl
    
  • Thanks David
  • David Betz wrote: »
    Here is a zip file that I believe contains everything you need to run spin2gui on the Mac. You should start the GUI from a command line prompt by setting your current directory to "spin2gui" and typing "wish spin2gui.tcl".
    unzip spin2gui
    cd spin2gui
    wish spin2gui.tcl
    
    FYI, I tried this today and ran the "blink1.bas" sample program. It worked fine on the ActivityBoard WX after I changed the PIN number to 26. I only tried a serial download.
Sign In or Register to comment.