Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The thing is, you will never replace C. Supplement it, extend it, yes, but not replace it

The fact is, C is still probably the lowest level HLL still used. It's the lowest level you can be, while still providing the HL constructs we're all used to. There is always going to be code that wants or needs to be there. Code where anything further up either can't give the performance, or provides impedance to the design or actual goal.

You still want to replace C? Fine. What will you write your bootstrapping compiler in? :-D.



> It's the lowest level you can be, while still providing the HL constructs we're all used to.

I disagree completely. A language much better than C will come along in its niche, and I'll be switching.

C isn't low level enough. It has too much undefined behaviour (and tries to be too portable), each instance of which denies you access to real machine behaviour. Signed ints don't even wrap around! Effectively, C does not even support twos-complement signed integers, as exist on all modern computers since decades ago, without a special compiler flag! You have to resort to tonnes of compiler-specific extensions to get things like leading-zero-count, SIMD, and computed-goto. Even with GCC's zillion extensions that were added for people who have to do really low level work, C is still hopeless for writing maximum-performance VMs, that's why Mike Pall wrote the LuaJIT2 interpreters (one for each architecture) in assembly. Here's one of his explanations why C shouldn't be used for such a thing [1]. I've also tried writing a high performance interpreter in C, and I found that I wasted 80% of my time trying to get the C compiler to output the sequence of instructions I wanted. Next time, maybe I'll just use assembly and save myself a lot of trouble.

Secondly, C is not high-level enough. A low level language like C needs a powerful macro system to let you abstract away the details of your object system or whatever. C's preprocessor has many flaws [2] and is one of the worst in existence. A good macro facility allows compile-time generation of code in a readable (or at least type safe) way, like D and Lisp do. C and C++ users don't realise they have the preprocessor equivalent of a Blub language [3]. Sure, C++ is an extension of C with high-level features, and was a good attempt, but it's too complex and C++'s template meta-programming just about the only compile-time codegen solution worse than C's preprocessor.

[1] https://web.archive.org/web/20160209102431/http://article.gm...

[2] Read any rant, e.g. http://c2.com/cgi/wiki?CeePreprocessor

[3] http://www.paulgraham.com/avg.html


Yes, C's preprocessor is weak, but that's a quality of life thing, not a necessity by any stretch.

And as for C not being low-level enough, that was my point - C is as low level as you can be, before you become unportable.


> And as for C not being low-level enough, that was my point - C is as low level as you can be, before you become unportable.

I don't think that's true. You can add first-class support for bitdata [1], much better than C's bit flags and portable, better support for alignment declarations, better/safer support for absolute addresses, native SIMD-like vectors [2], exposing arithmetic carry flags, and more without losing portability.

[1] http://web.cecs.pdx.edu/~mpj/pubs/bitdata-icfp05.pdf

[2] https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html


Well, now we know what to ask for in C17.


> You still want to replace C? Fine. What will you write your bootstrapping compiler in? :-D.

There are several examples of language implementations that are built directly from machine code incrementally. (In that case, the "bootstrap" happens via an already-built compiler of the previous version, or of the same version in the different architectures.) Also, you don't strictly need C for the bootstrapping compiler... Rust's one was OCaml for example.


And what's OCaml written in? How about the assembler?

If you really want to replace C, You'll need to be able to compile the language without ever having C on your system (at least, in theory). This is almost impossible, although you can do it, if you slowly work towards it.


That's not really fair. If you go far enough back in the ancestral compiler list on any language, you'll probably hit C. You'll definitely hit hit assembly and bare-metal machine code. Heck, at some point you might run into hand wire-wrapped microcode---but I don't think that's an argument that we should be using it. That's just an artifact of the history of operating system development, and the fact that C spent (is spending) a considerable period as the de facto standard for OS development. That it was first doesn't necessarily make it better. A few events turning out differently in history, and you'd be making the exact same arguments about lisp, BCPL or Fortran.


