Created
August 13, 2010 13:05
-
-
Save sinfu/522842 to your computer and use it in GitHub Desktop.
トリアエーズ alias this
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git src/mtype.c src/mtype.c | |
index 0dadfc6..c046505 100644 | |
--- src/mtype.c | |
+++ src/mtype.c | |
@@ -5403,6 +5403,10 @@ d_uns64 TypeQualified::size(Loc loc) | |
* if type, *pt is set | |
*/ | |
+static Dsymbol *searchForwardedSymbol(Loc loc, Scope *sc, | |
+ AggregateDeclaration *aggr, Identifier *id); | |
+static Dsymbol *searchDotIdent(Loc loc, Scope *sc, Dsymbol *basesym, Identifier *id); | |
+ | |
void TypeQualified::resolveHelper(Loc loc, Scope *sc, | |
Dsymbol *s, Dsymbol *scopesym, | |
Expression **pe, Type **pt, Dsymbol **ps) | |
@@ -5463,13 +5467,45 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc, | |
t = s->getType(); | |
if (!t && s->isDeclaration()) | |
t = s->isDeclaration()->type; | |
+ | |
+#if 1 | |
+ // Take properties into account. | |
+ if (s->isFuncDeclaration()) | |
+ { | |
+ FuncDeclaration *fd; | |
+ | |
+ // Choose a getter property out of function's overloads. | |
+ fd = s->isFuncDeclaration(); | |
+ fd = fd->overloadResolve(loc, NULL, NULL); | |
+ if (fd) | |
+ { | |
+ TypeFunction *ft = (TypeFunction *)fd->type; | |
+ assert(ft->parameters->dim == 0); | |
+ t = ft->next; | |
+ } | |
+ } | |
+#endif | |
+ | |
if (t) | |
{ | |
- sm = t->toDsymbol(sc); | |
- if (sm) | |
- { sm = sm->search(loc, id, 0); | |
+ Dsymbol *typeSym; // symbol of the type (struct declaration for example) | |
+ | |
+ typeSym = t->toDsymbol(sc); | |
+ if (typeSym) | |
+ { sm = typeSym->search(loc, id, 0); | |
if (sm) | |
goto L2; | |
+#if 1 | |
+ // The identifier might be found in the type's alias this. | |
+ if (typeSym->isAggregateDeclaration()) | |
+ { | |
+ AggregateDeclaration *aggr = typeSym->isAggregateDeclaration(); | |
+ | |
+ sm = ::searchForwardedSymbol(loc, sc, aggr, id); | |
+ if (sm) | |
+ goto L2; | |
+ } | |
+#endif | |
} | |
//e = t->getProperty(loc, id); | |
e = new TypeExp(loc, t); | |
@@ -5581,6 +5617,108 @@ L1: | |
} | |
} | |
+/* Searches an identifier id in aggr's alias this and opDot. | |
+ * Returns a symbol of the identifier if found. | |
+ */ | |
+static Dsymbol *searchForwardedSymbol(Loc loc, Scope *sc, | |
+ AggregateDeclaration *aggr, Identifier *id) | |
+{ | |
+ assert(aggr); | |
+ assert(id); | |
+ | |
+ if (aggr->aliasthis) | |
+ { | |
+ Dsymbol *found = searchDotIdent(loc, sc, aggr->aliasthis, id); | |
+ if (found) | |
+ return found; | |
+ } | |
+ | |
+ Dsymbol *opDot = search_function(aggr, Id::opDot); | |
+ if (opDot) | |
+ { | |
+ Expression *ethis; | |
+ Expression *call; | |
+ | |
+ // Get the type of aggr.opDot() and search in the type. | |
+ ethis = new DsymbolExp(loc, aggr); | |
+ ethis = ethis->semantic(sc); | |
+ call = build_overload(loc, sc, ethis, NULL, opDot->ident, NULL); | |
+ assert(call->type); | |
+ | |
+ Dsymbol *typesym = call->type->toDsymbol(sc); | |
+ if (typesym) | |
+ { | |
+ Dsymbol *found = searchDotIdent(loc, sc, typesym, id); | |
+ if (found) | |
+ return found; | |
+ } | |
+ } | |
+ | |
+ // opDispatch is not taken into account here since it's very different from | |
+ // other forwarding mechanisms. Still, it will be handled by t->dotExp() in | |
+ // TypeQualified::resolveHelper(). | |
+ | |
+ return NULL; | |
+} | |
+ | |
+/* Takes a symbol basesym and an identifier id and sees | |
+ * if basesym.id resolves to a symbol. Returns that symbol | |
+ * if so, or returns NULL otherwise. | |
+ */ | |
+static Dsymbol *searchDotIdent(Loc loc, Scope *sc, Dsymbol *basesym, Identifier *id) | |
+{ | |
+ assert(basesym); | |
+ assert(id); | |
+ | |
+ Dsymbol *found; | |
+ | |
+ // A symbol can be found here if basesym is, for example, a template instance. | |
+ found = basesym->searchX(loc, sc, id); | |
+ if (found) | |
+ return found; | |
+ | |
+ // Let's look into the type of basesym. It may be an aggregate type and the | |
+ // identifier may be found there. | |
+ Type *basetype; | |
+ | |
+ basetype = basesym->getType(); | |
+ if (basetype == NULL) | |
+ { | |
+ Declaration *decl = basesym->isDeclaration(); | |
+ if (decl && decl->type) | |
+ basetype = decl->type; | |
+ } | |
+ | |
+ if (basetype) | |
+ { | |
+ // If basesym is a function symbol, we must choose a getter property out | |
+ // of its overloads and take the return type of the property. | |
+ if (basetype->ty == Tfunction) | |
+ { | |
+ FuncDeclaration *fd = basesym->isFuncDeclaration(); | |
+ assert(fd); | |
+ | |
+ fd = fd->overloadResolve(loc, NULL, NULL); | |
+ if (fd == NULL) | |
+ return NULL; | |
+ | |
+ TypeFunction *ft = (TypeFunction *) fd->type; | |
+ assert(ft->parameters->dim == 0); | |
+ basetype = ft->next; | |
+ } | |
+ | |
+ // Search in the type symbol (a struct declaration for example). | |
+ Dsymbol *typesym = basetype->toDsymbol(sc); | |
+ if (typesym) | |
+ { | |
+ found = typesym->searchX(loc, sc, id); | |
+ if (found) | |
+ return found; | |
+ } | |
+ } | |
+ return NULL; | |
+} | |
+ | |
/***************************** TypeIdentifier *****************************/ | |
TypeIdentifier::TypeIdentifier(Loc loc, Identifier *ident) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment