The High-level Intermediate Representation (or HIR for short) is one of the main source code representations used in the compiler. It is obtained by lowering the syntax trees (Syntree nodes) to specific HIR structures.

Most of the HIR structures do recursion by indirection through the HirMap. In particular, what they store are HirId of the inner structures, and to access their data, a reference to the HirMap is needed.

HirMap

The narxia_hir::hir_map::HirMap structure holds all the Hir structures. HirIds can be used to get references to the elements inside the HirMap, like so: hir_map.get(hir_id).

There are some specific HirId newtypes defined and used throughout the HIR, which have an added guarantee that when you try to get the elements from the HirMap using them, the result is certain to be of a given type. To do that, there are specific hir_map.get_<type>(id) functions defined on the HirMap.

Visitors

Visitors allow simple and compact ways to have access and do some computations on all nodes of a specific type in the HIR.

The narxia_hir::visitor::HirVisitor trait defines a HIR visitor. It has only 2 mandatory items: the type Strategy and the fn get_strategy():

  • the type Strategy is some type that implements narxia_hir::visitor::IdHandleStrategy.
  • the fn get_strategy() returns a value of the Strategy type, which is used to handle Ids.

Caution

Unless you understand what you’re doing, go with the default RecursiveIdHandleStrategy:

struct Vis<'hir> {
  hir_map: &'hir HirMap,
}
 
impl<'hir> HirVisitor<'hir> for Vis<'hir> {
  type Strategy = RecursiveIdHandleStrategy<'hir>;
  
  fn get_strategy(&self) -> Self::Strategy {
  	RecursiveIdHandleStrategy::new(self.hir_map)
  }
  
  // ...
}

HIR lowering

HIR lowering happens shortly after a successful parse. It represents the process of taking a Syntree node and outputting a corresponding HIR node. It is all done in the narxia_hir::lower module.