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

1575860626367

Comments

  • JRoarkJRoark Posts: 549
    edited 2020-07-27 - 22:06:06
    @ersmith It appears the variable "cnt" is defined somewhere within the bowels of the compiler.

    Example code:
    	var cnt = 3
    	print "This is a test"
    	print cnt
    
    Running this code produces: "warning: definition of cnt hides a member variable".

    Looking at the FlexBASIC docs it appears cnt is reserved since it appears on Page 7 under "LANGUAGE SYNTAX 7 / Predefined functions and variables". But that is the only mention of "cnt" in the entire manual (except for its use as a normal variable in some of the examples).

    So the question is, is cnt an orphan from days gone past, a hint of a new feature as yet unimplemented, or is it a keyword/feature/function that got missed and should be documented?

    EDIT: After a bit of noodling, it appears that cnt() is an undocumented alias for the getCnt() function.


  • Wuerfel_21Wuerfel_21 Posts: 903
    edited 2020-07-27 - 22:25:56
    Less undocumented, more of a Spin1-ism that somehow (intentionally?) finds its way into P2 BASIC
  • Wuerfel_21 wrote: »
    Less undocumented, more of a Spin1-ism that somehow (intentionally?) finds its way into P2 BASIC

    Thats what I think too.

    Honestly, I rather like Cnt() over GetCnt() because the “get” sort of implies to a new coder there might be a SetCnt() lurking somewhere. But it is all good as long as it is documented.

    The compiler has historically handled this juggling nicely so it was a non-issue until Eric implemented the -Wall option. Now we have much more information about potential conflicts at out disposal. (It was an eyeopener to see page after page of warnings issued by 4.2.5 compiling my libraries that had long been considered as “tested and good”).

  • Warnings are a good thing. What would be even better is some sort of "show definition of this" function. In Code::Blocks I can right click on any identifier and choose "show declaration" or "show implementation" from the popup menu. This is especially useful for C where the namespace is flat and it's sometimes not easy to find out where an identifier has already declared before if you have a large project or include a large library.
  • JRoark wrote: »
    @ersmith It appears the variable "cnt" is defined somewhere within the bowels of the compiler.

    Yes, and the warning about re-defining it is bogus (you should be able to redefine weak aliases of this sort). I'll fix that in the next release. Meanwhile, just ignore the warning.
  • ManAtWork wrote: »
    Warnings are a good thing. What would be even better is some sort of "show definition of this" function. In Code::Blocks I can right click on any identifier and choose "show declaration" or "show implementation" from the popup menu. This is especially useful for C where the namespace is flat and it's sometimes not easy to find out where an identifier has already declared before if you have a large project or include a large library.

    FlexGUI is a poor IDE, no question about that. I think it would be nice if someone would take Code::Blocks or Visual Studio Code or some proper IDE like that and adapt it to use fastspin as the compiler.
  • VS Code already supports fastspin!... By way of not really supporting any compiler in particular and not really knowing or caring about your build system. You just set up a task with the commands to compile/run your project and off you go.

    For example, this is the task I use to compile+run the PC version of that game for which I have no good title yet:
            {
                "label": "Run",
                "type": "shell",
                "command": "rake run fastbuild=true",
                "presentation": {
                    "echo": true,
                    "reveal": "always",
                    "focus": false,
                    "panel": "shared",
                    "showReuseMessage": true,
                    "clear": true
                },
                "problemMatcher": []
            },
    
    Notice how it just calls the "run" task on my Rakefile. This could be literally any command.


    Now the C++ extension (which contains all the IDE features like definition lookup) is a bit more involved and needs a bunch of information about the compiler to perform at it's best, but as far as I could tell in a quick test, seems to do reasonably fine without any. It will just assume whatever defaults it has for things like sizeof(void*) though. If you do give it a compiler path, it will apparently somehow gather this information from it. Not sure how that exactly works, but it probably requires a gcc-like commandline interface. I assume it compiles some code and then tries to inspect the resulting binary? IDK.

    The big problem here is that it will all go haywire if you use the more... distinct... fastspin-isms, like struct __using, fastspin-style unquoted inline asm, etc, because the tools it uses internally only understand GCC/clang/VisualC++ brand nonstandard syntax. One will also have to explicitly define all the builtins somewhere, oterwise it'll be very sad when you use them.
  • @ersmith It appears that PI is pre-defined in FlexBASIC (weak alias), but this feature isn't reflected in the docs. Perhaps add a mention in the next release cycle?
  • @ersmith Maybe I missed it but... Are you planning on supporting the new PNut style of debugging?
    It looks useful to me...
  • JRoark wrote: »
    @ersmith It appears that PI is pre-defined in FlexBASIC (weak alias), but this feature isn't reflected in the docs. Perhaps add a mention in the next release cycle?

    I forgot about that, thanks.
    Rayman wrote: »
    @ersmith Maybe I missed it but... Are you planning on supporting the new PNut style of debugging?
    It looks useful to me...

    It's just a fancy printf. For PASM it's nice, but for Spin it doesn't add very much.

    What I'd really like to see is an interactive debugger.
  • What looks good about it is that it is nearly instant and doesn't affect Spin or PASM timing barely at all.
    Also, you can turn it all off and on very easily. That's maybe the best part.
  • I've been burned before by code timing changes after removing all my serial debugging lines from a code...
  • Yeah having a printf capability accessible from PASM should be pretty helpful if the overhead is low. Timing critical PASM may be impacted but I could certainly see a use for it during initial development of PASM objects where the code's logic might be wrong and you are hunting down a bug. It probably would have been very good in debugging my memory driver with a couple of issues I ran into where I had resorted to LEDs to pinpoint problems (still a usable technique but a little slower to use sometimes and hard to show actual data/address values).

    A full interactive debugger would be cool too. If we do get self hosted setups one day it might even be possible to integrate directly instead of needing an external PC and we could have minimal delay and direct memory access from a debug COG. It would be nice to have something like we had with the old TurboDebugger app on a PC where the dev tool and debugger is fairly nicely integrated with full symbols/source/regs etc. Of course this is mostly pie in the sky stuff and we should also have external serial debuggers, probably as the first priority.
  • jmgjmg Posts: 14,482
    rogloh wrote: »
    Yeah having a printf capability accessible from PASM should be pretty helpful if the overhead is low. Timing critical PASM may be impacted but I could certainly see a use for it during initial development of PASM objects where the code's logic might be wrong and you are hunting down a bug. It probably would have been very good in debugging my memory driver with a couple of issues I ran into where I had resorted to LEDs to pinpoint problems (still a usable technique but a little slower to use sometimes and hard to show actual data/address values)..

    I've been thinking there may be useful middle ground between LEDs and printf's

    The P2 smart pins can send up to 32 bits, with in-line loading.
    You could use that, with some simple packing, to send position tags and up to 3 bytes of data over the standard UART link, in a very fast and compact 'no polling' scheme and a fast UART
    [StartBit] + 8+1 +1+8+1 + 1+8   + [Stop]  = 28 bits of data, for 3 bytes, 1 stop bit 
    [StartBit] + 8+2 +1+8+2 + 1+8+1 + [Stop]  = 31 bits of data, for 3 bytes, 2 Stop bits, eg UB3 6Mbd and 8MBd settings.
    Transmit window (min time before next debug tag) is >= 4.125us at 8M.N.2
    
    

    A smarter terminal could collect debug messages and display those strings given the 3 byte ID P2 sends - that removes the message overhead entirely from P2 and slashes the time and size of inserted emit-debug messages.


  • roglohrogloh Posts: 2,707
    edited 2020-07-31 - 03:50:07
    Yeah that's a good idea too jmg. Also if this ESP32 is present for remote access/download etc it could also be employed to accumulate/ format some data over a SPI slave pin at very high speed and then pass up to a centralized debugger via a network which could offload the P2 from doing some of this. Of course that adds more complexity and SPI would need further smartpin clock control etc vs simple a serial interface, but it might then run faster and allow even more data to be passed in real time - it could be good thing for a debug COG to talk to perhaps.
  • Yes its a good idea. I think someone else was also packing 3 bytes + start/stop into a long, though I didn't think it would be possible with the UB3 needing 2 stop bits, so thats good

    On the SPI clocking it should be possible to kick off a matching series of clock pulses using the toggle (transitions) mode
  • The first start bit and final stop bit are built-in to the async smartpin modes. This provides up to 34 bits in total.
  • Cluso99Cluso99 Posts: 16,605
    edited 2020-08-06 - 07:36:58
    Eric,
    Found a problem with v4.2.6 whereas v4.2.4 works. Update: 4.2.5 also fails.
    The problem is in the _FAT32 object in the calls listentries("N") and listdirectory("A") which is called from OS226x1 line 207
    repeat while(buffer := taf.listEntries("N"))

    I have stripped out as much code as I easily can. There are listings for both 4.2.4 and 4.2.6 fastspin versions.
    The code requires a P2Eval with a FAT32 formatted card. Download and run the program and when SD:> appears type DIR<cr>.
    The faulty code displays the filenames and then blanks filenames until the sort table has been filled (I reduced this to 32). The correct code just displays the correct filenames and returns to the SD:> prompt.

    This could be the offending code
    PRI isDIRNotEnd() : result 
      result or= blockToByte(currentByte)
    

    I note that it is always returning $FFFFFFFF (when in error) even when blockToByte(currentByte) is 0.
    BTW I don't understand the or= function ???
  • That same bug is already fixed in the latest git version, I already found and reported it :)
  • Wuerfel_21 wrote: »
    That same bug is already fixed in the latest git version, I already found and reported it :)
    Thanks :)

    Can you explain what This is doing please
    result or= blockToByte(currentByte)

    I know that whenever blockToByte(currentByte) > 0 the function returns $FFFFFFFF (ie -1) and when 0 returns 0. I just don't understand why.
  • RESULT always starts out as zero when a function is called.
    result or= blockToByte(currentByte)
    
    is the same as
    result := 0 or blockToByte(currentByte)
    
    which is the same as
    result := NOT NOT blockToByte(currentByte)
    

    Basically, it returns -1 if blockToByte returns non-zero
  • Thanks for the bug report. I hope to have a new binary release soon with this bugfix for those who don't build from source.
  • Wuerfel_21 wrote: »
    RESULT always starts out as zero when a function is called.
    result or= blockToByte(currentByte)
    
    is the same as
    result := 0 or blockToByte(currentByte)
    
    which is the same as
    result := NOT NOT blockToByte(currentByte)
    

    Basically, it returns -1 if blockToByte returns non-zero
    Thanks. I knew result is initialised as zero. It’s the true/false statement of the or= that I didn’t get although I knew that was what was happening. It’s these shortcuts is what I dislike in C (and spin).
  • In Spin weird shortcuts are kinda common (especially in my code...) as it actually makes the code faster and smaller in non-fastpin compilers (and of course, there's similar weird patterns where fastspin can be made to emit smaller code by transforming something like
    if condition
      obj_var := string("abc")
    else
      obj_var := @something + x
    
    into
    local_tmp := string("abc")
    ifnot condition
      local_tmp := @something + x
    obj_var := local_tmp
    
    )

    Not as common in C/C++ anymore since the major compilers got really good at optimizing.
    ersmith wrote: »
    for those who don't build from source.
    I'm gonna try fiddling with GitHub's CI thing to see if I can get it to build fresh fastspins for each commit. That'd solve that problem.
  • Wuerfel_21 wrote: »
    I'm gonna try fiddling with GitHub's CI thing to see if I can get it to build fresh fastspins for each commit. That'd solve that problem.

    Doneski. PR submitted, should "just work" after merging

  • Just listend (well, still in the Q&A section) the C Live Forum and Eric brought up that he might want to rename the suite because he's bad at names.

    I have some internal tools that use a "multi-" prefix (they're called MultiRASM and MultiXMM), but since they aren't public at the moment, I can give that prefix to you if you want it ;)

    In general, I personally like puns (see JET Engine and all the Ventilator-stuff.. Homespun also, heh)... Would have to think about a good one that hasn't been used yet though.

  • Wuerfel_21 wrote: »
    Wuerfel_21 wrote: »
    I'm gonna try fiddling with GitHub's CI thing to see if I can get it to build fresh fastspins for each commit. That'd solve that problem.

    Doneski. PR submitted, should "just work" after merging

    Thanks, @Wuerfel_21 . I need to wrap my head around github's CI and what the implications are, but I'll take a look at it.
  • I've uploaded a new binary release (4.2.8) to the usual places. This is a bug fix release; the only new feature is an option -Werror to turn warnings into errors.
  • ersmith wrote: »
    I need to wrap my head around github's CI and what the implications are, but I'll take a look at it.

    It basically just runs some commands on a cloud server somewhere every time you push a commit. It doesn't really do anything else. Well, by default it sends you an email if you pushed something that fails to build/test.
  • JRoarkJRoark Posts: 549
    edited 2020-08-09 - 18:09:48
    @ersmith (or anyone): Is there any way, at runtime, to determine the type of a variable that is passed to a SUB or FUNCTION in FlexBASIC? Example:
    FUNCTION WhatAmI(a as any) as string
    
    if a = type_string then return "It's a string"
         ... (more of the same) ...
    if a = type_long then return "It's a long"
    
    END FUNCTION
    
    Edit: forgot the {code}{/code} formatting. Duh.
Sign In or Register to comment.