Implemented via specific overloads of the function.
It's not quite working correctly in that parameter names are taken from
the declaration instead of definition. However, this seems to be an old
bug that went unnoticed due to me almost always using the same parameter
names in declaration and definition.
Also, the code in get_function() is a horrible mess.
However, the basic idea turned out to be simpler than I though (though
details of the implementation are indeed a little trickier): generic
functions are essentially prototype generators when implemented using
non-generic specialized overloads.
Ruamoko and v6(p) have their own copies despite being (currently) the
same, and spir-v's is currently empty, but now targeting spir-v doesn't
try to emit ruamoko code.
When the parameter is a reference, implicit casting is not allowed, but
when the parameter is by value and the argument is a reference, the
argument is dereferenced and promotion is allowed.
However, this covers only the selection of generic functions. It doesn't
deal with otherwise overloaded functions, nor does it do the actual
dereferencing or address taking.
I'd gotten tired of all the convoluted progs version checks, and with
the addition of spirv, they're not even always relevant, and adding C
(when I get to it) will make things even worse. However, for now the
first victim is just the parameter/return value size check.
Now, ctor expressions are collected and emitted after all other code,
and the ctor function being created outside of class_finish_module means
it's no longer limited to just class related initialization.
I don't know why I thought it was a good idea to make sy_var context
dependent. Renaming sy_var to sy_def makes it a little easier to know to
use the def field, too.
I don't yet know whether the generated code is correct, but the little
functions that compute a generic type gets stored in the function's
params/return type.
Allows the parsing of the return type in the following:
@generic(vec=[vec2,vec3,vec4]) {
@vector(bool,@width(vec)) lessThan(vec x, vec y);
}
Unfortunately, can't use math in int value parameters just yet, the
processing of expressions needs to be delayed (it's currently done
immediately so type-checking happens to early).
It's not connected up yet, but does produce what looks like the correct
code.
Now parameters can be declared `const`, `@in`, `@out`, `@inout`. `@in`
is redundant as it's the default, but I guess it's nice for
self-documenting code. `const` marks the parameter as read-only in the
function, `@out` and `@inout` allow the parameter to pass the value back
out (by copy), but `@out` does not initialize the parameter before
calling and returning without setting an `@out` parameter is an error
(but unfortunately, currently detected only when optimizing).
Unfortunately, it seems to have broken (only!) v6 progs when optimizing
as the second parameter gets optimized out.
Simply referencing the original metafunc resulted in only the first
variant getting a def. Now my little test generates defs for all called
variants of a generic function.
However, I'm still not sure this is quite the direction I want to go
with making calls to generic functions, but I still need to figure out
defining them. I think making progress with the glsl front-end will
help.
Checking only the last function to be added results in false negatives
and thus duplicates when defining a generic function. eg:
genFType radians (genFType degrees);
genDType radians (genDType degrees);
genFType radians (genFType degrees) = #0;
genDType radians (genDType degrees) = #0;
Detecting generic functions needs to be done before finalizing the
function type for non-generic functions, otherwise the resulting
function type winds up being incorrect due to bogus resolution of the
return type (and probably a few other factors).
This takes care of handling the return type in function definitions as
well as declarations as
I never did like overloaded_function_t as a name, and with the
introduction of generic functions (or templates, I guess?) meta-function
makes more sense to me.
There's still the problem of defining implementations, but this gets a
lot of things working so long as the return type is one of the parameter
types rather than computed.
A working call isn't produced yet, but the generic function does seem to
be selected correctly preferring a minimum of type promotions, though I
suspect I'll need to do more work on the selection process.
With this, genFType and genDType functions are now treated separately
and expanding to all components (single row or column matrices are not
supported (at this stage, anyway) for generic parameters).
That is, `@generic(...) { ... };`, which is handy for bulk declarations
(such as for glsl). This proved to be a lot harder than expected, I
suspect handling of specifiers needs a lot of work.
It doesn't properly differentiate between (treats genDType as being the
same as genFType):
@generic(genFType=@vector(float)) genFType radians(genFType degrees);
@generic(genDType=@vector(double)) genDType radians(genDType degrees);
but this is due to problems with how the type is built from
@vector(float) and @vector(double). However, I thought it was about time
I got some of this into git.
Also, `@generic(...) { ... };` blocks don't work properly (they lose the
generic info): need to get a little smarter about handling generic scope
in `external_def_list`.