Skip to content

Instantly share code, notes, and snippets.

@sinfu
Created August 13, 2010 13:05
Show Gist options
  • Save sinfu/522842 to your computer and use it in GitHub Desktop.
Save sinfu/522842 to your computer and use it in GitHub Desktop.
トリアエーズ alias this
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