Shop Learn P1 Docs P2 Docs
Mixing PNut and flexspin specific code — Parallax Forums

Mixing PNut and flexspin specific code

flexspin and "standard" Spin2 are mostly compatible, but there are a few things (like how to do COG resident functions) that are different between them, mainly because of assumptions about the memory layout of the interpreter.

It'd be really nice if Spin2 had some basic preprocessor commands as standard (like #define and #ifdef). But until it does, there is a work-around in flexspin. You can include flexspin specific code in a comment that has a very specific form, namely a line starting with:

{$flexspin

If flexspin sees such a comment it ignores the first $flexspin in the comment and then re-processes the rest of the comment as if it were ordinary input. This can include preprocessor commands like #ifdef, so you can keep PNut specific code from being compiled in flexspin. For example:

CON
  _clkfreq = 160_000_000

PUB main()
{$flexspin
#ifdef __FLEXSPIN__
    ' this code is for flexspin only
    DEBUG("hello from flexspin", 13, 10)
#else
    ' code after this is for PNut/PropTool only
}
    DEBUG("hello from PNut", 13, 10)
    ' end the PNut only section
{$flexspin #endif}

    DEBUG("hello from both", 13, 10)

Will output:

Cog0 hello from flexspin
Cog 0 hello from both

when compiled with flexspin, but

Cog0 hello from PNut
Cog 0 hello from both

when compiled with PNut or PropTool.

Comments

  • evanhevanh Posts: 13,424

    Cool! Making that compatible with Pnut is the real trick.

    Same again but formatting variation:

    CON
      _clkfreq = 160_000_000
    
    PUB main()
    
    {$flexspin #ifdef __FLEXSPIN__
        DEBUG("hello from flexspin", 13, 10)
    #else}
        DEBUG("hello from PNut", 13, 10)
    {$flexspin #endif}
        DEBUG("hello from both", 13, 10)
    
  • @ersmith , adding Pascal-style {$...} versions of all the C-style preprocessor directives might be a good way to do what @evanh is suggesting.

  • evanhevanh Posts: 13,424

    Do you mean like this?

    {$flexspin #ifdef __FLEXSPIN__}
        DEBUG("hello from flexspin", 13, 10)
    {$flexspin #else}
        DEBUG("hello from PNut", 13, 10)
    {$flexspin #endif}
        DEBUG("hello from both", 13, 10)
    

    Problem is that won't compile in Pnut. As Eric stated, ideally Pnut/PropTool gets a preprocessor instead.

  • ersmithersmith Posts: 5,404

    @evanh said:
    Same again but formatting variation:

    Thank you, that looks much cleaner!

    @Electrodude said:
    @ersmith , adding Pascal-style {$...} versions of all the C-style preprocessor directives might be a good way to do what @evanh is suggesting.

    Unless PNut is changed to understand those it wouldn't help us to mix PNut and flexspin only code. :(

    I also should point out that this isn't a proposal, it's a feature that's already in flexspin (and has been for a little while). I can't control what PNut sees, except that I know that PNut ignores comments. So I added the $flexspin comment to provide a way to include flexspin only code that PNut will ignore. The neat part is that you can use the flexspin preprocessor inside those comments to make it possible to have PNut only code that flexspin will ignore.

  • I'm saying that you could more cleanly combine the existing {$flexspin directives with my proposed {$...} directives than you could with C-style directives, since Pascal-style ones are supposed to work anywhere in a line, while C ones are really only supposed to occur at the beginning of lines.

    Also, I imagine Chip would be less unwilling to implement a Pascal-style preprocessor than a C-style one.

  • evanhevanh Posts: 13,424

    Might want to give an example.

  • ElectrodudeElectrodude Posts: 1,486
    edited 2022-07-02 15:13

    @evanh said:
    Might want to give an example.

    The same as your first example, but with {$...} instead of #...\n. It seems cleaner this way because then you don't have C-style preprocessor directives embedded in the middle of the line, with other stuff before or after which the parser has to somehow understand isn't part of the directive even though the newline that normally delimits C-style preprocessor directives isn't there.

    This way, it's obvious where the directives start and end because these ones don't care about newlines.

    CON
      _clkfreq = 160_000_000
    
    PUB main()
    
    {$flexspin {$ifdef __FLEXSPIN__}
        DEBUG("hello from flexspin", 13, 10)
    {$else}}
        DEBUG("hello from PNut", 13, 10)
    {$flexspin {$endif}}
        DEBUG("hello from both", 13, 10)
    
  • evanhevanh Posts: 13,424
    edited 2022-07-02 22:56

    Comments inside comments aren't doing it for me. Eric's look is cleaner at the moment.

    Looking up FreePascal reference I get: {comment} for comments ... and {$DEFINE name comment} and {$IFDEF name comment} and {$IF expr comment} and {$ELSE comment} and {$ENDIF comment} for preprocessor macros with optional comments.

    So Chip would likely implement this:

    CON
      _clkfreq = 160_000_000
    
    PUB main()
    
    {$ifdef __FLEXSPIN__}
        DEBUG("hello from flexspin", 13, 10)
    {$else}
        DEBUG("hello from PNut", 13, 10)
    {$endif}
        DEBUG("hello from both", 13, 10)
    
  • cgraceycgracey Posts: 13,733

    @evanh said:
    Comments inside comments aren't doing it for me. Eric's look is cleaner at the moment.

    Looking up FreePascal reference I get: {comment} for comments ... and {$DEFINE name comment} and {$IFDEF name comment} and {$IF expr comment} and {$ELSE comment} and {$ENDIF comment} for preprocessor macros with optional comments.

    So Chip would likely implement this:

    CON
      _clkfreq = 160_000_000
    
    PUB main()
    
    {$ifdef __FLEXSPIN__}
        DEBUG("hello from flexspin", 13, 10)
    {$else}
        DEBUG("hello from PNut", 13, 10)
    {$endif}
        DEBUG("hello from both", 13, 10)
    

    I think I can do that. I am finishing the debugger right now.

  • evanhevanh Posts: 13,424

    Cool.

  • ersmithersmith Posts: 5,404

    @cgracey, @evanh : OpenSpin and FlexSpin already implement the #define / #ifdef / #endif preprocessor. Is it really necessary to introduce a different syntax (namely ($define} and such)? If PNut could understand the #define form that would do everything we want.

  • evanhevanh Posts: 13,424
    edited 2022-07-04 11:58

    I'm easy. So, Chip, that'd be:

    CON
      _clkfreq = 160_000_000
    
    PUB main()
    
    #ifdef __FLEXSPIN__
        DEBUG("hello from flexspin", 13, 10)
    #else
        DEBUG("hello from PNut", 13, 10)
    #endif
        DEBUG("hello from both", 13, 10)
    

    And commenting stays within curly braces.

  • But the Pascal syntax looks better because Spin uses curly braces for comments, like Pascal. It should be trivial to make Flexspin and OpenSpin (and PNut, for that matter, once it understands either) understand both syntaxes - the stuff inside the {$...} works exactly the same as what goes inside C-style #...\n.

  • ersmithersmith Posts: 5,404
    edited 2022-07-04 19:26

    @Electrodude said:
    But the Pascal syntax looks better because Spin uses curly braces for comments, like Pascal. It should be trivial to make Flexspin and OpenSpin (and PNut, for that matter, once it understands either) understand both syntaxes - the stuff inside the {$...} works exactly the same as what goes inside C-style #...\n.

    But, these aren't actually comments, nor are they directives that may be ignored. They matter!

    Embedding semantically important information (like #ifdef) inside comments is dangerous. Older versions of the compiler will just ignore the directives, which means that the code will not compile correctly and worse will not produce any errors or warnings. At least with a new syntax like #ifdef the older compiler will reject the code completely instead of silently mis-compiling it.

    Moreover, as I pointed out, several existing compilers already support the #ifdef syntax. Rather than changing all of those, it seems more parsimonious to use that syntax when adding the feature to PNut.

    I only added the {$flexspin directive because it was the only way to add conditional code that was compatible with PNut. If Chip can add #ifdef then the {$flexspin won't be necessary any more.

  • @ersmith said:

    @Electrodude said:
    But the Pascal syntax looks better because Spin uses curly braces for comments, like Pascal. It should be trivial to make Flexspin and OpenSpin (and PNut, for that matter, once it understands either) understand both syntaxes - the stuff inside the {$...} works exactly the same as what goes inside C-style #...\n.

    But, these aren't actually comments, nor are they directives that may be ignored. They matter!

    Embedding semantically important information (like #ifdef) inside comments is dangerous. Older versions of the compiler will just ignore the directives, which means that the code will not compile correctly and worse will not produce any errors or warnings. At least with a new syntax like #ifdef the older compiler will reject the code completely instead of silently mis-compiling it.

    Moreover, as I pointed out, several existing compilers already support the #ifdef syntax. Rather than changing all of those, it seems more parsimonious to use that syntax when adding the feature to PNut.

    I only added the {$flexspin directive because it was the only way to add conditional code that was compatible with PNut. If Chip can add #ifdef then the {$flexspin won't be necessary any more.

    Good point. We should make sure @cgracey is aware of this argument.

  • cgraceycgracey Posts: 13,733
    edited 2022-07-04 20:53

    #ifdef is easiest to implement.

  • Do it! You'll get a JPEG of a cookie! (need to open a pack for Rayman soon, anyways)

  • roglohrogloh Posts: 4,461

    @cgracey said:
    #ifdef is easiest to implement.

    Yes please! We really will need something like this if we want drivers to be compatible with both sets of environments. Ideally nesting is supported too because it will support more complex logic and multiple feature sets.

  • JonnyMacJonnyMac Posts: 8,163
    edited 2022-07-05 14:59

    Yes please! We really will need something like this if we want drivers to be compatible with both sets of environments. Ideally nesting is supported too because it will support more complex logic and multiple feature sets.

    Even though I only tend to use Propeller Tool, I want this so that I can selectively include or exclude objects and code.

  • roglohrogloh Posts: 4,461

    @JonnyMac said:

    Yes please! We really will need something like this if we want drivers to be compatible with both sets of environments. Ideally nesting is supported too because it will support more complex logic and multiple feature sets.

    Even though I only tend to use Propeller Tool, I want this so that I can selectively include or exclude objects and code.

    Yes it will help reduce the bloat. I've wanted to write libraries of graphics functions etc with lots of useful features for some time and only enable the required portions of it so it won't bloat, but without dead code elimination in PropTool it's not realistic so I didn't proceed. This is next best thing for realizing that.

  • JonnyMacJonnyMac Posts: 8,163

    dead code elimination

    I would love to have that, too. I have a P1 project in which I'm forced to use BST so that I can get the code to fit by eliminating unused functions.

  • ersmithersmith Posts: 5,404

    @JonnyMac said:

    dead code elimination

    I would love to have that, too. I have a P1 project in which I'm forced to use BST so that I can get the code to fit by eliminating unused functions.

    Ada has added P1 bytecode support to flexspin, so you could use that now instead of BST.

  • JonnyMacJonnyMac Posts: 8,163

    Thanks, Eric, I will give it a try.

Sign In or Register to comment.