Mercurial > projects > ddmd
annotate dmd/Expression.d @ 16:5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
author | Robert Clipsham <robert@octarineparrot.com> |
---|---|
date | Sun, 04 Apr 2010 22:41:11 +0100 |
parents | d706d958e4e8 |
children | 460959608115 |
rev | line source |
---|---|
0 | 1 module dmd.Expression; |
2 | |
3 import dmd.Loc; | |
4 import dmd.TOK; | |
5 import dmd.Type; | |
6 import dmd.WANT; | |
7 import dmd.Scope; | |
8 import dmd.ArrayTypes; | |
9 import dmd.OutBuffer; | |
10 import dmd.HdrGenState; | |
11 import dmd.MATCH; | |
12 import dmd.IntRange; | |
13 import dmd.Dsymbol; | |
14 import dmd.FuncDeclaration; | |
15 import dmd.InterState; | |
16 import dmd.InlineCostState; | |
17 import dmd.InlineDoState; | |
18 import dmd.InlineScanState; | |
19 import dmd.Identifier; | |
20 import dmd.IRState; | |
21 import dmd.DotIdExp; | |
22 import dmd.TypeExp; | |
23 import dmd.DYNCAST; | |
24 import dmd.TY; | |
25 import dmd.CallExp; | |
26 import dmd.VarExp; | |
27 import dmd.STC; | |
28 import dmd.TemplateInstance; | |
29 import dmd.CommaExp; | |
30 import dmd.NullExp; | |
31 import dmd.AddrExp; | |
32 import dmd.ErrorExp; | |
33 import dmd.TypeStruct; | |
34 import dmd.CastExp; | |
35 import dmd.Global; | |
36 import dmd.Token; | |
37 import dmd.TypeClass; | |
38 import dmd.PtrExp; | |
39 import dmd.TypeSArray; | |
40 import dmd.TypeReference; | |
41 import dmd.Util; | |
42 import dmd.Complex; | |
43 | |
44 import dmd.backend.elem; | |
45 import dmd.backend.dt_t; | |
46 | |
4 | 47 import core.memory; |
2 | 48 |
0 | 49 import std.stdio : writef; |
50 | |
51 import std.conv; | |
52 | |
53 /* Things like: | |
54 * int.size | |
55 * foo.size | |
56 * (foo).size | |
57 * cast(foo).size | |
58 */ | |
59 | |
60 Expression typeDotIdExp(Loc loc, Type type, Identifier ident) | |
61 { | |
62 return new DotIdExp(loc, new TypeExp(loc, type), ident); | |
63 } | |
64 | |
65 /***************************************** | |
66 * Determine if 'this' is available. | |
67 * If it is, return the FuncDeclaration that has it. | |
68 */ | |
69 | |
70 FuncDeclaration hasThis(Scope sc) | |
71 { | |
72 FuncDeclaration fd; | |
73 FuncDeclaration fdthis; | |
74 | |
75 //printf("hasThis()\n"); | |
76 fdthis = sc.parent.isFuncDeclaration(); | |
77 //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis.toChars() : ""); | |
78 | |
79 // Go upwards until we find the enclosing member function | |
80 fd = fdthis; | |
81 while (1) | |
82 { | |
83 if (!fd) | |
84 { | |
85 goto Lno; | |
86 } | |
87 if (!fd.isNested()) | |
88 break; | |
89 | |
90 Dsymbol parent = fd.parent; | |
91 while (parent) | |
92 { | |
93 TemplateInstance ti = parent.isTemplateInstance(); | |
94 if (ti) | |
95 parent = ti.parent; | |
96 else | |
97 break; | |
98 } | |
99 | |
100 fd = fd.parent.isFuncDeclaration(); | |
101 } | |
102 | |
103 if (!fd.isThis()) | |
104 { | |
105 //printf("test '%s'\n", fd.toChars()); | |
106 goto Lno; | |
107 } | |
108 | |
109 assert(fd.vthis); | |
110 return fd; | |
111 | |
112 Lno: | |
113 return null; // don't have 'this' available | |
114 } | |
115 | |
116 /*************************************** | |
117 * Pull out any properties. | |
118 */ | |
119 | |
120 Expression resolveProperties(Scope sc, Expression e) | |
121 { | |
122 //printf("resolveProperties(%s)\n", e.toChars()); | |
123 if (e.type) | |
124 { | |
125 Type t = e.type.toBasetype(); | |
126 | |
127 if (t.ty == TY.Tfunction || e.op == TOK.TOKoverloadset) | |
128 { | |
129 e = new CallExp(e.loc, e); | |
130 e = e.semantic(sc); | |
131 } | |
132 | |
133 /* Look for e being a lazy parameter; rewrite as delegate call | |
134 */ | |
135 else if (e.op == TOK.TOKvar) | |
136 { VarExp ve = cast(VarExp)e; | |
137 | |
138 if (ve.var.storage_class & STC.STClazy) | |
139 { | |
140 e = new CallExp(e.loc, e); | |
141 e = e.semantic(sc); | |
142 } | |
143 } | |
144 | |
145 else if (e.op == TOK.TOKdotexp) | |
146 { | |
147 e.error("expression has no value"); | |
148 } | |
149 } | |
150 else if (e.op == TOK.TOKdottd) | |
151 { | |
152 e = new CallExp(e.loc, e); | |
153 e = e.semantic(sc); | |
154 } | |
155 | |
156 return e; | |
157 } | |
158 | |
159 class Expression | |
160 { | |
161 Loc loc; // file location | |
162 TOK op; // handy to minimize use of dynamic_cast | |
163 Type type; // !=null means that semantic() has been run | |
164 int size; // # of bytes in Expression so we can copy() it | |
165 | |
166 this(Loc loc, TOK op, int size) | |
167 { | |
168 this.loc = loc; | |
169 //writef("Expression.Expression(op = %d %s) this = %p\n", op, to!(string)(op), this); | |
170 this.op = op; | |
171 this.size = size; | |
172 type = null; | |
173 } | |
174 | |
175 int equals(Object o) | |
176 { | |
177 return this is o; | |
178 } | |
179 | |
180 /********************************* | |
181 * Does *not* do a deep copy. | |
182 */ | |
183 Expression copy() /// bad bad bad | |
184 { | |
185 Expression e; | |
186 if (!size) | |
187 { | |
188 debug { | |
189 writef("No expression copy for: %s\n", toChars()); | |
190 writef("op = %d\n", op); | |
191 dump(0); | |
192 } | |
193 assert(0); | |
194 } | |
195 auto size = this.classinfo.init.length; | |
2 | 196 auto ptr = GC.malloc(size); |
0 | 197 memcpy(ptr, cast(void*)this, size); |
198 | |
199 return cast(Expression)ptr; | |
200 } | |
201 | |
202 Expression syntaxCopy() | |
203 { | |
204 //printf("Expression::syntaxCopy()\n"); | |
205 //dump(0); | |
206 return copy(); | |
207 } | |
208 | |
209 Expression semantic(Scope sc) | |
210 { | |
211 version (LOGSEMANTIC) { | |
212 printf("Expression.semantic() %s\n", toChars()); | |
213 } | |
214 if (type) | |
215 type = type.semantic(loc, sc); | |
216 else | |
217 type = Type.tvoid; | |
218 return this; | |
219 } | |
220 | |
221 Expression trySemantic(Scope sc) | |
222 { | |
223 uint errors = global.errors; | |
224 global.gag++; | |
225 Expression e = semantic(sc); | |
226 global.gag--; | |
227 if (errors != global.errors) | |
228 { | |
229 global.errors = errors; | |
230 e = null; | |
231 } | |
232 return e; | |
233 } | |
234 | |
235 DYNCAST dyncast() { return DYNCAST.DYNCAST_EXPRESSION; } // kludge for template.isExpression() | |
236 | |
237 void print() | |
238 { | |
239 assert(false); | |
240 } | |
241 | |
242 string toChars() | |
243 { | |
244 scope OutBuffer buf = new OutBuffer(); | |
245 HdrGenState hgs; | |
246 | |
247 toCBuffer(buf, &hgs); | |
248 return buf.toChars(); | |
249 } | |
250 | |
251 void dump(int indent) | |
252 { | |
253 assert(false); | |
254 } | |
255 | |
256 void error(T...)(string format, T t) | |
257 { | |
258 .error(loc, format, t); | |
259 } | |
260 | |
261 void warning(T...)(string formar, T t) | |
262 { | |
263 .warning(loc, format, t); | |
264 } | |
265 | |
266 void rvalue() | |
267 { | |
268 if (type && type.toBasetype().ty == TY.Tvoid) | |
269 { | |
270 error("expression %s is void and has no value", toChars()); | |
271 static if (false) { | |
272 dump(0); | |
273 halt(); | |
274 } | |
275 type = Type.terror; | |
276 } | |
277 } | |
278 | |
279 static Expression combine(Expression e1, Expression e2) | |
280 { | |
281 if (e1) | |
282 { | |
283 if (e2) | |
284 { | |
285 e1 = new CommaExp(e1.loc, e1, e2); | |
286 e1.type = e2.type; | |
287 } | |
288 } | |
289 else | |
290 { | |
291 e1 = e2; | |
292 } | |
293 | |
294 return e1; | |
295 } | |
296 | |
297 static Expressions arraySyntaxCopy(Expressions exps) | |
298 { | |
299 Expressions a = null; | |
300 | |
301 if (exps) | |
302 { | |
303 a = new Expressions(); | |
304 a.setDim(exps.dim); | |
305 for (int i = 0; i < a.dim; i++) | |
306 { | |
307 Expression e = cast(Expression)exps.data[i]; | |
308 | |
309 e = e.syntaxCopy(); | |
310 a.data[i] = cast(void*)e; | |
311 } | |
312 } | |
313 return a; | |
314 } | |
315 | |
316 ulong toInteger() | |
317 { | |
318 assert(false); | |
319 } | |
320 | |
321 ulong toUInteger() | |
322 { | |
323 //printf("Expression %s\n", Token.toChars(op)); | |
324 return cast(ulong)toInteger(); | |
325 } | |
326 | |
327 real toReal() | |
328 { | |
329 assert(false); | |
330 } | |
331 | |
332 real toImaginary() | |
333 { | |
334 assert(false); | |
335 } | |
336 | |
337 Complex!(real) toComplex() | |
338 { | |
339 assert(false); | |
340 } | |
341 | |
342 void toCBuffer(OutBuffer buf, HdrGenState* hgs) | |
343 { | |
344 buf.writestring(Token.toChars(op)); | |
345 } | |
346 | |
347 void toMangleBuffer(OutBuffer buf) | |
348 { | |
349 assert(false); | |
350 } | |
351 | |
352 int isLvalue() | |
353 { | |
354 assert(false); | |
355 } | |
356 | |
357 Expression toLvalue(Scope sc, Expression e) | |
358 { | |
359 assert(false); | |
360 } | |
361 | |
362 Expression modifiableLvalue(Scope sc, Expression e) | |
363 { | |
364 //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type.toChars()); | |
365 | |
366 // See if this expression is a modifiable lvalue (i.e. not const) | |
367 version (DMDV2) { | |
368 if (type && (!type.isMutable() || !type.isAssignable())) | |
369 error("%s is not mutable", e.toChars()); | |
370 } | |
371 return toLvalue(sc, e); | |
372 } | |
373 | |
374 /************************************** | |
375 * Do an implicit cast. | |
376 * Issue error if it can't be done. | |
377 */ | |
378 Expression implicitCastTo(Scope sc, Type t) | |
379 { | |
380 //printf("Expression.implicitCastTo(%s of type %s) => %s\n", toChars(), type.toChars(), t.toChars()); | |
381 | |
382 MATCH match = implicitConvTo(t); | |
383 if (match) | |
384 { | |
385 TY tyfrom = type.toBasetype().ty; | |
386 TY tyto = t.toBasetype().ty; | |
387 | |
388 version (DMDV1) { | |
389 if (global.params.warnings && | |
390 Type.impcnvWarn[tyfrom][tyto] && | |
391 op != TOKint64) | |
392 { | |
393 Expression e = optimize(WANT.WANTflags | WANT.WANTvalue); | |
394 | |
395 if (e.op == TOK.TOKint64) | |
396 return e.implicitCastTo(sc, t); | |
397 if (tyfrom == Tint32 && (op == TOKadd || op == TOKmin || op == TOKand || op == TOKor || op == TOKxor)) | |
398 { | |
399 /* This is really only a semi-kludge fix, | |
400 * we really should look at the operands of op | |
401 * and see if they are narrower types. | |
402 * For example, b=b|b and b=b|7 and s=b+b should be allowed, | |
403 * but b=b|i should be an error. | |
404 */ | |
405 ; | |
406 } | |
407 else | |
408 { | |
409 warning("implicit conversion of expression (%s) of type %s to %s can cause loss of data", toChars(), type.toChars(), t.toChars()); | |
410 } | |
411 } | |
412 } | |
413 version (DMDV2) { | |
414 if (match == MATCH.MATCHconst && t == type.constOf()) | |
415 { | |
416 Expression e = copy(); | |
417 e.type = t; | |
418 return e; | |
419 } | |
420 } | |
421 return castTo(sc, t); | |
422 } | |
423 | |
424 Expression e = optimize(WANT.WANTflags | WANT.WANTvalue); | |
425 if (e != this) | |
426 return e.implicitCastTo(sc, t); | |
427 | |
428 static if (false) { | |
429 printf("ty = %d\n", type.ty); | |
430 print(); | |
431 type.print(); | |
432 printf("to:\n"); | |
433 t.print(); | |
434 printf("%p %p type: %s to: %s\n", type.deco, t.deco, type.deco, t.deco); | |
435 //printf("%p %p %p\n", type.nextOf().arrayOf(), type, t); | |
436 fflush(stdout); | |
437 } | |
438 if (!t.deco) { | |
439 /* Can happen with: | |
440 * enum E { One } | |
441 * class A | |
442 * { static void fork(EDG dg) { dg(E.One); } | |
443 * alias void delegate(E) EDG; | |
444 * } | |
445 * Should eventually make it work. | |
446 */ | |
447 error("forward reference to type %s", t.toChars()); | |
448 } else if (t.reliesOnTident()) { | |
449 error("forward reference to type %s", t.reliesOnTident().toChars()); | |
450 } | |
451 | |
452 error("cannot implicitly convert expression (%s) of type %s to %s", toChars(), type.toChars(), t.toChars()); | |
453 return castTo(sc, t); | |
454 } | |
455 | |
456 /******************************************* | |
457 * Return !=0 if we can implicitly convert this to type t. | |
458 * Don't do the actual cast. | |
459 */ | |
460 MATCH implicitConvTo(Type t) | |
461 { | |
462 static if (false) { | |
463 printf("Expression.implicitConvTo(this=%s, type=%s, t=%s)\n", | |
464 toChars(), type.toChars(), t.toChars()); | |
465 } | |
466 //static int nest; if (++nest == 10) halt(); | |
467 if (!type) | |
468 { | |
469 error("%s is not an expression", toChars()); | |
470 type = Type.terror; | |
471 } | |
472 Expression e = optimize(WANT.WANTvalue | WANT.WANTflags); | |
473 if (e.type == t) | |
474 return MATCH.MATCHexact; | |
475 if (e != this) | |
476 { | |
477 //printf("\toptimized to %s of type %s\n", e.toChars(), e.type.toChars()); | |
478 return e.implicitConvTo(t); | |
479 } | |
480 MATCH match = type.implicitConvTo(t); | |
481 if (match != MATCH.MATCHnomatch) | |
482 return match; | |
483 | |
484 /* See if we can do integral narrowing conversions | |
485 */ | |
486 if (type.isintegral() && t.isintegral() && | |
487 type.isTypeBasic() && t.isTypeBasic()) | |
488 { | |
489 IntRange ir = getIntRange(); | |
490 if (ir.imax <= t.sizemask()) | |
491 return MATCH.MATCHconvert; | |
492 } | |
493 | |
494 static if (false) { | |
495 Type tb = t.toBasetype(); | |
496 if (tb.ty == Tdelegate) | |
497 { | |
498 TypeDelegate td = cast(TypeDelegate)tb; | |
499 TypeFunction tf = cast(TypeFunction)td.nextOf(); | |
500 | |
501 if (!tf.varargs && !(tf.arguments && tf.arguments.dim)) | |
502 { | |
503 match = type.implicitConvTo(tf.nextOf()); | |
504 if (match) | |
505 return match; | |
506 if (tf.nextOf().toBasetype().ty == Tvoid) | |
507 return MATCH.MATCHconvert; | |
508 } | |
509 } | |
510 } | |
511 return MATCH.MATCHnomatch; | |
512 } | |
513 | |
514 IntRange getIntRange() | |
515 { | |
516 assert(false); | |
517 } | |
518 | |
519 /************************************** | |
520 * Do an explicit cast. | |
521 */ | |
522 Expression castTo(Scope sc, Type t) | |
523 { | |
524 //printf("Expression.castTo(this=%s, t=%s)\n", toChars(), t.toChars()); | |
525 static if (false) { | |
526 writef("Expression.castTo(this=%s, type=%s, t=%s)\n", | |
527 toChars(), type.toChars(), t.toChars()); | |
528 } | |
529 if (type is t) | |
530 return this; | |
531 Expression e = this; | |
532 Type tb = t.toBasetype(); | |
533 Type typeb = type.toBasetype(); | |
534 if (tb != typeb) | |
535 { | |
536 // Do (type *) cast of (type [dim]) | |
537 if (tb.ty == TY.Tpointer && typeb.ty == TY.Tsarray | |
538 ) | |
539 { | |
540 //printf("Converting [dim] to *\n"); | |
541 | |
542 if (typeb.size(loc) == 0) | |
543 e = new NullExp(loc); | |
544 else | |
545 e = new AddrExp(loc, e); | |
546 } | |
547 else { | |
548 static if (false) { | |
549 if (tb.ty == Tdelegate && type.ty != Tdelegate) | |
550 { | |
551 TypeDelegate td = cast(TypeDelegate)tb; | |
552 TypeFunction tf = cast(TypeFunction)td.nextOf(); | |
553 return toDelegate(sc, tf.nextOf()); | |
554 } | |
555 } | |
556 if (typeb.ty == TY.Tstruct) | |
557 { | |
558 TypeStruct ts = cast(TypeStruct)typeb; | |
559 if (!(tb.ty == TY.Tstruct && ts.sym == (cast(TypeStruct)tb).sym) && | |
560 ts.sym.aliasthis) | |
561 { /* Forward the cast to our alias this member, rewrite to: | |
562 * cast(to)e1.aliasthis | |
563 */ | |
564 Expression e1 = new DotIdExp(loc, this, ts.sym.aliasthis.ident); | |
565 Expression e2 = new CastExp(loc, e1, tb); | |
566 e2 = e2.semantic(sc); | |
567 return e2; | |
568 } | |
569 } | |
570 else if (typeb.ty == TY.Tclass) | |
571 { | |
572 TypeClass ts = cast(TypeClass)typeb; | |
573 if (tb.ty != TY.Tclass && ts.sym.aliasthis) | |
574 { /* Forward the cast to our alias this member, rewrite to: | |
575 * cast(to)e1.aliasthis | |
576 */ | |
577 Expression e1 = new DotIdExp(loc, this, ts.sym.aliasthis.ident); | |
578 Expression e2 = new CastExp(loc, e1, tb); | |
579 e2 = e2.semantic(sc); | |
580 return e2; | |
581 } | |
582 } | |
583 e = new CastExp(loc, e, tb); | |
584 } | |
585 } | |
586 else | |
587 { | |
588 e = e.copy(); // because of COW for assignment to e.type | |
589 } | |
590 | |
591 assert(e != this); | |
592 e.type = t; | |
593 //printf("Returning: %s\n", e.toChars()); | |
594 return e; | |
595 } | |
596 | |
597 /************************************ | |
598 * Detect cases where pointers to the stack can 'escape' the | |
599 * lifetime of the stack frame. | |
600 */ | |
601 void checkEscape() | |
602 { | |
603 } | |
604 | |
605 void checkScalar() | |
606 { | |
607 if (!type.isscalar()) | |
608 error("'%s' is not a scalar, it is a %s", toChars(), type.toChars()); | |
609 | |
610 rvalue(); | |
611 } | |
612 | |
613 void checkNoBool() | |
614 { | |
615 if (type.toBasetype().ty == TY.Tbool) | |
616 error("operation not allowed on bool '%s'", toChars()); | |
617 } | |
618 | |
619 Expression checkIntegral() | |
620 { | |
621 if (!type.isintegral()) | |
622 { | |
623 error("'%s' is not of integral type, it is a %s", toChars(), type.toChars()); | |
624 return new ErrorExp(); | |
625 } | |
626 | |
627 rvalue(); | |
628 return this; | |
629 } | |
630 | |
631 Expression checkArithmetic() | |
632 { | |
633 if (!type.isintegral() && !type.isfloating()) | |
634 { | |
635 error("'%s' is not of arithmetic type, it is a %s", toChars(), type.toChars()); | |
636 return new ErrorExp(); | |
637 } | |
638 | |
639 rvalue(); | |
640 return this; | |
641 } | |
642 | |
643 void checkDeprecated(Scope sc, Dsymbol s) | |
644 { | |
645 s.checkDeprecated(loc, sc); | |
646 } | |
647 | |
648 void checkPurity(Scope sc, FuncDeclaration f) | |
649 { | |
650 static if (true) { | |
651 if (sc.func) | |
652 { | |
653 FuncDeclaration outerfunc = sc.func; | |
654 while (outerfunc.toParent2() && outerfunc.toParent2().isFuncDeclaration()) | |
655 { | |
656 outerfunc = outerfunc.toParent2().isFuncDeclaration(); | |
657 } | |
658 if (outerfunc.isPure() && !sc.intypeof && (!f.isNested() && !f.isPure())) | |
659 error("pure function '%s' cannot call impure function '%s'\n", | |
660 sc.func.toChars(), f.toChars()); | |
661 } | |
662 } else { | |
663 if (sc.func && sc.func.isPure() && !sc.intypeof && !f.isPure()) | |
664 error("pure function '%s' cannot call impure function '%s'\n", | |
665 sc.func.toChars(), .toChars()); | |
666 } | |
667 } | |
668 | |
669 /***************************** | |
670 * Check that expression can be tested for true or false. | |
671 */ | |
672 Expression checkToBoolean() | |
673 { | |
674 // Default is 'yes' - do nothing | |
675 | |
676 debug { | |
677 if (!type) | |
678 dump(0); | |
679 } | |
680 | |
681 if (!type.checkBoolean()) | |
682 { | |
683 error("expression %s of type %s does not have a boolean value", toChars(), type.toChars()); | |
684 } | |
685 | |
686 return this; | |
687 } | |
688 | |
689 Expression checkToPointer() | |
690 { | |
691 Expression e; | |
692 Type tb; | |
693 | |
694 //printf("Expression::checkToPointer()\n"); | |
695 e = this; | |
696 | |
697 // If C static array, convert to pointer | |
698 tb = type.toBasetype(); | |
699 if (tb.ty == Tsarray) | |
700 { | |
701 TypeSArray ts = cast(TypeSArray)tb; | |
702 if (ts.size(loc) == 0) | |
703 e = new NullExp(loc); | |
704 else | |
705 e = new AddrExp(loc, this); | |
706 e.type = ts.next.pointerTo(); | |
707 } | |
708 return e; | |
709 } | |
710 | |
711 Expression addressOf(Scope sc) | |
712 { | |
713 //printf("Expression::addressOf()\n"); | |
714 Expression e = toLvalue(sc, null); | |
715 e = new AddrExp(loc, e); | |
716 e.type = type.pointerTo(); | |
717 return e; | |
718 } | |
719 | |
720 /****************************** | |
721 * If this is a reference, dereference it. | |
722 */ | |
723 Expression deref() | |
724 { | |
725 //printf("Expression::deref()\n"); | |
726 if (type.ty == TY.Treference) | |
727 { | |
728 Expression e = new PtrExp(loc, this); | |
729 e.type = (cast(TypeReference)type).next; | |
730 return e; | |
731 } | |
732 return this; | |
733 } | |
734 | |
735 /*********************************** | |
736 * Do integral promotions (convertchk). | |
737 * Don't convert <array of> to <pointer to> | |
738 */ | |
739 Expression integralPromotions(Scope sc) | |
740 { | |
741 Expression e = this; | |
742 | |
743 //printf("integralPromotions %s %s\n", e.toChars(), e.type.toChars()); | |
744 switch (type.toBasetype().ty) | |
745 { | |
746 case TY.Tvoid: | |
747 error("void has no value"); | |
748 break; | |
749 | |
750 case TY.Tint8: | |
751 case TY.Tuns8: | |
752 case TY.Tint16: | |
753 case TY.Tuns16: | |
754 case TY.Tbit: | |
755 case TY.Tbool: | |
756 case TY.Tchar: | |
757 case TY.Twchar: | |
758 e = e.castTo(sc, Type.tint32); | |
759 break; | |
760 | |
761 case TY.Tdchar: | |
762 e = e.castTo(sc, Type.tuns32); | |
763 break; | |
764 default: | |
765 break; /// | |
766 } | |
767 return e; | |
768 } | |
769 | |
770 Expression toDelegate(Scope sc, Type t) | |
771 { | |
772 assert(false); | |
773 } | |
774 | |
775 void scanForNestedRef(Scope sc) | |
776 { | |
777 assert(false); | |
778 } | |
779 | |
780 Expression optimize(int result) | |
781 { | |
782 //printf("Expression.optimize(result = x%x) %s\n", result, toChars()); | |
783 return this; | |
784 } | |
785 | |
786 Expression interpret(InterState istate) | |
787 { | |
788 assert(false); | |
789 } | |
790 | |
791 int isConst() | |
792 { | |
793 //printf("Expression::isConst(): %s\n", toChars()); | |
794 return 0; | |
795 } | |
796 | |
797 /******************************** | |
798 * Does this expression statically evaluate to a boolean TRUE or FALSE? | |
799 */ | |
800 bool isBool(bool result) | |
801 { | |
802 return false; | |
803 } | |
804 | |
805 int isBit() | |
806 { | |
807 assert(false); | |
808 } | |
809 | |
810 /******************************** | |
811 * Check for expressions that have no use. | |
812 * Input: | |
813 * flag 0 not going to use the result, so issue error message if no | |
814 * side effects | |
815 * 1 the result of the expression is used, but still check | |
816 * for useless subexpressions | |
817 * 2 do not issue error messages, just return !=0 if expression | |
818 * has side effects | |
819 */ | |
820 bool checkSideEffect(int flag) | |
821 { | |
822 if (flag == 0) | |
823 { | |
824 if (op == TOKimport) | |
825 error("%s has no effect", toChars()); | |
826 else | |
827 error("%s has no effect in expression (%s)", | |
828 | |
829 Token.toChars(op), toChars()); | |
830 } | |
831 | |
832 return false; | |
833 } | |
834 | |
835 bool canThrow() | |
836 { | |
837 version (DMDV2) { | |
838 return false; | |
839 } else { | |
840 return true; | |
841 } | |
842 } | |
843 | |
844 int inlineCost(InlineCostState* ics) | |
845 { | |
846 return 1; | |
847 } | |
848 | |
849 Expression doInline(InlineDoState ids) | |
850 { | |
851 //printf("Expression.doInline(%s): %s\n", Token.toChars(op), toChars()); | |
852 return copy(); | |
853 } | |
854 | |
855 Expression inlineScan(InlineScanState* iss) | |
856 { | |
857 return this; | |
858 } | |
859 | |
860 /*********************************** | |
861 * Determine if operands of binary op can be reversed | |
862 * to fit operator overload. | |
863 */ | |
864 | |
865 // For operator overloading | |
866 bool isCommutative() | |
867 { | |
868 return false; // default is no reverse | |
869 } | |
870 | |
871 /*********************************** | |
872 * Get Identifier for operator overload. | |
873 */ | |
874 Identifier opId() | |
875 { | |
876 assert(false); | |
877 } | |
878 | |
879 /*********************************** | |
880 * Get Identifier for reverse operator overload, | |
881 * null if not supported for this operator. | |
882 */ | |
883 Identifier opId_r() | |
884 { | |
885 return null; | |
886 } | |
887 | |
888 // For array ops | |
889 void buildArrayIdent(OutBuffer buf, Expressions arguments) | |
890 { | |
891 assert(false); | |
892 } | |
893 | |
894 Expression buildArrayLoop(Arguments fparams) | |
895 { | |
896 assert(false); | |
897 } | |
898 | |
899 // Back end | |
900 elem* toElem(IRState* irs) | |
901 { | |
902 assert(false); | |
903 } | |
904 | |
905 dt_t** toDt(dt_t** pdt) | |
906 { | |
907 assert(false); | |
908 } | |
16
5c9b78899f5d
Implemented methods for Tuples, fixed some linking issues.
Robert Clipsham <robert@octarineparrot.com>
parents:
4
diff
changeset
|
909 } |