Please add a conditional compile feature to the SPIN parser.
epmoyer
Posts: 314
Parallax,
I would love to see a conditional compile feature added to the SPIN parser. I am developing music playback drivers for the HYDRA platform ( http://forums.parallax.com/showthread.php?p=650114 ) and constantly find myself wishing I could add some features that I know not everyone will use. Since Hydra developers are generally very pressed for RAM I don't want to clutter their precious code space with unused options. Support for even the most rudimentary of conditional compile syntax in the Propeller IDE would solve this problem. I'd love to be able to write something like:
I don't care what the actual syntax ends up being, so long as blocks of code can be conditionally included and excluded based on some global flags defined at the top of the source code.
What do you think?
Post Edited (epmoyer) : 5/22/2007 10:45:46 PM GMT
I would love to see a conditional compile feature added to the SPIN parser. I am developing music playback drivers for the HYDRA platform ( http://forums.parallax.com/showthread.php?p=650114 ) and constantly find myself wishing I could add some features that I know not everyone will use. Since Hydra developers are generally very pressed for RAM I don't want to clutter their precious code space with unused options. Support for even the most rudimentary of conditional compile syntax in the Propeller IDE would solve this problem. I'd love to be able to write something like:
CON SUPPORT_EEPROM_PLAYBACK = TRUE VAR #IF SUPPORT_EEPROM_PLAYBACK long eeprom_ptr #ENDIF #IF !SUPPORT_EEPROM_PLAYBACK long ram_ptr #ENDIF long command PUB start_player() #IF SUPPORT_EEPROM_PLAYBACK eeprom.start() #ENDIF ...
I don't care what the actual syntax ends up being, so long as blocks of code can be conditionally included and excluded based on some global flags defined at the top of the source code.
What do you think?
Post Edited (epmoyer) : 5/22/2007 10:45:46 PM GMT
Comments
I often find myself wasting valuable storage because I want to leave in some test code or data to make it easy to debug if I change something later.
I can skip over the code but the storage is still wasted.
There are many other good examples for wanting this.
It can't be that hard...
Guys?
-Phil
Something which is much more likely because it has a greater utility is a command line interface to the tool which provides no-GUI back end to the compiler. This hasn't been placed on the queue yet though we will press for it's addition in the coming weeks, if so it will likely become the 3rd item (after the revision of the Stamps and the debug terminal feature for the Propeller Tool). This means it will be sometime mid to late summer assuming no other high priority items intervene.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Paul Baker
Propeller Applications Engineer
Parallax, Inc.
I am sorry to hear that
I'd love to have it and it seems easy.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Paul Baker
Propeller Applications Engineer
Parallax, Inc.
What if we decide on a conditional compile syntax of our own like the one I detailed above, and write a stand-alone parser tool that would walk through a .spin file and selectively add braces "{ ... }" around code that was conditionally compiled out, and remove them from code which was conditionally compiled in. So...
Would become...
The syntax restrictions would be very simplistic. You can only define preprocessor directive constants as true of false, and the only valid inclusion/exclusion syntaxes would be '#IF <constant> and '#IF !<constant> (The single quote has to go in front of them so the IDE ignores them as comments).
Using that method:
1) The "preprocessor" is simple. I'll write us one in an hour.
2) You only have to run the external "preprocessor" if you change your preprocessing directives, so the fact that the IDE won't do it for you is only a minor annoyance. We can still use the method to distribute code with conditional sections and users can do a one-time configuration pass with the preprocessor to build the version they need.
3) You can still edit your code in the IDE and compile it like normal.
4) When Parallax gets around to supporting preprocessor directives the code will be forward compatible with the new preprocessor (assuming they adopt the same syntax).
What do you all think?
Paul, does Parallax have a preferred syntax that they would like to used if/when preprocessor directives are natively supported?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Paul Baker
Propeller Applications Engineer
Parallax, Inc.
or
The second one is easier to parse, but the first one is a little easier to read because of the way the IDE colors the text. The second one can go anywhere (like in the starting comment block), whereas the first one has to go in the CON section. I'll probably go with the second for simplicity. The second also is clearly a preprocessor directive and not related to the regular spin code, whereas the first is a bit ambiguous. Hmm, now that I say that, one of the advantages of the first is that regular spin code has access to behave conditionally on the flag as well (though you could accomplish the same thing by putting #IF's around some constants if you like, and then checking those constants in your code.
Please let me hear your opinions out there. I won't get to write the preprocessor until I finish my upcoming HDMF release, which is still a couple days away.
-Phil
It seems to me that your point 2), above, would have to be predicated on the fact that one is editing the post-processed code to begin with. Or am I mis-interpreting what you are saying?
I like the idea, though...
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Truly Understand the Fundamentals and the Path will be so much easier...
A standard "PREprocessor" runs when you hit "compile", turns your source (A) into an intermediate file which you generally don't ever see (B), and that file gets compiled. You always edit the source (A) and file B is a transient entity which disappears after the compile.
What I am proposing is perhaps more aptly named a "Configuration Management" utility. It will take source (A) and non-destructively add and remove block comments (braces) to generate a new version of the source (A) that gets saved on top of the old one (and yes, it will save a copy as .bak or something just to be safe).
Now, if you want to use this proposed Spin Configuration Managment (SCuM!) utility on your code you have to...
1) Modify your '#DEFINE statements
2) Close the source in the SPIN IDE
3) Run SCuM on the file (will support drag and drop to make that as quick and painless as possible)
4) Open the source in the SPIN IDE
5) Compile
So there are 4 steps (2-5 above) in place of what ideally would be one step (hit compile), but it seems like a livable interim solution to me.
Because SCuM never destroys, deletes, or modifies any of the original source code (it only adds and removes comment braces) you can turn the #DEFINE flags on and off as many times as you like, run SCuM as many times as needed, and you always edit the same source file.
Well, if I play devil's advocate for a moment I can see Paul's point. If you are Parallax and you are dedicated to making an integrated environment that is clear and easy to use for your customers then adding pre-processor directives ends up causing you to create a long list of action items to support, like:
1) Preprocessor syntax checking
2) Reporting preprocessor errors back to the IDE
3) Handling nested preprocessor directives
4) Coloring preprocessor blocks appropriately in the IDE (w/ nesting?)
I do think you could could keep it pretty simple for a first pass, but you would have to document it, and integrate it into the current build schedule, and test it, and support it. Then since you're running a business you have to look at it along with everything else on your plate and say "does this (yes, possibly cool and useful) feature drive my business forward more than the other features / tasks on my plate?".
For us the job is much easier. We want it, we throw it together, we use it with caution and poke at it until we're confident it works well, and we have nobody to answer to if we screw up. Unfortunately the best we can do is an external utility. Now if only the IDE were open source....
How about this syntax:
both version should be allowed. That is easy to parse (only check if a line contains '#DEFINE) and the user can choose if spin knows the constant too, or not.
Andy
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Paul Baker
Propeller Applications Engineer
Parallax, Inc.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Paul Baker
Propeller Applications Engineer
Parallax, Inc.
That way, we could add our own batch programs that pre-modify the '#IFs into a temp file then compiles that.
like in ManicMiner I have two keyboard objects in, but depending on a CON value depends which one is used, I have three configs and i just uncomment which config I want.
'uncomment the '{ block which suites your system.
{ Hydra Defines
_CLKMODE = xtal1 + pll8x
_XINFREQ = 10_000_000 + 0000
USE_SDCARD_INSTEAD_OF_HIEEPROM = 0 ' 0 for level files taken from HIEEPROM or 1 for level files taken from SD Card root
USE_SOUND_BITS_FOR_STEREO = 1 ' usually 3 for Proto/Demo boards and 1 for Hydra ... 1 for mono and 3 for stereo
USE_SOUND_PINS = 7 ' usually 10 for Proto/Demo boards and 7 for Hydra
USE_HYDRA_KEYBAORD = 1 ' usually 0 for Proto/Demo boards ( key.start(26,27) ) and 1 for Hydra ( keyhydra.start(3) )
USE_TV_ON_PIN_24 = 1 ' usually 0 for Proto/Demo boards ( JBSpecGfx.Start(12) ) and 1 for Hydra ( JBSpecGfx.Start(24) )
'}
{ Proto/Demoboard Defines - No SD card installed
_CLKMODE = xtal1 + pll16x
_XINFREQ = 5_000_000 + 0000
USE_SDCARD_INSTEAD_OF_HIEEPROM = 0 ' 0 for level files taken from HIEEPROM or 1 for level files taken from SD Card root
USE_SOUND_BITS_FOR_STEREO = 3 ' usually 3 for Proto/Demo boards and 1 for Hydra ... 1 for mono and 3 for stereo
USE_SOUND_PINS = 10 ' usually 10 for Proto/Demo boards and 7 for Hydra
USE_HYDRA_KEYBAORD = 0 ' usually 0 for Proto/Demo boards ( key.start(26,27) ) and 1 for Hydra ( keyhydra.start(3) )
USE_TV_ON_PIN_24 = 0 ' usually 0 for Proto/Demo boards ( JBSpecGfx.Start(12) ) and 1 for Hydra ( JBSpecGfx.Start(24) )
'}
'{ Proto/Demoboard Defines - SD card installed on pin 0-3
_CLKMODE = xtal1 + pll16x
_XINFREQ = 5_000_000 + 0000
USE_SDCARD_INSTEAD_OF_HIEEPROM = 1 ' 0 for level files taken from HIEEPROM or 1 for level files taken from SD Card root
USE_SOUND_BITS_FOR_STEREO = 3 ' usually 3 for Proto/Demo boards and 1 for Hydra ... 1 for mono and 3 for stereo
USE_SOUND_PINS = 10 ' usually 10 for Proto/Demo boards and 7 for Hydra
USE_HYDRA_KEYBAORD = 0 ' usually 0 for Proto/Demo boards ( key.start(26,27) ) and 1 for Hydra ( keyhydra.start(3) )
USE_TV_ON_PIN_24 = 0 ' usually 0 for Proto/Demo boards ( JBSpecGfx.Start(12) ) and 1 for Hydra ( JBSpecGfx.Start(24) )
'}
So although conditional would be nice I think CommandLine is the best way to go [noparse]:)[/noparse] but then Parallax don't just come up with great hardware without having good ideas too :P
My 2p's worth.
Baggers
This method leaves open the option of doing this type of code
Which is currently what I do when I need versions, but the above {CONSTANT method enables the use of conditional compilation in non-code sections such as VAR, CON, DAT·and especially useful in OBJ (I like to write code which supports multiple types of displays). If you wanted to get uber fancy you could search the code for "if CONSTANT" and·"if !CONSTANT"·code sections and do dead code optimization be removing always false code.·
And if I had my druthers the configuration management utility would leave a false condtional exactly how it is and in a true conditional would simply turn the {CONSTANT into 'CONSTANT and remove the trailing }, this way it still stays readable and IDE compatible. It would basically do an automatic uncomment of the appropriate sections like shown by Baggers.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Paul Baker
Propeller Applications Engineer
Parallax, Inc.
Post Edited (Paul Baker (Parallax)) : 5/23/2007 8:19:46 PM GMT
If we do it that way I don't see how the preprocessor can tell where a block of preprocessor switched code ends if it is currently "active" (i.e. has no braces around it). If I write:
..then there is no way to tell that I meant for the first two lines to be part of the conditional block and the last line not to be. I suppose you could indent, but that means you have extraneous indents (as seen by the IDE/compiler) and I'm not sure that the compiler does the right thing (probably does) and that the IDE coloring/indent highlighting does the right thing (probably doesn't; too lazy to go try[noparse]:)[/noparse]. Writing this:
would be unambiguous both in it's included form and in its excluded form:
Andy,
Your suggested syntax would be a bit harder to parse, and I think is a bit harder for people to read. I'd rather keep it simple. The syntax above always allows you to achieve the same end by putting a standard define inside your conditional preprocessor statements like:
Keeping it simple both keeps users from making mistakes but also keeps me from making mistakes in implementing the parser.
If you have Visual C++ 2005 (of which there is a free version) installed, then you can use the following in a command prompt to pre-process the file:
Then you can use all the C pre-processor facilities; including include files, conditionals, macros, etc. You can also use C style comments, since the pre-processor will strip those out for you.
If you have gcc installed, the pre-processor command is cpp. You'll have to check the docs for the arguments, I don't remember them off hand.
T.
The advantage of the syntax and parser proposed above is that you have 1 file to work with, and that file is always editable/compilable in the IDE. You only need to exit and run the preprocessor when/if you modify the preprocessor directives.
The "hooks" could be quite simple. I have an editor (UltraEdit) that uses F9 as "run" button, which will execute any command line I specify when I press it. The Propeller IDE could easily be set up this way, with the following as a default command line:
where %f specifies the file name of the Spin program. But, given the facility to change the default command line, I might prefer something like this:
In this example, mypreprocessor.exe would read %f and its subobject files, massage them, then output them to temporary files. Next it would invoke spin.exe, giving it the name of the top-level temporary file it created. Assuming spin.exe reports errors/success in some documented format, mypreprocessor.exe would retrieve this info and reformat it so errors would show up in the correct locations in the IDE. The compiler itself would not have to be touched.
-Phil
We recognize the need for pre-processing capabilities, however to arrive at the best solution we will need to spend some time deliberating on it.
With feature requests in general from now on I will be recording them into a wish list and only make a brief acknowlegement of the request rather than going into an in-depth discussion. This doesn't mean we won't take the requests seriously, it just means we will deliberate and prioritize them internally.
Thanks,
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Paul Baker
Propeller Applications Engineer
Parallax, Inc.