Skip to content

Commit

Permalink
add User Defined Attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright committed Nov 6, 2012
1 parent a8395d4 commit 0b6c74b
Show file tree
Hide file tree
Showing 15 changed files with 157 additions and 0 deletions.
98 changes: 98 additions & 0 deletions src/attrib.c
Expand Up @@ -1586,3 +1586,101 @@ const char *CompileDeclaration::kind()
}


/***************************** UserAttributeDeclaration *****************************/

UserAttributeDeclaration::UserAttributeDeclaration(Expressions *atts, Dsymbols *decl)
: AttribDeclaration(decl)
{
//printf("UserAttributeDeclaration()\n");
this->atts = atts;
}

Dsymbol *UserAttributeDeclaration::syntaxCopy(Dsymbol *s)
{
//printf("UserAttributeDeclaration::syntaxCopy('%s')\n", toChars());
assert(!s);
Expressions *atts = Expression::arraySyntaxCopy(this->atts);
return new UserAttributeDeclaration(atts, Dsymbol::arraySyntaxCopy(decl));
}

void UserAttributeDeclaration::semantic(Scope *sc)
{
//printf("UserAttributeDeclaration::semantic() %p\n", this);
atts = arrayExpressionSemantic(atts, sc);

if (decl)
{
Scope *newsc = sc;
#if 0
if (atts && atts->dim)
{
// create new one for changes
newsc = new Scope(*sc);
newsc->flags &= ~SCOPEfree;

// Append new atts to old one
if (!newsc->userAttributes)
newsc->userAttributes = atts;
else
newsc->userAttributes->append(atts);
}
#endif
for (size_t i = 0; i < decl->dim; i++)
{ Dsymbol *s = (*decl)[i];

s->semantic(newsc);
}
if (newsc != sc)
{
sc->offset = newsc->offset;
newsc->pop();
}
}
}

void UserAttributeDeclaration::setScope(Scope *sc)
{
//printf("UserAttributeDeclaration::setScope() %p\n", this);
if (decl)
{
Scope *newsc = sc;
#if 1
if (atts && atts->dim)
{
// create new one for changes
newsc = new Scope(*sc);
newsc->flags &= ~SCOPEfree;

// Append new atts to old one
if (!newsc->userAttributes)
newsc->userAttributes = atts;
else
newsc->userAttributes->append(atts);
}
#endif
for (size_t i = 0; i < decl->dim; i++)
{ Dsymbol *s = (*decl)[i];

s->setScope(newsc); // yes, the only difference from semantic()
}
if (newsc != sc)
{
sc->offset = newsc->offset;
newsc->pop();
}
}
}

void UserAttributeDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->writeByte('[');
argsToCBuffer(buf, atts, hgs);
AttribDeclaration::toCBuffer(buf, hgs);
}

const char *UserAttributeDeclaration::kind()
{
return "UserAttribute";
}


16 changes: 16 additions & 0 deletions src/attrib.h
Expand Up @@ -201,4 +201,20 @@ struct CompileDeclaration : AttribDeclaration
const char *kind();
};

