Mercurial > projects > ddmd
annotate dmd/DelegateExp.d @ 192:eb38fdcb3e62 default tip
updated to compile with dmd2.062
author | korDen |
---|---|
date | Sat, 02 Mar 2013 01:25:52 -0800 |
parents | b0d41ff5e0df |
children |
rev | line source |
---|---|
72 | 1 module dmd.DelegateExp; |
2 | |
114 | 3 import dmd.common; |
72 | 4 import dmd.Expression; |
0 | 5 import dmd.backend.elem; |
72 | 6 import dmd.AggregateDeclaration; |
0 | 7 import dmd.UnaExp; |
72 | 8 import dmd.TypeDelegate; |
9 import dmd.FuncDeclaration; | |
179 | 10 import dmd.InterState; |
72 | 11 import dmd.MATCH; |
12 import dmd.Type; | |
13 import dmd.OutBuffer; | |
0 | 14 import dmd.Loc; |
72 | 15 import dmd.TY; |
16 import dmd.Scope; | |
17 import dmd.InlineCostState; | |
0 | 18 import dmd.IRState; |
72 | 19 import dmd.PREC; |
20 import dmd.HdrGenState; | |
0 | 21 import dmd.TOK; |
22 | |
23 import dmd.expression.Util; | |
24 import dmd.codegen.Util; | |
25 import dmd.backend.Util; | |
26 import dmd.backend.Symbol; | |
27 import dmd.backend.TYM; | |
72 | 28 import dmd.backend.OPER; |
29 | |
187
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
179
diff
changeset
|
30 import dmd.DDMDExtensions; |
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
179
diff
changeset
|
31 |
0 | 32 class DelegateExp : UnaExp |
33 { | |
187
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
179
diff
changeset
|
34 mixin insertMemberExtension!(typeof(this)); |
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
179
diff
changeset
|
35 |
0 | 36 FuncDeclaration func; |
73 | 37 bool hasOverloads; |
0 | 38 |
73 | 39 this(Loc loc, Expression e, FuncDeclaration f, bool hasOverloads = false) |
72 | 40 { |
178 | 41 register(); |
0 | 42 super(loc, TOK.TOKdelegate, DelegateExp.sizeof, e); |
43 this.func = f; | |
44 this.hasOverloads = hasOverloads; | |
45 } | |
46 | |
72 | 47 override Expression semantic(Scope sc) |
0 | 48 { |
49 version (LOGSEMANTIC) { | |
50 printf("DelegateExp.semantic('%s')\n", toChars()); | |
51 } | |
52 if (!type) | |
53 { | |
54 e1 = e1.semantic(sc); | |
55 type = new TypeDelegate(func.type); | |
56 type = type.semantic(loc, sc); | |
57 AggregateDeclaration ad = func.toParent().isAggregateDeclaration(); | |
58 if (func.needThis()) | |
59 e1 = getRightThis(loc, sc, ad, e1, func); | |
60 } | |
61 return this; | |
62 } | |
179 | 63 |
192 | 64 override Expression interpret(InterState istate) |
179 | 65 { |
66 version (LOG) { | |
67 printf("DelegateExp::interpret() %s\n", toChars()); | |
68 } | |
69 return this; | |
70 } | |
0 | 71 |
72 | 72 override MATCH implicitConvTo(Type t) |
0 | 73 { |
74 static if (false) { | |
75 printf("DelegateExp.implicitConvTo(this=%s, type=%s, t=%s)\n", | |
76 toChars(), type.toChars(), t.toChars()); | |
77 } | |
78 MATCH result; | |
79 | |
80 result = type.implicitConvTo(t); | |
81 | |
82 if (result == MATCHnomatch) | |
83 { | |
84 // Look for pointers to functions where the functions are overloaded. | |
85 FuncDeclaration f; | |
86 | |
87 t = t.toBasetype(); | |
88 if (type.ty == Tdelegate && type.nextOf().ty == Tfunction && | |
89 t.ty == Tdelegate && t.nextOf().ty == Tfunction) | |
90 { | |
91 if (func && func.overloadExactMatch(t.nextOf())) | |
92 result = MATCHexact; | |
93 } | |
94 } | |
95 return result; | |
96 } | |
97 | |
72 | 98 override Expression castTo(Scope sc, Type t) |
0 | 99 { |
100 static if (false) { | |
101 printf("DelegateExp.castTo(this=%s, type=%s, t=%s)\n", | |
102 toChars(), type.toChars(), t.toChars()); | |
103 } | |
175 | 104 enum string msg = "cannot form delegate due to covariant return type"; |
0 | 105 |
106 Expression e = this; | |
107 Type tb = t.toBasetype(); | |
108 Type typeb = type.toBasetype(); | |
109 if (tb != typeb) | |
110 { | |
111 // Look for delegates to functions where the functions are overloaded. | |
112 FuncDeclaration f; | |
113 | |
114 if (typeb.ty == Tdelegate && typeb.nextOf().ty == Tfunction && | |
115 tb.ty == Tdelegate && tb.nextOf().ty == Tfunction) | |
116 { | |
117 if (func) | |
118 { | |
119 f = func.overloadExactMatch(tb.nextOf()); | |
120 if (f) | |
121 { | |
122 int offset; | |
123 if (f.tintro && f.tintro.nextOf().isBaseOf(f.type.nextOf(), &offset) && offset) | |
124 error("%s", msg); | |
125 f.tookAddressOf++; | |
126 e = new DelegateExp(loc, e1, f); | |
127 e.type = t; | |
128 return e; | |
129 } | |
130 if (func.tintro) | |
131 error("%s", msg); | |
132 } | |
133 } | |
134 e = Expression.castTo(sc, t); | |
135 } | |
136 else | |
137 { | |
138 int offset; | |
139 | |
140 func.tookAddressOf++; | |
141 if (func.tintro && func.tintro.nextOf().isBaseOf(func.type.nextOf(), &offset) && offset) | |
142 error("%s", msg); | |
143 e = copy(); | |
144 e.type = t; | |
145 } | |
146 return e; | |
147 } | |
148 | |
72 | 149 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 150 { |
151 buf.writeByte('&'); | |
152 if (!func.isNested()) | |
153 { | |
154 expToCBuffer(buf, hgs, e1, PREC.PREC_primary); | |
155 buf.writeByte('.'); | |
156 } | |
157 buf.writestring(func.toChars()); | |
158 } | |
159 | |
72 | 160 override void dump(int indent) |
0 | 161 { |
162 assert(false); | |
163 } | |
164 | |
72 | 165 override int inlineCost(InlineCostState* ics) |
0 | 166 { |
167 assert(false); | |
168 } | |
169 | |
72 | 170 override elem* toElem(IRState* irs) |
0 | 171 { |
172 elem* e; | |
173 elem* ethis; | |
174 elem* ep; | |
175 Symbol* sfunc; | |
176 int directcall = 0; | |
177 | |
178 //printf("DelegateExp.toElem() '%s'\n", toChars()); | |
179 sfunc = func.toSymbol(); | |
180 if (func.isNested()) | |
181 { | |
182 ep = el_ptr(sfunc); | |
183 ethis = getEthis(loc, irs, func); | |
184 } | |
185 else | |
186 { | |
187 ethis = e1.toElem(irs); | |
188 if (e1.type.ty != Tclass && e1.type.ty != Tpointer) | |
189 ethis = addressElem(ethis, e1.type); | |
190 | |
191 if (e1.op == TOKsuper) | |
192 directcall = 1; | |
193 | |
194 if (!func.isThis()) | |
195 error("delegates are only for non-static functions"); | |
196 | |
197 if (!func.isVirtual() || | |
198 directcall || | |
199 func.isFinal()) | |
200 { | |
201 ep = el_ptr(sfunc); | |
202 } | |
203 else | |
204 { | |
205 // Get pointer to function out of virtual table | |
206 assert(ethis); | |
207 ep = el_same(ðis); | |
208 ep = el_una(OPind, TYnptr, ep); | |
209 uint vindex = func.vtblIndex; | |
210 | |
211 // Build *(ep + vindex * 4) | |
212 ep = el_bin(OPadd,TYnptr,ep,el_long(TYint, vindex * 4)); | |
213 ep = el_una(OPind,TYnptr,ep); | |
214 } | |
215 | |
216 // if (func.tintro) | |
217 // func.error(loc, "cannot form delegate due to covariant return type"); | |
218 } | |
219 | |
220 if (ethis.Eoper == OPcomma) | |
221 { | |
222 ethis.E2() = el_pair(TYullong, ethis.E2, ep); | |
223 ethis.Ety = TYullong; | |
224 e = ethis; | |
225 } | |
226 else | |
227 e = el_pair(TYullong, ethis, ep); | |
228 | |
229 el_setLoc(e,loc); | |
230 | |
231 return e; | |
232 } | |
72 | 233 } |