Optionally beefed-up shadowing-prevention
Nick Sabalausky
a at a.a
Wed Oct 6 18:54:09 PDT 2010
"Nick Sabalausky" <a at a.a> wrote in message
news:i8j8m6$2utp$1 at digitalmars.com...
> bearophile just put up an interesting enhancement request, and I wanted to
> discuss it, but figured this would be a better place to discuss:
>
> bearophile's original message reproduced here:
> =========================
> @outer() attribute: http://d.puremagic.com/issues/show_bug.cgi?id=5007
> ----------------------------
> Generally it's not a good practice to use global values (or values from
> outer scopes, D has nested functions too, so names may come from the outer
> function too), but passed arguments increase the amount of used stack and
> they may slow down the code a little where high-performance is very
> important.
>
> So in some situations the programmer may need to use global/outer names.
> But allowing functions to freely access global scope as in C language may
> lead to bugs, because there is no control over the flow of information
> between the subsystems of the program, and also because accidental masking
> of an outer name
> is allowed:
>
> int x = 100;
> int foo(int y) {
> int x = 5;
> return x + y; // silently uses local x
> }
> void main() {
> assert(foo(10) == 15);
> }
>
> For this (and for other purposes) D has introduced the 'pure' attribute
> for functions that disallows the access to mutable outer state. But 'pure'
> is a blunt tool, and in some situations it can't be used. To avoid bugs in
> such
> situations, caused by unwanted usage of outer state, an attribute may be
> defined, it may be named "@outer".
>
> The purpose of the (optional) @outer attribute is similar to the 'global'
> attribute in the SPARK language:
>
> # global in out CallCount;
>
> A D function that is annotated with @outer must specify all global
> variables it uses, and if each of them is just read (in), written to
> (out), or both (inout).
>
> An example of its possible syntax:
>
> int x = 100;
> int y = 200;
>
> @outer(in x, inout y)
> int foo(int z) {
> y = x + z;
> return y;
> }
>
> Here the compiler enforces that foo() uses only the x and y outer defined
> variables, that x is just read and y is both read and written inside
> foo().
> This tidies up the flow of information.
>
> The @outer attribute is optional, and you may avoid its usage in small
> script-like D programs. But in situations where the D code must be very
> reliable, a simple automatic code review tool may require the usage of
> @outer
> by all functions/methods.
>
> The @outer(...) need to be shown both in the documentation produced by -D
> and
> -X (Json too) dmd compilation switches.
> =========================
>
My thoughts:
I like the general idea, but why the need to specify the globals you're
going to use? Why not something like this:
--------------------
module foo;
int globalVar;
class Foo()
{
int instanceVar;
static int classVar;
@noshadow // Name subject to change
void bar()
{
// These are also errors as function parameters
int globalVar; // Error
int instanceVar; // Error
int classVar; // Error
globalVar = 1; // Error
instanceVar = 1; // Error
classVar = 1; // Error
.globalVar = 1; // Ok
this.instanceVar = 1; // Ok
Foo.classVar = 1; // Ok
}
}
--------------------
And, of course, let it also be used like like this:
--------------------
module foo;
@noshadow: // Applies to all code below
int globalVar;
class Foo()
{
int instanceVar;
static int classVar;
void bar()
{
// Etc...same as before
}
}
--------------------
And if tracking read/write access to globals or whatever is needed it could
be done via ddoc or the json output or some other analysis tool.
More information about the Digitalmars-d
mailing list