/**
* User defined attributes look like:
* [ args, ... ]
*/
struct UserAttributeDeclaration : AttribDeclaration
{
Expressions *atts;

UserAttributeDeclaration(Expressions *atts, Dsymbols *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void setScope(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind();
};

#endif /* DMD_ATTRIB_H */
2 changes: 2 additions & 0 deletions src/class.c
Expand Up @@ -302,6 +302,7 @@ void ClassDeclaration::semantic(Scope *sc)
{
isdeprecated = true;
}
userAttributes = sc->userAttributes;

if (sc->linkage == LINKcpp)
error("cannot create C++ classes");
Expand Down Expand Up @@ -1294,6 +1295,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
{
isdeprecated = true;
}
userAttributes = sc->userAttributes;

// Expand any tuples in baseclasses[]
for (size_t i = 0; i < baseclasses->dim; )
Expand Down
5 changes: 5 additions & 0 deletions src/declaration.c
Expand Up @@ -314,6 +314,7 @@ Dsymbol *TypedefDeclaration::syntaxCopy(Dsymbol *s)
void TypedefDeclaration::semantic(Scope *sc)
{
//printf("TypedefDeclaration::semantic(%s) sem = %d\n", toChars(), sem);
userAttributes = sc->userAttributes;
if (sem == SemanticStart)
{ sem = SemanticIn;
parent = sc->parent;
Expand Down Expand Up @@ -342,6 +343,7 @@ void TypedefDeclaration::semantic(Scope *sc)
return;
}
storage_class |= sc->stc & STCdeprecated;
userAttributes = sc->userAttributes;
}
else if (sem == SemanticIn)
{
Expand Down Expand Up @@ -479,6 +481,7 @@ void AliasDeclaration::semantic(Scope *sc)

storage_class |= sc->stc & STCdeprecated;
protection = sc->protection;
userAttributes = sc->userAttributes;

// Given:
// alias foo.bar.abc def;
Expand Down Expand Up @@ -808,6 +811,8 @@ void VarDeclaration::semantic(Scope *sc)
if (storage_class & STCextern && init)
error("extern symbols cannot have initializers");

userAttributes = sc->userAttributes;

AggregateDeclaration *ad = isThis();
if (ad)
storage_class |= ad->storage_class & STC_TYPECTOR;
Expand Down
2 changes: 2 additions & 0 deletions src/dsymbol.c
Expand Up @@ -47,6 +47,7 @@ Dsymbol::Dsymbol()
this->comment = NULL;
this->scope = NULL;
this->errors = false;
this->userAttributes = NULL;
}

Dsymbol::Dsymbol(Identifier *ident)
Expand All @@ -62,6 +63,7 @@ Dsymbol::Dsymbol(Identifier *ident)
this->scope = NULL;
this->errors = false;
this->depmsg = NULL;
this->userAttributes = NULL;
}

int Dsymbol::equals(Object *o)
Expand Down
1 change: 1 addition & 0 deletions src/dsymbol.h
Expand Up @@ -123,6 +123,7 @@ struct Dsymbol : Object
Scope *scope; // !=NULL means context to use for semantic()
bool errors; // this symbol failed to pass semantic()
char *depmsg; // customized deprecation message
Expressions *userAttributes; // user defined attributes from UserAttributeDeclaration

Dsymbol();
Dsymbol(Identifier *);
Expand Down
1 change: 1 addition & 0 deletions src/enum.c
Expand Up @@ -113,6 +113,7 @@ void EnumDeclaration::semantic(Scope *sc)

if (sc->stc & STCdeprecated)
isdeprecated = 1;
userAttributes = sc->userAttributes;

parent = sc->parent;
protection = sc->protection;
Expand Down
1 change: 1 addition & 0 deletions src/expression.h
Expand Up @@ -87,6 +87,7 @@ int checkPostblit(Loc loc, Type *t);
#endif
struct ArrayExp *resolveOpDollar(Scope *sc, struct ArrayExp *ae);
struct SliceExp *resolveOpDollar(Scope *sc, struct SliceExp *se);
Expressions *arrayExpressionSemantic(Expressions *exps, Scope *sc);

/* Interpreter: what form of return value expression is required?
*/
Expand Down
1 change: 1 addition & 0 deletions src/func.c
Expand Up @@ -181,6 +181,7 @@ void FuncDeclaration::semantic(Scope *sc)
else
linkage = sc->linkage;
protection = sc->protection;
userAttributes = sc->userAttributes;

if (!originalType)
originalType = type;
Expand Down
1 change: 1 addition & 0 deletions src/idgen.c
Expand Up @@ -334,6 +334,7 @@ Msgtable msgtable[] =
{ "isSame" },
{ "compiles" },
{ "parameters" },
{ "getAttributes" },
};


Expand Down
8 changes: 8 additions & 0 deletions src/parse.c
Expand Up @@ -481,6 +481,14 @@ Dsymbols *Parser::parseDeclDefs(int once)
break;
}

case TOKlbracket:
{
Expressions *exps = parseArguments();
a = parseBlock();
s = new UserAttributeDeclaration(exps, a);
break;
}

case TOKextern:
if (peek(&token)->value != TOKlparen)
{ stc = STCextern;
Expand Down
2 changes: 2 additions & 0 deletions src/scope.c
Expand Up @@ -82,6 +82,7 @@ Scope::Scope()
this->lastdc = NULL;
this->lastoffset = 0;
this->docbuf = NULL;
this->userAttributes = NULL;
}

Scope::Scope(Scope *enclosing)
Expand Down Expand Up @@ -130,6 +131,7 @@ Scope::Scope(Scope *enclosing)
this->lastdc = NULL;
this->lastoffset = 0;
this->docbuf = enclosing->docbuf;
this->userAttributes = enclosing->userAttributes;
assert(this != enclosing);
}

Expand Down
1 change: 1 addition & 0 deletions src/scope.h
Expand Up @@ -103,6 +103,7 @@ struct Scope
#ifdef IN_GCC
Expressions *attributes; // GCC decl/type attributes
#endif
Expressions *userAttributes; // user defined attributes

DocComment *lastdc; // documentation comment for last symbol at this scope
unsigned lastoffset; // offset in docbuf of where to insert next dec
Expand Down
1 change: 1 addition & 0 deletions src/struct.c
Expand Up @@ -418,6 +418,7 @@ void StructDeclaration::semantic(Scope *sc)
assert(!isAnonymous());
if (sc->stc & STCabstract)
error("structs, unions cannot be abstract");
userAttributes = sc->userAttributes;

if (sizeok == SIZEOKnone) // if not already done the addMember step
{
Expand Down
17 changes: 17 additions & 0 deletions src/traits.c
Expand Up @@ -358,6 +358,23 @@ Expression *TraitsExp::semantic(Scope *sc)
}
return new IntegerExp(loc, cd->structsize, Type::tsize_t);
}
else if (ident == Id::getAttributes)
{
if (dim != 1)
goto Ldimerror;
Object *o = (*args)[0];
Dsymbol *s = getDsymbol(o);
if (!s)
{
error("first argument is not a symbol");
goto Lfalse;
}
//printf("getAttributes %s, %p\n", s->toChars(), s->userAttributes);
if (!s->userAttributes)
s->userAttributes = new Expressions();
TupleExp *tup = new TupleExp(loc, s->userAttributes);
return tup->semantic(sc);
}
else if (ident == Id::allMembers || ident == Id::derivedMembers)
{
if (dim != 1)
Expand Down

0 comments on commit 0b6c74b

Please sign in to comment.