The new behaviour is to check that both sides of a dyadic operator have the same type. This means that multiplying time by a scalar is no longer possible, but it also means (due to the lack of checks after unification) that multiplying two lists is possible, or concatenating two integers. This needs to be fixed by adding another pass.
Instead of storing the Constr, which was messy, we now store a String (to allow comparison of constructor types during unification) and a function to reform the type at the end of the type checking.
As part of this patch I also had to provide a Data instance for TypeExp (to allow CompState to still be an instance of Data). Using IORefs is easier than STRef RealWorld, and puts everything in terms of IO (which is already in PassM) rather than ST (which would require more lifting).
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.
The types get hairier, but the code is much simpler!
I've left {check,apply}DepthM{,2} there for now, but reimplemented them in
terms of the new combinators.
Fixes#58.
This is rather more expensive than the approach it was using, but it
does the right thing for things like "3 + 4(MYINT)" and "[3, 4(MYINT)]",
and the code's actually simpler.
This isn't the right behaviour, although it's closer: what it really needs to
do is to try to infer both sides in the current (or no) context, pick the more
specific type of the two inferred, then use that to redo the other one. Yuck!
This works the same way that it used to. I did experiment with actually
defining them as Procs and Functions in the normal way, but that'd require an
awful lot of special-casing later on, and would preclude support for multiple
types in the future, so I'll keep it this way for now.
This also changes the behaviour for array literals so that the inferred type of
the first item is used as the default for the rest. This satisfies all the
cgtests except for a test in cgtest59 which does "a IS [3, 4 (type)]:", which
I've never seen in a real program, and would require a bit more complication to
handle.
Unfortunately there appears to be exactly one place you can do this, and it
turns out to be inside inferTypes (because you need to know the type of c
completely, and you can't type-infer x until you know if it's a tag or a
variable). It's definitely nicer than doing it in the parser, though.
I've also started adding "-- AMBIGUITY" comments in the parser.