Live data from Hacker News

Obvious things C should do

digitalmars.com

251–260 of 310 posts

Re: Obvious things C should do

#251
post #219

Earlier quoted context omitted.

Your function looks like it's doing I/O, which won't work at compile time test. Here's an example of a unittest for the ImportC compiler: struct S22079 { int a, b, c; }; _Static_assert(sizeof(struct S22079){1,2,3} == sizeof(int)*3, "ok"); _Static_assert(sizeof(struct S22079){1,2,3}.a == sizeof(int), "ok"); The semantics are checked at compile time, so no need to link & run. With the large volume of tests, this speeds…

It is difficult to imagine that compile-time interpretation of tests is faster than compiling and running them for anything more complex. And for trivial stuff it should not matter. Not being able to do I/O is a limitation not a feature.

Linkers are slow and clunky. Yes, there is a crossover point where executable tests are faster.

Re: Obvious things C should do

#252

Earlier quoted context omitted.

> your own example of defining an enum value That is hardly the only place that has a constant-expression in the grammar. (BTW, D enums can also be floats, and even string literals!) You could use CTFE to initialize const floating point globals. static_assert also takes a constant-expression. > There's just a boatload of gotchas. The D community has 17 years experience with it. It remains an indispensable feature. As…

Not to take away from the possible usefulness of constant functions, but it's amusing that the article example of `sum(5,6)` would work great in C if written as 5 + 6, or done as the equivalent macro

Trivial examples make it easy to explain and understand the concept. Just like with Calculus, we don't start with integrating e^x. We start with integrating x.

Re: Obvious things C should do

#253

Earlier quoted context omitted.

> The parser being stand-alone means it is much simpler to understand and unittest. Stand-aloneness and single-passness are orthogonal. > I found no advantage to a single pass compiler. It isn't any faster. A gigantic advantage: a single-pass-compilable language is simpler. By definition. Implementations may or may not be simpler or faster. > C++ doesn't allow forward declarations either. Well, that's not what I mean…

> A gigantic advantage: a single-pass-compilable language is simpler. By definition. That's only "by definition" if you take a language that needs multiple passes, then remove the features that need multiple passes, and don't replace them with anything else to compensate. The "by definition simpler" version of C would not only disallow forward references, it would have no forward declarations either. As-is, forward d…

I have the impression you're mixing single-pass compilation and O(1) memory use of the compiler.

As is, C already is single-pass compilable, modulo some unnecessary syntax ambiguities.

As the compiler reads the text, it marks some character strings as tokens, these tokens are grouped as a fragment of code, and some fragments of code are turned into machine code. A simple function of a 100 lines doesn't need to be parsed until the end for the compiler to start emitting machine code.

Like the parser, this requires memory to keep tabs of information and doesn't work for all types of constructs, like a jump instruction to a label defined later in a function. The code emitter soaks input untill it is possible, and does so, like when the label is already known and can be jumped to.

Re: Obvious things C should do

#254

Earlier quoted context omitted.

> The parser being stand-alone means it is much simpler to understand and unittest. Stand-aloneness and single-passness are orthogonal. > I found no advantage to a single pass compiler. It isn't any faster. A gigantic advantage: a single-pass-compilable language is simpler. By definition. Implementations may or may not be simpler or faster. > C++ doesn't allow forward declarations either. Well, that's not what I mean…

> A gigantic advantage: a single-pass-compilable language is simpler. By definition. That's only "by definition" if you take a language that needs multiple passes, then remove the features that need multiple passes, and don't replace them with anything else to compensate. The "by definition simpler" version of C would not only disallow forward references, it would have no forward declarations either. As-is, forward d…

Doing jump instructions in a single pass is done by creating a patch list, and when the compilation is done walking the patch list and "fixing them up".

Doing this with functions is a lot more difficult, because one cannot anticipate the argument types and return types, which downstream influence the code generation. Of course, early C would just assume such forward references had integer arguments and integer types, but that has long since fallen by the wayside.

