I have now added the capability to make this work:
proc printf: +char * ... = "printf($a);";
printf (c"%d %f %d\n",1,2.2,3);
The current code is a bit hacky to say the least :-)
Rationale: lots of C APIs use variable argument lists.
Not being able to bind them is a pain.
Intended Semantics.
================
This is a form of row polymorphism which is isomorphic to replacing
the ellipsis with a type variable, except that the replacement for
the type variable is a tuple which is expanded into its components.
A type of the form
T1 * T2 * T3 * …
may only be used as the parameter of a C function or procedure.
The function or procedure will then accept a tuple argument
whose leading components match T1, T2, T3, and may have zero,
one, or more components. The whole argument tuple is passed to
the C function.
Bugs and todos:
* This is only implemented for tuples. It doesn’t work for arrays yet.
For example this fails:
printf (c"%s %s %s\n",c"1",c"2",c"3”);
because the argument type is an array. Will be fixed shortly.
* Felix currently doesn’t type check the specified argument
in all places it should. Basically if the parameter uses an ellipsis,
any argument might work. However the unification engine DOES
make the correct checks (but also only matches tuples that aren’t arrays).
Note this form is NOT the same as varargs. As in C, varargs is a way
in a function with an ellipsis tailed parameter can capture and pass the
trailing arguments to a function using varargs.
* It isn’t supported for Felix functions.
But it might work sometimes and could be given semantics.
There is no code in the compiler that restricts anything to C functions.
An idea would simply be that a subtyping coercion is applied
which strips off the trailing components of the argument,
since there’s no name to refer to those components.
However in C, there is: varargs macros can be used to capture
the actual tuple.
In Felix, the form
T1 <**> T2
and expression
head,,tail
allows a tuple to be processed with polymorphic recursion in type classes.
This is a form of row polymorphism for tuples, which is in fact stronger
than the record form. So we could decide that using
T1 * …
actually means
T1 <**> T2
except for the problem that this polymorphic recursion requires T2 to be a tuple.
I’ll be happy at the moment if it works for C bindings.
—
John Skaller
ska...@internode.on.net