1 // This file is part of Visual D
2 //
3 // Visual D integrates the D programming language into Visual Studio
4 // Copyright (c) 2010-2011 by Rainer Schuetze, All Rights Reserved
5 //
6 // Distributed under the Boost Software License, Version 1.0.
7 // See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt
8 
9 module vdc.ast.expr;
10 
11 import vdc.util;
12 import vdc.lexer;
13 import vdc.semantic;
14 import vdc.interpret;
15 
16 import vdc.ast.node;
17 import vdc.ast.decl;
18 import vdc.ast.misc;
19 import vdc.ast.tmpl;
20 import vdc.ast.aggr;
21 import vdc.ast.mod;
22 import vdc.ast.type;
23 import vdc.ast.writer;
24 
25 import vdc.parser.engine;
26 
27 import stdext.util;
28 import std.conv;
29 import std.string;
30 
31 ////////////////////////////////////////////////////////////////
32 // Operator precedence - greater values are higher precedence
33 enum PREC
34 {
35     zero,
36     expr,
37     assign,
38     cond,
39     oror,
40     andand,
41     or,
42     xor,
43     and,
44     equal,
45     rel,
46     shift,
47     add,
48     mul,
49     pow,
50     unary,
51     primary,
52 }
53 shared static PREC[NumTokens] precedence;
54 
55 shared static char[NumTokens] recursion;
56 
57 ////////////////////////////////////////////////////////////////
58 void writeExpr(CodeWriter writer, Expression expr, bool paren)
59 {
60     if(paren)
61         writer("(");
62     writer(expr);
63     if(paren)
64         writer(")");
65 }
66 
67 enum Spaces
68 {
69     None = 0,
70     Left = 1,
71     Right = 2,
72     LeftRight = Left | Right
73 }
74 
75 void writeOperator(CodeWriter writer, TokenId op, int spaces)
76 {
77     if(spaces & Spaces.Left)
78         writer(" ");
79     writer(op);
80     if(spaces & Spaces.Right)
81         writer(" ");
82 }
83 
84 ////////////////////////////////////////////////////////////////
85 //Expression:
86 class Expression : Node
87 {
88     // semantic data
89     Type type;
90 
91     mixin ForwardCtor!();
92 
93     abstract PREC getPrecedence();
94 
95     override Type calcType()
96     {
97         if(!type)
98             return semanticErrorType(this, ".calcType not implemented");
99         return type;
100     }
101 }
102 
103 //BinaryExpression:
104 //    [Expression Expression]
105 class BinaryExpression : Expression
106 {
107     mixin ForwardCtor!();
108 
109     TokenId getOperator() { return id; }
110     Expression getLeftExpr() { return getMember!Expression(0); }
111     Expression getRightExpr() { return getMember!Expression(1); }
112 
113     override PREC getPrecedence() { return precedence[id]; }
114     bool isAssign() { return false; }
115 
116     override void _semantic(Scope sc)
117     {
118         getLeftExpr().semantic(sc);
119         getRightExpr().semantic(sc);
120     }
121 
122     override void toD(CodeWriter writer)
123     {
124         Expression exprL = getLeftExpr();
125         Expression exprR = getRightExpr();
126 
127         bool parenL = (exprL.getPrecedence() < getPrecedence() + (recursion[id] == 'L' ? 0 : 1));
128         bool parenR = (exprR.getPrecedence() < getPrecedence() + (recursion[id] == 'R' ? 0 : 1));
129 
130         writeExpr(writer, exprL, parenL);
131         writeOperator(writer, id, Spaces.LeftRight);
132         writeExpr(writer, exprR, parenR);
133     }
134 
135     override Type calcType()
136     {
137         if(!type)
138         {
139             Type typeL = getLeftExpr().calcType();
140             Type typeR = getRightExpr().calcType();
141             type = typeL.commonType(typeR);
142         }
143         return type;
144     }
145 
146     override Value interpret(Context sc)
147     {
148         Value vL, vR;
149         if(isAssign())
150         {
151             // right side evaluated first in assignments
152             vR = getRightExpr().interpret(sc);
153             vL = getLeftExpr().interpret(sc);
154         }
155         else
156         {
157             vL = getLeftExpr().interpret(sc);
158             vR = getRightExpr().interpret(sc);
159         }
160 version(all)
161 {
162         auto btL = cast(BasicType) vL.getType();
163         auto avR = cast(ArrayValueBase) vR;
164         if(btL && avR)
165             return vR.opBin_r(sc, id, vL);
166         return vL.opBin(sc, id, vR);
167 }
168 else
169         switch(id)
170         {
171             case TOK_equal:        return vL.opBinOp!"=="(vR);
172             case TOK_notequal:  return vL.opBinOp!"!="(vR);
173             case TOK_lt:        return vL.opBinOp!"<"(vR);
174             case TOK_gt:        return vL.opBinOp!">"(vR);
175             case TOK_le:        return vL.opBinOp!"<="(vR);
176             case TOK_ge:        return vL.opBinOp!">="(vR);
177             case TOK_unord:        return vL.opBinOp!"!<>="(vR);
178             case TOK_ue:        return vL.opBinOp!"!<>"(vR);
179             case TOK_lg:        return vL.opBinOp!"<>"(vR);
180             case TOK_leg:        return vL.opBinOp!"<>="(vR);
181             case TOK_ule:        return vL.opBinOp!"!>"(vR);
182             case TOK_ul:        return vL.opBinOp!"!>="(vR);
183             case TOK_uge:        return vL.opBinOp!"!<"(vR);
184             case TOK_ug:        return vL.opBinOp!"!<="(vR);
185             case TOK_is:        return vL.opBinOp!"is"(vR);
186             case TOK_notcontains:return vL.opBinOp!"!in"(vR);
187             case TOK_notidentity:return vL.opBinOp!"!is"(vR);
188 
189             case TOK_shl:        return vL.opBinOp!"<<"(vR);
190             case TOK_shr:        return vL.opBinOp!">>"(vR);
191             case TOK_ushr:        return vL.opBinOp!">>>"(vR);
192 
193             case TOK_add:        return vL.opBinOp!"+"(vR);
194             case TOK_min:        return vL.opBinOp!"-"(vR);
195             case TOK_mul:        return vL.opBinOp!"*"(vR);
196             case TOK_pow:        return vL.opBinOp!"^^"(vR);
197 
198             case TOK_div:        return vL.opBinOp!"/"(vR);
199             case TOK_mod:        return vL.opBinOp!"%"(vR);
200     //[ "slice",            ".." ],
201     //[ "dotdotdot",        "..." ],
202             case TOK_xor:        return vL.opBinOp!"^"(vR);
203             case TOK_and:        return vL.opBinOp!"&"(vR);
204             case TOK_or:        return vL.opBinOp!"|"(vR);
205             case TOK_tilde:        return vL.opBinOp!"~"(vR);
206     //[ "plusplus",         "++" ],
207     //[ "minusminus",       "--" ],
208     //[ "question",         "?" ],
209             case TOK_assign:    return vL.opassign!"="(vR);
210             case TOK_addass:    return vL.opassign!"+="(vR);
211             case TOK_minass:    return vL.opassign!"-="(vR);
212             case TOK_mulass:    return vL.opassign!"*="(vR);
213             case TOK_powass:    return vL.opassign!"^^="(vR);
214 
215             case TOK_shlass:    return vL.opassign!"<<="(vR);
216             case TOK_shrass:    return vL.opassign!">>="(vR);
217             case TOK_ushrass:    return vL.opassign!">>>="(vR);
218             case TOK_xorass:    return vL.opassign!"^="(vR);
219             case TOK_andass:    return vL.opassign!"&="(vR);
220             case TOK_orass:        return vL.opassign!"|="(vR);
221             case TOK_catass:    return vL.opassign!"~="(vR);
222 
223             case TOK_divass:    return vL.opassign!"/="(vR);
224             case TOK_modass:    return vL.opassign!"%="(vR);
225 
226             default:
227                 return semanticErrorType("interpretation of binary operator ", tokenString(id), " not implemented");
228         }
229     }
230 
231 };
232 
233 mixin template BinaryExpr()
234 {
235     this() {} // default constructor needed for clone()
236 
237     this(Token tok)
238     {
239         super(tok);
240     }
241 }
242 
243 class CommaExpression : BinaryExpression
244 {
245     mixin BinaryExpr!();
246 
247     override Type calcType()
248     {
249         return getRightExpr().calcType();
250     }
251 }
252 
253 class AssignExpression : BinaryExpression
254 {
255     override bool isAssign() { return true; }
256 
257     mixin BinaryExpr!();
258 
259     override Type calcType()
260     {
261         return getLeftExpr().calcType();
262     }
263 }
264 
265 //ConditionalExpression:
266 //    [Expression Expression Expression]
267 class ConditionalExpression : Expression
268 {
269     this() {} // default constructor needed for clone()
270 
271     this(Token tok)
272     {
273         super(tok);
274     }
275 
276     Expression getCondition() { return getMember!Expression(0); }
277     Expression getThenExpr() { return getMember!Expression(1); }
278     Expression getElseExpr() { return getMember!Expression(2); }
279 
280     override PREC getPrecedence() { return PREC.cond; }
281 
282     override void _semantic(Scope sc)
283     {
284         getCondition().semantic(sc);
285         getThenExpr().semantic(sc);
286         getElseExpr().semantic(sc);
287     }
288 
289     override void toD(CodeWriter writer)
290     {
291         Expression condExpr = getCondition();
292         Expression thenExpr = getThenExpr();
293         Expression elseExpr = getElseExpr();
294 
295         bool condParen = (condExpr.getPrecedence() <= getPrecedence());
296         bool thenParen = (thenExpr.getPrecedence() < PREC.expr);
297         bool elseParen = (elseExpr.getPrecedence() < getPrecedence());
298 
299         writeExpr(writer, condExpr, condParen);
300         writeOperator(writer, TOK_question, Spaces.LeftRight);
301         writeExpr(writer, thenExpr, thenParen);
302         writeOperator(writer, TOK_colon, Spaces.LeftRight);
303         writeExpr(writer, elseExpr, elseParen);
304     }
305 
306     override Type calcType()
307     {
308         if(!type)
309         {
310             Type typeL = getThenExpr().calcType();
311             Type typeR = getElseExpr().calcType();
312             type = typeL.commonType(typeR);
313         }
314         return type;
315     }
316 
317     override Value interpret(Context sc)
318     {
319         Value cond = getCondition().interpret(sc);
320         Expression e = (cond.toBool() ? getThenExpr() : getElseExpr());
321         return e.interpret(sc); // TODO: cast to common type
322     }
323 }
324 
325 class OrOrExpression : BinaryExpression
326 {
327     mixin BinaryExpr!();
328 
329     override Type calcType()
330     {
331         if(!type)
332             type = createBasicType(TOK_bool);
333         return type;
334     }
335 
336     override Value interpret(Context sc)
337     {
338         Value vL = getLeftExpr().interpret(sc);
339         if(vL.toBool())
340             return Value.create(true);
341         Value vR = getRightExpr().interpret(sc);
342         return Value.create(vR.toBool());
343     }
344 }
345 
346 class AndAndExpression : BinaryExpression
347 {
348     mixin BinaryExpr!();
349 
350     override Type calcType()
351     {
352         if(!type)
353             type = createBasicType(TOK_bool);
354         return type;
355     }
356 
357     override Value interpret(Context sc)
358     {
359         Value vL = getLeftExpr().interpret(sc);
360         if(!vL.toBool())
361             return Value.create(false);
362         Value vR = getRightExpr().interpret(sc);
363         return Value.create(vR.toBool());
364     }
365 }
366 
367 class OrExpression : BinaryExpression
368 {
369     mixin BinaryExpr!();
370 }
371 
372 class XorExpression : BinaryExpression
373 {
374     mixin BinaryExpr!();
375 }
376 
377 class AndExpression : BinaryExpression
378 {
379     mixin BinaryExpr!();
380 }
381 
382 class CmpExpression : BinaryExpression
383 {
384     mixin BinaryExpr!();
385 
386     void _checkIdentityLiterals()
387     {
388         if(id == TOK_is || id == TOK_notidentity)
389         {
390             if(auto litL = cast(IntegerLiteralExpression) getLeftExpr())
391                 litL.forceLargerType(getRightExpr().calcType());
392             if(auto litR = cast(IntegerLiteralExpression) getRightExpr())
393                 litR.forceLargerType(getLeftExpr().calcType());
394         }
395     }
396 
397     override Type calcType()
398     {
399         if(!type)
400         {
401             _checkIdentityLiterals();
402             if(id == TOK_in)
403             {
404                 auto t = getRightExpr().calcType();
405                 if(auto ti = cast(TypeIndirection)t)
406                 {
407                     auto tp = new TypePointer();
408                     tp.setNextType(ti.getNextType());
409                     type = tp;
410                 }
411                 else
412                     type = semanticErrorType("cannot calculate type of operator in on ", t);
413             }
414             else
415                 type = createBasicType(TOK_bool);
416         }
417         return type;
418     }
419 
420     override void _semantic(Scope sc)
421     {
422         _checkIdentityLiterals();
423         getLeftExpr().semantic(sc);
424         getRightExpr().semantic(sc);
425     }
426 }
427 
428 class ShiftExpression : BinaryExpression
429 {
430     mixin BinaryExpr!();
431 }
432 
433 class AddExpression : BinaryExpression
434 {
435     mixin BinaryExpr!();
436 }
437 
438 class MulExpression : BinaryExpression
439 {
440     mixin BinaryExpr!();
441 }
442 
443 class PowExpression : BinaryExpression
444 {
445     mixin BinaryExpr!();
446 }
447 
448 //UnaryExpression:
449 //    id [Expression]
450 class UnaryExpression : Expression
451 {
452     mixin ForwardCtor!();
453 
454     override PREC getPrecedence() { return PREC.unary; }
455 
456     Expression getExpression() { return getMember!Expression(0); }
457 
458     override void _semantic(Scope sc)
459     {
460         getExpression().semantic(sc);
461     }
462 
463     override Type calcType()
464     {
465         if(!type)
466         {
467             Type exprtype = getExpression().calcType();
468             switch(id)
469             {
470                 default:
471                     type = exprtype;
472                     break;
473                 case TOK_delete:
474                     type = createBasicType(TOK_void);
475                     break;
476                 case TOK_not:
477                     type = createBasicType(TOK_bool);
478                     break;
479             }
480         }
481         return type;
482     }
483 
484     override Value interpret(Context sc)
485     {
486         Value v = getExpression().interpret(sc);
487 version(all)
488         switch(id)
489         {
490             case TOK_plusplus:
491                 return v.opBin(sc, TOK_addass, Value.create(cast(byte)1));
492             case TOK_minusminus:
493                 return v.opBin(sc, TOK_minass, Value.create(cast(byte)1));
494             case TOK_delete:
495                 // TODO: call destructor?
496                 v.opBin(sc, TOK_assign, v.getType().createValue(sc, null));
497                 return theVoidValue;
498             default:
499                 return v.opUn(sc, id);
500         }
501 else
502         switch(id)
503         {
504             case TOK_and:        return v.opRefPointer();
505             case TOK_mul:        return v.opDerefPointer();
506             case TOK_plusplus:   return v.opUnOp!"++"();
507             case TOK_minusminus: return v.opUnOp!"--"();
508             case TOK_min:        return v.opUnOp!"-"();
509             case TOK_add:        return v.opUnOp!"+"();
510             case TOK_not:        return v.opUnOp!"!"();
511             case TOK_tilde:      return v.opUnOp!"~"();
512             default:
513                 return semanticErrorValue("interpretation of unary operator ", tokenString(id), " not implemented");
514         }
515     }
516 
517     override void toD(CodeWriter writer)
518     {
519         Expression expr = getExpression();
520         bool paren = (expr.getPrecedence() < getPrecedence());
521 
522         writeOperator(writer, id, Spaces.Right);
523         writeExpr(writer, expr, paren);
524     }
525 }
526 
527 //NewExpression:
528 //    NewArguments Type [ AssignExpression ]
529 //    NewArguments Type ( ArgumentList )
530 //    NewArguments Type
531 //    NewArguments ClassArguments BaseClassList_opt { DeclDefs }
532 class NewExpression : Expression
533 {
534     bool hasNewArgs;
535 
536     this() {} // default constructor needed for clone()
537 
538     this(Token tok)
539     {
540         super(TOK_new, tok.span);
541     }
542 
543     override NewExpression clone()
544     {
545         NewExpression n = static_cast!NewExpression(super.clone());
546         n.hasNewArgs = hasNewArgs;
547         return n;
548     }
549     override bool compare(const(Node) n) const
550     {
551         if(!super.compare(n))
552             return false;
553 
554         auto tn = static_cast!(typeof(this))(n);
555         return tn.hasNewArgs == hasNewArgs;
556     }
557 
558     override PREC getPrecedence() { return PREC.unary; }
559 
560     ArgumentList getNewArguments() { return hasNewArgs ? getMember!ArgumentList(0) : null; }
561     Type getType() { return getMember!Type(hasNewArgs ? 1 : 0); }
562     ArgumentList getCtorArguments() { return members.length > (hasNewArgs ? 2 : 1) ? getMember!ArgumentList(members.length - 1) : null; }
563 
564     override void _semantic(Scope sc)
565     {
566         if(auto args = getNewArguments())
567             args.semantic(sc);
568         getType().semantic(sc);
569         if(auto args = getCtorArguments())
570             args.semantic(sc);
571     }
572 
573     override Type calcType()
574     {
575         return getType().calcType();
576     }
577 
578     override Value interpret(Context sc)
579     {
580         Value initVal;
581         if(auto args = getCtorArguments())
582             initVal = args.interpret(sc);
583         else
584             initVal = new TupleValue; // empty args force new instance
585         return calcType().createValue(sc, initVal);
586     }
587 
588     override void toD(CodeWriter writer)
589     {
590         if(ArgumentList nargs = getNewArguments())
591             writer("new(", nargs, ") ");
592         else
593             writer("new ");
594         writer(getType());
595         if(ArgumentList cargs = getCtorArguments())
596             writer("(", cargs, ")");
597     }
598 }
599 
600 class AnonymousClassType : Type
601 {
602     mixin ForwardCtor!();
603 
604     ArgumentList getArguments() { return members.length > 1 ? getMember!ArgumentList(0) : null; }
605     AnonymousClass getClass() { return getMember!AnonymousClass(members.length - 1); }
606 
607     override bool propertyNeedsParens() const { return true; }
608 
609     override void toD(CodeWriter writer)
610     {
611         if(ArgumentList args = getArguments())
612             writer("class(", args, ") ");
613         else
614             writer("class ");
615         writer(getClass());
616     }
617 
618     override Type calcType()
619     {
620         return getClass().calcType();
621     }
622 
623 }
624 
625 //CastExpression:
626 //    attr [Type_opt Expression]
627 class CastExpression : Expression
628 {
629     this() {} // default constructor needed for clone()
630 
631     this(Token tok)
632     {
633         super(TOK_cast, tok.span);
634     }
635 
636     override PREC getPrecedence() { return PREC.unary; }
637 
638     Type getType() { return members.length > 1 ? getMember!Type(0) : null; }
639     Expression getExpression() { return getMember!Expression(members.length - 1); }
640 
641     override void toD(CodeWriter writer)
642     {
643         writer("cast(");
644         writer.writeAttributesAndAnnotations(attr, annotation);
645         if(Type type = getType())
646             writer(getType());
647         writer(")");
648 
649         if(getExpression().getPrecedence() < getPrecedence())
650             writer("(", getExpression(), ")");
651         else
652             writer(getExpression());
653     }
654 
655     override void _semantic(Scope sc)
656     {
657         if(auto type = getType())
658             type.semantic(sc);
659         getExpression().semantic(sc);
660     }
661 
662     override Type calcType()
663     {
664         if(type)
665             return type;
666 
667         if(auto t = getType())
668             type = getType().calcType();
669         else
670         {
671             // extract basic type and attributes from expression
672             Type t = getExpression().calcType();
673             Attribute mattr = 0;
674             while(t)
675             {
676                 auto mf = cast(ModifiedType) t;
677                 if(!mf)
678                     break;
679                 mattr |= tokenToAttribute(mf.id);
680                 t = mf.getType();
681             }
682             assert(t);
683             if(mattr != attr)
684             {
685                 // rebuild modified type
686                 for(Attribute a = attr, ta; a; a -= ta)
687                 {
688                     ta = a & -a;
689                     TokenId aid = attributeToToken(attr);
690                     auto mt = new ModifiedType(aid, span);
691                     mt.addMember(t);
692                     t = mt;
693                 }
694             }
695             type = t;
696         }
697         return type;
698     }
699 
700     override Value interpret(Context sc)
701     {
702         Value val = getExpression().interpret(sc);
703         Type t = calcType();
704         Type vt = val.getType();
705         if(t.compare(vt))
706             return val;
707         Value v = t.createValue(sc, null);
708         return v.doCast(val);
709     }
710 }
711 
712 //PostfixExpression:
713 //    PrimaryExpression
714 //    PostfixExpression . Identifier
715 //    PostfixExpression . NewExpression
716 //    PostfixExpression ++
717 //    PostfixExpression --
718 //    PostfixExpression ( )
719 //    PostfixExpression ( ArgumentList )
720 //    IndexExpression
721 //    SliceExpression
722 //
723 //IndexExpression:
724 //    PostfixExpression [ ArgumentList ]
725 //
726 //SliceExpression:
727 //    PostfixExpression [ ]
728 //    PostfixExpression [ AssignExpression .. AssignExpression ]
729 class PostfixExpression : Expression
730 {
731     mixin ForwardCtor!();
732 
733     override PREC getPrecedence() { return PREC.primary; }
734 
735     Expression getExpression() { return getMember!Expression(0); }
736 
737     override Type calcType()
738     {
739         if(type)
740             return type;
741 
742         auto expr = getExpression();
743         auto etype = expr.calcType();
744         switch(id)
745         {
746             // TOK_dot handled by DotExpression
747             case TOK_lbracket:
748                 if(members.length == 2) // if slice, same type as expression
749                 {
750                     auto args = getMember!ArgumentList(1);
751                     auto vidx = args.interpret(nullContext);
752                     Value idx;
753                     if(vidx.values.length != 1)
754                         return semanticErrorType("exactly one value expected as array index");
755                     idx = vidx.values[0];
756                     type = etype.opIndex(idx.toInt());
757                 }
758                 else if(members.length == 3)
759                 {
760                     Scope sc = getScope();
761                     Value beg = getMember(1).interpret(nullContext);
762                     Value end = getMember(2).interpret(nullContext);
763                     type = etype.opSlice(beg.toInt(), end.toInt());
764                 }
765                 else
766                 {
767                     assert(members.length == 1);  // full slice
768                     type = etype;
769                 }
770                 break;
771             case TOK_lparen:
772                 Type args;
773                 if(members.length == 2)
774                     args = getMember!ArgumentList(1).calcType();
775                 else
776                     args = new TypeArraySlice;
777                 type = etype.opCall(args);
778                 break;
779             default:
780                 type = semanticErrorType("cannot determine type of ", this);
781                 break;
782         }
783         return type;
784     }
785 
786     override ArgumentList getFunctionArguments()
787     {
788         switch(id)
789         {
790             case TOK_lparen:
791                 if(members.length == 2)
792                     return getMember!ArgumentList(1);
793                 return new ArgumentList;
794             default:
795                 return null;
796         }
797     }
798 
799     override Value interpret(Context sc)
800     {
801         Expression expr = getExpression();
802         Value val = expr.interpret(sc);
803         switch(id)
804         {
805             // TOK_dot handled by DotExpression
806             case TOK_lbracket:
807                 if(members.length == 2)
808                 {
809                     auto args = getMember!ArgumentList(1);
810                     auto vidx = args.interpret(sc);
811                     Value idx;
812                     if(vidx.values.length != 1)
813                         return semanticErrorValue("exactly one value expected as array index");
814                     idx = vidx.values[0];
815                     return val.opIndex(idx);
816                 }
817                 else if(members.length == 3)
818                 {
819                     Value beg = getMember(1).interpret(sc);
820                     Value end = getMember(2).interpret(sc);
821                     return val.opSlice(beg, end);
822                 }
823                 assert(members.length == 1);  // full slice
824                 Node nodelen = val.getType().getScope().resolve("length", val.getType(), false);
825                 if(nodelen)
826                     return val.opSlice(Value.create(0), nodelen.interpret(sc));
827                 return val;
828 
829             case TOK_lparen:
830                 TupleValue args;
831                 if(members.length == 2)
832                     args = getMember!ArgumentList(1).interpret(sc);
833                 else
834                     args = new TupleValue;
835                 return val.opCall(sc, args);
836 
837             case TOK_plusplus:
838                 Value v2 = val.getType().createValue(sc, val);
839                 val.opBin(sc, TOK_addass, Value.create(cast(byte)1));
840                 return v2;
841             case TOK_minusminus:
842                 Value v2 = val.getType().createValue(sc, val);
843                 val.opBin(sc, TOK_minass, Value.create(cast(byte)1));
844                 return v2;
845             case TOK_new:
846             default:
847                 return super.interpret(sc);
848         }
849     }
850 
851     override void toD(CodeWriter writer)
852     {
853         Expression expr = getExpression();
854         bool paren = (expr.getPrecedence() < getPrecedence());
855 
856         writeExpr(writer, expr, paren);
857         switch(id)
858         {
859             case TOK_lbracket:
860                 writer("[");
861                 if(members.length == 2)
862                     writer(getMember!ArgumentList(1));
863                 else if(members.length == 3)
864                 {
865                     writer(getMember!Expression(1));
866                     writer(" .. ");
867                     writer(getMember!Expression(2));
868                 }
869                 writer("]");
870                 break;
871 
872             case TOK_lparen:
873                 writer("(");
874                 if(members.length > 1)
875                     writer(getMember!ArgumentList(1));
876                 writer(")");
877                 break;
878 
879             case TOK_dot:
880             case TOK_new:
881                 writer(".", getMember(1));
882                 break;
883 
884             default:
885                 writeOperator(writer, id, Spaces.Right);
886                 break;
887         }
888     }
889 }
890 
891 class DotExpression : PostfixExpression
892 {
893     mixin ForwardCtor!();
894 
895     Identifier getIdentifier() { return id == TOK_new ? null : getMember!Identifier(1); }
896 
897     Node resolved;
898 
899     override Node resolve()
900     {
901         if(resolved)
902             return resolved;
903 
904         auto expr = getExpression();
905         auto etype = expr.calcType();
906         switch(id)
907         {
908             case TOK_new:
909                 auto nexpr = getMember!NewExpression(1);
910                 resolved = nexpr.calcType();
911                 break;
912             default:
913                 auto id = getMember!Identifier(1);
914                 if(auto pt = cast(TypePointer)etype)
915                     etype = pt.getNextType();
916                 Scope s = etype.getScope();
917                 resolved = s ? s.resolve(id.ident, id, false) : null;
918                 break;
919         }
920         return resolved;
921     }
922 
923     override Type calcType()
924     {
925         if(type)
926             return type;
927 
928         if(auto n = resolve())
929             type = n.calcType();
930         else if(id == TOK_new)
931             type = semanticErrorType("cannot resolve type of new expression ", getMember(1));
932         else
933             type = semanticErrorType("cannot resolve type of property ", getMember!Identifier(1).ident);
934         return type;
935     }
936 
937     override Value interpret(Context sc)
938     {
939         Expression expr = getExpression();
940         Value val = expr.interpret(sc);
941 
942         if(!type)
943             calcType();
944         if(!resolved)
945             return Singleton!ErrorValue.get(); // calcType already produced an error
946 
947         //auto id = getMember!Identifier(1);
948         auto ctx = new AggrContext(sc, val);
949         if(expr.id == TOK_super)
950             ctx.virtualCall = false;
951         return resolved.interpret(ctx);
952     }
953 }
954 
955 //ArgumentList:
956 //    [Expression...]
957 class ArgumentList : Node
958 {
959     mixin ForwardCtor!();
960 
961     override void _semantic(Scope sc)
962     {
963         foreach(m; members)
964             m.semantic(sc);
965     }
966 
967     override TupleValue interpret(Context sc)
968     {
969         TupleValue args = new TupleValue;
970         foreach(m; members)
971             args.addValue(m.interpret(sc));
972         return args;
973     }
974 
975     override void toD(CodeWriter writer)
976     {
977         bool writeSep = false;
978         foreach(m; members)
979         {
980             if(writeSep)
981                 writer(", ");
982             writeSep = true;
983 
984             bool paren = false;
985             if(auto expr = cast(Expression) m)
986                 paren = (expr.getPrecedence() <= PREC.expr);
987 
988             if(paren)
989                 writer("(", m, ")");
990             else
991                 writer(m);
992         }
993     }
994 }
995 
996 //PrimaryExpression:
997 //    Identifier
998 //    . Identifier
999 //    TemplateInstance
1000 //    this
1001 //    super
1002 //    null
1003 //    true
1004 //    false
1005 //    $
1006 //    __FILE__
1007 //    __LINE__
1008 //    IntegerLiteral
1009 //    FloatLiteral
1010 //    CharacterLiteral
1011 //    StringLiterals
1012 //    ArrayLiteral
1013 //    AssocArrayLiteral
1014 //    Lambda
1015 //    FunctionLiteral
1016 //    AssertExpression
1017 //    MixinExpression
1018 //    ImportExpression
1019 //    TypeProperty
1020 //    Typeof
1021 //    TypeidExpression
1022 //    IsExpression
1023 //    ( Expression )
1024 //    ( Type ) . Identifier
1025 //    TraitsExpression
1026 
1027 class PrimaryExpression : Expression
1028 {
1029     mixin ForwardCtor!();
1030 
1031     override PREC getPrecedence() { return PREC.primary; }
1032 
1033     override Value interpret(Context sc)
1034     {
1035         switch(id)
1036         {
1037             case TOK_super:
1038             case TOK_this:
1039                 Value v = sc ? sc.getThis() : null;
1040                 if(!v)
1041                     return semanticErrorValue("this needs context");
1042                 return v;
1043 
1044             case TOK_true:  return Value.create(true);
1045             case TOK_false: return Value.create(false);
1046             case TOK_null:  return new NullValue;
1047             case TOK___LINE__: return Value.create(span.start.line);
1048             case TOK___FILE__: return createStringValue(getModuleFilename());
1049             case TOK_dollar:
1050             default:        return super.interpret(sc);
1051         }
1052     }
1053 
1054     override Type calcType()
1055     {
1056         if(type)
1057             return type;
1058 
1059         switch(id)
1060         {
1061             case TOK_this:
1062             case TOK_super:
1063                 auto sc = getScope();
1064                 type = sc ? sc.getThisType() : null;
1065                 if(id == TOK_super)
1066                     if(auto clss = cast(Class)type)
1067                         if(auto bc = clss.getBaseClass())
1068                             type = bc.calcType();
1069                 if(!type)
1070                     type = semanticErrorType("this needs context");
1071                 break;
1072 
1073             case TOK_true:
1074             case TOK_false:
1075                 type = createBasicType(TOK_bool);
1076                 break;
1077 
1078             case TOK_null:
1079                 type = Singleton!NullType.get();
1080                 break;
1081 
1082             case TOK_dollar:
1083             case TOK___LINE__:
1084                 type = createBasicType(TOK_uint);
1085                 break;
1086 
1087             case TOK___FILE__:
1088                 type = getTypeString!char();
1089                 break;
1090             default:
1091                 return super.calcType();
1092         }
1093         return type;
1094     }
1095 
1096     override void toD(CodeWriter writer)
1097     {
1098         writer(id);
1099     }
1100 }
1101 
1102 //ArrayLiteral:
1103 //    [ ArgumentList ]
1104 class ArrayLiteral : Expression
1105 {
1106     bool isAssoc;
1107 
1108     mixin ForwardCtor!();
1109 
1110     override PREC getPrecedence() { return PREC.primary; }
1111 
1112     ArgumentList getArgumentList() { return getMember!ArgumentList(0); }
1113 
1114     override void toD(CodeWriter writer)
1115     {
1116         writer("[");
1117         writer.writeArray(members);
1118         writer("]");
1119     }
1120 
1121     override void _semantic(Scope sc)
1122     {
1123         super._semantic(sc);
1124 
1125         auto argl = getArgumentList();
1126         int cntPairs = 0;
1127         int cntIndex = 0;
1128         foreach(m; argl.members)
1129         {
1130             m.semantic(sc);
1131             if(auto kv = cast(KeyValuePair) m)
1132             {
1133                 Type kt = kv.getKey().calcType();
1134                 Type st = BasicType.getSizeType();
1135                 if(st.convertableFrom(kt, Type.ConversionFlags.kImpliciteConversion))
1136                     cntIndex++;
1137                 cntPairs++;
1138             }
1139             else
1140                 break;
1141         }
1142         if(cntPairs == argl.members.length && cntIndex < argl.members.length)
1143             isAssoc = true;
1144 
1145         if(!isAssoc)
1146         {
1147             type = new TypeDynamicArray;
1148             if(argl.members.length)
1149             {
1150                 Type vt = argl.members[0].calcType();
1151                 foreach(m; argl.members[1..$])
1152                     vt = vt.commonType(m.calcType());
1153                 type.addMember(vt.clone());
1154             }
1155             else
1156                 type.addMember(new AutoType(TOK_auto, span));
1157         }
1158     }
1159 
1160     override Type calcType()
1161     {
1162         if(type)
1163             return type;
1164         semantic(getScope());
1165         return type;
1166     }
1167 
1168     override Value interpret(Context sc)
1169     {
1170         TupleValue val;
1171         if(auto args = getArgumentList())
1172             val = args.interpret(sc);
1173         else
1174             val = new TupleValue;
1175 
1176         if(auto tda = cast(TypeDynamicArray) calcType())
1177         {
1178             auto telem = tda.getNextType();
1179             auto vda = new DynArrayValue(tda);
1180             vda.setLength(sc, val.values.length);
1181             for(size_t i = 0; i < val.values.length; i++)
1182                 vda.setItem(sc, i, val.values[i]);
1183             debug vda.sval = vda.toStr();
1184             return vda;
1185         }
1186         return val;
1187     }
1188 }
1189 
1190 //VoidInitializer:
1191 //    void
1192 class VoidInitializer : Expression
1193 {
1194     mixin ForwardCtor!();
1195 
1196     override PREC getPrecedence() { return PREC.primary; }
1197 
1198     override Type calcType()
1199     {
1200         if(!type)
1201             type = createBasicType(TOK_void);
1202         return type;
1203     }
1204     override void toD(CodeWriter writer)
1205     {
1206         writer("void");
1207     }
1208     override Value interpret(Context sc)
1209     {
1210         return theVoidValue();
1211     }
1212 }
1213 
1214 // used for Expression_opt in for and return statements
1215 class EmptyExpression : Expression
1216 {
1217     mixin ForwardCtor!();
1218 
1219     override PREC getPrecedence() { return PREC.expr; }
1220 
1221     override void toD(CodeWriter writer)
1222     {
1223     }
1224 }
1225 
1226 
1227 //KeyValuePair:
1228 //    [Expression Expression]
1229 class KeyValuePair : BinaryExpression
1230 {
1231     mixin ForwardCtor!();
1232 
1233     static this()
1234     {
1235         precedence[TOK_colon] = PREC.assign;
1236     }
1237 
1238     this() {} // default constructor needed for clone()
1239 
1240     this(Token tok)
1241     {
1242         super(TOK_colon, tok.span);
1243     }
1244 
1245     Expression getKey() { return getMember!Expression(0); }
1246     Expression getValue() { return getMember!Expression(1); }
1247 }
1248 
1249 //FunctionLiteral:
1250 //    id [ Type_opt ParameterList_opt FunctionBody ] attr
1251 class FunctionLiteral : Expression
1252 {
1253     mixin ForwardCtor!();
1254 
1255     Type getType() { return members.length > 2 ? getMember!Type(0) : null; }
1256     override ParameterList getParameterList() { return getMember!ParameterList(members.length - 2); }
1257     FunctionBody getFunctionBody() { return getMember!FunctionBody(members.length - 1); }
1258 
1259     override PREC getPrecedence() { return PREC.primary; }
1260 
1261     override void toD(CodeWriter writer)
1262     {
1263         if(id != 0)
1264             writer(id, " ");
1265         if(Type type = getType())
1266             writer(type, " ");
1267         writer(getParameterList(), " ");
1268         writer.writeAttributesAndAnnotations(attr, annotation, false);
1269         writer(getFunctionBody());
1270     }
1271 
1272     override bool createsScope() const { return true; }
1273 
1274     override void _semantic(Scope sc)
1275     {
1276         if(auto t = getType())
1277             t.semantic(sc);
1278 
1279         sc = enterScope(sc);
1280         getFunctionBody().semantic(sc);
1281         sc = sc.pop();
1282     }
1283 
1284     TypeFunction func;
1285 
1286     override Type calcType()
1287     {
1288         if(!func)
1289         {
1290             auto pl = getParameterList();
1291             if(!pl)
1292                 pl = new ParameterList();
1293 
1294             if(id == TOK_function)
1295             {
1296                 auto funclit = new TypeFunctionLiteral;
1297                 funclit.paramList = pl;
1298                 func = funclit;
1299             }
1300             else
1301             {
1302                 auto funclit = new TypeDelegateLiteral;
1303                 funclit.paramList = pl;
1304                 func = funclit;
1305             }
1306             /+
1307             auto rt = getType();
1308             if(!rt)
1309             rt = new AutoType(TOK_auto, span);
1310             else
1311             rt = rt.clone();
1312             func.addMember(rt);
1313 
1314             auto pl = getParameterList();
1315             if(!pl)
1316             pl = new ParameterList();
1317             else
1318             pl = pl.clone();
1319             func.addMember(pl);
1320             +/
1321 
1322             auto decl = new FuncLiteralDeclarator;
1323             decl.type = func;
1324             decl.funcbody = getFunctionBody();
1325             func.funcDecl = decl;
1326         }
1327         return func;
1328     }
1329 
1330     override Value interpret(Context sc)
1331     {
1332         if(!func)
1333             calcType();
1334 
1335         if(id == TOK_function)
1336         {
1337             auto fn = new FunctionValue;
1338             fn.functype = func;
1339             return fn;
1340         }
1341         else
1342         {
1343             auto dg = new DelegateValue;
1344             dg.context = sc;
1345             dg.functype = func;
1346             return dg;
1347         }
1348     }
1349 }
1350 
1351 //Lambda:
1352 //    [ ParameterList Expression ]
1353 class Lambda : Expression
1354 {
1355     mixin ForwardCtor!();
1356 
1357     override PREC getPrecedence() { return PREC.primary; }
1358 
1359     override void toD(CodeWriter writer)
1360     {
1361         writer(getMember(0), " => ", getMember(1));
1362     }
1363 }
1364 
1365 class TypeFunctionLiteral : TypeFunction
1366 {
1367     override Type getReturnType()
1368     {
1369         if (returnType)
1370             return returnType;
1371         if(members.length)
1372             returnType = getMember!Type(0);
1373 
1374         // TODO: infer return type from code
1375         if (!returnType)
1376             returnType = new AutoType;
1377         return returnType;
1378     }
1379 }
1380 
1381 class TypeDelegateLiteral : TypeDelegate
1382 {
1383     override Type getReturnType()
1384     {
1385         if (returnType)
1386             return returnType;
1387         if(members.length)
1388             returnType = getMember!Type(0);
1389 
1390         // TODO: infer return type from code
1391         if (!returnType)
1392             returnType = new AutoType;
1393         return returnType;
1394     }
1395 }
1396 
1397 class FuncLiteralDeclarator : Declarator
1398 {
1399     FunctionBody funcbody;
1400 
1401     override Value interpretCall(Context sc)
1402     {
1403         return funcbody.interpret(sc);
1404     }
1405 }
1406 
1407 //StructLiteral:
1408 //    [ArrayValueList]
1409 class StructLiteral : Expression
1410 {
1411     mixin ForwardCtor!();
1412 
1413     override PREC getPrecedence() { return PREC.primary; }
1414 
1415     override void toD(CodeWriter writer)
1416     {
1417         writer("{ ", getMember(0), " }");
1418     }
1419 
1420     override Value interpret(Context sc)
1421     {
1422         return getMember(0).interpret(sc);
1423     }
1424 }
1425 
1426 //AssertExpression:
1427 //    assert ( AssignExpression )
1428 //    assert ( AssignExpression , AssignExpression )
1429 class AssertExpression : Expression
1430 {
1431     mixin ForwardCtor!();
1432 
1433     override PREC getPrecedence() { return PREC.primary; }
1434 
1435     Expression getExpression() { return getMember!Expression(0); }
1436     Expression getMessage() { return getMember!Expression(1); }
1437 
1438     override void toD(CodeWriter writer)
1439     {
1440         writer("assert(");
1441         writer(getExpression());
1442         if(Expression msg = getMessage())
1443             writer(", ", msg);
1444         writer(")");
1445     }
1446 
1447     override Value interpret(Context sc)
1448     {
1449         auto actx = new AssertContext(sc);
1450         auto cond = getExpression().interpret(actx);
1451         if(!cond.toBool())
1452         {
1453             string msg;
1454             if(auto m = getMessage())
1455                 msg = m.interpret(sc).toMixin();
1456             else
1457                 msg = "assertion " ~ writeD(getExpression()) ~ " failed";
1458             foreach(id, val; actx.identVal)
1459                 msg ~= "\n\t" ~ writeD(id) ~ " = " ~ val.toStr();
1460             return semanticErrorValue(msg);
1461         }
1462         return theVoidValue;
1463     }
1464 }
1465 
1466 //MixinExpression:
1467 //    mixin ( AssignExpression )
1468 class MixinExpression : Expression
1469 {
1470     mixin ForwardCtor!();
1471 
1472     override PREC getPrecedence() { return PREC.primary; }
1473 
1474     Expression getExpression() { return getMember!Expression(0); }
1475 
1476     Expression resolved;
1477 
1478     override void toD(CodeWriter writer)
1479     {
1480         if(resolved)
1481             resolved.toD(writer);
1482         else
1483             writer("mixin(", getMember!Expression(0), ")");
1484     }
1485 
1486     override void _semantic(Scope sc)
1487     {
1488         if(resolved)
1489             return;
1490 
1491         Value v = getMember(0).interpretCatch(nullContext);
1492         string s = v.toMixin();
1493         Parser parser = new Parser;
1494         if(auto prj = sc.getProject())
1495             parser.saveErrors = prj.saveErrors;
1496 
1497         Node n = parser.parseExpression(s, span);
1498         resolved = cast(Expression) n;
1499         if(resolved)
1500         {
1501             addMember(resolved);
1502             resolved.semantic(sc);
1503         }
1504     }
1505 
1506     override Type calcType()
1507     {
1508         if(!resolved)
1509             semantic(getScope());
1510         if(resolved)
1511             return resolved.calcType();
1512         return new ErrorType;
1513     }
1514 
1515     override Value interpret(Context sc)
1516     {
1517         if(!resolved)
1518             semantic(getScope());
1519         if(resolved)
1520             return resolved.interpret(sc);
1521         return semanticErrorValue("cannot interpret mixin");
1522     }
1523 }
1524 
1525 //ImportExpression:
1526 //    import ( AssignExpression )
1527 class ImportExpression : Expression
1528 {
1529     mixin ForwardCtor!();
1530 
1531     override PREC getPrecedence() { return PREC.primary; }
1532 
1533     Expression getExpression() { return getMember!Expression(0); }
1534 
1535     override Type calcType()
1536     {
1537         if(!type)
1538             type = getTypeString!char();
1539         return type;
1540     }
1541     override void toD(CodeWriter writer)
1542     {
1543         writer("import(", getMember!Expression(0), ")");
1544     }
1545 }
1546 
1547 //TypeidExpression:
1548 //    typeid ( Type )
1549 //    typeid ( Expression )
1550 class TypeIdExpression : Expression
1551 {
1552     mixin ForwardCtor!();
1553 
1554     override PREC getPrecedence() { return PREC.primary; }
1555 
1556     override void toD(CodeWriter writer)
1557     {
1558         writer("typeid(", getMember(0), ")");
1559     }
1560 }
1561 
1562 //IsExpression:
1563 //    is ( Type )
1564 //    is ( Type : TypeSpecialization )
1565 //    is ( Type == TypeSpecialization )
1566 //    is ( Type Identifier )
1567 //    is ( Type Identifier : TypeSpecialization )
1568 //    is ( Type Identifier == TypeSpecialization )
1569 //    is ( Type Identifier : TypeSpecialization , TemplateParameterList )
1570 //    is ( Type Identifier == TypeSpecialization , TemplateParameterList )
1571 //
1572 //TypeSpecialization:
1573 //    Type
1574 //    struct
1575 //    union
1576 //    class
1577 //    interface
1578 //    enum
1579 //    function
1580 //    delegate
1581 //    super
1582 //    const
1583 //    immutable
1584 //    inout
1585 //    shared
1586 //    return
1587 //
1588 class IsExpression : PrimaryExpression
1589 {
1590     int kind;
1591     string ident;
1592 
1593     this() {} // default constructor needed for clone()
1594 
1595     this(Token tok)
1596     {
1597         super(TOK_is, tok.span);
1598     }
1599 
1600     override IsExpression clone()
1601     {
1602         IsExpression n = static_cast!IsExpression(super.clone());
1603         n.kind = kind;
1604         n.ident = ident;
1605         return n;
1606     }
1607     override bool compare(const(Node) n) const
1608     {
1609         if(!super.compare(n))
1610             return false;
1611 
1612         auto tn = static_cast!(typeof(this))(n);
1613         return tn.kind == kind
1614             && tn.ident == ident;
1615     }
1616 
1617     Type getType() { return getMember!Type(0); }
1618     TypeSpecialization getTypeSpecialization() { return members.length > 1 ? getMember!TypeSpecialization(1) : null; }
1619 
1620     override void toD(CodeWriter writer)
1621     {
1622         writer("is(", getType());
1623         if(ident.length)
1624         {
1625             writer(" ");
1626             writer.writeIdentifier(ident);
1627         }
1628         if(kind != 0)
1629             writer(" ", kind, " ");
1630         if(auto ts = getTypeSpecialization())
1631             writer(ts);
1632         writer(")");
1633     }
1634 
1635     override Type calcType()
1636     {
1637         if(!type)
1638             type = createBasicType(TOK_bool);
1639         return type;
1640     }
1641 }
1642 
1643 class TypeSpecialization : Node
1644 {
1645     mixin ForwardCtor!();
1646 
1647     Type getType() { return getMember!Type(0); }
1648 
1649     override void toD(CodeWriter writer)
1650     {
1651         if(id != 0)
1652             writer(id);
1653         else
1654             writer(getMember(0));
1655     }
1656 }
1657 
1658 class IdentifierExpression : PrimaryExpression
1659 {
1660     bool global;
1661 
1662     // semantic data
1663     Node resolved;
1664 
1665     this() {} // default constructor needed for clone()
1666 
1667     this(Token tok)
1668     {
1669         super(TOK_Identifier, tok.span);
1670     }
1671 
1672     override IdentifierExpression clone()
1673     {
1674         IdentifierExpression n = static_cast!IdentifierExpression(super.clone());
1675         n.global = global;
1676         return n;
1677     }
1678 
1679     override bool compare(const(Node) n) const
1680     {
1681         if(!super.compare(n))
1682             return false;
1683 
1684         auto tn = static_cast!(typeof(this))(n);
1685         return tn.global == global;
1686     }
1687 
1688     Identifier getIdentifier() { return getMember!Identifier(0); }
1689 
1690     override void toD(CodeWriter writer)
1691     {
1692         if(global)
1693             writer(".");
1694         writer(getIdentifier());
1695     }
1696 
1697     override void toC(CodeWriter writer)
1698     {
1699         //resolve();
1700         if(resolved)
1701         {
1702             Module thisMod = getModule();
1703             Module thatMod = resolved.getModule();
1704             if(global || thisMod is thatMod)
1705             {
1706                 thatMod.writeNamespace(writer);
1707             }
1708         }
1709         writer(getIdentifier());
1710     }
1711 
1712     override Node resolve()
1713     {
1714         if(resolved)
1715             return resolved;
1716 
1717         if(!scop)
1718             semantic(getScope());
1719         auto id = getIdentifier();
1720         resolved = scop.resolveWithTemplate(id.ident, scop, id);
1721         return resolved;
1722     }
1723 
1724     override void _semantic(Scope sc)
1725     {
1726         if(global)
1727             scop = getModule().scop;
1728         else
1729             scop = sc;
1730 
1731         resolve();
1732     }
1733 
1734     override Type calcType()
1735     {
1736         if(type)
1737             return type;
1738         if(!scop)
1739             semantic(getScope());
1740         if(resolved)
1741             type = resolved.calcType();
1742         if(!type)
1743             return semanticErrorType("cannot determine type");
1744         return type;
1745     }
1746 
1747     override ArgumentList getFunctionArguments()
1748     {
1749         if(parent)
1750             return parent.getFunctionArguments();
1751         return null;
1752     }
1753 
1754     override Value interpret(Context sc)
1755     {
1756         if(!resolved)
1757             semantic(getScope());
1758         if(!resolved)
1759             return semanticErrorValue("unresolved identifier ", writeD(this));
1760         Value v = resolved.interpret(sc);
1761         if(auto actx = cast(AssertContext)sc)
1762             actx.identVal[this] = v;
1763         return v;
1764     }
1765 }
1766 
1767 class IntegerLiteralExpression : PrimaryExpression
1768 {
1769     string txt;
1770 
1771     ulong value; // literals are never negative by themselves
1772     bool unsigned;
1773     bool lng;
1774 
1775     bool forceInt; // set in semantic pass
1776     bool forceShort;
1777 
1778     this() {} // default constructor needed for clone()
1779 
1780     this(Token tok)
1781     {
1782         super(tok);
1783         txt = tok.txt;
1784         initValue();
1785     }
1786 
1787     void initValue()
1788     {
1789         string val = txt;
1790         while(val.length > 1)
1791         {
1792             if(val[$-1] == 'L')
1793                 lng = true;
1794             else if(val[$-1] == 'U' || val[$-1] == 'u')
1795                 unsigned = true;
1796             else
1797                 break;
1798             val = val[0..$-1];
1799         }
1800         int radix = 10;
1801         if(val[0] == '0' && val.length > 1)
1802         {
1803             if(val[1] == 'x' || val[1] == 'X')
1804             {
1805                 radix = 16;
1806                 val = val[2..$];
1807             }
1808             else if(val[1] == 'b' || val[1] == 'B')
1809             {
1810                 radix = 2;
1811                 val = val[2..$];
1812             }
1813             else
1814             {
1815                 radix = 8;
1816             }
1817             unsigned = true;
1818         }
1819         import std.array : replace;
1820         val = val.replace("_", "");
1821         value = parse!ulong(val, radix);
1822     }
1823 
1824     override IntegerLiteralExpression clone()
1825     {
1826         IntegerLiteralExpression n = static_cast!IntegerLiteralExpression(super.clone());
1827         n.txt = txt;
1828         n.value = value;
1829         n.unsigned = unsigned;
1830         n.lng = lng;
1831         return n;
1832     }
1833 
1834     override bool compare(const(Node) n) const
1835     {
1836         if(!super.compare(n))
1837             return false;
1838 
1839         auto tn = static_cast!(typeof(this))(n);
1840         return tn.txt == txt
1841             && tn.value == value
1842             && tn.unsigned == unsigned
1843             && tn.lng == lng;
1844     }
1845 
1846     override void toD(CodeWriter writer)
1847     {
1848         writer(txt);
1849     }
1850 
1851     void forceLargerType(Type t)
1852     {
1853         if(t.id == TOK_int || t.id == TOK_uint)
1854             forceInt = true;
1855         if(t.id == TOK_short || t.id == TOK_ushort)
1856             forceShort = true;
1857     }
1858 
1859     override Type calcType()
1860     {
1861         if(type)
1862             return type;
1863 
1864         long lim = unsigned ? 0x1_0000_0000 : 0x8000_0000;
1865         if(lng || value >= lim)
1866             if(unsigned)
1867                 type = new BasicType(TOK_ulong, span);
1868             else
1869                 type = new BasicType(TOK_long, span);
1870         else if(true || forceInt || value >= (lim >> 16))
1871             if(unsigned)
1872                 type = new BasicType(TOK_uint, span);
1873             else
1874                 type = new BasicType(TOK_int, span);
1875         else if(forceShort || value >= (lim >= 24))
1876             if(unsigned)
1877                 type = new BasicType(TOK_ushort, span);
1878             else
1879                 type = new BasicType(TOK_short, span);
1880         else
1881             if(unsigned)
1882                 type = new BasicType(TOK_ubyte, span);
1883             else
1884                 type = new BasicType(TOK_byte, span);
1885 
1886         return type;
1887     }
1888 
1889     override void _semantic(Scope sc)
1890     {
1891         calcType().semantic(sc);
1892     }
1893 
1894     Value _interpret(Context sc)
1895     {
1896         if(lng || value >= 0x80000000)
1897             if(unsigned)
1898                 return Value.create(cast(ulong)value);
1899             else
1900                 return Value.create(cast(long)value);
1901         else if(true || forceInt || value >= 0x8000)
1902             if(unsigned)
1903                 return Value.create(cast(uint)value);
1904             else
1905                 return Value.create(cast(int)value);
1906         else if(forceShort || value >= 0x80)
1907             if(unsigned)
1908                 return Value.create(cast(ushort)value);
1909             else
1910                 return Value.create(cast(short)value);
1911         else
1912             if(unsigned)
1913                 return Value.create(cast(ubyte)value);
1914             else
1915                 return Value.create(cast(byte)value);
1916     }
1917     override Value interpret(Context sc)
1918     {
1919         Value v = _interpret(sc);
1920         v.literal = true;
1921         return v;
1922     }
1923 
1924     int getInt()
1925     {
1926         if(value > int.max)
1927             semanticErrorPos(span.start, text(value, " too large to fit an integer"));
1928         return cast(int) value;
1929     }
1930     uint getUInt()
1931     {
1932         if(value > uint.max)
1933             semanticErrorPos(span.start, text(value, " too large to fit an unsigned integer"));
1934         return cast(uint) value;
1935     }
1936 }
1937 
1938 class FloatLiteralExpression : PrimaryExpression
1939 {
1940     string txt;
1941 
1942     real value;
1943     bool complex;
1944     bool lng;
1945     bool flt;
1946 
1947     this() {} // default constructor needed for clone()
1948 
1949     this(Token tok)
1950     {
1951         super(tok);
1952         txt = tok.txt;
1953         initValue();
1954     }
1955 
1956     void initValue()
1957     {
1958         string val = txt;
1959         while(val.length > 1)
1960         {
1961             if(val[$-1] == 'L')
1962                 lng = true;
1963             else if(val[$-1] == 'f' || val[$-1] == 'F')
1964                 flt = true;
1965             else if(val[$-1] == 'i')
1966                 complex = true;
1967             else if(val[$-1] == '.')
1968             {
1969                 val = val[0..$-1];
1970                 break;
1971             }
1972             else
1973                 break;
1974             val = val[0..$-1];
1975         }
1976         import std.array : replace;
1977         val = val.replace("_", "");
1978         value = parse!real(val);
1979     }
1980 
1981     override FloatLiteralExpression clone()
1982     {
1983         FloatLiteralExpression n = static_cast!FloatLiteralExpression(super.clone());
1984         n.txt = txt;
1985         n.value = value;
1986         n.complex = complex;
1987         n.lng = lng;
1988         n.flt = flt;
1989         return n;
1990     }
1991     override bool compare(const(Node) n) const
1992     {
1993         if(!super.compare(n))
1994             return false;
1995 
1996         auto tn = static_cast!(typeof(this))(n);
1997         return tn.txt == txt
1998             && tn.value == value
1999             && tn.complex == complex
2000             && tn.flt == flt
2001             && tn.lng == lng;
2002     }
2003 
2004     override Type calcType()
2005     {
2006         if(type)
2007             return type;
2008 
2009         if(complex)
2010             if(lng)
2011                 type = new BasicType(TOK_ireal, span);
2012             else if(flt)
2013                 type = new BasicType(TOK_ifloat, span);
2014             else
2015                 type = new BasicType(TOK_idouble, span);
2016         else
2017             if(lng)
2018                 type = new BasicType(TOK_real, span);
2019             else if(flt)
2020                 type = new BasicType(TOK_float, span);
2021             else
2022                 type = new BasicType(TOK_double, span);
2023 
2024         return type;
2025     }
2026 
2027     override void _semantic(Scope sc)
2028     {
2029         calcType().semantic(sc);
2030     }
2031 
2032     Value _interpret(Context sc)
2033     {
2034         if(complex)
2035             assert(0, "Complex numbers aren't supported anymore.");
2036         else
2037             if(lng)
2038                 return Value.create(cast(real)value);
2039             else if(flt)
2040                 return Value.create(cast(float)value);
2041             else
2042                 return Value.create(cast(double)value);
2043     }
2044     override Value interpret(Context sc)
2045     {
2046         Value v = _interpret(sc);
2047         v.literal = true;
2048         return v;
2049     }
2050 
2051     override void toD(CodeWriter writer)
2052     {
2053         writer(txt);
2054     }
2055 }
2056 
2057 class StringLiteralExpression : PrimaryExpression
2058 {
2059     string txt;
2060     string rawtxt;
2061 
2062     this() {} // default constructor needed for clone()
2063 
2064     static string raw(string s)
2065     {
2066         if(s.length == 0)
2067             return s;
2068         if(s.length > 2 && s[0] == 'q' && s[1] == '{' && s[$-1] == '}')
2069             return s[2..$-1];
2070 
2071         // TODO: missing hex/escape translation and delimiter string handling
2072         size_t p = 0;
2073         while(p < s.length && s[p] != '"' && s[p] != '`')
2074             p++;
2075         if(p >= s.length)
2076             return s;
2077         size_t q = s.length - 1;
2078         while(q > p && s[q] != s[p])
2079             q--;
2080         if(q <= p)
2081             return s;
2082         return s[p+1..q];
2083     }
2084     unittest
2085     {
2086         assert(raw(`r"abc"`) == "abc");
2087         assert(raw(`q{abc}`) == "abc");
2088         assert(raw(`"abc"c`) == "abc");
2089     }
2090 
2091     this(Token tok)
2092     {
2093         super(tok);
2094         txt = tok.txt;
2095 
2096         rawtxt = raw(txt);
2097     }
2098 
2099     void addText(Token tok)
2100     {
2101         txt ~= " " ~ tok.txt;
2102         rawtxt ~= raw(tok.txt);
2103     }
2104 
2105     override StringLiteralExpression clone()
2106     {
2107         StringLiteralExpression n = static_cast!StringLiteralExpression(super.clone());
2108         n.txt = txt;
2109         n.rawtxt = rawtxt;
2110         return n;
2111     }
2112     override bool compare(const(Node) n) const
2113     {
2114         if(!super.compare(n))
2115             return false;
2116 
2117         auto tn = static_cast!(typeof(this))(n);
2118         return tn.txt == txt;
2119     }
2120 
2121     override Type calcType()
2122     {
2123         if(!type)
2124         {
2125             switch(txt[$-1])
2126             {
2127                 default:
2128                 case 'c':
2129                     type = getTypeString!char();
2130                     break;
2131                 case 'w':
2132                     type = getTypeString!wchar();
2133                     break;
2134                 case 'd':
2135                     type = getTypeString!dchar();
2136                     break;
2137             }
2138         }
2139         return type;
2140     }
2141     override void _semantic(Scope sc)
2142     {
2143         calcType();
2144     }
2145 
2146     override Value interpret(Context sc)
2147     {
2148         Value v = Value.create(rawtxt);
2149         v.literal = true;
2150         return v;
2151     }
2152 
2153     override void toD(CodeWriter writer)
2154     {
2155         writer(txt);
2156     }
2157 }
2158 
2159 class CharacterLiteralExpression : PrimaryExpression
2160 {
2161     string txt;
2162 
2163     this() {} // default constructor needed for clone()
2164 
2165     this(Token tok)
2166     {
2167         super(tok);
2168         txt = tok.txt;
2169     }
2170 
2171     override CharacterLiteralExpression clone()
2172     {
2173         CharacterLiteralExpression n = static_cast!CharacterLiteralExpression(super.clone());
2174         n.txt = txt;
2175         return n;
2176     }
2177 
2178     override bool compare(const(Node) n) const
2179     {
2180         if(!super.compare(n))
2181             return false;
2182 
2183         auto tn = static_cast!(typeof(this))(n);
2184         return tn.txt == txt;
2185     }
2186 
2187     override Type calcType()
2188     {
2189         if(type)
2190             return type;
2191 
2192         if(txt.length >= 3)
2193         {
2194             if(txt[$-1] == 'd')
2195                 type = new BasicType(TOK_dchar, span);
2196             else if(txt[$-1] == 'w')
2197                 type = new BasicType(TOK_wchar, span);
2198         }
2199         if(!type)
2200             type = new BasicType(TOK_char, span);
2201 
2202         return type;
2203     }
2204 
2205     Value _interpret(Context sc)
2206     {
2207         if(txt.length < 3)
2208             return Value.create(char.init);
2209 
2210         // TODO: missing escape decoding
2211         dchar ch = txt[1];
2212         if(txt[$-1] == 'd')
2213             return Value.create(ch);
2214         if(txt[$-1] == 'w')
2215             return Value.create(cast(wchar)ch);
2216         return Value.create(cast(char)ch);
2217     }
2218 
2219     override Value interpret(Context sc)
2220     {
2221         Value v = _interpret(sc);
2222         v.literal = true;
2223         return v;
2224     }
2225 
2226     override void _semantic(Scope sc)
2227     {
2228         calcType().semantic(sc);
2229     }
2230 
2231     override void toD(CodeWriter writer)
2232     {
2233         writer(txt);
2234     }
2235 }
2236 
2237 //TypeProperty:
2238 //    [Type Identifier]
2239 class TypeProperty : PrimaryExpression
2240 {
2241     Node resolved;
2242 
2243     this() {} // default constructor needed for clone()
2244 
2245     this(Token tok)
2246     {
2247         super(0, tok.span);
2248     }
2249 
2250     Type getType() { return getMember!Type(0); }
2251     Identifier getProperty() { return getMember!Identifier(1); }
2252 
2253     override void toD(CodeWriter writer)
2254     {
2255         Type type = getType();
2256         if(type.propertyNeedsParens())
2257             writer("(", getType(), ").", getProperty());
2258         else
2259             writer(getType(), ".", getProperty());
2260     }
2261 
2262     override Node resolve()
2263     {
2264         if(resolved)
2265             return resolved;
2266 
2267         auto id = getProperty();
2268         resolved = getType().getScope().resolve(id.ident, id);
2269         return resolved;
2270     }
2271 
2272     override Type calcType()
2273     {
2274         if(type)
2275             return type;
2276 
2277         if(auto n = resolve())
2278             type = n.calcType();
2279         else
2280             type = semanticErrorType("cannot determine type of property ", getProperty().ident);
2281         return type;
2282     }
2283 
2284     override Value interpret(Context sc)
2285     {
2286         if(!type)
2287             calcType();
2288         if(!resolved)
2289             return Singleton!ErrorValue.get(); // calcType already produced an error
2290         return resolved.interpret(nullContext);
2291     }
2292 }
2293 
2294 class StructConstructor : PrimaryExpression
2295 {
2296     this() {} // default constructor needed for clone()
2297 
2298     this(Token tok)
2299     {
2300         super(0, tok.span);
2301     }
2302 
2303     Type getType() { return getMember!Type(0); }
2304     ArgumentList getArguments() { return getMember!ArgumentList(1); }
2305 
2306     override void toD(CodeWriter writer)
2307     {
2308         Type type = getType();
2309         if(type.propertyNeedsParens())
2310             writer("(", getType(), ")(", getArguments(), ")");
2311         else
2312             writer(getType(), "(", getArguments(), ")");
2313     }
2314 }
2315 
2316 class TraitsExpression : PrimaryExpression
2317 {
2318     this() {} // default constructor needed for clone()
2319 
2320     this(Token tok)
2321     {
2322         super(TOK___traits, tok.span);
2323     }
2324 
2325     override void toD(CodeWriter writer)
2326     {
2327         writer("__traits(", getMember(0));
2328         if(members.length > 1)
2329             writer(", ", getMember(1));
2330         writer(")");
2331     }
2332 }
2333 
2334 class TraitsArguments : TemplateArgumentList
2335 {
2336     mixin ForwardCtorNoId!();
2337 }