Re: Obvious things C should do

#255

Earlier quoted context omitted.

> A gigantic advantage: a single-pass-compilable language is simpler. By definition. That's only "by definition" if you take a language that needs multiple passes, then remove the features that need multiple passes, and don't replace them with anything else to compensate. The "by definition simpler" version of C would not only disallow forward references, it would have no forward declarations either. As-is, forward d…

I have the impression you're mixing single-pass compilation and O(1) memory use of the compiler. As is, C already is single-pass compilable, modulo some unnecessary syntax ambiguities. As the compiler reads the text, it marks some character strings as tokens, these tokens are grouped as a fragment of code, and some fragments of code are turned into machine code. A simple function of a 100 lines doesn't need to be par…

You cannot do any optimization when generating machine code that way. That's fine for a primitive compiler built for a school project, but not much else. (Even "no optimization" switch settings on a compile do a lot of optimizations, because otherwise the code quality is execrable.)

Re: Obvious things C should do

#257

Earlier quoted context omitted.

> if you're working within a translation unit, thats much simplified, but then you're much more limited in what you can do without repeating a lot of code. I wonder how the author solves this. You are correct in that the source code to the function being evaluated must be available to the compiler. This can be done with #include. I do it in D with importing the modules with the needed code. > This is already somewhat…

Nice explanation. Modules are the way forward. Looks to always have been. Not understanding the resistance, when the advantages are clear.

I do understand the resistance. C is a simple, comfortable language, and its adherents want it to stay that way, warts and all.

But in the context of that, what baffles me is the additions to the C Standard, such as useless (but complicated!) things like normalized Unicode identifiers, things with very marginal utility like generic functions, etc. Why those and not forward declarations?

Re: Obvious things C should do

#258
post #202

Earlier quoted context omitted.

> I dont have the power to make large decisions on an existing codebase like "lets switch languages" We struggled with that for a long time with D. And finally found a solution. D can compile Standard C source files and make all the C declarations available to the D code. When I proposed it, there was a lot of skepticism that this could ever work. But when it was implemented and debugged, it's been a huge win for D.…

I know that in other languages, one obstacle for "just compile the C files" is that the target language might not have pointers and thus have difficulty representing things such as return-by-pointer. I suppose in D this was less of an issue because D has pointers?

I'm not sure what you mean.

Re: Obvious things C should do

#259
post #57

Earlier quoted context omitted.

Thanks for taking the time to respond! I have a few followup questions if thats ok: > You are correct in that the source code to the function being evaluated must be available to the compiler. This can be done with #include. I do it in D with importing the modules with the needed code. > D's strategy is to separate the parse from the semantic analysis. I suppose it is a hair slower, but it also doesn't have to recomp…

> Is a translation unit the same as in C, but since you're #including the file you would expect multiple compilations of a re-included C file? woudnt this bloat the resulting executable (/ bundle in case of a library) I think the idea is that compiling a translation unit produces two outputs, the object code (as it currently does), and an intermediate representation of the exported declarations, that could be basical…

The D compiler has an option to generate a "header file" from D modules. It's called a .di file. It's useful if you want to hide the implementation from a compiler, as you would with libraries.

As it turned out, though, people just found it too convenient to just import the .d file.

But as a very unexpected dividend, it was discovered that the D compiler would generate .di files from compiling .c files, and realized that D had an inherent ability to translate C code to D code!!!! This has become rather popular.

Re: Obvious things C should do

#260

Earlier quoted context omitted.

Can't you use precompiled headers?

I had an intern try to use precompiled headers for the Linux kernel. The road block they found was that the command line parameters used to compile the header must exactly match for all translation units which it is used. This is no the case for the Linux kernel. We could compile the header multiple times, but the build complexity was not something we could overcome during the course of one internship.

> must exactly match

Yup. My compiler kept a list of which switches would perturb compilation and so would invalidate the precompiled header, and which did not.

Precompiled headers are an awful, desperate feature. Good riddance.

Post reply on HN