Protection trait #856

Merged
merged 2 commits into from Nov 11, 2012

Projects

None yet

9 participants

@yebblies yebblies and 1 other commented on an outdated diff Apr 2, 2012
src/traits.c
@@ -206,6 +206,36 @@ static int fptraits(void *param, FuncDeclaration *f)
StringExp *se = new StringExp(loc, s->ident->toChars());
return se->semantic(sc);
}
+ else if (ident == Id::getProtection)
+ {
+
+ if (dim != 1)
+ goto Ldimerror;
+ PROT protection = PROTundefined;
+ Object *o = args->tdata()[0];
@yebblies
yebblies Apr 2, 2012 D Programming Language member

Walter will get mad if you use tdata!

@adamdruppe
adamdruppe Aug 9, 2012

(Finally looking at this again!) What should it be? Most the other code uses this same member. (I started this by copying the " else if (ident == Id::identifier)" branch)

@yebblies yebblies and 1 other commented on an outdated diff Apr 2, 2012
src/traits.c
@@ -206,6 +206,36 @@ static int fptraits(void *param, FuncDeclaration *f)
StringExp *se = new StringExp(loc, s->ident->toChars());
return se->semantic(sc);
}
+ else if (ident == Id::getProtection)
+ {
+
+ if (dim != 1)
+ goto Ldimerror;
+ PROT protection = PROTundefined;
+ Object *o = args->tdata()[0];
+ DotVarExp* d = dynamic_cast<DotVarExp*>(o);
@yebblies
yebblies Apr 2, 2012 D Programming Language member

Don't use rtti, use the methods in Object (something like isExpression/isType) to get an Expression, then check e->op == TOKdotid before doing a c-style cast.

@yebblies
yebblies Apr 2, 2012 D Programming Language member

Also, things other than DotVarExps should work with getProtection. VarExp, SymbolExp, etc.

@adamdruppe
adamdruppe Aug 9, 2012

Object doesn't have an isExpression method. Is there another way?

@yebblies yebblies and 3 others commented on an outdated diff Apr 2, 2012
src/traits.c
+ {
+ Declaration *s = d->var->isDeclaration();
+ if (s)
+ {
+ protection = s->prot();
+ }
+ }
+ const char* protName =
+ protection == PROTundefined ? ""
+ : protection == PROTnone ? "none"
+ : protection == PROTprivate ? "private"
+ : protection == PROTpackage ? "package"
+ : protection == PROTprotected ? "protected"
+ : protection == PROTpublic ? "public"
+ : protection == PROTexport ? "export"
+ : (assert(0), ""); // unknown
@yebblies
yebblies Apr 2, 2012 D Programming Language member

This should probably be a switch... and should possibly assert on 'none' as well as unknown, I think these should be replaced by the time they reach here?

@MartinNowak
MartinNowak Apr 3, 2012 D Programming Language member

Protection to chars is already duplicated in JSON and HdrGen,
you might want to merge them, see MartinNowak@f3513e6.

@9rnsr
9rnsr Sep 29, 2012 D Programming Language member

@adamdruppe , at least stop using hard tab.

@adamdruppe
adamdruppe Sep 29, 2012

On Sat, Sep 29, 2012 at 01:41:26PM -0700, Hara Kenji wrote:

@adamdruppe , at least stop using hard tab.

oh oops, I missed that one converting. My habit and editor both
use tab automatically so I type it that way then edit it later.

@MartinNowak MartinNowak and 1 other commented on an outdated diff Apr 3, 2012
src/traits.c
@@ -206,6 +206,36 @@ static int fptraits(void *param, FuncDeclaration *f)
StringExp *se = new StringExp(loc, s->ident->toChars());
return se->semantic(sc);
}
+ else if (ident == Id::getProtection)
+ {
+
+ if (dim != 1)
+ goto Ldimerror;
@MartinNowak
MartinNowak Apr 3, 2012 D Programming Language member

How about returning a tuple, so this can be used with multiple symbols?

@adamdruppe
adamdruppe Aug 9, 2012

I don't think that's needed because you can always just call it multiple times. I don't think any the other traits work that way.

@MartinNowak
Member

ping

@adamdruppe

I've been very busy the last several weeks and intend to get back
to all this stuff probably after the 15th of this month.

@andralex
Member

This is a useful trait. Ping @adamdruppe.

@adamdruppe

I went through and added some comments a while ago about details... I don't know how to solve all the comments' concerns myself.

@adamdruppe

I just pushed up some new code. I think this covers all the bases - both kinds of dot expressions and, of course, symbols. I also updated the style to match dmd git.

There's still the duplication of the protection names though. I just wanted to do one thing at a time though, we could DRY that in a separate little pull.

@ghost
ghost commented Sep 26, 2012

Considering we have the ParameterStorageClass/FunctionAttribute enums I think we should also introduce a getProtection template in std.traits which would return an enum. Internally it could do string comparisons via __traits(getProtection).

@adamdruppe

Yeah, that'd be easy enough, though we'll sadly have to find names other that "public" etc. thanks to keywords. Ugh. But the phobos change can happen after the compiler is updated.

@ghost
ghost commented Sep 27, 2012

Yup. I typically use uppercase names to avoid clashes. ParameterStorageClass uses underscores, maybe we should use that for consistency.

@ghost
ghost commented Sep 27, 2012

Btw this pull will fix an undiscovered bug in std.typecons:

module inter;

interface Inter
{
    protected void test();
}
module test;

import inter;
import std.typecons;

void main()
{
    auto o = new BlackHole!Inter;
    o.test();  // works, o.test was declared public
}

BlackHole will be able to set the right protection attribute and disallow the above from compiling. I'd imagine this pull will be welcome for these sorts of templates that deal with classes.

@andralex
Member

Great. Could you please file that so we keep track of it? Thanks!

@adamdruppe

Hmm, the autotester is saying a test fails, but it works on my box, and I don't think my changes here could be responsible anyway.

http://d.puremagic.com/test-results/pull-history.ghtml?repoid=1&pullid=856

It looks like it was passing until last night though, and I haven't changed anything.... is this something I should worry about?

@braddr
Member
braddr commented Sep 27, 2012

The master is broken, so it's not shocking that all pulls on top of that are also broken. It doesn't happen often, but when it does, it's annoying. Glare at @WalterBright for checking in broken code.

@9rnsr 9rnsr and 1 other commented on an outdated diff Sep 29, 2012
src/traits.c
+ Object *o = (*args)[0];
+ Dsymbol *s = getDsymbol(o);
+ if(!s)
+ {
+ // it might also be a trait getMember or something,
+ // which returns a dot expression rather than a symbol
+ if(o->dyncast() == DYNCAST_EXPRESSION)
+ {
+ Expression* e = (Expression*) o;
+
+ if (e->op == TOKdotvar)
+ {
+ DotVarExp *dv = (DotVarExp *)e;
+ s = dv->var->isDeclaration();
+ }
+ else if (e->op == TOKvar)
@9rnsr
9rnsr Sep 29, 2012 D Programming Language member

This is redundant code, because getDsymbol catches TOKvar.

@adamdruppe
adamdruppe Sep 29, 2012

On Sat, Sep 29, 2012 at 01:39:48PM -0700, Hara Kenji wrote:

This is redundant code, because getDsymbol catches TOKvar.

ok, removed. The DotVar one is still needed to pass the test using
traits(getMember) though.

@9rnsr 9rnsr and 1 other commented on an outdated diff Sep 29, 2012
test/compilable/traitprot.d
+class Test {
+ public int a;
+ private int b;
+ export string c;
+ protected int d;
+ package void e() {}
+}
+
+void main() {
+ Test t;
+ static assert(__traits(getProtection, __traits(getMember, t, "a")) == "public");
+ static assert(__traits(getProtection, __traits(getMember, t, "b")) == "private");
+ static assert(__traits(getProtection, __traits(getMember, t, "c")) == "export");
+ static assert(__traits(getProtection, __traits(getMember, t, "d")) == "protected");
+ static assert(__traits(getProtection, __traits(getMember, t, "e")) == "package");
+}
@9rnsr
9rnsr Sep 29, 2012 D Programming Language member

You should move this test to test/runnable/traits.d, it's a module for the __traits.

@adamdruppe
adamdruppe Sep 29, 2012

On Sat, Sep 29, 2012 at 01:42:40PM -0700, Hara Kenji wrote:

You should move this test to test/runnable/traits.d, it's a module for the __traits.

OK. It isn't actually runnable so I just made ti a function in there
to compile.

@9rnsr 9rnsr commented on an outdated diff Sep 29, 2012
test/runnable/traits.d
@@ -764,6 +764,31 @@ void test7858()
static assert(__traits(isSame, C.sfunc, __traits(getOverloads, C, "sfunc")[0])); // NG
}
+void getProtection() {
@9rnsr
9rnsr Sep 29, 2012 D Programming Language member

Please insert separator comment between each tests.

@9rnsr 9rnsr and 1 other commented on an outdated diff Sep 29, 2012
test/runnable/traits.d
+
+ Test t;
+ // should work both directly and through getMember
+ static assert(__traits(getProtection, t.a) == "public");
+ static assert(__traits(getProtection, t.b) == "private");
+ static assert(__traits(getProtection, t.c) == "export");
+ static assert(__traits(getProtection, t.d) == "protected");
+ static assert(__traits(getProtection, t.e) == "package");
+
+ static assert(__traits(getProtection, __traits(getMember, t, "a")) == "public");
+ static assert(__traits(getProtection, __traits(getMember, t, "b")) == "private");
+ static assert(__traits(getProtection, __traits(getMember, t, "c")) == "export");
+ static assert(__traits(getProtection, __traits(getMember, t, "d")) == "protected");
+ static assert(__traits(getProtection, __traits(getMember, t, "e")) == "package");
+}
+
@9rnsr
9rnsr Sep 29, 2012 D Programming Language member

More exhaustive test I think.

private   struct TestProt1 {}
package   struct TestProt2 {}
protected struct TestProt3 {}
public    struct TestProt4 {}
export    struct TestProt5 {}

void getProtection()
{
    class Test
    {
        private   { int va; void fa(){} }
        package   { int vb; void fb(){} }
        protected { int vc; void fc(){} }
        public    { int vd; void fd(){} }
        export    { int ve; void fe(){} }
    }
    Test t;

    // TOKvar and VarDeclaration
    static assert(__traits(getProtection, Test.va) == "private");
    static assert(__traits(getProtection, Test.vb) == "package");
    static assert(__traits(getProtection, Test.vc) == "protected");
    static assert(__traits(getProtection, Test.vd) == "public");
    static assert(__traits(getProtection, Test.ve) == "export");

    // TOKdotvar and VarDeclaration
    static assert(__traits(getProtection, t.va) == "private");
    static assert(__traits(getProtection, t.vb) == "package");
    static assert(__traits(getProtection, t.vc) == "protected");
    static assert(__traits(getProtection, t.vd) == "public");
    static assert(__traits(getProtection, t.ve) == "export");

    // TOKvar and FuncDeclaration
    static assert(__traits(getProtection, Test.fa) == "private");
    static assert(__traits(getProtection, Test.fb) == "package");
    static assert(__traits(getProtection, Test.fc) == "protected");
    static assert(__traits(getProtection, Test.fd) == "public");
    static assert(__traits(getProtection, Test.fe) == "export");

    // TOKdotvar and FuncDeclaration
    static assert(__traits(getProtection, t.fa) == "private");
    static assert(__traits(getProtection, t.fb) == "package");
    static assert(__traits(getProtection, t.fc) == "protected");
    static assert(__traits(getProtection, t.fd) == "public");
    static assert(__traits(getProtection, t.fe) == "export");

    // TOKtype
    static assert(__traits(getProtection, TestProt1) == "private");
    static assert(__traits(getProtection, TestProt2) == "package");
    static assert(__traits(getProtection, TestProt3) == "protected");
    static assert(__traits(getProtection, TestProt4) == "public");
    static assert(__traits(getProtection, TestProt5) == "export");
}
@adamdruppe
adamdruppe Sep 29, 2012

On Sat, Sep 29, 2012 at 02:09:53PM -0700, Hara Kenji wrote:

More exhaustive test I think.

Yes, indeed. I kept the specific getMember tests too because that implementation
might some day change, and it is important to me that this specific code works.
(I'll probably always use it in a loop with getMember in real code.)

@9rnsr
Member
9rnsr commented Sep 29, 2012

OK, now implementation looks good to me.
But, this is a language enhancement, and there is another pull request #952 for the design of protection traits feature.
So I can't merge this in my authority.
@WalterBright and @andralex , I'd like to assign this to you!

@klickverbot
Member

Maybe squash the commits together?

@adamdruppe

On Sat, Sep 29, 2012 at 02:51:27PM -0700, David Nadlinger wrote:

Maybe squash the commits together?

I have no idea how to do that.....

@adamdruppe

eh i tried it and think got some success, but it was complaining about merge conflicts and rejected non-fast-forward and other stuff. But it still builds so I'm gonna leave it here.

@nazriel
nazriel commented Oct 7, 2012

@adamdruppe if you are on IRC I can help you with it

@adamdruppe

On Sun, Oct 07, 2012 at 01:22:29PM -0700, Damian Ziemba wrote:

@adamdruppe if you are on IRC I can help you with it

I probably will be later today. Thanks!

@adamdruppe

I read some more about the git rebase and think I got it right this time. The diff looks clean now... we should be good to go.

@yebblies yebblies commented on an outdated diff Oct 10, 2012
src/traits.c
@@ -206,6 +206,59 @@ Expression *TraitsExp::semantic(Scope *sc)
StringExp *se = new StringExp(loc, s->ident->toChars());
return se->semantic(sc);
}
+ else if (ident == Id::getProtection)
+ {
+ if (dim != 1)
+ goto Ldimerror;
+ Object *o = (*args)[0];
+ Dsymbol *s = getDsymbol(o);
+ if(!s)
+ {
+ // it might also be a trait getMember or something,
+ // which returns a dot expression rather than a symbol
+ if(o->dyncast() == DYNCAST_EXPRESSION)
+ {
+ Expression* e = (Expression*) o;
@yebblies
yebblies Oct 10, 2012 D Programming Language member

Expression* e = (Expression*) o;
->
Expression *e = (Expression *)o;

@yebblies yebblies commented on an outdated diff Oct 10, 2012
src/traits.c
+ {
+ Expression* e = (Expression*) o;
+
+ if (e->op == TOKdotvar)
+ {
+ DotVarExp *dv = (DotVarExp *)e;
+ s = dv->var->isDeclaration();
+ }
+ }
+ }
+ if(!s)
+ {
+ bool gagError = false;
+ if(o->dyncast() == DYNCAST_EXPRESSION)
+ {
+ Expression* e = (Expression*) o;
@yebblies
yebblies Oct 10, 2012 D Programming Language member

Same here

@yebblies yebblies and 1 other commented on an outdated diff Oct 10, 2012
src/traits.c
+ if(o->dyncast() == DYNCAST_EXPRESSION)
+ {
+ Expression* e = (Expression*) o;
+ if(e->op == TOKerror)
+ gagError = true;
+ }
+
+ if(!gagError)
+ error("argument %s has no protection", o->toChars());
+
+ goto Lfalse;
+ }
+
+ PROT protection = s->prot();
+
+ const char* protName =
@yebblies
yebblies Oct 10, 2012 D Programming Language member

I suspect this would be much nicer as a switch.

@adamdruppe
adamdruppe Oct 14, 2012

On Wed, Oct 10, 2012 at 08:33:30AM -0700, Daniel Murphy wrote:

I suspect this would be much nicer as a switch.

Since this was duplicated a few times anyway, what I did was take the
list from json.c and move it to dsymbol.h so it is accessible globally.

Then all the various repetitions of the protection names started to use
it, following json.c's example.

So now my list is unnecessary too.

(I was planning to do this as a separate pull anyway, but I guess we can
just do it now.)

@yebblies yebblies commented on an outdated diff Oct 10, 2012
src/traits.c
+ goto Lfalse;
+ }
+
+ PROT protection = s->prot();
+
+ const char* protName =
+ protection == PROTundefined ? ""
+ : protection == PROTnone ? "none"
+ : protection == PROTprivate ? "private"
+ : protection == PROTpackage ? "package"
+ : protection == PROTprotected ? "protected"
+ : protection == PROTpublic ? "public"
+ : protection == PROTexport ? "export"
+ : (assert(0), ""); // unknown
+
+ StringExp *se = new StringExp(loc, (char*) protName);
@yebblies
yebblies Oct 10, 2012 D Programming Language member

char*
char *

@adamdruppe

We now have two commits: one is the protection trait, all changes squashed into one, and the other is removing some duplication on the protection names, by moving json.c's impl into a global area.

This should cover everyone's concerns.

@adamdruppe

Any chance we can get this pulled for the next release?

@WalterBright WalterBright merged commit 913b485 into dlang:master Nov 11, 2012

1 check failed

Details default Fail: 9
@WalterBright WalterBright added a commit that referenced this pull request Nov 11, 2012
@WalterBright WalterBright fix D2 pull #856 931d305
@WalterBright WalterBright added a commit that referenced this pull request Nov 11, 2012
@WalterBright WalterBright fix D2 pull #856 b940d6d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment