It seems to me that it's pretty impossible to actually replace C (although I fully support the people trying to do so). All the things that "make C fast" are really ways of making the "underlying machine" fast through C, and trying to come up with new language constructs that facilitate these techniques seems like a losing game. Any new languages are going to have a hard time catching up to C when it comes to compiler optimizations and can never really catch up when it comes to ubiquity. (Would your 5-year-old compiler target dsPIC and have support for their IO ports and interrupts? clearly not)
So, what about a modern safe language that's meant to be used alongside C? For example, the language presents a modern approach to modules and imports, but a function 'bar' in a module 'foo' is compiled down to a straightforward foo___bar() in the generated C. The generated C has straightforward type declarations and readable code, with a minimum of macro abstractions. The source language emphasizes features that allow one to write concise reasonably performant code (H-M, local inference, sum types, some kind of object polymorphism). It has implicit GC, but mostly relies on linear references and stack allocation, falling back to real GC only for explicit unknown-life allocations (with swappable collectors for different runtime overhead). Do-everything capabilities like unsafe pointer arithmetic are completely left out, as the programmer can drop back to C in a neighboring file or inline. The per-project ratio of this new language to C would vary depending on the type of the project - something like a network server would use a minimum of C, perhaps just in cordoned-off performance critical code.
(I've been mulling on this idea for a few weeks. I ran across Felix the other day, and found myself nodding a lot, but the language seemed quite complicated and the array details in particular left me wondering if memory safety was even a design goal.)
>(Would your 5-year-old compiler target dsPIC and have support for their IO ports and interrupts? clearly not)
C doesn't have support for dsPIC and its IO ports and interrupts. People writing real kernels or embedded code have to write little shims in platform-specific assembly code to hook their C code up to the hardware.
>All the things that "make C fast" are really ways of making the "underlying machine" fast through C, and trying to come up with new language constructs that facilitate these techniques seems like a losing game.
Yes and no. C's so-called speed comes from its transparency: everything you write in C can be cleanly mapped down to its constituent assembly code without extra code being inserted by the compiler or runtime library. C has a fundamental principle: you only pay for what you use. Other languages can, but mostly choose not to, emulate this.
>Any new languages are going to have a hard time catching up to C when it comes to compiler optimizations
GCC and LLVM make this not so much of a problem. Most of the major compiler optimizations nowadays are done on intermediate representation code, not C source itself.
>The source language emphasizes features that allow one to write concise reasonably performant code (H-M, local inference, sum types, some kind of object polymorphism).
Local inference is only necessary in situations where Hindley Milner or another HM-based algorithm doesn't work (see: Scala).
There's bunches of languages like this. In addition to BitC, there's also Cyclone, Rust, ATS, and Deca -- all of which are in various stages of development. ATS has a stable release, IIRC, Rust is in alpha, Cyclone has made a release but development stopped, and Deca is in active pre-alpha development.
> In addition to BitC, there's also Cyclone, Rust, ATS, and Deca -- all of which are in various stages of development. ATS has a stable release, IIRC, Rust is in alpha, Cyclone has made a release but development stopped, and Deca is in active pre-alpha development.
There is also Clay (http://claylabs.com/clay/) which keeps a low profile, but there are a lot of work being done on it. What I like best there is that it has no complicated run-time system, which is an obvious plus if you want to supplant C, and that it does whole program optimization right out of the box, no old-fashioned notions about separate compilation units.
Yes, sorry, I love Clay, but this field has gotten large enough that I don't always remember every contender when I list them out. For example, there's also Habit and Tart.
> People writing real kernels or embedded code have to write little shims in platform-specific assembly code to hook their C code up to the hardware
Platform-specific extensions to C, but not assembly. IIRC declaring a register on the hitech picc18 compiler was a cast of an address to a specific type, and on another compiler was a pragma. But that happens in compiler-supplied include files, so the C programmer ends up with a PORTA macro. Point being, the algorithmic code written in C isn't entirely beholden to a specific implementation and what platforms it chooses to support.
> C has a fundamental principle: you only pay for what you use
Unfortunately, there is a lot you are unable to use even when you are more than willing to pay. I'm basically proposing augmenting C with modern statically analyzable language features, so that one is able to pay for more capabilities.
The problem with the current bunches of languages is their extreme lack of maturity. Rust currently looks the most promising to me, but I can't be sure that at version 0.4 the main contributors won't move on to other things, leaving its popularity to be eclipsed by Deca 1.0. A working application can always be recompiled with a frozen version of the compiler, but if your goal is to write a major library that exports its abstractions as more than a C FFI, language community is a major concern.
So, what about a modern safe language that's meant to be used alongside C? For example, the language presents a modern approach to modules and imports, but a function 'bar' in a module 'foo' is compiled down to a straightforward foo___bar() in the generated C. The generated C has straightforward type declarations and readable code, with a minimum of macro abstractions. The source language emphasizes features that allow one to write concise reasonably performant code (H-M, local inference, sum types, some kind of object polymorphism). It has implicit GC, but mostly relies on linear references and stack allocation, falling back to real GC only for explicit unknown-life allocations (with swappable collectors for different runtime overhead). Do-everything capabilities like unsafe pointer arithmetic are completely left out, as the programmer can drop back to C in a neighboring file or inline. The per-project ratio of this new language to C would vary depending on the type of the project - something like a network server would use a minimum of C, perhaps just in cordoned-off performance critical code.
(I've been mulling on this idea for a few weeks. I ran across Felix the other day, and found myself nodding a lot, but the language seemed quite complicated and the array details in particular left me wondering if memory safety was even a design goal.)