Due to awkward module dependencies, some functions had to be moved around to accommodate this change. Two from Types have gone to EvalLiterals, and two to CompState. Everything still compiles just as before though.
This patch hides all the old typeOfExpression, typeOfName, typeOfVariable, etc, and unifies them into a single type-class with an "astTypeOf" function. The type-class is currently named Typed, but that can easily be changed (it's only explicitly referred to in the Types module). The patch is essentially the type-class with a giant find-and-replace on the other modules.
This makes sure that literals produced by the constant evaluator will never
contain UnknownDimension. The change looks a lot more complex than it really
is; it already carried the type "downwards", and most of this is just making it
carry it back up to where the A.Literal is being constructured.
This means you don't have to have folded constants throughout the tree/state in
order to evaluate them, which makes the early passes less awkward to manage.
The rendering code now takes the type it's aiming for, so it can produce a
value of exactly the same type as the expression that was being folded
originally (rather than trying to work it out for itself).
This touches an awful lot of code, but cgtest07/17 (arrays and retyping) pass.
This is useful because there are going to be places in the future where we'll
want to represent dimensions that are known at runtime but not at compile time
-- for example, mobile allocations, or dynamically-sized arrays. It simplifies
the code in a number of places.
However, we do now need to be careful that expressions containing variables do
not leak into the State, since they won't be affected by later passes.
Two caveats (marked as FIXMEs in the source):
- Retypes checking in the occam parser is disabled, since the plan is to move
it out to a pass anyway.
- There's some (now very obvious) duplication, particularly in the backend, of
bits of code that construct expressions for the total size of an array
(either in bytes or elements); this should be moved to a couple of helper
functions that everything can use.
ErrorReport is of type (Maybe Meta, String), thereby adding an optional code position to error messages.
Die has been changed so that die and dieP are now implemented in terms of dieReport (:: ErrorReport -> m a). This involved changing less code than changing die to be of type ErrorReport -> m a. All that had to be changed directly was that Die instances now implement dieReport instead of die.
Any bits of code that "caught" errors has been changed so that it handles ErrorReport instead of String. This ErrorReport is eventually, in Main, passed to dieIO, which will soon be changed to read the file in and provide the context. Accordingly, MonadIO m has been added as a constraint to dieIO, and dieInternal has been changed to no longer use dieIO (because really we can't add the MonadIO constraint to dieInternal).
Various error messages have been changed. Notably, all instances of fail in ParseOccam have been changed to use die or, wherever possible, dieP. A similar thing has been done in EvalConstants and EvalLiterals.
The function showCode shows code as either occam or Rain depending on the frontend. This is then used by a formatCode function that acts similar to
printf, which makes it easy to format error messages that use showCode.