It is a weak claim. You'd hit Pascal for a whole family of them with FreePascal well-maintained, fast, and portable. The Wirth ones vary language-by-language. There are BASIC's written in BASIC, LISP's in LISP (or 1940's machine code or microcode), silicon implementations of Java (eg JOP), Hyde's HLA assembly, IBM's PL/S that's still around, Amiga-E in M68K assembly, and Hansen's simpler Edison language in machine code or Pascal one.

So, yeah, C wasn't at the bottom of all kinds of past and present developments, many more complex than C. It being at bottom of many current ones is social and economic, not a technical necessity. One could just as easily target FreePascal, a low-level VM w/out C's built-in preferences, or a HLA on a specific ISA.


I know full well: my point was that you cannot depend on that which you wish to replace: Targeting something that doesn't is a valid approach for doing so.


That is simply untrue.

Replace your example with assembly and C. According to this, C can't replace assembly and assembly can't replace machine code, which is an absurd statement.

No modern development of OS is done in assembly only.


C didn't fully replace asm

Asm is still a language that is used. If we're talking about fully replacing a language, than yes, you cannot have it in your toolchain.


Right, and C is widely used/successful language.

As a poet once said - "Perfect is the enemy of good".

Rust never aimed to replace all of C/C++ forever, everyhwere. That's nigh impossible. Much in the same way, it's impossible for ASM to replace machine code or 386 processors to replace Commodore 64 or Analytical engine. There will always be some shop that programs in ASM/C/C++, like there are shops that program in COBOL.

Rust point was - to replace C/C++ in domains that require safety and speed.


No, Rust didn't. Zig does.


Care to elaborate? You can depend on what you want to replace for bootstrapping. You can use tools written in it, compiled with it, or even hand-converted to assembly for first run. That it was a stepping stone doesn't undermine an argument to replace it in general or even say much about it. The common flaw in reasoning is that "If C was used at any point, then C is technically good, essential, or something similar." It can come down to something as simple as author's convenience, personal preference, or even timetable. Using vs replacing a C compiler fits into all three I imagine. :)


Okay. Let's imagine Zig does replace C: 20 years from now, nobody uses C, except in a few specialized fields, same as FORTRAN. However, every time somebody has to recompile Zig, they have to go get a C compiler. Furthermore, most people don't know C any more than they know FORTRAN, making the compiler hard to contribute to.

I'm not saying C is technically good, or essential, I'm saying that you cannot be dependant on something you want to get rid of, because then you can't get rid of it.


I think you're missing the whole concept of bootstrapping. C, if only language, would be used to compile the first, Zig compiler. The next compiler, written in Zig, would go through the first one. You then have a pile of machine code that turns Zig into machine code. No C left after the first pass.

So, there's no dependency if you're switching languages or getting rid of it. There's just a one-time use. For legacy systems, there's also potential for a source-to-source compiler if semantics are close. There's also binary recompilation and integration into new language a la AS/400 or OpenVMS migrations.


True, but what about the bootstrapping compiler, for new architectures? That can't be C. Neither can the libraries the compiler depends on. And you'll eventually have to rewrite the assembler, because that can't be C...

It's a fairly monumental effort.


You cross-compile.


...Well, I'm an idiot. Good point, Steve.


You have to know that you're making a hugely stretch of an argument, I mean none of the "C replacement" languages really expect to replace C so completely that there will be no more C code written or no C compiler that runs on modern hardware in 20 years - you have to realise that's not what they mean by "replace".

It's meant as in "replace for the majority of modern use cases, where the power of C is needed, but a better language is desired" (or some variation thereof) and if it does come to it...meaning a language will replace C so completely that there'll be no C in sight in 20 years time, (hard to believe), then it'll probably be so, because we figured out how to not depend on C and go on without it.


I don't expect it, but if that's what you're shooting for, that's the sort of thing you've got to contend with.

And no, I don't know what they mean by replace, but if they make such a big point of stdlib not depending in cstdlib, what other conclusions am I supposed to draw?


Contrary to AT&T preachers there were plenty of languages being used before C.

I never used C on the few compilers I worked on.


