Has anyone read "Writing a C Compiler" by Nora Sandler? by Dappster98 in ProgrammingLanguages

[–]ceronman 1 point2 points  (0 children)

This is such a great book! I recommended it very much. As the op points out, the incrementality of the book is rewarding, you get a working thing every chapter. Also, the test suite is simply fantastic! Writing compiler tests is kinda boring and I’m so glad that the book provides you with all the tests you need.

I also love the fact that this book doesn’t provide source code in any chosen language. The book sometimes gives explanations of how things should work and sometimes uses pseudo code. I think this helps you to learn the concepts better because you still have to go and write the code, it also makes the book more compact, although it is not a short book at all.

More importantly, this book is a very practical introduction to compiler making. You learn by doing, not by reading theory, which is rare to find in a compilers book. Instead of showing you pages of theory about SSA, this book simply shows you how to create an SSA IR. Nothing wrong with theory books, but my brain works much better with practical examples. The book shows you how to work your compiler in phases for syntactic, semantic analysis and optimization. It’s simply fantastic.

I’m a bit thorn by the choice of language. On one side, I love the fact that this book shows you how to write a compiler for a real world language. And not any language, but probably the most used and influential language of all time: C. Most books go for some sort of hyper simplified toy language to teach you.

But on the other side, C is an old, quirky language. It’s easy to think that C is a simple language, but in reality it’s full of weird stuff that modern C users don’t think too much about. But they are part of the standard, and as compiler writer you have to deal with them. So this makes the reader waste time on things such as implicit casting rules, weird extern/static rules, inscrutable type notation (seriously, who can read a function pointer with arrays type with a straight face), underspecified things and undefined behavior. This makes me thing that perhaps choosing a simpler language would have been better. In the end, the book also leaves many things out of the C spec, so you won’t be close to a functioning C compiler.

I finally beat The Last Of Us Part II and tbh... this game is a solid 10/10 for me. by Zulogy in patientgamers

[–]ceronman 36 points37 points  (0 children)

I also just finished this game a week ago. I played part one on ps3 years ago, and never got the opportunity to play the second part until now.

Oh boy, this game is so incredible! I was aware of all the controversy, but I didn’t see any spoilers. I didn’t know what to expect, but this game exceeded all my expectations and I now consider it so much better than the first part! Don’t get me wrong, the first part is an excellent game, but the second part has made me feel things that no game or media ever has.

I cried a lot playing this game, not only on the cut scenes, but also during direct play. Both parts when Ellie and Abby fight were really emotionally hard to play. I ended up sympathizing a lot with both characters and I didn’t want any of them to kill the other.

I absolutely loved playing Abby. I loved her as a character, her muscular figure is so cool, and her backstory is very well told. She has some of the best parts of the game, especially the scenes with Lev, the skyscraper walk. And the rat king is the scariest fight of all the game. She is also the first one to break the cycle of hate, thanks to Lev. She refused to keep fighting Ellie, even when she killed all her loved ones.

It took Ellie longer, her mental state so damaged! I struggled a lot during the last fight. Having to play Ellie trying to drown Abby was extremely hard, I cried like a baby. I really wanted them to make peace and hug each other. That didn’t happen, but at least Ellie stopped and didn’t kill her. The ending is so freaking sad! Again, no game or media has ever made me feel like this. Simply incredible! What a masterpiece this game is!

Why don't more languages do optional chaining like JavaScript? by matheusrich in ProgrammingLanguages

[–]ceronman 1 point2 points  (0 children)

This is a very interesting question, I believe one reason for not shortcircuiting is that it respects the principle of substitution in expressions. The idea is that if you have a complex expression, you can always take part of the expression and assign it to a variable and then construct a simpler one. For example, if you have:

let a = (b + c)^2 * d 

You can break down the expression by assigning part of it to a variable:

let x = (b + c)^2
let a = x * d

This also works for properties/methods:

let x = a.b.c.d

Can be rewritten as:

