This took sorting out a few issues with type property evaluation, but it
seems to work nicely now. Just one known error to sort out and then it's
time to get the spir-v correct.
The goal is to make it easy to get size/coord/base types from image
types without creating a zillion type functions.
It was necessary to make it possible for any type to have an attribute
function (returns an expression so it can be more useful: types are
returned via type expressions). Algebra types were the first victim
(which was nice for testing).
And disable it for GLSL. I might need to make it target-dependent
instead as I don't know if I'll be able to implement it in SPIR-V, and
when I get to the C back-end, it will be superfluous.
They should now work in generic contexts, but the pressing need to work
on arrays was due to constant expressions for element counts breaking.
As a side effect, function pointers are now a thing (and seem to work
like they do in C)
GA expressions need to be optimized so things that should cancel out do,
and this requires everything to be dagged. Doing so in expr_process gets
most of the expressions, and then a few stragglers in proc_field. There
might still be some more, but my test scene compiles again.
I suspect this is actually a bug in parameter setup for inline function
calls, but it would certainly be a bug to get an unprocessed swizzle
expression as they're generated from field expressions.
The code is pretty lousy in that it assumes there's only one `return`
and it's the end of the function, and the generated code is even worse
(too many load/store ops in the spir-v), but it looks like it at least
works. It does pass validation.
If the block's result is just a variable reference, it won't match any
expression in the block's list so it needs to be processed independently
in such cases. The `mix(genFType x, genFType y, float a)` inline now
gets as far as spir-v code gen although there are still many issues to
fix (parameter symbols, `return` handling, etc).
I decided to not mess with actual casts. In retrospect, this is probably
for the best as it avoids any bit-cast conflicts, but should allow for
block initializers with a few tweaks. `@construct (type, args...)` in
Ruamoko follows the same path as `type(args...)` in glsl.
They're buggy in that the defspaces for parameters and locals are
incorrect (they need to point to the calling scope's space). Also,
parameters are not yet hooked up correctly. However, errors (because I
need to allow casts from scalars to vectors) do get handled.
xvalue symbols refer to two expressions: an lvalue and an rvalue. They
are meant to be used with xvalue expressions.
xvalue expressions are useful when a distinction must be made between
the behavior of something (eg, a pascal function symbol) must change
depending on whether it's an lvalue (assignment of the function's return
value) or an rvalue (a call to the function, especially when the
function takes no parameters).
Because the glsl front-end uses Ruamoko to compile its builtins, it
needs to switch languages, and the cleanest way to do so is to use a
context object that gets passed around. This removes not only the
current_language global, but also (as a bonus) any real references to
flex's scanner object (there's still a pointer in rua_ctx_t, but it's no
longer a parameter (which caused some pain in the change)).
The main goal was to make it possible to give generic functions
definitions (since the code would be very dependent on the actual
parameter types), but will also allow for inline functions. It also
helped move a lot of the back-end dependent code out of semantics
processing and almost completely (if not completely) out of the parser.
Possibly more importantly, it gets the dags flushing out of the parser,
which means such is now shared by all front-ends.
There's probably a lot of dead code in expr.c now, but that can be taken
care of another time.
Arrays done via the field code since they use the same opcode and logic.
For now swizzles are just swizzles and don't support zeroing or negating
(but doing one or the other (not both) should be easy).
While storing the scope in a block was the right idea, the
implementation wasn't quite right as it resulted in the current scope
getting set at the wrong times resulting in incorrect symbol access when
shadowing was in effect.
I guess that was a mental FIXME for later, but later came sooner. The
declaration doesn't seem to be working properly, but I'll worry about
that later when I can get some automated tests going.
As I suspected, the dereference was premature, although it can act as an
optimization when multiple fields of an object are accessed, though it
won't work for writes to lvalues (which means my fixes for spir-v
code-gen currently don't work for lvalue writes). Still, progress. Need
to get field member ids set.
Now declarations can be deferred too, thus things like generic/template
and inline functions should be possible. However, the most important
thing is this is a step towards a cleaner middle layer for compilation,
separating front-end language from back-end code-gen.
I plan to do this eventually for Ruamoko, but I need it to keep working
for now; it's rather nice having multiple languages. I expect this will
open up a lot of options for inlining, generic/template function
instantiation, etc. Right now, it's helping with specialization
constants in glsl.