5 ms·
This last bit is so true: > I always have it in the back of my head that I want to make a slightly better C. Just to clean up some of the rough edges and fix s
by byuu 12y ago
This last bit is so true:
> I always have it in the back of my head that I want to make a slightly better C. Just to clean up some of the rough edges and fix some of the more egregious problems.
I'm always mulling over that. "Maybe just namespaces, better macros, function overloading and member functions (eg this->) would work." Yet I'm sure Bjarne Stroustrup was thinking the same thing when he started on "C with Classes." The power to add features must be so overwhelmingly corruptive. So justifiable in each and every case, in the moment. And then you just can't stop. "Closures would be helpful. I'd love to write generic containers. Inheritance would save so much typing.", and the next thing you know, you're working on virtual inheritance, concepts and user-defined literals. :/
In my opinion, C really does need just a bit more to be great, but it would need someone with a will of steel to stop and leave things be after that.
- andrewchambers 12y agoI agree totally, my top level comment in this thread has my version of what a great C replacement would be. I'm slowly working on it.
- byuu 12y agoLooks like a decent start, but not enough there to really judge it yet. Best of luck, I'll keep an eye on it! If you'd like feedback (ignore this post if not): Caseless switch is a great idea, especially no-fallthrough by default. Consider extending it with substituion, eg "case > 7:", "case >= 13 && < 16:", or "switch longvariablename as N { case N > 13 && N < 16:". Return types after function parameters are nice, consider saying "function foo(params) returns type" instead. Tuples always feel important but in practice I tend to not like them. Variable definitions are a bit clunky, and inconsistent with struct variable definitions. Consider ctors/dtors and/or inline member initialization. I would recommend not to compress keywords: func -> function, const -> constant, etc. "type name struct" would feel better and more consistent as "class name". The C. prefix feels like it'd be great if you only use a very small number of C APIs, and very annoying if you used a lot of them. The boldest and coolest part is building this directly on LLVM. My thought was always to transform the IL into C (trying my best to preserve line numbers and variable names), and then let GCC or Clang build that. My ideas were unified function call syntax (never any functions inside classes), subclasses (declare a class inside another class, but the child class has direct access to the parent class' scope), namespace-aware multi-line macros (trailing \ is grotesque), and if implementing a backend instead of a translator, zero undefined behaviors in the language (do what people expect on eg signed integer overflow instead of GCC doing whatever is fastest yet obviously wrong. Aim for hardware that is actually used today instead of worrying about hypothetical PDP-11 programs, so no 9-bit chars.)
- andrewchambers 12y agotuples + destructuring may or may not be the way I decide to implement multiple return. Structs overlap in functionality a fair bit. I think if you emit C code, it is much harder to get good debug information, which is important. I am also thinking hard how to approach macros/preprocessor. For now there is none, but a powerful system could make all the difference.
- byuu 12y agoI've put some thought into macros into my various cross-assemblers. One thing that's important is to have different types of macros, and different types of argument values (some that are evaluated for you, some that are intentionally not evaluated.) macro function square(integer value) { return value * value; } integer x = square(foo() + bar()); //foo() and bar() each only called once //square(integer) will exist as an exported function symbol macro inline twice(statement operation) { operation; operation; } twice(foo()); //invokes foo() two times //twice() will not generate an actual function macro class vector(type T) { T* pool; integer capacity; integer size; function append(type U) { ... } ... } vector(integer) powersOfTwo{2, 4, 8, 16, 32, 64}; //any vector(type) will generate all the class functions for it
- panzi 12y ago> I think if you emit C code, it is much harder to get good debug information, which is important. I think you can annotate the generated code with certain preprocessor instructions to tell the compiler about the real source lines in order to get proper debug information. I think lex/yacc or flex/bison use that. Don't know if it's a gcc extension.
- caf 12y agoIf you're extending switch/case syntax it probably makes sense to incorporate gcc's existing ranged case extension: https://gcc.gnu.org/onlinedocs/gcc/Case-Ranges.html https://gcc.gnu.org/onlinedocs/gcc/Case-Ranges.html
- 12y ago
- tonysuper 12y agoC needs wider adaptation of Apple's "Blocks" extension and MAYBE extremely limited generics and it's perfect.
- bjz_ 12y ago> and MAYBE extremely limited generics C11 has _Generic, but it's pretty much an abomination: http://www.robertgamble.net/2012/01/c11-generic-selections.html http://www.robertgamble.net/2012/01/c11-generic-selections.h...
- rozap 12y agohttp://libcello.org/ http://libcello.org/ looks like it might fit that bill. I haven't tried it, though I've been meaning to.
- KeytarHero 12y agoSo why not use C++? Since it's a superset of C, why not just use C++ to program C-style code, using only the C++ features you want? C++ is a multi-paradigm language; you don't have to write object-oriented code if you don't want.
- byuu 12y agoCode portability is a big one. People write C compilers in a week as a hobby. Now compare to how long it took Clang to fully support all of C++. Now certainly, C++ is on every major platform in broad use. But maybe you are targeting something embedded, or a hobbyist OS. Or maybe you want to write up a quick embedded interpreter for scripting in your application. There's something intrinsically satisfying about minimalism and simplicity. It's also really hard to control the feature-set of C++ you want. The second you start pulling in code libraries, you find yourself needing to use the parts you don't want. Not in your own code directly, but in your interactions with their library code. Catching exceptions, needing RTTI, etc. Symbol exporting is also a really sore point in C++. The symbol names C++ compilers spit out are just terrifying. With a C language, it's trivial to write bindings for other languages like C# and Python. But for what it's worth, I still program almost exclusively in C++.
- KeytarHero 12y agoAren't there C++ compilers that will compile to C code? Doesn't that effectively make C++ just as portable as C?
- byuu 12y ago> Aren't there C++ compilers that will compile to C code? Uh ... no? CFront did that when it was just "C with Classes", but nowadays with C++14? That would be absolutely terrifying.
- cokernel_hacker 12y agoArguably the most versatile compiler in the world is EDG's. One of its features is: "a C-generating back end, which can be used to generate C code for C++ programs" source: https://www.edg.com/index.php?location=c_frontend https://www.edg.com/index.php?location=c_frontend In fact, the Itanium C++ ABI (which has no relation to the architecture) specifically uses valid C identifiers to mangle C++ names to support products like EDG. source: http://mentorembedded.github.io/cxx-abi/abi.html#mangling-type http://mentorembedded.github.io/cxx-abi/abi.html#mangling-ty...