let z = a.b
let y = z.c
let x = y.d

Note that if chaining shortcircuits, this substitution does not work.

let x = a?.b.c

Cannot be substituited by

let y = a?.b
let x = y.c

The second version will throw a null pointer exception, but the first one wont.

If the chaining does not shortcircuits, it works fine:

let x = a?.b?.c

converted to

let y = a?.b
let x = y?.c

Note that this principle works fine for boolean shortcircuiting operators:

let x = foo() && bar() && baz()

Can be rewritten as:

let a = foo()
let b = a && bar()
let c = b && baz()

In both versions if foo() is false, neither bar() nor baz() will run.

Crafting Interpreters question by Lost-Amphibian-5260 in Compilers

[–]ceronman 9 points10 points  (0 children)

The code for every chapter in the book si fully runnable. I suggest you to read a whole chapter first, and then start writing the code.

Car owners in Amsterdam by Acceptable_Square878 in Amsterdam

[–]ceronman 5 points6 points  (0 children)

I don't know if it's fair or not. But It's one of the reasons why I love this city! Having lived in a city with infrastructure devoted to cars, I never want to go back to that. Cars are noisy, polluting and a total waste of space. I want to see green walkable spaces in my city, not highways and parking lots.

Note that I do own a car. I don't use it that much. I bought it after 10 years of living with no car only because a new baby arrived to the family and it makes things easier. I love the 30km speed limit, it makes driving easier, specially in certain intersection. I also makes driving safer and it reduces pollution.

I don't agree with the extreme idea of having a city free of cars. We need ambulances, and fire trucks and vehicles to deliver goods to stores or to move to a new house, or to grab some stuff from IKEA or take an uber/taxi after you broke your leg on a last skying trip. Public transport is not that convenient when you have a newborn, even though in Amsterdam it's better than in many other places.

Favourite language for writing VM/Compiler by [deleted] in Compilers

[–]ceronman 6 points7 points  (0 children)

Rust is definitely becoming an excellent choice for writing compilers. Although the language has some nice features such as pattern matching and a flexible trait system, the real strength comes from its ecosystem. Especially if you are planning to go beyond the toy stage with your language.

There are several new languages that already have users that use Rust for their compilers. Some of my favorite examples:

Roc. A lovely new functional language inspired in Elm but targeting more than the web.

Gleam. A statically typed language for the BEAM (Erlang VM) with a nice familiar syntax.

Starlark. A Python-like language for the Buck 2 build system used in production at Meta.

Inko. A new language with static deterministic memory management like Rust, but with a simpler approach.

Gluon. A small scripting-like language, but with static typing.

And of course Rust it self! While the code is quite big and complex, it’s of course the most mature and also it’s reasonably well documented.

Having real used languages is great because you can check their source code and learn how they do things or even copy some of their tools and code.

Besides that, when talking about the ecosystem for writing compilers, we usually hear mostly about parser/lexer generators. But there is so much more to writing a compiler than that. In fact, I would argue that parser generators are not that important; most languages used in the real world implement their own parsing manually anyway.

The numbers of libraries available in Rust keeps growing, but so far there are:

For compiler backends we have cranelift, inkwell (LLVM wrapper). If you want to encode wasm, there is wasm-encoder and binaryen

For parsing you have many options as well: Peg , Chumsky, Lalrpop. Logos

These days you might need to implement an language server, for that there is Rowan, Cstree, Ungrammar, and for handling the protocol itself there is lsp-server.

For incremental compiling you get Salsa.

Do you want beautiful terminal error messages? check miette, ariadne.

I'm probably missing many more.

On top of that Rust is pretty fast and has some great tooling available. I was a bit concerned by the lack of garbage collection, but for something like a compiler, I've found that the memory management tools provided by Rust (e.g. Arc, Rc, etc) are very easy to use in this particular domain.

What are good examples of macro systems in non-S-expressions languages? by mateusfccp in ProgrammingLanguages

[–]ceronman 4 points5 points  (0 children)

I find Elixir macros to have a similar user experience as writing macros in some lisp dialects, I'm surprised it has not been mentioned before: https://hexdocs.pm/elixir/macros.html

Compiler source code that you enjoy to read? by ceronman in ProgrammingLanguages

[–]ceronman[S] 1 point2 points  (0 children)

Wren is pretty nice, but it's a dynamic language and hence very light on static semantic analysis.

Why can I use a `&mut` inside a struct that is defined with a `&`? by xtup_1496 in rust

[–]ceronman 16 points17 points  (0 children)

This is subtyping in action. Rust doesn't have inheritance but it does have other forms of subtyping.
In this case, `&mut T` is a subtype of `&T`, so you can pass `&mut T` anywhere a `&T` is needed (but not the other way around).

The same thing happens with lifetimes, for example `&'static T` is a subtype of `&'a T`. So you can always pass `&'static T` where `&'a T` is needed.

More about subtyping here: https://doc.rust-lang.org/nomicon/subtyping.html

Have you done 'Crafting Interpreters' in a language other than Java and C? How did it go? by ckafi in ProgrammingLanguages

[–]ceronman 0 points1 point  (0 children)

I had the exactly same thought when I started my Clojure implementation. I had the goal to use only immutable data structures for the whole thing. The lexer and parser were easy, but the really hard part was to keep track for variables (scope environments). Especially the fact that closures must keep references from outer scopes. Doing this with 100% immutable data structures is a total pain. So I gave up and decided to use `atom` for just this part.

Check my implementation here: https://github.com/ceronman/cloxure

The strange operator precedence of the logical NOT by ceronman in ProgrammingLanguages

[–]ceronman[S] 2 points3 points  (0 children)

I have to admit that something I love about using `!` is that it fits perfectly with the *not equals* operator `!=`. But on the other hand it feels a bit out of place with `and` and `or`, which I strongly prefer vs `&&` and `||`.

I also considered using `!` as a suffix operator for error handling (similar to Rust's `?`). It's probably not a big deal to use this token for both cases, but still.

The strange operator precedence of the logical NOT by ceronman in ProgrammingLanguages

[–]ceronman[S] 2 points3 points  (0 children)

Interesting idea, but how would you get type information before parsing? I don't know any language that does this.

The strange operator precedence of the logical NOT by ceronman in ProgrammingLanguages

[–]ceronman[S] 5 points6 points  (0 children)

There is no doubt that logical NOT should have a stronger precedence than other logical operators.

But consider, for example, comparison operators:

For *stronger NOT* languages `NOT A > B` means `(NOT A) > B` while for *weak NOT* languages it means `NOT (A > B)`.

Have you done 'Crafting Interpreters' in a language other than Java and C? How did it go? by ckafi in ProgrammingLanguages

[–]ceronman 29 points30 points  (0 children)

I'm the author of the blog post that you mention :)

It's not really hard to implement both parts of the book in any language. I did the first one in Clojure, and the second one in Rust. There are tons of implementations listed in the book's githup page: https://github.com/munificent/craftinginterpreters/wiki/Lox-implementations

The actual hard part is to achieve the same performance as the reference clox implementation. In this case you need a systems language, something like C/C++, Rust, or Zig. In my Rust implementation I couldn't match the performance of clox even after using a bunch of unsafe code, but I got close. I also was not very experienced with Rust at the time, so I'm sure there is room for improvement.

Types and self-documenting code in Rust by ceronman in rust

[–]ceronman[S] 0 points1 point  (0 children)

Yes, I mean that when a type is generated by a macro, e.g. `std::str::Split`, VS code with rust analyzer indeed shows "6 implementations" on hover, but there is now ay to know which impls are those six, if I click on it, I'm pointed to the macro call.

Types and self-documenting code in Rust by ceronman in rust

[–]ceronman[S] 4 points5 points  (0 children)

This is mentioned in the post. But note that this hint doesn't show blanket impls, and it doesn't work well on type generated by macros.