Expression *ArrayExp::op_overload(Scope *sc) { //printf("ArrayExp::op_overload() (%s)\n", toChars()); AggregateDeclaration *ad = isAggregate(e1->type); if (ad) { Dsymbol *fd = search_function(ad, opId()); if (fd) { for (size_t i = 0; i < arguments->dim; i++) { Expression *x = arguments->tdata()[i]; // Create scope for '$' variable for this dimension ArrayScopeSymbol *sym = new ArrayScopeSymbol(sc, this); sym->loc = loc; sym->parent = sc->scopesym; sc = sc->push(sym); lengthVar = NULL; // Create it only if required currentDimension = i; // Dimension for $, if required x = x->semantic(sc); x = resolveProperties(sc, x); if (!x->type) error("%s has no value", x->toChars()); if (lengthVar) { // If $ was used, declare it now Expression *av = new DeclarationExp(loc, lengthVar); x = new CommaExp(0, av, x); x->semantic(sc); } arguments->tdata()[i] = x; sc = sc->pop(); } /* Rewrite op e1[arguments] as: * e1.opIndex(arguments) */ Expression *e = new DotIdExp(loc, e1, fd->ident); e = new CallExp(loc, e, arguments); e = e->semantic(sc); return e; } // Didn't find it. Forward to aliasthis if (ad->aliasthis) { /* Rewrite op(e1) as: * op(e1.aliasthis) */ UnaExp *e = (UnaExp *)syntaxCopy(); e->e1 = new DotIdExp(loc, e->e1, ad->aliasthis->ident); return e->trySemantic(sc); } } return NULL; }
/*********************************************** * This is mostly the same as UnaryExp::op_overload(), but has * a different rewrite. */ Expression *CastExp::op_overload(Scope *sc) { //printf("CastExp::op_overload() (%s)\n", toChars()); AggregateDeclaration *ad = isAggregate(e1->type); if (ad) { Dsymbol *fd = NULL; /* Rewrite as: * e1.opCast!(T)(); */ fd = search_function(ad, Id::cast); if (fd) { #if 1 // Backwards compatibility with D1 if opCast is a function, not a template if (fd->isFuncDeclaration()) { // Rewrite as: e1.opCast() return build_overload(loc, sc, e1, NULL, fd); } #endif Objects *targsi = new Objects(); targsi->push(to); Expression *e = new DotTemplateInstanceExp(loc, e1, fd->ident, targsi); e = new CallExp(loc, e); e = e->semantic(sc); return e; } // Didn't find it. Forward to aliasthis if (ad->aliasthis) { /* Rewrite op(e1) as: * op(e1.aliasthis) */ UnaExp *e = (UnaExp *)syntaxCopy(); e->e1 = new DotIdExp(loc, e->e1, ad->aliasthis->ident); return e->trySemantic(sc); } } return NULL; }
Expression *ArrayExp::op_overload(Scope *sc) { //printf("ArrayExp::op_overload() (%s)\n", toChars()); AggregateDeclaration *ad = isAggregate(e1->type); if (ad) { Dsymbol *fd = search_function(ad, opId()); if (fd) { /* Rewrite op e1[arguments] as: * e1.opIndex(arguments) */ Expression *e0 = resolveOpDollar(sc, this); Expression *e = new DotIdExp(loc, e1, fd->ident); e = new CallExp(loc, e, arguments); e = combine(e0, e); e = e->semantic(sc); return e; } // Didn't find it. Forward to aliasthis if (ad->aliasthis && this->e1->type != att1) { /* Rewrite op(e1) as: * op(e1.aliasthis) */ //printf("att arr e1 = %s\n", this->e1->type->toChars()); Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident); UnaExp *ue = (UnaExp *)copy(); if (!ue->att1 && this->e1->type->checkAliasThisRec()) ue->att1 = this->e1->type; ue->e1 = e1; return ue->trySemantic(sc); } } return NULL; }
Expression *UnaExp::op_overload(Scope *sc) { //printf("UnaExp::op_overload() (%s)\n", toChars()); #if DMDV2 if (e1->op == TOKarray) { ArrayExp *ae = (ArrayExp *)e1; ae->e1 = ae->e1->semantic(sc); ae->e1 = resolveProperties(sc, ae->e1); AggregateDeclaration *ad = isAggregate(ae->e1->type); if (ad) { /* Rewrite as: * a.opIndexUnary!("+")(args); */ Dsymbol *fd = search_function(ad, Id::opIndexUnary); if (fd) { ae = resolveOpDollar(sc, ae); Objects *tiargs = opToArg(sc, op); Expression *e = new DotTemplateInstanceExp(loc, ae->e1, fd->ident, tiargs); e = new CallExp(loc, e, ae->arguments); e = e->semantic(sc); return e; } // Didn't find it. Forward to aliasthis if (ad->aliasthis && ae->e1->type != att1) { /* Rewrite op(a[arguments]) as: * op(a.aliasthis[arguments]) */ Expression *e1 = ae->copy(); ((ArrayExp *)e1)->e1 = new DotIdExp(loc, ae->e1, ad->aliasthis->ident); UnaExp *ue = (UnaExp *)copy(); if (!ue->att1 && ae->e1->type->checkAliasThisRec()) ue->att1 = ae->e1->type; ue->e1 = e1; if (Expression *e = ue->trySemantic(sc)) return e; } att1 = NULL; } } else if (e1->op == TOKslice) { SliceExp *se = (SliceExp *)e1; se->e1 = se->e1->semantic(sc); se->e1 = resolveProperties(sc, se->e1); AggregateDeclaration *ad = isAggregate(se->e1->type); if (ad) { /* Rewrite as: * a.opSliceUnary!("+")(lwr, upr); */ Dsymbol *fd = search_function(ad, Id::opSliceUnary); if (fd) { se = resolveOpDollar(sc, se); Expressions *a = new Expressions(); assert(!se->lwr || se->upr); if (se->lwr) { a->push(se->lwr); a->push(se->upr); } Objects *tiargs = opToArg(sc, op); Expression *e = new DotTemplateInstanceExp(loc, se->e1, fd->ident, tiargs); e = new CallExp(loc, e, a); e = e->semantic(sc); return e; } // Didn't find it. Forward to aliasthis if (ad->aliasthis && se->e1->type != att1) { /* Rewrite op(a[lwr..upr]) as: * op(a.aliasthis[lwr..upr]) */ Expression *e1 = se->copy(); ((SliceExp *)e1)->e1 = new DotIdExp(loc, se->e1, ad->aliasthis->ident); UnaExp *ue = (UnaExp *)copy(); if (!ue->att1 && se->e1->type->checkAliasThisRec()) ue->att1 = se->e1->type; ue->e1 = e1; if (Expression *e = ue->trySemantic(sc)) return e; } att1 = NULL; } } #endif e1 = e1->semantic(sc); e1 = resolveProperties(sc, e1); AggregateDeclaration *ad = isAggregate(e1->type); if (ad) { Dsymbol *fd = NULL; #if 1 // Old way, kept for compatibility with D1 if (op != TOKpreplusplus && op != TOKpreminusminus) { fd = search_function(ad, opId()); if (fd) { if (op == TOKarray) { /* Rewrite op e1[arguments] as: * e1.fd(arguments) */ Expression *e = new DotIdExp(loc, e1, fd->ident); ArrayExp *ae = (ArrayExp *)this; e = new CallExp(loc, e, ae->arguments); e = e->semantic(sc); return e; } else { // Rewrite +e1 as e1.add() return build_overload(loc, sc, e1, NULL, fd); } } } #endif #if DMDV2 /* Rewrite as: * e1.opUnary!("+")(); */ fd = search_function(ad, Id::opUnary); if (fd) { Objects *tiargs = opToArg(sc, op); Expression *e = new DotTemplateInstanceExp(loc, e1, fd->ident, tiargs); e = new CallExp(loc, e); e = e->semantic(sc); return e; } // Didn't find it. Forward to aliasthis if (ad->aliasthis && this->e1->type != att1) { /* Rewrite op(e1) as: * op(e1.aliasthis) */ //printf("att una %s e1 = %s\n", Token::toChars(op), this->e1->type->toChars()); Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident); UnaExp *ue = (UnaExp *)copy(); if (!ue->att1 && this->e1->type->checkAliasThisRec()) ue->att1 = this->e1->type; ue->e1 = e1; return ue->trySemantic(sc); } #endif } return NULL; }