Okay, is this a fair summary of yesterday's recommendations? Sorry if I missed something; please feel free to copy/paste and add to the list. Alternately, I can edit this one.
- Host a repository that has the libraries (Propeller GCC, Simple, and Community) all in one place.
Yes. I'd like the Parallax library to be a single monolithic code repository, with no libpropeller or SimpleTools (or PropWare if David adds it). Instead, the code would follow a consistent style guide and be integrated with all the other code in the repository. libpropeller needs a good home, and I have little interest in maintaining it on it's own long term.
Of course, the C and C++ split of the libraries makes this integration more difficult.
...the C and C++ split of the libraries makes this integration more difficult.
Interesting observation.
I'm thinking a "simple" IDE should only ever use C++. As does the Arduino IDE. You can always call libraries written in C from C++. There is no reason you cannot write purely C code and compile it with the C++ compiler. There is zero overhead in doing that in the generated code. Using C++ classes in a simple way results is code that is structurally very similar to objects in Spin, sweet. It's one less check box for the beginner user to have to worry about. One less quirk in the build system.
Name mangling is often a little different between C and C++, so if you use an external C lib, you have to know to wrap the #include for the header in:
extern "C" {
#include "CHeader.h"
};
That's about the only downside I can think of. If the C lib was compiled with the C++ compiler, that problem goes away, because the name mangling is the same.
Name mangling : In C, functions (and labels in general) get prefixed with an underscore. In C++, because of function overloading, the names get mangled in a way that reflects the argument list as well.
Yes. I'd like the Parallax library to be a single monolithic code repository, with no libpropeller or SimpleTools (or PropWare if David adds it). Instead, the code would follow a consistent style guide and be integrated with all the other code in the repository. libpropeller needs a good home, and I have little interest in maintaining it on it's own long term.
Of course, the C and C++ split of the libraries makes this integration more difficult.
I definitely see your point, and I think I even agree. I'm open to discussion, but also much more hesitant to give up control of PropWare's classes in such a way. Doesn't mean I wouldn't... but I'm hesitant.
...the C and C++ split of the libraries makes this integration more difficult.
Interesting observation.
I'm thinking a "simple" IDE should only ever use C++. As does the Arduino IDE. You can always call libraries written in C from C++. There is no reason you cannot write purely C code and compile it with the C++ compiler. There is zero overhead in doing that in the generated code. Using C++ classes in a simple way results is code that is structurally very similar to objects in Spin, sweet. It's one less check box for the beginner user to have to worry about. One less quirk in the build system.
Anyone know a down side to this idea ?
As I recall, Parallax heard directly from their educational customers that they wanted C and not C++, because that's what the school curriculum was teaching (or that's what the teachers knew). Maybe that's changed in the last few years? I doubt it though
...how do you plan to handle driver code, like cogc files?
I don't.
Compiling C into COG is a silly idea. Use PASM for such driver code, as we do in Spin.
My cc may quite likely be a script of some sort. Not one the user would ever expect to have to look at or change.
I don't think it's silly at all to compile C to run directly from COG memory. There are advantages to having all of the code written in C. Of course, there are many cases where this is not practical and PASM must be used, but it is still good to have the option to use cogc files.
I definitely see your point, and I think I even agree. I'm open to discussion, but also much more hesitant to give up control of PropWare's classes in such a way. Doesn't mean I wouldn't... but I'm hesitant.
More thoughts on this.
libpropeller and PropWare are both C++ and both use header-mostly functions. It would not be hard to merge their styles together. The styling is slightly different - I use underscores in function names, he uses camelcase with first letter caps, but I have no problem conforming to whatever ultimate standard Parallax sets.
I do have a problem with downgrading everything to C. Not happening. My source is MIT licensed, someone else is welcome to go through that trouble, but it won't be me. I put a ton of work into upgrading about a year and a half ago and I'm thrilled with that decision.
I think that's what worries me the most - that Parallax would want to standardize everything as C.
Naming changes, whitespace formatting, documentation style, no problem. I'd even be willing to go as far as removing some of the (I think awesome) complex inheritance used in PropWare if it meant Parallax adopted and publicly encouraged folks to use it.
I can quite understand educational users not wanting to get into the infinite complexity of C++. I would have thought though that there is no reason they cannot teach C using a C++ compiler. Arduino users use C++ all the time without knowing it.
@Dave
I'm all for being able to compile C code into COG. What I leaning toward though is that it is an extra complexity that does not belong in a "simple" IDE, an advanced use case. Back in school we were taught programming initially with BASIC. That was soon followed by assembler. That's why I like Spin/PASM on the Prop and think C++/PASM would be cool too.
I think that's what worries me the most - that Parallax would want to standardize everything as C.
Not to worry, Parallax would very much like to see more resources in both C and C++.
The Propeller education program started with C instead of C++ for three main reasons. First, at the time we started, a lot more work (PropGCC testing) had been done in C than C++. Again, at that time (not the case any more) going down the C++ path meant risking a show-stopper after a time investment in the project. Since, we could see the path to testing out the simpletools library in C, we followed that path. Second, as languages go, C is really a common denominator, which made sense as an education starting point. Third, it allowed a path for another set of educational materials in C++ at some later point.
...I would have thought though that there is no reason they cannot teach C using a C++ compiler. Arduino users use C++ all the time without knowing it...
Your point about compiling everything in C++ is something I've been looking at. At this point, it does make more sense as a default setting for SimpleIDE. The Simple Libraries are all compatible, but there'll probably be a few code examples that need to be changed so that they compile correctly. That can end up costing a lot in tech support calls, so it will have to be tested and phased in carefully.
I don't think it's silly at all to compile C to run directly from COG memory. There are advantages to having all of the code written in C. Of course, there are many cases where this is not practical and PASM must be used, but it is still good to have the option to use cogc files.
Of course it makes sense to compile C to COG.
That is also a good way to teach Assembler programming, and it is common in other MCUs to start with C, and optimize the generated ASM as needed.
Often, merely reading the generated ASM and re-coding the C, is enough to improve code.
Even doing that, does teach students a good amount about ASM coding.
PropBASIC is also good for this - isn't support for that coming into SimpleIDE ?
If you use a C++ compiler to compile and teach C you won't be able to teach correct use of 'const'..
-Tor
That's interesting. In what way is the handling of const different between C and C++?
I misspoke - I tested that last year so it's been a while. It's not the const, it's C++ handling of 'void' which prevents a common use for the ANSI void type - one of the points of introducing the 'void' type was to avoid having to cast everything to a char pointer in order to be able to pass it to a function which wants to handle it as a buffer of bytes. So instead of sprinkling potentially thousands of (char *) &my_buffer everywhere in the code where you call a function, with ANSI C you simple declare that function to take a void pointer and pass it the address of anything. Then inside the function you use the 'void can be anything' feature to make it a buffer pointer, e.g. a char *
[Yes in some old architectures a char pointer may not be the size of an int pointer or another type pointer, but I don't know about any such architecture still alive so the above is an extremely common and safe way of flexible C coding with the least amount of excessive casting]
#include <stdio.h>
#include <string.h>
static void universal_buf_prnt (const void *const data, // Any type
int bytes)
{
int i;
const char *const cdata = data;
for (i = 0; i < bytes; i++) {
printf ("%02x", cdata[i]);
}
return;
}
int main (void)
{
int a = 1024;
char str[] = "hello world";
universal_buf_prnt (&a, sizeof (a));
universal_buf_prnt (str, strlen (str));
return (0);
}
Won't compile with g++.
I also use the 'void *' type with functions that take handlers - an oblique type where the caller doesn't know the layout (i.e. you don't expose that as e.g. a struct in the header file the caller uses - so the caller can't fiddle with what is supposed to be internal data to be passed around with your library functions). That also won't compile with g++.
Ah yes, the different void*. We could say it is a fuss about nothing
For those of hippies who don't like too much regulation there is always -fpermissive.
Oddly enough the standard string functions, in string.h, are also defined as taking void*. For example memset:
extern void *memset (void *__s, int __c, size_t __n);
But when used in C++ they produce no warning or error, for example:
int main (void)
{
int a = 1024;
char str[] = "hello world";
memset (&a, 0, sizeof (a));
memset (str, 0, sizeof (str));
return (0);
}
All is good with the void.
Edit: I guess what I mean to say is that adding the (char*) required to fix your code for C++ is no hardship and probably a good idea anyway. The resulting code is compatible with C and C++. In practice the void difference is not an issue.
Ah yes, the different void*. We could say it is a fuss about nothing
For those of hippies who don't like too much regulation there is always -fpermissive.
Oddly enough the standard string functions, in string.h, are also defined as taking void*. For example memset:
extern void *memset (void *__s, int __c, size_t __n);
But when used in C++ they produce no warning or error, for example:[..]
There are presumably some convoluted header declarations in there somewhere which modifies how the compiler handles that, but I can't nest through it (but it probably starts with that __BEGIN_NAMESPACE_STD in the header file)
Edit: I guess what I mean to say is that adding the (char*) required to fix your code for C++ is no hardship and probably a good idea anyway. The resulting code is compatible with C and C++. In practice the void difference is not an issue.
If you really mean that I should have to write
universal_buffer_printer ((char *)&a, sizeof (as));
universal_buffer_printer ((char *) &my_struct..
and so on and so forth, that would be absolutely terrible. The void type and the void pointer are, in addition to real prototypes *the* reason for having ANSI C at all. It's not having to throw casts into your code all over the place, and not having to do fiddly things like
struct abcd_def * k = (struct abcd_def *) malloc (some_size);
Casts are error prone, and can hide real problems (try forgetting to include stdlib.h, for example, and use a cast with malloc - won't be detected, and will fail on 64-bit platforms at runtime). I'm definitely not going back to K&R C. No way.
No. If g++ (C++) cannot compile nice, clean user-written C-code where function parameters are void pointers then it's not C compatible and I wouldn't use it to teach C programming.
I have no idea how GCC handles those string decls in C and C++. Gave up trying to follow it through the header files.
Yes I did really mean that. BUT I would not do what you showed I would do it the easy way, add a cast to one line in your function:
const char *const cdata = (char*)data;
So there we have it, nice clean, user written code that compiles without warning or error with C and C++.
I do agree that "Casts are error prone, and can hide real problems". But I don't see how a cast like that is any worse than having the implicit cast that C does. I would in fact argue that it is preferable to write the cast in there, as I show above, rather than just have it happen by "magic". The C++ way is better.
Oh yeah, certainly we don't want to go back to K&R days.
We had some good talks in this thread. The title is not particularly... "nice" but the content in the second half is worth keeping in mind.
My question is this: where do we stand? Are there action items? Is there anything we, as a community, can do to help push the Propeller C/C++ tooling forward?
My work continues on a PropWare-backed version of SimpleIDE, but beyond that I do not know what Parallax needs most from the community.
Comments
Yes. I'd like the Parallax library to be a single monolithic code repository, with no libpropeller or SimpleTools (or PropWare if David adds it). Instead, the code would follow a consistent style guide and be integrated with all the other code in the repository. libpropeller needs a good home, and I have little interest in maintaining it on it's own long term.
Of course, the C and C++ split of the libraries makes this integration more difficult.
I'm thinking a "simple" IDE should only ever use C++. As does the Arduino IDE. You can always call libraries written in C from C++. There is no reason you cannot write purely C code and compile it with the C++ compiler. There is zero overhead in doing that in the generated code. Using C++ classes in a simple way results is code that is structurally very similar to objects in Spin, sweet. It's one less check box for the beginner user to have to worry about. One less quirk in the build system.
Anyone know a down side to this idea ?
extern "C" {
#include "CHeader.h"
};
That's about the only downside I can think of. If the C lib was compiled with the C++ compiler, that problem goes away, because the name mangling is the same.
Name mangling : In C, functions (and labels in general) get prefixed with an underscore. In C++, because of function overloading, the names get mangled in a way that reflects the argument list as well.
Of course all libs shipped with such a system would be compiled with C++ or the header files would have the standard wrapping: A user would not have to worry about any of this.
I definitely see your point, and I think I even agree. I'm open to discussion, but also much more hesitant to give up control of PropWare's classes in such a way. Doesn't mean I wouldn't... but I'm hesitant.
As I recall, Parallax heard directly from their educational customers that they wanted C and not C++, because that's what the school curriculum was teaching (or that's what the teachers knew). Maybe that's changed in the last few years? I doubt it though
More thoughts on this.
libpropeller and PropWare are both C++ and both use header-mostly functions. It would not be hard to merge their styles together. The styling is slightly different - I use underscores in function names, he uses camelcase with first letter caps, but I have no problem conforming to whatever ultimate standard Parallax sets.
I do have a problem with downgrading everything to C. Not happening. My source is MIT licensed, someone else is welcome to go through that trouble, but it won't be me. I put a ton of work into upgrading about a year and a half ago and I'm thrilled with that decision.
I think that's what worries me the most - that Parallax would want to standardize everything as C.
Naming changes, whitespace formatting, documentation style, no problem. I'd even be willing to go as far as removing some of the (I think awesome) complex inheritance used in PropWare if it meant Parallax adopted and publicly encouraged folks to use it.
I can quite understand educational users not wanting to get into the infinite complexity of C++. I would have thought though that there is no reason they cannot teach C using a C++ compiler. Arduino users use C++ all the time without knowing it.
@Dave
I'm all for being able to compile C code into COG. What I leaning toward though is that it is an extra complexity that does not belong in a "simple" IDE, an advanced use case. Back in school we were taught programming initially with BASIC. That was soon followed by assembler. That's why I like Spin/PASM on the Prop and think C++/PASM would be cool too.
-Tor
Not to worry, Parallax would very much like to see more resources in both C and C++.
The Propeller education program started with C instead of C++ for three main reasons. First, at the time we started, a lot more work (PropGCC testing) had been done in C than C++. Again, at that time (not the case any more) going down the C++ path meant risking a show-stopper after a time investment in the project. Since, we could see the path to testing out the simpletools library in C, we followed that path. Second, as languages go, C is really a common denominator, which made sense as an education starting point. Third, it allowed a path for another set of educational materials in C++ at some later point.
Your point about compiling everything in C++ is something I've been looking at. At this point, it does make more sense as a default setting for SimpleIDE. The Simple Libraries are all compatible, but there'll probably be a few code examples that need to be changed so that they compile correctly. That can end up costing a lot in tech support calls, so it will have to be tested and phased in carefully.
That is also a good way to teach Assembler programming, and it is common in other MCUs to start with C, and optimize the generated ASM as needed.
Often, merely reading the generated ASM and re-coding the C, is enough to improve code.
Even doing that, does teach students a good amount about ASM coding.
PropBASIC is also good for this - isn't support for that coming into SimpleIDE ?
OK, I could easily have confused the two.... There are so many names in the pot, it is hard to keep up...
It is indeed PropellerIDE that is getting PropBASIC support, not SimpleIDE.
I misspoke - I tested that last year so it's been a while. It's not the const, it's C++ handling of 'void' which prevents a common use for the ANSI void type - one of the points of introducing the 'void' type was to avoid having to cast everything to a char pointer in order to be able to pass it to a function which wants to handle it as a buffer of bytes. So instead of sprinkling potentially thousands of (char *) &my_buffer everywhere in the code where you call a function, with ANSI C you simple declare that function to take a void pointer and pass it the address of anything. Then inside the function you use the 'void can be anything' feature to make it a buffer pointer, e.g. a char *
[Yes in some old architectures a char pointer may not be the size of an int pointer or another type pointer, but I don't know about any such architecture still alive so the above is an extremely common and safe way of flexible C coding with the least amount of excessive casting]
Won't compile with g++.
I also use the 'void *' type with functions that take handlers - an oblique type where the caller doesn't know the layout (i.e. you don't expose that as e.g. a struct in the header file the caller uses - so the caller can't fiddle with what is supposed to be internal data to be passed around with your library functions). That also won't compile with g++.
Ah yes, the different void*. We could say it is a fuss about nothing
For those of hippies who don't like too much regulation there is always -fpermissive.
Oddly enough the standard string functions, in string.h, are also defined as taking void*. For example memset:
But when used in C++ they produce no warning or error, for example:
All is good with the void.
Edit: I guess what I mean to say is that adding the (char*) required to fix your code for C++ is no hardship and probably a good idea anyway. The resulting code is compatible with C and C++. In practice the void difference is not an issue.
If you really mean that I should have to write
universal_buffer_printer ((char *)&a, sizeof (as));
universal_buffer_printer ((char *) &my_struct..
and so on and so forth, that would be absolutely terrible. The void type and the void pointer are, in addition to real prototypes *the* reason for having ANSI C at all. It's not having to throw casts into your code all over the place, and not having to do fiddly things like
struct abcd_def * k = (struct abcd_def *) malloc (some_size);
Casts are error prone, and can hide real problems (try forgetting to include stdlib.h, for example, and use a cast with malloc - won't be detected, and will fail on 64-bit platforms at runtime). I'm definitely not going back to K&R C. No way.
No. If g++ (C++) cannot compile nice, clean user-written C-code where function parameters are void pointers then it's not C compatible and I wouldn't use it to teach C programming.
-Tor
I have no idea how GCC handles those string decls in C and C++. Gave up trying to follow it through the header files.
Yes I did really mean that. BUT I would not do what you showed I would do it the easy way, add a cast to one line in your function: So there we have it, nice clean, user written code that compiles without warning or error with C and C++.
I do agree that "Casts are error prone, and can hide real problems". But I don't see how a cast like that is any worse than having the implicit cast that C does. I would in fact argue that it is preferable to write the cast in there, as I show above, rather than just have it happen by "magic". The C++ way is better.
Oh yeah, certainly we don't want to go back to K&R days.
We had some good talks in this thread. The title is not particularly... "nice" but the content in the second half is worth keeping in mind.
My question is this: where do we stand? Are there action items? Is there anything we, as a community, can do to help push the Propeller C/C++ tooling forward?
My work continues on a PropWare-backed version of SimpleIDE, but beyond that I do not know what Parallax needs most from the community.
Thanks