Shop OBEX P1 Docs P2 Docs Learn Events
flexspin compiler for P2: Assembly, Spin, BASIC, and C in one compiler - Page 28 — Parallax Forums

flexspin compiler for P2: Assembly, Spin, BASIC, and C in one compiler

12526283031116

Comments

  • Cluso99 wrote: »
    Eric,
    Were there changes to loadp2 from version 3.9.31 to 3.9.33?

    v3.9.33 fails to run programs that run fine with v3.9.31 :(

    pnut compiles and loads/runs fine. I have compared the fastspin and pnut binarys and they are fine.

    Yes, there were changes to support the new P2 ES boards. My original P2 ES board still works though.

    What problems exactly are you having? What command line are you using for loadp2, and what symptoms do you see? Does the -SINGLE mode (using the ROM loader work for you)?
  • Rayman wrote: »
    Looks like the compile error message format was changed, right?
    Yes, this was intentional. The old code had a mix of compiler error messages -- the preprocessor used one format and the main compiler used a different one. I changed the main compiler to match the preprocessor, which also happens to match the format used by GCC and other C compilers, so it's somewhat standard.

    In flexgui to find error lines I look for "error:" and then back up to look at preceding ":" to find the line number and file name.

  • Cluso99Cluso99 Posts: 18,066
    ersmith wrote: »
    Cluso99 wrote: »
    Eric,
    Were there changes to loadp2 from version 3.9.31 to 3.9.33?

    v3.9.33 fails to run programs that run fine with v3.9.31 :(

    pnut compiles and loads/runs fine. I have compared the fastspin and pnut binarys and they are fine.

    Yes, there were changes to support the new P2 ES boards. My original P2 ES board still works though.

    What problems exactly are you having? What command line are you using for loadp2, and what symptoms do you see? Does the -SINGLE mode (using the ROM loader work for you)?

    I recompiled this simple program with pnut.
    If pnut or loadp2 (called L31.exe) load this obj file then the P56 LED flashes and a message is output every second.
    I looadp2 (called L33.exe) load this object, the LED flashes but there is no serial output (on the loadp2 terminal or PST)
    The program is NOT sending serial as there is no tiny flash on the P62 LED. I've found other instances where my test led is not flashing.
    Seems like a download corruption even tho no errors are reported.

    l33 autodetect_p2ev.obj -b115200 -t

    This works..
    l33 autodetect_p2ev.obj -b115200 -t -SINGLE

    I use the serial and debug code in ROM. It is the same program as I posted above with this change to force P2EV detection.
    '              mov       pcb, #0                         ' P2D2    = 0
    '        if_c  neg       pcb                             ' P2EVAL  = 1
    '
    '        if_c  jmp       #p2eval
    
    ' FORCE P2EVAL
                    jmp     #p2eval        
    
  • @ersmith When using FlexGui version 3.9.33 and writing in FlexBASIC:

    If you DIM a variable at the module level, it is initialized appropriately, ie, an INTEGER or LONG type gets set to zero, and a string is set to a zero-length/empty string (i.e ""). This is the expected behavior. However, if you DIM a variable in a SUB or FUNCTION, it is not initialized at all and will contain whatever was in that memory location before it was allocated.

    Can we make variable initialization behavior symmetrical between the module-level code and the SUB/FUNCTION level code? In otherwords, always set numerics to zero and strings to zero-length/empty when they are DIM'd?
  • Cluso99 wrote: »
    I recompiled this simple program with pnut.
    If pnut or loadp2 (called L31.exe) load this obj file then the P56 LED flashes and a message is output every second.
    I looadp2 (called L33.exe) load this object, the LED flashes but there is no serial output (on the loadp2 terminal or PST)
    The program is NOT sending serial as there is no tiny flash on the P62 LED. I've found other instances where my test led is not flashing.
    Seems like a download corruption even tho no errors are reported.
    It looks like there are some timing problems with the fast download path. Sometimes the downloader misses the first few bytes of the download and hangs waiting for the rest (so your program never starts).

    I'm trying to figure out why this is happening -- it seems to be much more frequent at 115200 baud, I hadn't seen it at 230400 before, although there are a few strange glitches sometimes that may be the same thing.
  • JRoark wrote: »
    @ersmith When using FlexGui version 3.9.33 and writing in FlexBASIC:

    If you DIM a variable at the module level, it is initialized appropriately, ie, an INTEGER or LONG type gets set to zero, and a string is set to a zero-length/empty string (i.e ""). This is the expected behavior. However, if you DIM a variable in a SUB or FUNCTION, it is not initialized at all and will contain whatever was in that memory location before it was allocated.
    There's never any guarantee of what's in a variable -- if you want it to be zero you should set it to zero explicitly. Most of memory happens to be zero, so that's what you've seen, but that's not guaranteed by the language.

    Changing functions to always initialize variables to 0 would probably increase code size and slow things down.

  • ersmith wrote: »
    JRoark wrote: »
    @ersmith When using FlexGui version 3.9.33 and writing in FlexBASIC:

    If you DIM a variable at the module level, it is initialized appropriately, ie, an INTEGER or LONG type gets set to zero, and a string is set to a zero-length/empty string (i.e ""). This is the expected behavior. However, if you DIM a variable in a SUB or FUNCTION, it is not initialized at all and will contain whatever was in that memory location before it was allocated.
    There's never any guarantee of what's in a variable -- if you want it to be zero you should set it to zero explicitly. Most of memory happens to be zero, so that's what you've seen, but that's not guaranteed by the language.

    Changing functions to always initialize variables to 0 would probably increase code size and slow things down.

    OK. That works for me. I was thinking you intended for FlexBASIC to behave in a manner similar to FreeBASIC, and this initialization is one of the behaviors that FreeBASIC exhibits. From the FBWiki at https://www.freebasic.net/wiki/wikka.php?wakka=KeyPgDim:
    "Arrays, variables, strings, and user defined types (UDTs) are initialized to zero (or False for Boolean) or null strings by default when they are created".

    "To avoid the overhead of default variable initialization, the Any initializer can be used with Dim to tell the compiler to only reserve the place for the variable in memory but not initialize it, so the variable will contain garbage. In this case the programmer should not make assumptions about the initial values".

    On to pillage!
  • jmgjmg Posts: 15,140
    edited 2019-09-29 21:59
    JRoark wrote: »
    OK. That works for me. I was thinking you intended for FlexBASIC to behave in a manner similar to FreeBASIC, and this initialization is one of the behaviors that FreeBASIC exhibits. From the FBWiki at https://www.freebasic.net/wiki/wikka.php?wakka=KeyPgDim:
    "Arrays, variables, strings, and user defined types (UDTs) are initialized to zero (or False for Boolean) or null strings by default when they are created".
    "To avoid the overhead of default variable initialization, the Any initializer can be used with Dim to tell the compiler to only reserve the place for the variable in memory but not initialize it, so the variable will contain garbage. In this case the programmer should not make assumptions about the initial values".

    It's fairly common, but not universal, for compilers to clear all VAR memory (eg up to stack) as part of INIT pass, so that will implicitly clear on startup.
    That pass is separate from loading to values <> 0, if those are specified & `clear all` code can be very compact.

    It's also common for compilers to treat local vars inside functions, as overlayable, and that means their initial value cannot be assumed for every call.
    ie Only the first function call that uses that address will initially see a 0, later calls, and other functions, have ?? in the var address.

    ersmith wrote: »
    .... Most of memory happens to be zero, so that's what you've seen, but that's not guaranteed by the language.
    When you say 'happens to be zero' does that mean there is already a `clear RAM` pass done ?

  • Cluso99Cluso99 Posts: 18,066
    IIRC correctly, hub is initialised to all 0's on powerup but a reset does not clear the hub so what was there remains.
  • ersmith wrote: »
    Cluso99 wrote: »
    I recompiled this simple program with pnut.
    If pnut or loadp2 (called L31.exe) load this obj file then the P56 LED flashes and a message is output every second.
    I looadp2 (called L33.exe) load this object, the LED flashes but there is no serial output (on the loadp2 terminal or PST)
    The program is NOT sending serial as there is no tiny flash on the P62 LED. I've found other instances where my test led is not flashing.
    Seems like a download corruption even tho no errors are reported.
    It looks like there are some timing problems with the fast download path. Sometimes the downloader misses the first few bytes of the download and hangs waiting for the rest (so your program never starts).

    I'm trying to figure out why this is happening -- it seems to be much more frequent at 115200 baud, I hadn't seen it at 230400 before, although there are a few strange glitches sometimes that may be the same thing.
    A few revisions ago I had problems with not sending the whole binary. This happened because I didn't wait for the serial buffer to fully empty before changing from the loader baud rate to the user baud rate. I added a wait_drain() function to handle this, which called tcdrain() on Linux systems and msleep(100) on Windows. The msleep(100) is not long enough for low baud rates. Maybe something changed between rev 31 and 32 that affected the timeouts.
  • jmgjmg Posts: 15,140
    Cluso99 wrote: »
    IIRC correctly, hub is initialised to all 0's on powerup but a reset does not clear the hub so what was there remains.

    There is no async reset on RAM (that costs too much die area) so any memory clear needs to be software based.
    That means it should behave the same on reset, as on powerup ?
    Compilers also often include code to clear the VAR space they use, which is in the startup before main() or the equiv.
  • yetiyeti Posts: 818
    edited 2019-09-30 11:00
    ersmith wrote: »
    Changing functions to always initialize variables to 0 would probably increase code size and slow things down.
    That's ok... it just should be documented (-: in bold letters? :-) because it deviates from what we are used to e.g. in HomeSpun, BSTC and OpenSpin.
    Edit 201909301100UTC: I mixed up zeroing at program start and zeroing on each function call here.
  • yeti wrote: »
    ersmith wrote: »
    Changing functions to always initialize variables to 0 would probably increase code size and slow things down.
    That's ok... it just should be documented (-: in bold letters? :-) because it deviates from what we are used to e.g. in HomeSpun, BSTC and OpenSpin.

    Actually no.

    Spin does not set local variables to anything, except RESULT which is set to 0.

    Mike
  • yeti wrote: »
    ersmith wrote: »
    Changing functions to always initialize variables to 0 would probably increase code size and slow things down.
    That's ok... it just should be documented (-: in bold letters? :-) because it deviates from what we are used to e.g. in HomeSpun, BSTC and OpenSpin.

    I agree the documentation is the more important part. It isnt hard to programatically clear a variable, as long as you know that such an action is needed.

    Assumptions are tricky things. I assumed since FlexBASIC was being implemented along the lines of FreeBASIC, that it would follow the same conventions. Compounding this belief was the anecdotal evidence that the compiler had been clearing variables. For weeks I had accidently gotten away with not clearing variables without ill effects. Today my good luck finally ran out.

    I think this just needs a quick note in the docs to “fix” the “problem”. The fact that FlexBASIC does not clear memory or initialize variables may even be useful at some point.


  • yeah, my guess is that the stack in bytecode spin and all compilers is either zeroed or relies on being zero at boot time.

    So the first call work. After that you don't now.

    Basically the same with PASM. A res variable contains whatever is behind the DAT block in the Spin Image.

    One thing is different here, GLOBAL vars you put into a VAR section in SPIN do get initialized to zero at program load.

    I don't know why. That difference. I like the freebasic version somehow attribute ANY - but does it really makes a difference?

    I think it does and explain:

    You would need to write ANY for all the declarations to avoid code produced to init the variable. We are all lazy so we will not do that consequently and produce bigger binaries. But if you need to write code to init the var you think about if you really need that one - so smaller code.

    Mike
  • JRoark wrote: »
    ...
    I think this just needs a quick note in the docs to “fix” the “problem”. The fact that FlexBASIC does not clear memory or initialize variables may even be useful at some point.
    It is already stated in the documentation:

    https://github.com/totalspectrum/spin2cpp/blob/af4ed633585275b3da391c73a5ef7a412860a876/doc/basic.md#global-member-and-local-variables
    Global (shared) variables may be accessed from anywhere in the program, and exist for the duration of the program. They are created with the dim shared declaration, and may be given an initial value.
    Member variables are automatically initialized to 0, and may not be initialized to any other value.
    Local variables may be initialized to values, but this initialization is done at run time so it has some overhead.

    @ersmith : is it still true that member variables are initialized to 0?
  • When using FlexGui version 3.9.33 and writing in FlexBASIC:
       const cTemp = 3_000.123456   <-- this works fine
       const cTemp = 3000.123_456   <-- error: syntax error, unexpected identifier `_456', expecting $end or end of
                                        line or end or ':'
    
       var cTemp = 3_000.123456     <-- this works fine
       var cTemp = 3000.123_456   <-- error: syntax error, unexpected identifier `_456', expecting $end or end of
                                        line or end or ':'
    

    The manual says:
    Integers

    Decimal integers are a sequence of digits, 0-9. Hexadecimal (base 16) integers start with the sequence "&h", "0h", or "0x" followed by digits and/or the letters A-F or a-f. Binary (base 2) integers start with the sequence "&b" or "0b" followed by the digits 0 and 1. Numbers may contain underscores anywhere to separate digits; those underscores are ignored.
    The manual clearly references underscores only within the context of talking about "integers" (there is no similar discussion for floats/SINGLEs), so this really isn't a bug. However, since an underscore can appear to the left of the decimal, but not to the right of the decimal, it seems appropriate to raise this issue based on consistency.



  • rosco_pc wrote: »
    It is already stated in the documentation:

    https://github.com/totalspectrum/spin2cpp/blob/af4ed633585275b3da391c73a5ef7a412860a876/doc/basic.md#global-member-and-local-variables
    Global (shared) variables may be accessed from anywhere in the program, and exist for the duration of the program. They are created with the dim shared declaration, and may be given an initial value.
    Member variables are automatically initialized to 0, and may not be initialized to any other value.
    Local variables may be initialized to values, but this initialization is done at run time so it has some overhead.

    @ersmith : is it still true that member variables are initialized to 0?

    Whoops, that line is mistaken -- it's based on an older version of FlexBASIC where there were only very limited uses possible for classes. Now that classes can be used for any kind of variable (including local variables within functions) it's no longer true that member variables are always initialized to 0. Thanks for pointing that out, I'll fix the documentation.
  • JRoark wrote: »
    When using FlexGui version 3.9.33 and writing in FlexBASIC:
       const cTemp = 3_000.123456   <-- this works fine
       const cTemp = 3000.123_456   <-- error: syntax error, unexpected identifier `_456', expecting $end or end of
                                        line or end or ':'
    
       var cTemp = 3_000.123456     <-- this works fine
       var cTemp = 3000.123_456   <-- error: syntax error, unexpected identifier `_456', expecting $end or end of
                                        line or end or ':'
    
    That's an oversight. Thanks for bringing it to my attention!
  • When using FlexGui version 3.9.33 on Win 10:

    @ersmith Really minor stuff here, but I'll post it anyway in case you get inspired during the next release cycle.

    1). The Undo/Redo in the FlexGUI editor seems to be broken. In the last revision there was one level of Undo/Redo that was functional (if memory serves). Undo/Redo seems to have no effect now.

    2). Consider adding two things to FlexGUI's user interface:
    - Add a "Replace" function to supplement the "Find" capability in the Search widget.
    - When you right-click a file tab, add a "Close" function to the existing Cut/Copy/Paste/Undo/Save/Save As widget.
  • JRoark wrote: »
    1). The Undo/Redo in the FlexGUI editor seems to be broken. In the last revision there was one level of Undo/Redo that was functional (if memory serves). Undo/Redo seems to have no effect now.
    Whoops, a typo I think. There's a line in gui.tcl that reads:
        ctext $w.txt -wrap none -yscrollcommand $yscmd -xscroll $xscmd -tabstyle wordprocessor -linemap $config(showlinenumbers)
    
    (It's in the setupFramedText procedure, near line 440). If you add "-undo 1" to the end of that then the Undo/Redo should work again.
    2). Consider adding two things to FlexGUI's user interface:
    - Add a "Replace" function to supplement the "Find" capability in the Search widget.
    - When you right-click a file tab, add a "Close" function to the existing Cut/Copy/Paste/Undo/Save/Save As widget.

    The "Close" should be easy, it's just adding an entry to the .popup1 menu, something like:
    .popup1 add command -label "Close" -command { closeTab }
    
    Not sure about the replace function, but the searchrep widget seems to have that functionality, so I'll look into that.
  • @ersmith Both work perfectly now! Thanks.
  • @ersmith I've had some minor issues with flexgui, running on macOS. The buttons on the edit screen as well as the Configure Commands screen do not show up until I manipulate the UI (resize the window, click in the edit fields, etc.) with the mouse. So, on each execution of flexgui and selection of Configure Commands, the buttons need to be "resurrected" with the mouse... Seems to just happen on macOS, as I ran flexgui on Linux & WIN10 without the problems.

    To temporarily fix the problems I added several small changes in gui.tcl that have gotten the buttons to display... Here's an example:
    # added Tk requirement
    package require Tk
    #...
    # added "ttk::" to each button creation
      ttk::button .toolbar.compile -text "Compile" -command doCompile
      ttk::button .toolbar.runBinary -text "Run Binary" -command doLoadRun
      ttk::button .toolbar.compileRun -text "Compile & Run" -command doCompileRun
    #...
      ttk::button .runopts.change.p2a -text "P2a defaults" -command setShadowP2aDefaults
      ttk::button .runopts.change.p2b -text "P2b defaults" -command setShadowP2bDefaults
      ttk::button .runopts.change.p1 -text "P1 defaults" -command setShadowP1Defaults
    #...
      ttk::button .runopts.end.ok -text " OK " -command {copyShadowClose .runopts}
      ttk::button .runopts.end.cancel -text " Cancel " -command {wm withdraw .runopts}
    
    # one more minor issue is the small input fields for the Configure Commands compile & run options...
    # expand width of input fields from 32 to 72 chars.
      entry .runopts.a.compiletext -width 72 -textvariable shadow(compilecmd)
    #...
      entry .runopts.b.runtext -width 72 -textvariable shadow(runcmd)
    

    Not sure if this was a good solution and how it might effect flexgui on other platforms. You may have a much better solution. The button issue is probably in the macOS version of Tcl/Tk, as I witnessed the same problem in other Tcl/Tk code on macOS.

    Thanks,
    dgately

  • @dgately: Thanks for trying this on MacOS and for the ttk::button tip. That seems to work OK on Linux and Windows so I've made it the default now.

    @JRoark: I have a simple replace function that seems to work now. It's in the preview release (see below).

    All: I've posted a 4.0.0-preview release to

    https://github.com/totalspectrum/flexgui/releases

    Besides the fixes above, it has a new loadp2 that allows the loader and user program to have different baud rates on Linux. With that change the loader now defaults to 921600 baud download speed, which is nice. There are also some improvements to allow integration with the Windows desktop and to let flexgui run from a directory other than its "home" directory.

    If you get a chance please try the preview out and let me know of any problems you find.
  • JRoarkJRoark Posts: 1,214
    edited 2019-10-06 15:58
    @ersmith When using FlexGui version 4.0.0-beta and writing in FlexBASIC for a P1:

    A BASIC file that contains only FUNCTIONs and SUBs can not be compiled. This error results: error: could not find function program

    This code will generate the error:
       OPTION EXPLICIT	
       const cPI = 3.14159
    	
    FUNCTION Echo1(anyString as string) as string
       'just return the string that was supplied
       return AnyString
    END FUNCTION
    
    FUNCTION Echo2(anyString as string) as string
       'just return the string that was supplied
       return AnyString
    END FUNCTION
    

    The error does NOT occur if you put a single line of code in the main part of the program, like this:
       OPTION EXPLICIT	
       const cPI = 3.14159
    
       print "hi!"      '<-- adding this line makes it all better. It could be anything, really...
    
    FUNCTION Echo1(anyString as string) as string
       'just return the string that was supplied
       return AnyString
    END FUNCTION
    
    FUNCTION Echo2(anyString as string) as string
       'just return the string that was supplied
       return AnyString
    END FUNCTION
    

    My goal is to have standalone libraries ("StringLib.bas" for string handling, "Math.bas" for advanced math, etc) that contain routines (ATAN, SIN, INSTR$, etc) that can be called by other programs via #INCLUDE "myLib.bas". In order to fully debug these libraries, I need to do a test-compile on them as a final sanity check. Since libraries dont have a "main" routine per se, this error is problematic.
  • yetiyeti Posts: 818
    edited 2019-10-06 17:01
    Includes and libraries are different concepts. Both won't get compiled on their own in FlexBASIC.

    Libraries are external classes (objects):
    File "basic-library.bas":
    function martian_quotient(m as single, n as single) as single
      martian_quotient = n / m
    end function
    
    File "basic-library-test.bas":
    dim mars as class using "basic-library.bas"
    
    print mars.martian_quotient(113, 355)
    
    Build it:
    $ fastspin basic-library-test.bas -o basic-library-test.bas.binary
    Propeller Spin/PASM Compiler 'FastSpin' (c) 2011-2019 Total Spectrum Software Inc.
    Version 4.0.0-beta-317bfbe5 Compiled on: Oct  5 2019
    basic-library-test.bas
    |-basic-library.bas
    fmt.c
    strcpy.c
    strlen.c
    basic-library-test.bas.pasm
    Done.
    Program size is 8352 bytes
    
    Run it:
    spinsim -b basic-library-test.bas.binary
    3.1420                                                                                            
    

    "#include" is just a text operation inlining the included files contents into the program. This will need no external compile either.

    Functions from (external) classes have their own namespace, functions from #include files just are literally part of the program's namespace.

    If you want to test compile a library which shall be used as #include file, just add some test code wrapped in e.g. "#ifdef selftest"/"#endif" and add defining "selftest" ("-D selftest") to the compiler options.
  • JRoark wrote: »
    @ersmith When using FlexGui version 4.0.0-beta and writing in FlexBASIC for a P1:

    A BASIC file that contains only FUNCTIONs and SUBs can not be compiled. This error results: error: could not find function program

    My goal is to have standalone libraries ("StringLib.bas" for string handling, "Math.bas" for advanced math, etc) that contain routines (ATAN, SIN, INSTR$, etc) that can be called by other programs via #INCLUDE "myLib.bas". In order to fully debug these libraries, I need to do a test-compile on them as a final sanity check. Since libraries dont have a "main" routine per se, this error is problematic.

    As @yeti suggested, the best way to do this is to provide some actual test code in the library file, and compile with that test code enabled. That way you can also test the functionality of the code, not just whether it compiles. (Since fastspin eliminates unused methods, even if you could compile a file with no actual functions it would produce an empty output and wouldn't do all the checking it could on the unused methods.)

    If you're only using "class using" (and not #include) you can skip the #ifdef around test code. In that case anything in the top level of the library class will be put into a subroutine called "program". That is:
    ' mylib.bas
    sub greet(msg as string)
      print msg
    end sub
    
    greet "hello, world"
    
    ' main.bas
    dim G as class using "mylib.bas"
    G.greet("hello")
    G.greet("goodbye")
    
    In this case if you compile and run just "mylib.bas" it will print "hello, world" as a test. If you compile and run "main.bas" it will print "hello" and then "goodbye". The class G will contain two subroutines, G.greet and G.program. G.program is the test program that prints "hello, world". Since it isn't actually used in main.bas it will be removed automatically by the compiler (just like any unused subroutine).
  • Thanks guys. This not only set me straight, it also answered two other questions I had rolling around in my head. Good stuff!
  • @ersmith When using FlexGui version 4.0.0-beta and writing in FlexBASIC for a P1 under Win10:

    The following program bricks the compiler and the editor, and after a few seconds causes Windows to give a "not responding" error:
    CONST clkfreq = 80_000_000
    print "hi"
    
    Attempting to set CLKFREQ to a CONSTant is a programmer error, but ideally this should get trapped and throw a compile-time error instead of hanging FlexGUI.

    FWIW, I'm *really* liking the 4.0.0-beta!
  • JRoark wrote: »
    @ersmith When using FlexGui version 4.0.0-beta and writing in FlexBASIC for a P1 under Win10:

    The following program bricks the compiler and the editor, and after a few seconds causes Windows to give a "not responding" error:
    CONST clkfreq = 80_000_000
    print "hi"
    
    Ah, interesting. There's a bug in fastspin where redefining some built-in objects causes a hang. That'll be fixed in the final 4.0.0 version.

    Thanks for the bug report!
Sign In or Register to comment.