On Sunday, 20 April 2014 at 15:04:28 UTC, Rikki Cattermole wrote:
On Sunday, 20 April 2014 at 14:38:47 UTC, Frustrated wrote:
On Wednesday, 16 April 2014 at 02:14:18 UTC, Walter Bright
wrote:
On 4/15/2014 6:57 PM, Mike wrote:
I suspect some of the motivation for this is to give
customers "faster horses".
I would be surprised if a @nogc attribute increased D's
appeal, and I think
efforts would be better allocated to some form of the above.
Asking for @nogc comes up *constantly*.
How bout this!
Why not allow one to define their own attributes from a
generalized subset and then define a few standard ones like
@nogc.
i.e., instead of having to define specific attributes every
few years to satisfy some new thing, why not just abstract the
process.
Attributes, I believe, are essentially relationships between
parts of code?
If so, then one simply has to implement some generic way to
specify the attributes and properties of the relationship to
the compiler. Then anyone would have the tools to define and
use these attributes as they wish. (in fact, I think it would
just involve enhancing the current attribute support, probably
just need to rewrite it all so that the same code is used for
built in attributes(@safe, @pure, etc...) and user define
attributes.
So, we just need to define the attribute name and the
properties it has such as:
Assume Y uses X in some way(function call) and X has an
attribute A defined on it:
Inheritance - Y inherits attribute A.
Exclusion - If Y has attribute B and B is mutually excluded
from A then error
Composition - If Y also uses Z and Z has attribute B then Y
has the compound attribute (A:B). Compound attributes can be
rewritten to other attributes using a grammar/reduction
scheme. Some compositions can be invalid. E.g., @nogc and @gc,
@pure and @notpure, etc...
Duality - If an attribute A is not specified for a block of
code then it's inverse attribute is implicitly specified
always. e.g., @gc and @!gc = @nogc are duals and one or the
other always is specified, even if implicit.
etc... [Note, I'm not saying all attributes have these
properties, just that these the possible properties they can
have]
By coming up with a general system(I'm sure there is some
mathematical structure that describes attributes) it would be
very easy to add attributes in the future and there would be a
consistent code backing for them. It would also be easier for
CT reflection on attributes.
Anyways, just a thought, sounds easy in theory...
Sounds like a neat idea, now for some code examples? Because it
sounds like we would need an entirely different notation
mechanism or something crazy.
Like:
struct MyPureFunction(alias MYFUNC) {
shared static this() {
registerFunc!(MYFUNC);
}
__annotation() {
static if (!is(ReturnType!MYFUNC == void)) {
return Tuple!(__annotation(pure),
__annotation(property));
} else {
return Tuple!(__anotation(pure));
}
}
}
@MyPureFunction
string mypurefunc() {
return "hi";
}
pragma(msg, mypurefunc);
I added the constructor in there because being able to run code
dependent on it would enable registering of certain types
(useful
for e.g. Cmsed so users don't have to).
This would add a new keyword (__annotation) in the same style as
__traits.
__annotation function would be called post constructor meaning
you could negate what you would normally return.
Perhaps another function !__annotation to remove current ones.
Not quite sure how this would relate to @nogc but.. Maybe it
means we can fine tune it per attribute/compiler or something.
But hey just my take.
The way I see it is that attributes, in general, are simply meta
tags applied to things. Just like tags used in audio files. You
apply tags, do things with them. You can sort them based on tag,
only play certain song with certain tags, etc...
Hence, the compiler does not to be coded for specific attributes
because attributes, in and of themselves do not need code at the
compiler level to handle them except for possibly optimizations.
In any case, there should then be a common base for
attributes(built in or user defined) that generalizes what they
are now which would also make them more powerful with a little
work.
As far as @nogc goes, I think it's probably one of the more
simpler tags in that it it only uses inheritance and logical and
composition. i.e., if all sub-attribute uses are @nogc then the
the attribute use becomes @nogc.
E.g., Q uses X, Y, Z which each have attributes x, y, z
Then Q's attribute q = (x == y == z == @nogc) ? @nogc : @gc
[To start off we could say Q's attribute q = x:y:z, a compound
attribute... and use a "grammar" to simplify q if possible. If
q's simplified compound attribute exists in the defined
attributes then processing continues until a atomic attribute is
found... of course one has to be careful with ambiguity but
probably won't ever be much of a problem]
Simple expressions and statements can also have implicitly
defined attributes.
e.g., all of D is, by default @nogc except slicing, new, etc..
The GC module then introduces the @gc attribute on some of it's
functions(not that it really matters cause usually you don't use
the gc directly but through the core features of D(slicing, new,
etc...).
If @nogc is defined as above then everything should just *work*.
The compiler will form compound attributes and simplify them and
@nogc will propagate. You would rarely ever have to explicitly
use @nogc or @gc.
Same thing would happen with @pure, @safe, etc... Using the rules
and possible some deduction the compiler could cute out most of
the work.
e.g., @pure could be automatically deduced in almost all
cases(99% of use cases) by marking everything that is no an
assignment in D as pure. Assignments may or may not be pure
depending on if they modify parent scope. The compiler determines
if they do, and if they do then it marks that assignment
@impure... then uses the same rule for combining all the
attributes as @nogc.
If the compound attribute can't be reduced. e.g., some
assignments in D can't be determined as pure or not by D, then
the pureness is unknown which results in a compound attribute
that can't be reduced... and hence the user must explicitly mark.
(e.g., using a pointer assignment which can't guarantee pureness
unless, maybe, static analysis is used to try and figure it out.
So, in D, some assignments are pure, some are impure, some are
not provably pure and some are not provably impure. In the case
of not probably pure/impure one might allow the user force the
attribute to be one or the other so the compound attribute can be
resolved. If that is not enough the user could tell the compiler
to assume the compound attribute resolves to something.
Anyways, really feels like there is some simple mathematical
structure going on here but I can't quite put my finger on it. We
have a set of attributes, a set of operators on the set of
attributes(probably just need symmetric binary operators but
would be nice to be able to handle the more general case), and
some "code" to do things with them so user defined attributes are
more useful.
For example, suppose we have a complex program with two
functions. Depending on something one function may or may not be
pure. But lets suppose there is an external reason why the other
function must always have the same pureness as the first
function. This seems like a difficult problem because it depends
on context.
If we have CT reflection of attributes and the ability to define
attributes in cool ways then
void foo() { } // pure
void bar() @@forceSame(foo, @#pureness)
{ }
where @@forceSame is an attribute meta function that takes a
symbol and a attribute group, which is the group of related
attributes, in this case @#pureness = {@pure, @impure}, and
forces bar to have the same attribute as foo that is within that
group.
D being as cool as it is, we could even execute user defined code:
void foo() { } // pureness unknown
void bar() @@execute({ if (foo:attributes.is(@pure)) @@set(bar,
@disable)}
{ }
(just pseudo code so don't get your panties in a wad, but should
be obvious, if foo is pure then bar is disabled, else it is
enabled)
Of course one can take it as far as one wants... The point is,
that we have attributes but no underlying common system which to
easily build on. Seems like every attribute added to D requires
re-implementing the wheel more or less.
If such a system was already in D, there would not be any
discussion about @nogc except possibly should it become a built
in attribute which the compiler could use for optimization
purposes.