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.
Type inference and checking is now handled entirely by the later passes.
There are a few remaining places in the parser that look at the types of things
that have been defined; this is in order to resolve syntax ambiguities (e.g.
c[x], c ! x). This is a temporary measure to minimise cgtest breakage; it can't
work for things that need to be inferred (e.g. "CHAN INT c:" "d IS c:" "d !
x"), so it'll need moving out to a pass in the near future.
There's still quite a bit of work to do on this, but results so far are
encouraging: the code is an awful lot cleaner, and about four hundred lines
shorter.
This infers the types of literals and abbreviations.
This is not yet complete, but it's mostly there. I was surprised at how complex
it turned out to be, but it's significantly less awkward than having it
threaded through the parser (plus it works correctly, unlike the old code).
There are a few FIXMEs for things I've yet to implement.
Previously the parser set it to the element type, but everything that used it
set it to the type of the whole array. Now it's documented in AST.hs, and the
parser makes it the type of the whole array, since that's almost always what
you really want later on.
We now have three kinds of canned tree traversals, all of which are smart about
which types they're applied to: explicit-descent transformations,
implicit-descent transformations, and implicit-descent checks. I've only
provided depth-first application of the latter two, but we could do
breadth-first in the future if necessary.
It's redundant, since you can always compute them from the variable, and it
makes the code that deals with actuals rather cleaner.
On the other hand, it slightly complicates some of the tests, because any names
you use in an Actual need to be defined...