TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Amplifying C (2010)

140 pointsby jhackover 9 years ago

17 comments

pcwaltonover 9 years ago
&gt; The system introduces an &quot;amplification&quot; phase where s-expressions are transformed to C code before a traditional build system runs.<p>In other words, this is a compiler.<p>At this point I have to say what I always say: Don&#x27;t compile to C. You will spend forever eliminating undefined behavior, the debugging experience will be bad because you don&#x27;t have direct control over the DWARF DIEs, your compilation will be slower for no reason, you will not be able to add custom metadata to be consumed by optimization passes (for example, aliasing passes), you won&#x27;t have access to special instructions like LLVM add nuw&#x2F;nsw, etc.<p>Virtually all languages I know of that started out compiling to C stopped doing it at some point in their development, for one or more of the above reasons. Skip the major technical overhaul you&#x27;re going to inevitably have to do and just build LLVM IR from the beginning. The LLVM API is excellent, so it ends up being less work to begin with.
评论 #11055723 未加载
评论 #11055229 未加载
评论 #11054851 未加载
评论 #11055071 未加载
评论 #11055328 未加载
评论 #11054992 未加载
评论 #11054704 未加载
评论 #11056662 未加载
评论 #11054767 未加载
评论 #11055490 未加载
评论 #11057587 未加载
Animatsover 9 years ago
This road is well traveled. Objective-C, C#, and Java are all on that road - start with C, and add only the stuff you need. A few years down the road, and the new language has feature bloat.<p>The three big problems in C are &quot;how big is it&quot;, &quot;who released it&quot;, and &quot;who locks it&quot;. The language provides no help with any of these issues. C++ allows papering over the problem, but the abstractions always leak and the mold always comes through the wallpaper. There are times when you need a raw pointer (for system calls, for example) and the availability of raw pointers breaks the size and ownership protection.<p>Rust deals effectively with all three of those issues. That was a major breakthrough, one of the few fundamental advances in language design in years. Rust, unfortunately, seems to have taken a turn for the worse in the last year. Rust has been infected with the Boost disease - overly clever templates. Rust is a procedural language, but template enthusiasts have been making it pseudo-functional with constructs like &quot;.and_then()&quot; and &quot;.or_else()&quot;. Then there&#x27;s &quot;try!()&quot;, with its invisible return statement. The result is painful to read and hard to maintain.<p>The author of the parent article has a point about &quot;with-&quot; type constructs. Python has a general &quot;with&quot; statement, which can be used on any object that implements &quot;__enter__&quot; and &quot;__exit__&quot;. That&#x27;s a very useful and safe language feature. Both Go and Rust lack it, and their workarounds (&quot;defer&quot; and destructors) are worse.<p>Python&#x27;s &quot;with&quot; plays well with exceptions. Exceptions in Python work well. Exceptions in C++, not so much, mainly because ownership and exceptions mix badly. Go could fix that with GC, and Rust could fix that with the borrow checker. But neither has exceptions. As a result, error handling in Go is wordy, and in Rust, both complicated and wordy.<p>I had high hopes for Rust, but they may have jumped the shark by getting too clever. We don&#x27;t need a new C, but we may need a new Rust. At this point, any new low level language that doesn&#x27;t have a borrow checker is flawed from the start.
评论 #11057293 未加载
评论 #11057497 未加载
mapcarsover 9 years ago
There is a project by Fernando Borretti for Lisp-style macros in C, with macro expander written in Common Lisp: <a href="https:&#x2F;&#x2F;github.com&#x2F;eudoxia0&#x2F;cmacro" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;eudoxia0&#x2F;cmacro</a>, and a collection of basic macros: <a href="https:&#x2F;&#x2F;github.com&#x2F;eudoxia0&#x2F;magma" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;eudoxia0&#x2F;magma</a><p>This way he has already added lambdas, lazy evaluation, types, anaphoric macros, with- macros.
评论 #11054876 未加载
评论 #11054874 未加载
eigenbomover 9 years ago
Always fun to see projects like this, but I don&#x27;t get some of the motivations. Regarding the code examples:<p><pre><code> &#x2F;&#x2F; c++ AutoFile file(&quot;c:&#x2F;temp&#x2F;foo.txt&quot;, &quot;w&quot;); fprintf(file, &quot;Hello, world&quot;); &#x2F;&#x2F; lisp (with-open-file (f &quot;c:&#x2F;temp&#x2F;foo.txt&quot; &quot;w&quot;) (fprintf f &quot;Hello, world&quot;)) </code></pre> .. the author thinks the former is cluttered and latter uncluttered (simply because the fprintf is within a sub-scope of with-open-file)? That&#x27;s a fragile rationale, but you can certainly write c++ that way if you like.
评论 #11056773 未加载
评论 #11056209 未加载
评论 #11056931 未加载
overgardover 9 years ago
Wouldn&#x27;t it make more sense to use a Scheme that compiles down to C (like, Chicken scheme or something like that)?<p>I guess the argument might be readability of the output, but I&#x27;m guessing as his lisp grows more complex the output is going to diverge from the input quite a bit anyway (I&#x27;m trying to imagine what a closure would look like.. I&#x27;m guessing it wouldn&#x27;t be pretty)
评论 #11054570 未加载
eatonphilover 9 years ago
I don&#x27;t know a lot about C or about Lisp, but I do know that this isn&#x27;t the first compile-to-C Lisp. So why not use one of the ones that already exist instead of starting from scratch? And the blog post seemed to treat it like this is the first attempt to compile a high level language to C (MLTon, JHC, various Schemes, etc).
评论 #11054566 未加载
评论 #11054485 未加载
jamiiover 9 years ago
IMO Terra (<a href="http:&#x2F;&#x2F;terralang.org&#x2F;" rel="nofollow">http:&#x2F;&#x2F;terralang.org&#x2F;</a>) is a more interesting approach to this problem, since it not only enables macros but also staged compilation, polymorphism-as-a-library, runtime specialization etc.<p>&gt; You can use Terra and Lua as…<p>&gt; A scripting-language with high-performance extensions. While the performance of Lua and other dynamic languages is always getting better, a low-level of abstraction gives you predictable control of performance when you need it. Terra programs use the same LLVM backend that Apple uses for its C compilers. This means that Terra code performs similarly to equivalent C code. For instance, our translations of the nbody and fannhakunen programs from the programming language shootout1 perform within 5% of the speed of their C equivalents when compiled with Clang, LLVM’s C frontend. Terra also includes built-in support for SIMD operations, and other low-level features like non-temporal writes and prefetches. You can use Lua to organize and configure your application, and then call into Terra code when you need controllable performance.<p>&gt; An embedded JIT-compiler for building languages. We use techniques from multi-stage programming to make it possible to meta-program Terra using Lua. Terra expressions, types, and functions are all first-class Lua values, making it possible to generate arbitrary programs at runtime. This allows you to compile domain-specific languages (DSLs) written in Lua into high-performance Terra code. Furthermore, since Terra is built on the Lua ecosystem, it is easy to embed Terra-Lua programs in other software as a library. This design allows you to add a JIT-compiler into your existing software. You can use it to add a JIT-compiled DSL to your application, or to auto-tune high-performance code dynamically.<p>&gt; A stand-alone low-level language. Terra was designed so that it can run independently from Lua. In fact, if your final program doesn’t need Lua, you can save Terra code into a .o file or executable. In addition to ensuring a clean separation between high- and low-level code, this design lets you use Terra as a stand-alone low-level language. In this use-case, Lua serves as a powerful meta-programming language. You can think of it as a replacement for C++ template metaprogramming or C preprocessor X-Macros4 with better syntax and nicer properties such as hygiene. Since Terra exists only as code embedded in a Lua meta-program, features that are normally built into low-level languages can be implemented as Lua libraries. This design keeps the core of Terra simple, while enabling powerful behavior such as conditional compilation, namespaces, templating, and even class systems implemented as libraries.
评论 #11056333 未加载
junkeover 9 years ago
Code: <a href="https:&#x2F;&#x2F;github.com&#x2F;deplinenoise&#x2F;c-amplify" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;deplinenoise&#x2F;c-amplify</a>
评论 #11056217 未加载
ktRolsterover 9 years ago
This quote from the article really echoes my experience:<p>&quot;Every C++ shop has its own &#x27;accepted&#x27; subset.&quot;<p>And it&#x27;s frustrating. This quote from the article too:<p><i>&quot;these are clear signs that C++ isn’t providing any real cost benefit for us, and that we should be writing code in other ways.&quot;</i>
评论 #11055647 未加载
fsaintjacquesover 9 years ago
Is debugging C++ worse than generated C code?
评论 #11054591 未加载
评论 #11054969 未加载
atilanevesover 9 years ago
&quot;compiles super fast&quot;: compared to C++, sure. But not really, no.
评论 #11054801 未加载
评论 #11055372 未加载
signa11over 9 years ago
&gt; from the article: &quot;In my prototype system, c-amplify, I’m doing exactly this. The system introduces an &quot;amplification&quot; phase where s-expressions are transformed to C code before a traditional build system runs.&quot;<p>haven&#x27;t gambit&#x2F;chicken already tried something similar for scheme ? don&#x27;t know what the latest state of affairs there is though.
rumcajzover 9 years ago
We&#x27;ve experimented extensively with code generation resulting in C and there a single most important reason why it does not work: Nobody except the authors can read and understand, let alone modify, the source code.
ctzover 9 years ago
&gt; Answer: none, they are equivalent as far as semantics go.<p>The C function does not have any defined semantics for certain values of a and b. The Common Lisp function merely adds two integers (or runs out of memory trying).
评论 #11054506 未加载
nickpsecurityover 9 years ago
I built something like this that compiled BASIC to C or C++ to avoid dealing with the later. Later re-implemented it in LISP. Doing a one-to-one mapping from LISP to 3GL code makes it easier than some here think. Using a correct-by-construction coding method eliminates a <i>lot</i> of the problems. Your code generator can also avoid C-related errors and undefined behavior wherever possible with tools available to check for most of both. Mine was a simplistic tool with very-few targets in terms of compilers. <i>Great</i> safety and productivity, though.<p>Here&#x27;s main benefits a LISP-like C can give you:<p>1. Automate boilerplate 2. Automate safety 3. 4GL-style doing very much with very little 4. Context-specific optimizations 5. My favorite: interactive testing &amp; incremental compilation for sub-1s code-to-execute and maximizing mental flow. Safe, C alternatives will probably never be able to do this. 6. Update while the system is running if still in prototyping mode. Fun stuff. 7. Save exact execution state of mock C application for debugging if you design that feature.<p>I don&#x27;t recall most of details of implementation due to a broken memory. I worked in industrial BASIC more than C because C has too many issues. However, as &quot;dang&quot; and &quot;jhack&quot; are into this, I&#x27;ll add that I did find it useful as a non-compiler-expert to setup at least two versions or states of the development environment: prototyping and production.<p>The prototyping system was designed for interactive development. It had all the libraries I might use loaded up, pre-wrapped, and with interface checks. The 3GL commands, or emulation of them, ran instantly as LISP expressions. You develop in this mode with no connection to the 3GL except logical and [mostly] semantic equivalence. Your code is straight up code at the moment.<p>When done with that, you switch to production where your code is data that&#x27;s interpreted and turned into the 3GL. The generator should take care to make portable code or at least cover your targets. Throw in out-of-bounds checks and such by default. Can have a declaration to decide that. Anyway, you get your BASIC, C, C++, whatever code here. I can even imagine one for Rust that works faster than the actual compiler.<p>So, two versions of the system: interactive interpretation, incremental compilation, and live updating of LISP version for quick development w&#x2F; optional checks inside (eg typing); version that generates code for external compilers. Both operate on same input but ignore what they don&#x27;t need. Can avoid most debugging issues with a robust, coding style and plenty interface checks. All I did with that.<p>Hope lessons from that old project helps someone doing the next. I expect if I recreate it that the Amplifying C stuff will be helpful in figuring out how to do that. So might be tools like Racket and me learning LISP <i>for real</i>. ;)
fleitzover 9 years ago
I seem to recall something about C programs becoming bug ridden implementations of half of Common Lisp
评论 #11054800 未加载
sklogicover 9 years ago
I tried &quot;amplifying&quot; C with Lisp-like syntax macros. Looks like there is a lot of potential on this route:<p><a href="https:&#x2F;&#x2F;github.com&#x2F;combinatorylogic&#x2F;clike" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;combinatorylogic&#x2F;clike</a>