High C Compiler – A C language extension ahead of its time
cohost.org
cohost.org
It just seems like such a clear win to me, that and writing long numbers like 1_000_000. So much more readable.
Why aren't these features more common? I'm a bit surprised Typescript never added them. Are they too difficult to implement in compilers/interpreters? Do they cause too many issues for interop?
I'm honestly curious. Is it just that not that many people find these features appealing?
PD: I know you can emulate named parameters using objects in JS/TS. I don't love the performance consequences of this; it's good in some situations, but terrible in others.
That was the first issue. But this made me extremely fearful in the general case, as parsing a number incorrectly can have quite dire consequences when dealing with money for example. So suddenly accept any random string of numbers interspersed at random places with underscores is a Bad Thing, and not a tiny little implementation detail to push through the most popular programming language in the world without any discussion.
As long as Linux doesn't prevent user space code to be written in more recent C standards (which it obviously does) it's fine.
Apart from that, there's also the Visual Studio compiler team to blame because they didn't manage to catch up with C99 until around 2015 (and even then only an incomplete implementation), and only in 2019 decided to 'officially' support the latest C standards again.
In general it makes a lot more sense today to start new C projects in more recent standard versions then it was 5..10 years ago.
[1]: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n34...
E.g. for a function:
void my_func(const bla_t* bla);
It would look like this: my_func(&(bla_t){ .x = 123, .y = 542 });
Designators can be in any order and can also be optional (missing items are zero-initialized, so the function should be aware of that and replace them with defaults.C++20 has a much more restricted designated init feature (basically useless for complex structs), but one nice thing in C++ is that default values can be declared right in the struct declaration.
Objects are good enough and it would add complexity for minimal reward.
As to your question, I share this feeling. Naming parameters must be standard feature in every language. Absolute majority of functions would benefit from verbose calling syntax.
Get used to writing your functions using objects for the arguments:
function myFunc({ foo, bar }) {}
Then you can call function myFunc({ foo: 1, bar: "x" })
Similarly in C/C++ struct MyFuncArgs { int foo; char bar; };
void myFunc(MyFuncArgs args) {}
myFunc({ .foo = 1, .bar = 'x' });No, not really. You just have to be aware of them, decide that you want to implement them, then sit down and implement them.
For numeric literals with underscores the implementation is rather trivial, you fiddle a bit with the lexer to make it skip the underscores during the text consumption and value conversion.
For named arguments the main problem is not in the implementation itself, it's deciding on what semantics you want when you mix named and positional parameters: e.g. if you have f(a,b,c) then what does f(1, 2, a=3) or f(c=1, 2, 3) or f(b=2, 3, a=1) mean?
TypeScript's pretty insistent on not adding features to the language that can't be "compiled" just by stripping types away. There was a little bit of slack around this early on (enums, most notably) but these days something like named parameters would probably be a non-starter until/unless JS implemented them first.
The High C Compiler was fast, I remember that, as I was used to getting a cup of coffee when compiling anything decent sized back in the late 80's, and High C compiled too fast for a cup. Of the non-standard C features available in the High C Compiler: we were not allowed to use any of them, they were seen as proprietary locks that would render our application unable to change compilers if needed.
Anyone remember Ted Gruber's FastGraph?
Seems to me some programmer from the future has journeyed to the past to design High C.
Gives me a slight urge to write some High C, an urge I’ll never follow through on.
I also don't understand why the "C standard" hasn't evolved further -- there was a discussion lately about the committee being out of touch. Some of these extensions makes life so much easier. Instead we get stupid stuff nobody need, or have been in a header for 200 years (ie, <pthread.h>, whoohoo, I'm delighted this standard header is now a... standard!)
For nested/sub function, it makes so much sense it's not even funny. Having micro-callbacks right there before the call to qsort() (or any other) is SO much better than having to farm out a context, yet-another-static-function etc...
Wild!
Makes one wonder how something could have evolved if it took C and made it more “functional” and/or smalltalk-ish, without going the dynamic way of ObjectiveC.
I don’t exactly love C++ but I find it very useful. Maybe I could have loved that other never conceived C offspring.
The difference is that High C gives you lexically-nested function definitions, thus making labels into things like local variables that have scope + shadowing. And so it becomes sensible — necessary, really, to have a coherent semantics — to extend the (runtime, dynamic) longjmp, into a compile-time-targeted, lexical, syntax-sugared version that jumps to in-scope labels (incl. ones defined outside the current lexically-nested function definition.)
If you didn't, then you'd have to decide on what a `goto` to an in-scope but out-of-function label would do instead — compiler error, maybe? — and whatever you choose, it would probably be just as hard to implement as just making it work. (Most of the effort is in extending the CFG to allow some analysis pass to notice that this is happening, after all.)
The POSIX standard isn't the C standard though (for better or worse).
Especially on Windows with MSVC "obvious" things like this are traditionally a royal PITA (which also means that a lot of C code coming from the UNIX world simply doesn't build on MSVC even though MSVC is now a decent standard-C compiler again).
But yeah, the C standard is just the minimal common subset of what C compilers offer. The good stuff is all in Clang and GCC extensions.
Why is this? Most other standards — for languages or otherwise — seem to run ahead of implementation, as meetings of major players agreeing on what they'll all implement next, with the standard constraining the implementations on how to do that.
But the C standard is seemingly instead just an external, descriptivist report on "what you can get away with writing in C while keeping it completely portable."
TBH I think the general idea of "let's only standardise what has already been implemented in real world extensions and proven its worth" isn't too bad, especially when looking at the mess that the C++ standard committee made of C++ in the last decade.
But even with this pragmatic approach I imagine it's a highly political balancing act to get multiple powerful compiler vendors to actually agree on the same thing.
See for instance the C23 auto proposal which contains a special exception for Clang's behaviour which clashes with GCC's behaviour:
For example the [[keywords]] that had was rolled in because it was already out there -- imagine proposing that out of the blue and see a people self-propel into orbit...
On other hand the Case A ... B: syntax that has been out there for 30+ years, well there's a proposal for it but it won't be THAT because well it hasn't been invented here really, we'll make up a different syntax for it instead...
It is not because it is implemented like that in gcc (requiring a space, possibly so they didnt have to modify the lexer) that it ought to be specced like that.
To do what you suggest, the lexers would need a major redesign, not just a small change.
It promises e.g. that 0..9 is contiguous, but e.g. "case 'A' ... 'Z'" would behave differently.
Most other languages never supported EBCDIC or dropped it long ago.
(Also: 'A' ... 'Z' may not do what the programmer intended in most other languages, too. Even ignoring Unicode, quite a few encodings have accented letters that are outside of that range)
Can you explain what that is? There’s supreme awkwardness around allowing `auto int i;` at block scope to work as before (with `auto` being ignored), but I’ve stared at that proposal a fair bit and haven’t noticed such an exception there.
For instance this is valid Clang C23 code (and entirely C23 standard-compliant):
int i = 0;
auto p0 = &i;
auto* p1 = &i;
...both p0 and p1 have the same type of int*.In GCC this code doesn't compile because GCC already had a simpler "C style" __auto_type extension which doesn't allow the form "auto*", but this behaviour is also entirely valid C23 ¯\_(ツ)_/¯.
(personally I prefer GCC's version as it makes more sense for C)
This will cause some head-scratching when code that builds on Clang doesn't build on GCC, especially since Clang usually tries to emulate GCC behaviour. But OTH I think/hope that C's auto will only be used when absolutely necessary in "type-generic" macros, and no "almost always auto" nonsense which was fashionable in the C++ world for a while.
I hope to work on a guide for developers who want a “dependable-C” where they can guarantee it will compile and run correctly in as many implementations as possible.
<pthreads.h> is POSIX, it has never been - and still don't is! - part of the C standard. In particular, MSVC only supports it through third party libraries.
However, C11 added cross-platform thread support with <threads.h>: https://en.cppreference.com/w/c/thread. I wouldn't call that "stupid stuff nobody needs".
"isn't," not "don't is"
You're right, though
Automatic yield flattening is a scary feature. Python has explicit control via `yield from`.
The 80s and 90s were a time of interesting experimentation in the Japanese PC market. Sadly it eventually it converged into the grey goo of baseline Wintel, just as the contemporaneous and exciting world of keitai just ended up as the same boring smartphones as everywhere else.
Standardization of things like POSIX and languages ironically has the effect of reducing extensions -- most people write to the standard for maximum portability. I do it too. I'm not a fan of single-implementation languages* (python, pearl, go, rust etc) but at least they do hark back to a time when languages really were written with greater programmer affordances (just as CISC machines had all sorts of affordances for writing applications in assembly code, such as BCD instructions, string maninipulation, etc).
* Yes, I know about gccgo and rust-gcc but both were written to be compatible with the original implementation rather than to an independent standard. So de facto those are single-implementation languages.
Though D still has no named parameters :D (I know it's in the works).
I agree that named parameters can be very helpful. For example, if there are three bool arguments, it makes calls like:
test(true, false, false);
into: test(format: true, output: false, skip: false);
which makes it much more readable.i'm not sure if ironman listed generators as a requirement or not; i suspect they were added later
this paper doesn't mention clu, modula-2, or icon as influences, for whatever that's worth
https://dl.acm.org/doi/10.1145/154766.155376
We come to https://link.springer.com/book/10.1007/BFb0021415 from the references, with an interesting table of contents.
Similar approach can be done for other quoted references, if one is really keen in who did it first, and how much the Ada folks were aware of them.
Naturally since not all of them are scanned, it is going to be a lot of work.
Maybe it can be "ported" to some other kind of OS.
I actually used that compiler over 25 years ago, it generates Intel OMF files with 8086/80186/80286 - As I recall one can select the target.
So post compiling, one should be able to link the result to target a DOS machine, VM, or even Dosbox.
I'd suggest porting it, but rather simply simulating the FlexOS SVCs, since it doesn't really need any of the RT capabilities, merely the file access, memory allocation / free, and possibly execution (COMMAND SVC).
The package contains two forms of the compiler, a single executable version, and an overlaid version. The non overlaid version would be easiest to get working in such a simulated approach, as one would not have to implement the OVERLAY SVC.
Most (if not all) the needed information will be available in the documents under this directory:
https://bitsavers.org/pdf/digitalResearch/flexos/
There are also copies of the OS available here: https://bitsavers.org/bits/DigitalResearch/FlexOS/there are 18 sovereign countries in https://en.wikipedia.org/wiki/List_of_countries_and_dependen... with smaller populations than fujitsu, and 31 with smaller economies than fujitsu https://en.wikipedia.org/wiki/List_of_countries_by_GDP_(nomi...
The post hoc insistance on using it's rebrand helps with the 'othering' of making it sound like a foreign company doing all the dodgy shit.
Second, you're wrong because that was until 2002 when they were acquired and kept doing "dodgy shit" together with the Post Office until 2015. The Post Office recorded the profits, the private prosecutors got a cut of false reclaimed losses, and the software contractor enabled them.