A C/C++ compiler to emit Spin byte codes?
Phil Pilgrim (PhiPi)
Posts: 23,514
I'm resigned to the momentum that C enjoys for programming the Propeller. Not elated, mind you, but accepting of its inevitable ascendency. I'm even trying to teach students in a robotics seminar this language which I've studiously avoided these many years -- for good reason, I maintain and continue to submit. But what troubles me still is the fact that so much good Spin/PASM code has to be rewritten to accommodate this philosophical sea change in emphasis from Parallax. I'm fully aware of spin2cpp, BTW, although I've not yet tried it.
But what I'm wondering instead is whether there could be any benefit from a C/C++ compiler that produces Spin bytecodes in such a way that existing Spin objects can used as-is, without also having to convert them to C. It would not have to be a full-blown C, of course. After all, the Lego Mindstorms-centric NQC (not quote C) enjoys considerable success among those who feel limited by the Mindstroms GUI. But if it were enough of a C to teach C to new programmers, who could later progress to the full gcc/SimpleIDE paradigm, it would be a huge benefit for educators (like me) looking for something simpler yet than gcc under "Simple"IDE.
The impetus for this query was an email from Ken, asking whether the S2 GUI could produce C code instead of Spin. I responded that yes, it could, and it would be easy to make it do so. But, behind the scenes, a 99-fold greater effort to complete the project would be spent rewriting S2.spin, which is called by the S2 GUI code, and much of which includes very tight PASM control code, in C so that gcc could use it,
Obviously, a C program interpreted as Spin bytecodes would be as slow as Spin and not as fast as native C-to-PASM or C-to-LMM compilation. But that hardly matters when the object is to teach C programming. Maybe the easiest way to get there is a c2spin translator that converts C source code to Spin on the fly as a Spin preprocessor. It might not be that hard to implement in Perl and may be worth my looking into. I suspect that the hardest part will be dealing with the differing operator precedence rules between the two languages, entailing a lot of parentheses in the generated Spin code.
-Phil
P.S. BTW, this thread is not about gcc per se, and that's why I did not post it to the gcc subforum. If it gets moved there, I will move it back. -P.
But what I'm wondering instead is whether there could be any benefit from a C/C++ compiler that produces Spin bytecodes in such a way that existing Spin objects can used as-is, without also having to convert them to C. It would not have to be a full-blown C, of course. After all, the Lego Mindstorms-centric NQC (not quote C) enjoys considerable success among those who feel limited by the Mindstroms GUI. But if it were enough of a C to teach C to new programmers, who could later progress to the full gcc/SimpleIDE paradigm, it would be a huge benefit for educators (like me) looking for something simpler yet than gcc under "Simple"IDE.
The impetus for this query was an email from Ken, asking whether the S2 GUI could produce C code instead of Spin. I responded that yes, it could, and it would be easy to make it do so. But, behind the scenes, a 99-fold greater effort to complete the project would be spent rewriting S2.spin, which is called by the S2 GUI code, and much of which includes very tight PASM control code, in C so that gcc could use it,
Obviously, a C program interpreted as Spin bytecodes would be as slow as Spin and not as fast as native C-to-PASM or C-to-LMM compilation. But that hardly matters when the object is to teach C programming. Maybe the easiest way to get there is a c2spin translator that converts C source code to Spin on the fly as a Spin preprocessor. It might not be that hard to implement in Perl and may be worth my looking into. I suspect that the hardest part will be dealing with the differing operator precedence rules between the two languages, entailing a lot of parentheses in the generated Spin code.
-Phil
P.S. BTW, this thread is not about gcc per se, and that's why I did not post it to the gcc subforum. If it gets moved there, I will move it back. -P.
Comments
You could start a Spin byte-code COG program from C that runs in a well defined memory block (as defined before COG start in the Spin pointers). For the moment the byte-codes could be put into an ASCII-HEX array in a .c file. Shouldn't take you very long to figure that out.
I used to do hand translation of Arduino code to Spin. For a restricted subset of C++ there's a pretty direct mapping, but some things don't translate. For example you can't pass object references or method pointers in Spin.
Sounds like you want Propeller MicroC (PMC). Announced by Parallax in 2010.
http://forums.parallax.com/showthread.php/121707-So-we-hear-you-were-interested-in-C-for-the-Propeller…
Rereading that thread made me sad -- in part due to Parallax's unfulfilled promises vis-
The early versions simply compiled the source into an intermediate form which was then translated into 8085 assembler. Porting to another CPU was a simple (!) case of substituting the right assembly mnemonics. And having a suitable cross-assembler.
In later versions, about the time it moved to MSDOS, P-Code was introduced as an intermediate stage along with rudimentary optimisation. Again though, all it needed was a 2-register plus stack pointer 16-bit CPU. It ought be be quite easy to knock up a P-Code interpreter in PASM to directly execute the intermediate file.
I detect some paradox in your statements here.
On the one hand you don't like C/C++ - "studiously avoided these many years... for good reason,"
On the other hand C/C++ is what you are asking for.
That does not inspire enthusiasm for the idea. And why feel sad for not getting something you did not want?
I seem to remember that my main objection to PMC was that it would not be C, only C like. If it's not trying to be a proper C then it is another language and the last thing the world need is YAFL (Yet Another Fine Language). We already have far too many and PMC had less reason to exist than most of those.
Thinking about it now, if you look at it from the point of view of combining PMC with existing SPIN/PASM objects the it would be better if PMC was C++ like. After all Spin has objects and whilst you can write object oriented code in C to some extent it's not pretty. Then what you have is not a "not quite C" but a "not even close C++". which would be even worse in my opinion.
Anyway. This NQC or PMC ends up being as slow as Spin whilst not being C as you say. It has no possible use except as an educational device.
Meanwhile Spin is not going anywhere. Hmmm..that's ambiguous..I mean it will still be around in the future of the Prop and Prop 2 but it is not going to grow beyond that. As far the non-prop using world is concerned Spin is YAFL that they would rather not bother with.
Aside: This thread may not be about GCC but it might be if some bright spark creates a Spin byte code target for GCC. Then can we move this to the GCC forum?
Question...at the lowest level how would one integrate some SPIN bytecode with other SPIN bytecode? And what sort of virtual machine does the SPIN bytecode interpreter assume?
The Spin virtual machine is defined by the Spin byte code interpreter in the Propeller ROM. I don't think it is actually officially specified or documented anywhere. Or you could say it is defined by the Prop Tool Spin compiler. The source code for that is not open. So we can say it has no formal definition.
However the Prop ROM code has been published here, God knows where now, and people have documented the byte code operations as well.
Edit: I must be asleep, it's in there in black and white "...in such a way that existing Spin objects can used as-is..."
Have you tried using spin2cpp? It (usually) produces working C++ objects from Spin objects. If for some reason it doesn't work on your object please let me know and I'll try to fix it.
Eric
I ask as someone who learned Spin, but never really warmed up to it. I actually disliked C syntax when I first learned it in the 80's, but learned to appreciate it for its ubiquity.
Phil can answer that for himself. But I don't think the issue is the C syntax or semantics vs Spin that is the problem.
The issue is how to present programming to youngsters or other who have never programmed before and perhaps don't even know what a program is. That's before we get onto the idea that you can control your robot or whatever with your own programs.
The fundamentals or programming involve simple concepts like variables, expressions, sequences of expressions, conditional execution of expressions and iteration. So what you want to start off with when introducing programming is something like: And the best is if you can type than in somewhere and the answer immediately jumps out. There we have instant gratification, no hassle, we have grabbed the students attention and we can move on to the next concept. You can do that sort of thing in, BASIC, Python, JavaScript etc. Many programmers got hooked by the BASIC prompt on their C64 or whatever back in the 1980's.
Contrast that to the typical C introduction: Clearly that has already got a ton of concepts included that we have to explain, or worse still tell students to ignore till later: Include files, standard input output, functions, return values, parameters, "main" function, types, scope, format strings, varadic functions, arrays, pointers....Hey what is that "int" thing? It's an integer. What's an integer?. It's a number. How come it does not work with "a = 2.5"?....
It may be clear enough to us but to a beginner it is as intimidating as hex dump.
We have the complication of editing source files first then compiling them, then download them. Oh it does not work, do all that again....At this point you are very lucky to have your students attention any more.
Then there is all that nonsense about header files, make files bla bla.
From that educational perspective C is hard, Spin and the Prop Tool are easier but if you want to really see how easy this sort of intro should be check out the Espruino project.
BTW I'm squarely in the JavaScript is a work of the devil camp, but I use it every day anyway.
WARNING Language war alert.
OK you have my attention. I have to turn your question around, I'm genuinely curious why you prefer BASIC to JavaScript?
What is needed at the very beginning is something like LiveCode:
https://www.youtube.com/watch?v=ghvYqwsgsmI#t=127
http://www.kickstarter.com/projects/1755283828/open-source-edition-of-livecode
Of course these ideas have been around since Alan Kay, how come it's taking so long?
I would only use Basic in an educational setting and wouldn't use it on real projects.
I dislike JavaScript because it is a fundamentally unreliable language that doesn't scale to large projects. For example JavaScript doesn't support interfaces, inheritance, or encapsulation as a core part of the language. It’s possible to add the first two (e.g. Dojo does it), but to my knowledge not the third. Dojo used a convention called bed lump functions as an analogy to a kid hiding under a blanket. Because of its dynamic nature bugs will creep into production that a compiler would have found. JavaScript's defenders blame this on inadequate unit tests, but I didn't need to write unit test to type check Java code! Also testing for undefined can drive you to drink:
http://stackoverflow.com/questions/3390396/how-to-check-for-undefined-in-javascript
But its defenders keep claiming this time it is different (https://www.paypal-engineering.com/2013/11/22/node-js-at-paypal/). They also keep selling it to management with presentations like the above. Management in turn tells you that you must use it on your next project. But they and the JavaScript defenders will take zero responsibility when the project fails!
Yes I received a Node.js edict, and yes I'm bitter about it.
But consider this: One never needs to test, at compile time or otherwise, whether your types are right.
Yes, I did say that, and in all seriousness.
What you are interested in is whether your program functions as desired or not.
Unit tests, integration tests etc are what tells you that, the compiler cannot. If you don't test you don't know.
Having a type error in your code, comparing a signed to an unsigned for example, is no more or less important than having put a "+" where a "-" should be.
Your testing should uncover both of these kinds of errors. If it does not then you have seriously skimped on your testing.
Turns out that in JS you can write the test harness, then the code that makes the test pass, quicker than C++ can compile the thing:)
As for node, don't be bitter, it's great. I have put together server processes that sling XML and JSON around in a tenth the time it takes to create the equivalent C++ and end up running as reliably and performantly as the C++ equivalents.
How well that scales to larger projects I have yet to find out....
The biggest concern I have about Spin is that it's a proprietary language, and it's not portable to other platforms. Eric's spin2cpp helps to alleviate that concern. The only Propeller project that I did for my day job was written in C, so that my coworkers could work with the code without having to learn Spin.
That's what libraries are for. My umath object does unsigned comparisons. The same would apply to floating point expressions.
-Phil
There is no formal definition of the Spin language. No, I don't count the prop manual as that. The Prop Tool is currently the final arbiter of what Spin actually is.
One could imagine building a Spin compiler, perhaps based on Open Spin, that generates code for a different target. But wait Spin carries PASM around as an integral part. One could replace the PASM syntax with something for your target architecture. Do you really want to see Spin programs with x86 assembler in the DAT sections? Gak. It's not portable anyway. That means you need a Prop emulator on your target. Hardly what I would call "cross-platform".
One could decide to not support the assembler in DAT sections on other architectures, but then all you have left is YAFL and not a very good one at that.
I'm sure one could work around the signed/unsigned issues with libraries. But any smart compiler might inline those library codes for speed making bigger code. Or you might settle for actually calling functions all the time and take the performance hit. Either way it makes no odds if the code is in a library or if the compiler generates it behind the scenes.
-Phil
The more I program in Spin the more I like it. It's biggest drawback, in my view, is execution speed. (PASM is a superb assembly language, but I'd rather not have to drop into it quite so often.) Otherwise, Spin is perfectly fine for 99% of what I'm doing.
Feel free to be emotional. This is a language war right? I don't feel that it is so clear cut. Obviously JS has JSON built in so it makes life a bit easier. With XML or whatever you need some module to help you,
that is a little bit more hassle and perhaps less performant but not such a big deal. We have used node with JSON, XML and MQTT to good effect.
I was very sceptical when I started out with JS a couple of years back, "It's not a real language, right", "It's interpreted, it must be horrible slow, right", "Oh, and what about that type checking business?"
I ended up using it for one project because we wanted websockets, not knowing anything about web technologies node seemed to be the easiest way to get it done in the time I had available.
It was amazing to find that the resulting process was dead easy to create with it's XML in, filtering, massaging, database connection, websockets, pub/sub and JSON out to clients. Not only that it used about as much CPU capacity as similar codes we have in C++ !
Node shines where you have lot's of connections, and you don't have a lot of compute work to do. Get the request, fetch whatever from the database, ship out the result. Or, stream data in, translate, filter, whatever, stream it out again. Most of the work in jobs like that is spent in the module code which is often just an interface to an underlying C library like an XML parser or database connector. The JS is only orchestrating those things so performance is good. Plus you have no overheads or complexity of threads to worry about.
-Phil