В версии 1.4 JetBrains немного поменяли архитектуру компилятора и про это есть довольно интересный доклад (слайды). В старом компиляторе были немного срезаны углы для быстрой разработки, а в новом все по классике: фронтенд-часть с выходом промежуточного представления (по факту — AST с дополнительной информацией) и бэкенд (который отвечает за генерацию исполняемого кода).

Из интересного:

  • У языка все еще нет спецификации, покрывающей все нюансы языка. Источник правды про его работу — исходный код. Сейчас есть только черновик спецификации. Например, на момент доклада узнать, какие есть варианты смарт-кастов, можно было только из кода (хотя сейчас в спецификации довольно подробно описана куча вариантов, в том числе пример-загадка из доклада).
  • Внутри компилятора есть типы-пересечения (например, общий родитель у Int и FloatComparable<*> & Number), но они невыразимы (надеюсь, что это "пока").
  • Все if конвертируются в when, но писать лучше все равно по-человечески, ручные микрооптимизации будут только мешать компилятору.
  • В бэкенд-части компилятора есть оптимизации, но они в основном используются для того, чтобы упростить конструкции, чтобы потом JIT'у было их проще понять и оптимизировать. Однако для Native и JS есть еще свои оптимизации, их больше.

Про устройство компиляторов есть еще доклад от небезызвестного Брагилевского (но там про Haskell уже). Я слушал его вживую на конференции, и он был неплох.