As you all probably know, I've been tinkering with the type system in Pike 7.7 for a while now, and I've now reached the point of implementing attributed types.
The question once again is "which syntax do you prefer?":
GCC-style:
void __attribute(noreturn) error(string msg); string werror(string __attribute(sprintf_format) fmt, mixed __attribute(sprintf_args) args);
or (analogous with other pike types):
__attribute(noreturn, void) throw(mixed); string werror(__attribute(sprintf_format, string) fmt, __attribute(sprintf_args, mixed) args);
noreturn as attribute looks wrong to me. Consider:
void __attribute(noreturn) error(string msg) int __attribute(noreturn) error(string msg)
For noreturn I would vote for a new keyword and do
noreturn error(string msg)
Otherwise I think I would favor method number two, but the way you show it looks very wrong. I would find string(sprintf_format) or type(string, sprintf_format) more natural.
I'm not sure it is a good idea to implement this for 7.7.
can you explain what that allows us to do?
__attribute(...) looks like a function call. what does it do? it returns a type?
do i define this function like any other and make it return types based on runtime information.?
where would this be useful? can you give an example?
greetings, martin.
As you all probably know, I've been tinkering with the type system in Pike 7.7 for a while now, and I've now reached the point of implementing attributed types.
The question once again is "which syntax do you prefer?":
GCC-style:
void __attribute(noreturn) error(string msg); string werror(string __attribute(sprintf_format) fmt, mixed __attribute(sprintf_args) ... args);
or (analogous with other pike types):
__attribute(noreturn, void) throw(mixed); string werror(__attribute(sprintf_format, string) fmt, __attribute(sprintf_args, mixed) ... args);
One alternative way would be to implement it via typedef.
Either without syntax change, and go via the type name (a bit too magic for my taste):
typedef void noreturn; typedef string sprintf_format; typedef mixed sprintf_args;
noreturn error(string msg); string werror(sprintf_format fmt, sprintf_args ... args);
Or with some extended syntax:
typedef void noreturn::noreturn; typedef string sprintf_format::sprintf_format; typedef mixed sprintf_args::sprintf_args;
noreturn error(string msg); string werror(sprintf_format fmt, sprintf_args ... args);
These alternatives have the advantage of not needing any extra keywords.
Yes, I was thinking in terms of predeclared types as well, but didn't actually come up with a proposal. I like the idea a lot since it doesn't clutter the actual code with any more syntax, so it doesn't make the code look any more difficult. In your examples you have only declared one attribute per type though. How would an integer with both foo and bar look like?
I think the __attribute syntax is a good basis because it keeps the type expressions fully generic. It's a sound design principle to allow any type to be described with a self-contained type expression. You can always put in typedefs to make things easier to read anyway:
typedef __attribute(noreturn, void) noreturn; typedef __attribute(sprintf_format, string) sprintf_format; typedef __attribute(sprintf_args, mixed) sprintf_args;
noreturn error(string msg); string werror(sprintf_format fmt, sprintf_args ... args);
Along the same vein, I think the types written by the type checker in various error messages etc should have exactly the same syntax as the types that are possible to write in Pike, to avoid confusion. And I guess this __attribute(...) syntax still would occur in such messages.
Side note: I don't think it's correct to put a "noreturn" property on a void type. That's a concept that only can be applied to a function, not to a type. I.e. it would rather be like this using the __attribute syntax:
__attribute(noreturn, function(string:void))
It's unfortunately not syntactically possible to associate anything with the function itself in the normal function declaration syntax. In the long run it'd be nice to have a syntax for that, so we can add a whole lot of attributes to functions (or declarations in general, for that matter) without introducing new keywords for all of them.
I believe C# has a syntax for that which looks something like this:
[noreturn, synchronized, foo, bar, blah(attributes, can, take, args, too)] int my_little_function (int a) { ... }
Also, __attribute could be used to declare object variables as weak:
__attribute(weak, Foo) weak_foo_ref;
Currently one has to wrap the reference in an array to achieve this:
array(Foo) indirect_weak_foo_ref = set_weak_flag (({0}), 1);
Essentially all the low level support for weak flags on object variables has been there for a long time; it's only the syntax bit that's missing.
As opposed to sprintf_format et al, typedefs don't work very well in this case. It'd be very clumsy since you'd have to write a new typedef for essentially every variable.
I wouldn't mind a more brief syntax than __attribute(a,b) though. Maybe the C#-style [...] is difficult to get into the parser, but what about e.g. [[...]]?
[[noreturn]] void error(string msg); string werror([[sprintf_format]] string fmt, [[sprintf_args]] mixed ... args); [[weak]] Foo weak_foo_ref;
Not implying that some typedefs wouldn't improve the sprintf_format case still, of course.
pike-devel@lists.lysator.liu.se