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 }