True, it's not fair. I didn't say that your first implementation had to be beneath C, but if you really want to replace the language at the bottom of the stack, you have to rewrite the stack. Otherwise, you haven't really replaced it, now have you?


No, that's not true. You can replace lots of unsafe C code with safer code even if C is used somewhere in the system.

You can decide to stop using dynamite to remove weeds and still use it in mining.


But that's not what we're talking about: we're talking about replacing C entirely. You can't outlaw dynamite if it's in use for making the dynamite replacement.


If you want to be pedantic, Caml was bootstrapped from Lisp, not C. Quoting from http://caml.inria.fr/about/history.en.html

"The first implementation of Caml appeared in 1987. This implementation compiled Caml down to LLM3, the virtual machine of the Le_Lisp system."


Sooooo easy compared to a C compiler...

https://speakerdeck.com/nineties/creating-a-language-using-o...

More powerful, safe platform results as well. ;)

http://scheme2006.cs.uchicago.edu/11-ghuloum.pdf

Another one for gradually building an ML which incidentally results in one of best languages for writing compilers, including Ocaml. You never need C so long as there's an assembler on source or target machine.


"but not replace it"

I've long proven you can on a per project basis for both system apps non-C languages and C apps with better, C variants.

"What will you write your bootstrapping compiler in? :-D."

Any language better than C for writing a compiler, esp Ocaml w/ design-by-contract, compiling to target assembler. Worked wonders for Esterel's SCADE. Optionally, any such language transpiling to any other HLL on target system, including C w/ safety checks & no undef behavior. Working wonders for COGENT language team. Or go Wirth-style with a better-than-C (esp Component Pascal) to P-code compiler plus P-code interpreter for target hand-written in assembly. Simple backend + interpreter got Pascal/P on 70 architectures. Any are easier than a whole compiler for complex language (or C) in C using a C compiler.

For doubters:

https://embed.cs.utah.edu/csmith/


Fair 'nuff on the compiler stuff. I was talking about replacing C globally, however, and that's not happening any more than we're replacing FORTRAN.


"I was talking about replacing C globally"

I gave up on that when I noticed the COBOL and Windows situations. ;)


Well, yeah, but that's what Zig seems to be trying to do. And as various tech comes up for replacement, it may one day be possible.


You can bootstrap in any language that is widely available, so today that could be Javascript even. The biggest advantage of C as a language is, that a simple compiler is very easy to write. But I would bootstrap from Lisp (Scheme). A naive interpreter can be easily implemented in assembly and then you have a nice high level language for implementing the target system.


at hundreds of pages defining the standard, it's not low level at all, sadly. The apparent simplicity is deceiving at first, IMHO.

Low level doesn't mean simple, but yet because of the desire for portability, it's rather abstract. It can't even check for a carry flag. It's not hard to imagine a language that could. Coming from microcontrollers, that is a huge disappointment. That is just the an example. Is there more?


It's lowlevel, that's why there's so much spec. And much of it is just defining that behaviour is implementation defined.

And as I said, it's as lowlevel as an HLL can be.

I wish we could check the carry flag. You could totally write a C library for that, I bet, by mixing in some asm, and using conditional compilation. Language extension!


GCC since 5.0 and Clang since longer ago than that support (the same) set of builtin functions to check carry and overflow bits:

https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins...

http://clang.llvm.org/docs/LanguageExtensions.html#checked-a...


I'll probably write it in Haskell or possibly ML. The Haskell compiler is written in Haskell, so there's nothing to C here.

OTOH, I'm not sure if C needs replacing. It models state machines fairly well. Sure, we could use more systems languages like rust, but at best they replace C++ in some circumstances.


But isn't Haskell's runtime (RTS) written in C?


Nothing prevents it to be rewritten in Haskell.

It wasn't been done just because no one cared to do it.


Hmm you may be right. I'd say rust, but LLVM is written in C (and writing a compiler in Ocaml or Haskell is so much nicer.) That leaves assembly and god knows what else in my repertoire.

Not that it matters once it's bootstrapped though.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: