Visiting an Abstract Syntax Tree

New article from Pat Shaughnessy, the author of Ruby Under a Microscope

https://patshaughnessy.net/2022/1/22/visiting-an-abstract-syntax-tree

I really hope we’ll have a Crystal Under a Microscope book one day :smile:

He also asks a question from someone from the Crystal team:

This binding dependency allows Crystal to later update the type of the arr variable whenever necessary. In this case the value [12345, 67890] will always have the same type, but I suspect that sometimes the Crystal compiler can update types during semantic analysis. In this way if the Crystal compiler ever changed its mind about the type of some value, it can easy update the types of any dependent values. I also suspect Crystal uses these type dependency connections to produce error messages whenever you pass an incorrect type to some function, for example. These are just guesses, however; if anyone from the Crystal team knows exactly what these type bindings are used for let me know.

6 Likes

Here’s an example:

x = 1
while x
  a = [x]
  if x == 1
    x = "hello"
  elsif x == "hello"
    x = nil
  end
end
p! typeof(a)
p! a

It’s not enough to know what the type of [x] is on the first pass of the while loop. You need to analyze the body and types might change which might affect dependent variables. In this case a goes from Array(Int32) to being Array(Int32 | String | Nil) (I guess Nil shouldn’t form part of that, so that’s an improvement, but still…)

I’ll send a comment with a link to this post.

8 Likes

Thanks Ary for taking the time to look at this… Wow, it’s remarkable that the Crystal compiler is smart enough to recalculate types and update dependencies like this as your code iterates through a loop… at compile time! Amazing.

6 Likes

The actual type is Array(Int32 | String) | Nil (notice Nil is outside Array); x cannot be nil inside the loop, but the compiler cannot figure out that the assignment to a always happens.

Oh, thanks! I must have read the output too quickly :blush:

2 Likes