Consider an issue like #1214, where a division produces the wrong result. To fix that issue properly, you need to know how the type checker works, how the ast to builder feeding thingy works, and how the LLVM builder works. And to make this even harder, you need to store type checking results into the AST and access them later.
An early, bad version of the new design
At first I wanted to refactor the Jou compiler so that all division stuff (except parsing) is done in the same place, let's say a function compile_division() in compiler/syntax_features/division.jou. This way you would know where to look if division doesn't work. Specifically, compile_division() would:
- type-check both operands (that is, the
a and b of a division a / b)
- figure out result type of division
- do implicit casts on the operands as needed
- generate LLVM IR
- generate hash (see
doc/compiler_internals/lazy-recompile.md)
- generate UVG (see
doc/compiler_internals/uvg.md)
But now we run into another problem: this is a lot of stuff for one function to do.
The new design
Here's what compile_division() would actually do:
- type-check both operands (that is, the
a and b of a division a / b)
- figure out result type of division
- do implicit casts on the operands as needed
- tell builder to emit a division
And here's what the builder would do when you tell it to emit a division:
- generate LLVM IR
- generate hash
- generate UVG
The same builder would generate all three at once, because I don't want to call compile_division() and other such functions multiple times.
Advantages of new design
- Very easy to find the relevant code
- We wouldn't have a file compiler/typecheck/step3_function_and_method_bodies.jou that is very long (currently 1757 lines)
Disadvantages of new design
- LLVM IR is built at the same time as the hash, so it may be built unnecessarily (probably doesn't matter, optimizing and emitting to file are much slower than building the IR)
- No longer possible for builders to avoid inlining calls to
@inline functions like the UVG builder currently does
Steps to implement new design
Consider an issue like #1214, where a division produces the wrong result. To fix that issue properly, you need to know how the type checker works, how the ast to builder feeding thingy works, and how the LLVM builder works. And to make this even harder, you need to store type checking results into the AST and access them later.
An early, bad version of the new design
At first I wanted to refactor the Jou compiler so that all division stuff (except parsing) is done in the same place, let's say a function
compile_division()incompiler/syntax_features/division.jou. This way you would know where to look if division doesn't work. Specifically,compile_division()would:aandbof a divisiona / b)doc/compiler_internals/lazy-recompile.md)doc/compiler_internals/uvg.md)But now we run into another problem: this is a lot of stuff for one function to do.
The new design
Here's what
compile_division()would actually do:aandbof a divisiona / b)And here's what the builder would do when you tell it to emit a division:
The same builder would generate all three at once, because I don't want to call
compile_division()and other such functions multiple times.Advantages of new design
Disadvantages of new design
@inlinefunctions like the UVG builder currently doesSteps to implement new design
@inlinefunctions just like all other builder stuffcompile_division()