The solution is a bit hacky, but this was an important problem. If your PRAGMA failed to parse, that was worthy of a warning. But if that then caused the parse to fail, all you would get is the parser error (could not find name), and you would never see the warnings about the pragmas not being recognised. So now the pragmas are shoved into the error (using a basic encoding) and pulled out and issued if the parser dies.
The separately compiled occam PROCs now use #PRAGMA OCCAMEXTERNAL, which also discards the "= number" thing at the end. These PROCs then need to be processed differently when adding on the sizes (C externals have one size per dimension, occam externals have the normal array of sizes).
We also now record which processes were originally at the top-level, and keep their original names (i.e. minus the _u43 suffixes) plus an "occam_" prefix to avoid collisions.
With my previous change to PRAGMAs, unknown pragmas would fatally fail in the lexer, so that an unknown pragma would always stop compilation, which is not good. I've changed it more towards Adam's suggestion of re-lexing and re-parsing the pragma from the parser, so we now gracefully ignore unknown pragmas again. The lexer is a bit messy, though.
At the moment, the information is only needed in the parser, which must define recursive names before parsing the body of the function. But in future, we should keep the information when the function becomes a proc, and then the C/C++ backends may need to use it (for example, when calculating stack space usage)
For now, I have fixed the occam parser so that it allows 1 or more direction specifiers after channel names. So c?? is valid, and should end up being equivalent to c?, but this may need altering later.
This lets you write things like "[cs! FOR 5]", which is horrible; I
would prefer "[cs FOR 5]!", since then that doesn't imply that you can
do things like "cs![0] ! 0".
However, Tock now compiles and passes cgtest87 -- the first occam-pi
cgtest we've handled. :)
This is mostly straightforward: modify the parser to allow direction
decorators in the right places, and extend the type checker to match.
There's some slight awkwardness in that some of the Types functions
have to perform the same checks as the type checker (e.g. directing a
non-channel), so I've tidied up their error messages a bit.
At the backend, I've just added a little pass to strip out all the
DirectedVariables, since the other backend passes don't handle them
gracefully. From the occam/C point of view this is fine, but I'm not
sure if it's going to cause problems for C++.
Previously it was a tuple, which meant it couldn't have sensible
custom instances. Token and TokenType now have Show instances, so we
get more useful output when parsing fails.
This fixes the AST, parser and typechecker, and adds a pass to
transform Result back into Abbrev, but doesn't transform Initial yet.
(It actually works for trivial stuff anyway, but it won't do the right
thing for complex types or PROC parameters.)
It appears (to me) to make sense to support INITIAL/RESULT reshaping
and retyping too, so this does.
Refs #42.
NameType is only really needed in the parser, so this takes it out of
NameDef, meaning that later passes defining names no longer need to
set an arbitrary NameType for them. The parser gets slightly more
complicated (because some productions now have to return a SpecType
and a NameType too), but lots of other code gets simpler.
The code that removed free names was the only thing outside the parser
using NameType, and it now makes a more sensible decision based on the
SpecType. Since unscoped names previously didn't have a SpecType at
all, I've added an Unscoped constructor to it and arranged matters
such that unscoped names now get a proper entry in csNames.
Fixes#61.
This makes it possible to mark a slice as not needing runtime
checking, which is immediately useful for _sizes arrays.
This fixes cgtest03, which was previously failing to compile because
the _sizes array for one of the constants in it contained a runtime
check and thus wasn't itself constant. I've added a testcase file for
the relevant bit of code.
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.
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.