(If you're thinking that interfacing with C would be easier: No, the FFIs to C are usually as complex as they are for exactly the right reasons, namely that C's semantics don't match very well with $OTHER_LANGUAGE.)
... at which point you're practically implementing your own VM anyway, so, y'know...
That's not the point. C is a great common tongue, as its function call and name lookup semantics are simple, and it doesn't insist on being in control of memory, scheduling, etc. Perl and Python are pretty similar, and both talk to C, but calling between Perl and Python is enough of an unholy mess that it's usually easier to just print text over a pipe.
Maybe not, but did you miss the bit in my post about FFI and GC? Have you actually tried to implement a non-trivial extension to a GC'ed language which needed to interface with C code?
EDIT: The point is not so much that it cannot be done -- the point is that it needs a human ("programmer") to do it. Which kind of defeats the point of "C-as-lingua-franca". Which, if you think about it C already kind of is, sadly. Any FFI currently in existence focuses on C already. What more do you want? ;)
No. It's a huge pain, but much less of a pain than calling between two GC'd languages. (I haven't tried calling directly between e.g. Perl and Haskell, but I'd rather gouge my eyes out with a spoon. The handles alone would bury me.) If there were one obvious GC solution, then all GC'd languages would use it, and C would not be as useful. But we've had the JVM and countless other abstractions, yet none has managed to be a higher common denominator than C, so it looks like human labor for the foreseeable future.
(Almost all languages do offer some "FFI" to call C. But in languages that don't naturally fit, there will often be significant overhead to e.g. aligning memory management so that the same memory doesn't get freed twice, as might happen when a garbage-collected language called a C library)
The submitted essay addresses the problems that can result from this sort of compilation style with the question "Will native compilation of a big project result in so much code that there's a global slowdown (something actually true of mid-1990s Erlang to C translators)?"
(If you're worried about duplicating effort in optimizers, do what many languages do and offer an LLVM frontend. LLVM optimizations are (mostly) language-independent, and LLVM bytecode, while imperfect, often allows a better representation of language semantics than C source would)
Optimizers is also one thing I was worried about, LLVM is not the only compiler out there. And also there is friction. Most of the systems already have C compiler installed, if you target it, there is no friction in setting up building environment and so on.
How much of that is because Golang doesn't compile to C, and how much is because the languages just don't fit? E.g. you'd still need a way to mark whether Golang was supposed to garbage-collect a value that had been returned from a C call, or not.
> Most of the systems already have C compiler installed, if you target it, there is no friction in setting up building environment and so on.
Yes there is, because you still need to build the thing that interprets to C. If anything there's more friction than having a compiler that directly builds native binaries like e.g. ghc, because you need two tools - your translate-to-C tool and your C compiler. "Most systems already have a C compiler" is only really true on *nix; it will be easier for a Mac or Windows user to run your system if you distribute e.g. java bytecode.
This. If you just want C interop, SWIG[1] has been around forever, and is pretty good at generating bindings from a C/C++ header with minimal effort. But if you've ever tried it, you'll know that you still have to do most of the work by hand to create an idiomatic interface in your language of choice.
The bindings are easy to create (there is an automated tool that does most of the work), they look like Nim function declaration and can add better typing checks on FFI calls. You still have manual memory management and pausable, optional GC.
I should also note that all correct C code does bounds checking somewhere. The difference with languages that are bounds-checked by default is that they pessimistically assume that you haven't checked the bound manually, and so can potentially do more bounds checking than is strictly necessary if their optimizers aren't capable of hoisting out the checks.