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 // Interpretation passes around a context, holding the current variable stack 10 // class Context { Scope sc; Value[Node] vars; Context parent; } 11 // 12 // static shared values are not looked up in the context 13 // thread local static values are looked up in a global thread context 14 // non-static values are looked up in the current context 15 // 16 // member/field lookup in aggregates uses an instance specific Context 17 // 18 // when entering a scope, a new Context is created with the current 19 // Context as parent 20 // when leaving a scope, the context is destroyed together with scoped values 21 // created within the lifetime of the context 22 // a delegate value saves the current context to be used when calling the delegate 23 // 24 // local functions are called with the context of the enclosing function 25 // member functions are called with the context of the instance 26 // static or global functions are called with the thread context 27 // 28 module vdc.interpret; 29 30 import vdc.util; 31 import vdc.semantic; 32 import vdc.lexer; 33 import vdc.logger; 34 35 import vdc.ast.decl; 36 import vdc.ast.type; 37 import vdc.ast.aggr; 38 import vdc.ast.expr; 39 import vdc.ast.node; 40 import vdc.ast.writer; 41 42 import stdext.util; 43 import stdext.string; 44 45 import std.conv; 46 import std.meta; 47 import std.string; 48 import std.traits; 49 import std.utf; 50 import std.variant; 51 52 template Singleton(T, ARGS...) 53 { 54 T get() 55 { 56 static T instance; 57 if(!instance) 58 instance = new T(ARGS); 59 return instance; 60 } 61 } 62 63 class Value 64 { 65 bool mutable = true; 66 bool literal = false; 67 debug string sval; 68 debug string ident; 69 70 static T _create(T, V)(V val) 71 { 72 T v = new T; 73 *v.pval = val; 74 debug v.sval = v.toStr(); 75 return v; 76 } 77 78 static Value create(bool v) { return _create!BoolValue (v); } 79 static Value create(byte v) { return _create!ByteValue (v); } 80 static Value create(ubyte v) { return _create!UByteValue (v); } 81 static Value create(short v) { return _create!ShortValue (v); } 82 static Value create(ushort v) { return _create!UShortValue (v); } 83 static Value create(int v) { return _create!IntValue (v); } 84 static Value create(uint v) { return _create!UIntValue (v); } 85 static Value create(long v) { return _create!LongValue (v); } 86 static Value create(ulong v) { return _create!ULongValue (v); } 87 static Value create(char v) { return _create!CharValue (v); } 88 static Value create(wchar v) { return _create!WCharValue (v); } 89 static Value create(dchar v) { return _create!DCharValue (v); } 90 static Value create(float v) { return _create!FloatValue (v); } 91 static Value create(double v) { return _create!DoubleValue (v); } 92 static Value create(real v) { return _create!RealValue (v); } 93 static Value create(string v) { return createStringValue (v); } 94 95 Type getType() 96 { 97 semanticError("cannot get type of ", this); 98 return Singleton!(ErrorType).get(); 99 } 100 101 bool toBool() 102 { 103 semanticError("cannot convert ", this, " to bool"); 104 return false; 105 } 106 107 int toInt() 108 { 109 long lng = toLong(); 110 return cast(int) lng; 111 } 112 113 long toLong() 114 { 115 semanticError("cannot convert ", this, " to integer"); 116 return 0; 117 } 118 119 void setLong(long lng) 120 { 121 semanticError("cannot convert long to ", this); 122 } 123 124 string toStr() 125 { 126 semanticError("cannot convert ", this, " to string"); 127 return ""; 128 } 129 130 string toMixin() 131 { 132 semanticError("cannot convert ", this, " to mixin"); 133 return ""; 134 } 135 136 Value getElement(size_t idx) 137 { 138 return semanticErrorValue("cannot get ", idx, ". element of array of ", this); 139 } 140 141 void setElements(size_t oldcnt, size_t newcnt) 142 { 143 semanticError("cannot set no of elements of array of ", this); 144 } 145 146 PointerValue toPointer(TypePointer to) 147 { 148 return null; 149 } 150 151 final void validate() 152 { 153 debug sval = toStr(); 154 } 155 156 //override string toString() 157 //{ 158 // return text(getType(), ":", toStr()); 159 //} 160 161 version(all) 162 Value opBin(Context ctx, int tokid, Value v) 163 { 164 return semanticErrorValue("cannot calculate ", this, " ", tokenString(tokid), " ", v); 165 //return semanticErrorValue("binary operator ", tokenString(tokid), " on ", this, " not implemented"); 166 } 167 168 Value opBin_r(Context ctx, int tokid, Value v) 169 { 170 return semanticErrorValue("cannot calculate ", v, " ", tokenString(tokid), " ", this); 171 //return semanticErrorValue("binary operator ", tokenString(tokid), " on ", this, " not implemented"); 172 } 173 174 Value opUn(Context ctx, int tokid) 175 { 176 switch(tokid) 177 { 178 case TOK_and: return opRefPointer(); 179 case TOK_mul: return opDerefPointer(); 180 default: break; 181 } 182 return semanticErrorValue("unary operator ", tokenString(tokid), " on ", this, " not implemented"); 183 } 184 185 Value opRefPointer() 186 { 187 auto tp = new TypePointer(); 188 tp.setNextType(getType()); //addMember(getType().clone()); 189 return PointerValue._create(tp, this); 190 } 191 Value opDerefPointer() 192 { 193 return semanticErrorValue("cannot dereference a ", this); 194 } 195 196 final Value interpretProperty(Context ctx, string prop) 197 { 198 if(Value v = _interpretProperty(ctx, prop)) 199 return v; 200 return semanticErrorValue("cannot calculate property ", prop, " of value ", toStr()); 201 } 202 203 Value _interpretProperty(Context ctx, string prop) 204 { 205 return getType()._interpretProperty(ctx, prop); 206 } 207 208 Value doCast(Value v) 209 { 210 return semanticErrorValue("cannot cast a ", v, " to ", this); 211 } 212 213 Value opIndex(Value v) 214 { 215 return semanticErrorValue("cannot index a ", this); 216 } 217 218 Value opSlice(Value b, Value e) 219 { 220 return semanticErrorValue("cannot slice a ", this); 221 } 222 223 Value opCall(Context sc, Value args) 224 { 225 return semanticErrorValue("cannot call a ", this); 226 } 227 228 //mixin template operators() 229 version(none) 230 Value opassign(string op)(Value v) 231 { 232 TypeInfo ti1 = typeid(this); 233 TypeInfo ti2 = typeid(v); 234 foreach(iv1; BasicTypeValues) 235 { 236 if(ti1 is typeid(iv1)) 237 { 238 foreach(iv2; BasicTypeValues) 239 { 240 if(ti2 is typeid(iv2)) 241 static if (__traits(compiles, { 242 iv1.ValType x; 243 iv2.ValType y; 244 mixin("x " ~ op ~ "y;"); 245 })) 246 { 247 iv2.ValType v2 = (cast(iv2) v).val; 248 static if(op == "/=" || op == "%=") 249 if(v2 == 0) 250 return semanticErrorValue("division by zero"); 251 mixin("(cast(iv1) this).val " ~ op ~ "v2;"); 252 return this; 253 } 254 } 255 } 256 } 257 return semanticErrorValue("cannot execute ", op, " on a ", v, " with a ", this); 258 } 259 260 version(none) 261 Value opBinOp(string op)(Value v) 262 { 263 TypeInfo ti1 = typeid(this); 264 TypeInfo ti2 = typeid(v); 265 foreach(iv1; BasicTypeValues) 266 { 267 if(ti1 is typeid(iv1)) 268 { 269 foreach(iv2; BasicTypeValues) 270 { 271 if(ti2 is typeid(iv2)) 272 { 273 static if (__traits(compiles, { 274 iv1.ValType x; 275 iv2.ValType y; 276 mixin("auto z = x " ~ op ~ "y;"); 277 })) 278 { 279 iv1.ValType v1 = (cast(iv1) this).val; 280 iv2.ValType v2 = (cast(iv2) v).val; 281 static if(op == "/" || op == "%") 282 if(v2 == 0) 283 return semanticErrorValue("division by zero"); 284 mixin("auto z = v1 " ~ op ~ "v2;"); 285 return create(z); 286 } 287 else 288 { 289 return semanticErrorValue("cannot calculate ", op, " on a ", this, " and a ", v); 290 } 291 } 292 } 293 } 294 } 295 return semanticErrorValue("cannot calculate ", op, " on a ", this, " and a ", v); 296 } 297 298 version(none) 299 Value opUnOp(string op)() 300 { 301 TypeInfo ti1 = typeid(this); 302 foreach(iv1; BasicTypeValues) 303 { 304 if(ti1 is typeid(iv1)) 305 { 306 static if (__traits(compiles, { 307 iv1.ValType x; 308 mixin("auto z = " ~ op ~ "x;"); 309 })) 310 { 311 mixin("auto z = " ~ op ~ "(cast(iv1) this).val;"); 312 return create(z); 313 } 314 } 315 } 316 return semanticErrorValue("cannot calculate ", op, " on a ", this); 317 } 318 319 //////////////////////////////////////////////////////////// 320 mixin template mixinBinaryOp1(string op, iv2) 321 { 322 Value binOp1(Value v) 323 { 324 if(auto vv = cast(iv2) v) 325 { 326 iv2.ValType v2 = *vv.pval; 327 static if(op == "/" || op == "%") 328 if(v2 == 0) 329 return semanticErrorValue("division by zero"); 330 mixin("auto z = *pval " ~ op ~ "v2;"); 331 return create(z); 332 } 333 return semanticErrorValue("cannot calculate ", op, " on ", this, " and ", v); 334 } 335 } 336 337 mixin template mixinBinaryOp(string op, Types...) 338 { 339 Value binOp(Value v) 340 { 341 TypeInfo ti = typeid(v); 342 foreach(iv2; Types) 343 { 344 if(ti is typeid(iv2)) 345 { 346 static if (__traits(compiles, { 347 iv2.ValType y; 348 mixin("auto z = (*pval) " ~ op ~ " y;"); 349 })) 350 { 351 iv2.ValType v2 = *(cast(iv2) v).pval; 352 static if(op == "/" || op == "%") 353 if(v2 == 0) 354 return semanticErrorValue("division by zero"); 355 static if(op == "^^" && isIntegral!(ValType) && isIntegral!(iv2.ValType)) 356 if(v2 < 0) 357 return semanticErrorValue("integer pow with negative exponent"); 358 359 mixin("auto z = (*pval) " ~ op ~ " v2;"); 360 return create(z); 361 } 362 else 363 break; 364 } 365 } 366 return semanticErrorValue("cannot calculate ", op, " on a ", this, " and a ", v); 367 } 368 } 369 370 mixin template mixinAssignOp(string op, Types...) 371 { 372 Value assOp(Value v) 373 { 374 if(!mutable) 375 return semanticErrorValue(this, " value is not mutable"); 376 377 TypeInfo ti = typeid(v); 378 foreach(iv2; Types) 379 { 380 if(ti is typeid(iv2)) 381 { 382 static if (__traits(compiles, { 383 iv2.ValType y; 384 mixin("*pval " ~ op ~ " y;"); 385 })) 386 { 387 iv2.ValType v2 = *(cast(iv2) v).pval; 388 static if(op == "/=" || op == "%=") 389 if(v2 == 0) 390 return semanticErrorValue("division by zero"); 391 static if(op == "%=" && (is(T == float) || is(T == double) || is(T == real))) // compiler bug 392 mixin("*pval = *pval % v2;"); 393 else 394 mixin("*pval " ~ op ~ " v2;"); 395 396 debug logInfo("value %s changed by %s to %s", ident, op, toStr()); 397 debug sval = toStr(); 398 return this; 399 } 400 else 401 break; 402 } 403 } 404 return semanticErrorValue("cannot assign ", op, " a ", v, " to a ", this); 405 } 406 } 407 } 408 409 T createInitValue(T)(Context ctx, Value initValue) 410 { 411 T v = new T; 412 if(initValue) 413 v.opBin(ctx, TOK_assign, initValue); 414 return v; 415 } 416 417 alias AliasSeq!(bool, byte, ubyte, short, ushort, 418 int, uint, long, ulong, 419 char, wchar, dchar, 420 float, double, real, 421 ifloat, idouble, ireal, 422 cfloat, cdouble, creal) BasicTypes; 423 424 alias AliasSeq!(BoolValue, ByteValue, UByteValue, ShortValue, UShortValue, 425 IntValue, UIntValue, LongValue, ULongValue, 426 CharValue, WCharValue, DCharValue, 427 FloatValue, DoubleValue, RealValue) BasicTypeValues; 428 alias AliasSeq!(BasicTypeValues, SetLengthValue) RHS_BasicTypeValues; 429 430 alias AliasSeq!(TOK_bool, TOK_byte, TOK_ubyte, TOK_short, TOK_ushort, 431 TOK_int, TOK_uint, TOK_long, TOK_ulong, 432 TOK_char, TOK_wchar, TOK_dchar, 433 TOK_float, TOK_double, TOK_real) BasicTypeTokens; 434 435 int BasicType2Token(T)() { return BasicTypeTokens[staticIndexOf!(T, BasicTypes)]; } 436 437 template BasicType2ValueType(T) 438 { 439 alias BasicTypeValues[staticIndexOf!(T, BasicTypes)] BasicType2ValueType; 440 } 441 442 template Token2BasicType(int tok) 443 { 444 alias BasicTypes[staticIndexOf!(tok, BasicTypeTokens)] Token2BasicType; 445 } 446 447 template Token2ValueType(int tok) 448 { 449 alias BasicTypeValues[staticIndexOf!(tok, BasicTypeTokens)] Token2ValueType; 450 } 451 452 class ValueT(T) : Value 453 { 454 alias T ValType; 455 456 ValType* pval; 457 458 this() 459 { 460 pval = (new ValType[1]).ptr; 461 debug sval = toStr(); 462 } 463 464 static int getTypeIndex() { return staticIndexOf!(ValType, BasicTypes); } 465 466 override Type getType() 467 { 468 static Type instance; 469 if(!instance) 470 instance = createBasicType(BasicTypeTokens[getTypeIndex()]); 471 return instance; 472 } 473 474 override string toStr() 475 { 476 return to!string(*pval); 477 } 478 479 override Value getElement(size_t idx) 480 { 481 alias BasicTypeValues[getTypeIndex()] ValueType; 482 auto v = new ValueType; 483 v.pval = pval + idx; 484 debug v.sval = v.toStr(); 485 return v; 486 } 487 488 override void setElements(size_t oldcnt, size_t newcnt) 489 { 490 ValType[] arr = pval[0 .. oldcnt]; 491 arr.length = newcnt; 492 pval = arr.ptr; 493 debug sval = toStr(); 494 } 495 496 // pragma(msg, ValType); 497 // pragma(msg, text(" compiles?", __traits(compiles, val ? true : false ))); 498 499 // pragma(msg, "toBool " ~ ValType.stringof ~ (__traits(compiles, *pval ? true : false) ? " compiles" : " fails")); 500 static if(__traits(compiles, *pval ? true : false)) 501 override bool toBool() 502 { 503 return *pval ? true : false; 504 } 505 506 // pragma(msg, "toLong " ~ ValType.stringof ~ (__traits(compiles, function long () { ValType v; return v; }) ? " compiles" : " fails")); 507 static if(__traits(compiles, function long () { ValType v; return v; } )) 508 override long toLong() 509 { 510 return *pval; 511 } 512 513 //////////////////////////////////////////////////////////// 514 static string genMixinBinOpAll() 515 { 516 string s; 517 for(int i = TOK_binaryOperatorFirst; i <= TOK_binaryOperatorLast; i++) 518 { 519 static if(!supportUnorderedCompareOps) if(i >= TOK_unorderedOperatorFirst && i <= TOK_unorderedOperatorLast) 520 continue; 521 if(i >= TOK_assignOperatorFirst && i <= TOK_assignOperatorLast) 522 s ~= text("mixin mixinAssignOp!(\"", tokenString(i), "\", RHS_BasicTypeValues) ass_", operatorName(i), ";\n"); 523 else 524 s ~= text("mixin mixinBinaryOp!(\"", tokenString(i), "\", RHS_BasicTypeValues) bin_", operatorName(i), ";\n"); 525 } 526 return s; 527 } 528 529 mixin(genMixinBinOpAll()); 530 mixin mixinBinaryOp!("is", RHS_BasicTypeValues) bin_is; 531 532 static string genBinOpCases() 533 { 534 string s; 535 for(int i = TOK_binaryOperatorFirst; i <= TOK_binaryOperatorLast; i++) 536 { 537 static if(!supportUnorderedCompareOps) if(i >= TOK_unorderedOperatorFirst && i <= TOK_unorderedOperatorLast) 538 continue; 539 if(i >= TOK_assignOperatorFirst && i <= TOK_assignOperatorLast) 540 s ~= text("case ", i, ": return ass_", operatorName(i), ".assOp(v);\n"); 541 else 542 s ~= text("case ", i, ": return bin_", operatorName(i), ".binOp(v);\n"); 543 } 544 return s; 545 } 546 547 override Value opBin(Context ctx, int tokid, Value v) 548 { 549 switch(tokid) 550 { 551 mixin(genBinOpCases()); 552 case TOK_is: return bin_is.binOp(v); 553 default: break; 554 } 555 556 return semanticErrorValue("cannot calculate '", tokenString(tokid), "' on a ", this, " and a ", v); 557 } 558 559 //////////////////////////////////////////////////////////// 560 mixin template mixinUnaryOp(string op) 561 { 562 Value unOp() 563 { 564 static if (__traits(compiles, { mixin("auto z = " ~ op ~ "(*pval);"); })) 565 { 566 mixin("auto z = " ~ op ~ "(*pval);"); 567 return create(z); 568 } 569 else 570 { 571 return semanticErrorValue("cannot calculate '", op, "' on a ", this); 572 } 573 } 574 } 575 576 enum int[] unOps = [ TOK_plusplus, TOK_minusminus, TOK_min, TOK_add, TOK_not, TOK_tilde ]; 577 578 static string genMixinUnOpAll() 579 { 580 string s; 581 foreach(id; unOps) 582 s ~= text("mixin mixinUnaryOp!(\"", tokenString(id), "\") un_", operatorName(id), ";\n"); 583 return s; 584 } 585 586 mixin(genMixinUnOpAll()); 587 588 static string genUnOpCases() 589 { 590 string s; 591 foreach(id; unOps) 592 s ~= text("case ", id, ": return un_", operatorName(id), ".unOp();\n"); 593 return s; 594 } 595 596 override Value opUn(Context ctx, int tokid) 597 { 598 switch(tokid) 599 { 600 case TOK_and: return opRefPointer(); 601 case TOK_mul: return opDerefPointer(); 602 mixin(genUnOpCases()); 603 default: break; 604 } 605 return semanticErrorValue("cannot calculate '", tokenString(tokid), "' on a ", this); 606 } 607 608 override Value doCast(Value v) 609 { 610 if(!mutable) // doCast changes this value 611 return semanticErrorValue(this, " value is not mutable"); 612 613 TypeInfo ti = typeid(v); 614 foreach(iv2; RHS_BasicTypeValues) 615 { 616 if(ti is typeid(iv2)) 617 { 618 static if (__traits(compiles, { 619 iv2.ValType y; 620 *pval = cast(ValType)(y); 621 })) 622 { 623 iv2.ValType v2 = *(cast(iv2) v).pval; 624 *pval = cast(ValType)(v2); 625 626 debug logInfo("value %s changed by cast(" ~ ValType.stringof ~ ") to %s", ident, toStr()); 627 debug sval = toStr(); 628 return this; 629 } 630 else 631 break; 632 } 633 } 634 return super.doCast(v); 635 } 636 } 637 638 class VoidValue : Value 639 { 640 override string toStr() 641 { 642 return "void"; 643 } 644 } 645 646 VoidValue _theVoidValue; 647 648 @property VoidValue theVoidValue() 649 { 650 if(!_theVoidValue) 651 { 652 _theVoidValue = new VoidValue; 653 _theVoidValue.mutable = false; 654 } 655 return _theVoidValue; 656 } 657 658 class ErrorValue : Value 659 { 660 override string toStr() 661 { 662 return "_error_"; 663 } 664 665 override Type getType() 666 { 667 return Singleton!ErrorType.get(); 668 } 669 } 670 671 class NullValue : Value 672 { 673 override string toStr() 674 { 675 return "null"; 676 } 677 678 override Type getType() 679 { 680 return Singleton!NullType.get(); 681 } 682 } 683 684 class BoolValue : ValueT!bool 685 { 686 } 687 688 class ByteValue : ValueT!byte 689 { 690 } 691 692 class UByteValue : ValueT!ubyte 693 { 694 } 695 696 class ShortValue : ValueT!short 697 { 698 } 699 700 class UShortValue : ValueT!ushort 701 { 702 } 703 704 class IntValue : ValueT!int 705 { 706 } 707 708 class UIntValue : ValueT!uint 709 { 710 } 711 712 class LongValue : ValueT!long 713 { 714 } 715 716 class ULongValue : ValueT!ulong 717 { 718 } 719 720 class CharValue : ValueT!char 721 { 722 override string toStr() 723 { 724 return "'" ~ toUTF8Safe(pval[0..1]) ~ "'"; 725 } 726 } 727 728 class WCharValue : ValueT!wchar 729 { 730 override string toStr() 731 { 732 return "'" ~ toUTF8Safe(pval[0..1]) ~ "'w"; 733 } 734 } 735 736 class DCharValue : ValueT!dchar 737 { 738 override string toStr() 739 { 740 return "'" ~ toUTF8Safe(pval[0..1]) ~ "'d"; 741 } 742 } 743 744 class FloatValue : ValueT!float 745 { 746 } 747 748 class DoubleValue : ValueT!double 749 { 750 } 751 752 class RealValue : ValueT!real 753 { 754 } 755 756 class ArrayValueBase : Value 757 { 758 Value first; 759 size_t len; 760 761 override string toStr() 762 { 763 string s = "["; 764 for(size_t i = 0; i < len; i++) 765 { 766 if(i > 0) 767 s ~= ","; 768 Value v = first.getElement(i); 769 s ~= v.toStr(); 770 } 771 s ~= "]"; 772 return s; 773 } 774 775 override Value opIndex(Value v) 776 { 777 int idx = v.toInt(); 778 if(idx < 0 || idx >= len) 779 return semanticErrorValue("index ", idx, " out of bounds on value tuple"); 780 return first.getElement(idx); 781 } 782 783 void setItem(Context ctx, size_t idx, Value v) 784 { 785 if(idx < 0 || idx >= len) 786 return semanticError("index ", idx, " out of bounds on dynamic array"); 787 first.getElement(idx).opBin(ctx, TOK_assign, v); 788 } 789 790 ArrayValueBase createResultArray(Context ctx, Value fv, size_t nlen) 791 { 792 auto dim = new IntegerLiteralExpression(); 793 dim.txt = to!string(nlen); 794 dim.value = nlen; 795 auto ntype = new TypeStaticArray; 796 ntype.addMember(fv.getType().clone()); 797 ntype.addMember(dim); 798 799 auto narr = static_cast!ArrayValueBase(ntype.createValue(ctx, null)); 800 narr.first.getElement(0).opBin(ctx, TOK_assign, fv); 801 return narr; 802 } 803 804 private Value getItem(size_t idx) 805 { 806 return first.getElement(idx); 807 } 808 809 static Value _opBin(Context ctx, int tokid, Value v1, Value v2, bool reverse) 810 { 811 if(reverse) 812 return v2.opBin(ctx, tokid, v1); 813 return v1.opBin(ctx, tokid, v2); 814 } 815 816 Value _opBin(Context ctx, int tokid, Value v, bool reverse) 817 { 818 switch(tokid) 819 { 820 case TOK_equal: 821 case TOK_lt: 822 case TOK_le: 823 case TOK_gt: 824 case TOK_ge: 825 static if(supportUnorderedCompareOps) { 826 case TOK_unord: 827 case TOK_ue: 828 case TOK_lg: 829 case TOK_leg: 830 case TOK_ule: 831 case TOK_ul: 832 case TOK_uge: 833 case TOK_ug: 834 } 835 //case TOK_notcontains: 836 //case TOK_notidentity: 837 //case TOK_is: 838 //case TOK_in: 839 if(auto tv = cast(ArrayValueBase) v) 840 { 841 if(tv.len != len) 842 return Value.create(false); 843 for(int i = 0; i < len; i++) 844 if(!_opBin(ctx, tokid, first.getElement(i), tv.first.getElement(i), reverse).toBool()) 845 return Value.create(false); 846 return Value.create(true); 847 } 848 for(int i = 0; i < len; i++) 849 if(!_opBin(ctx, tokid, first.getElement(i), v, reverse).toBool()) 850 return Value.create(false); 851 return Value.create(true); 852 853 case TOK_notequal: 854 return Value.create(!opBin(ctx, TOK_equal, v).toBool()); 855 856 case TOK_add: 857 case TOK_min: 858 case TOK_mul: 859 case TOK_div: 860 case TOK_mod: 861 case TOK_pow: 862 case TOK_shl: 863 case TOK_shr: 864 case TOK_ushr: 865 case TOK_xor: 866 case TOK_or: 867 case TOK_and: 868 //case TOK_cat: 869 if(auto tv = cast(ArrayValueBase) v) 870 { 871 if(tv.len != len) 872 return semanticErrorValue(tokenString(tokid), " on arrays of different length ", len, " and ", tv.len); 873 874 if(len == 0) 875 return getType().createValue(ctx, null); 876 877 Value fv = _opBin(ctx, tokid, first.getElement(0), tv.first.getElement(0), reverse); 878 auto narr = createResultArray(ctx, fv, len); 879 for(int i = 1; i < len; i++) 880 { 881 fv = _opBin(ctx, tokid, first.getElement(i), tv.first.getElement(i), reverse); 882 narr.first.getElement(i).opBin(ctx, TOK_assign, fv); 883 } 884 debug narr.sval = narr.toStr(); 885 return narr; 886 } 887 888 if(len == 0) 889 return getType().createValue(ctx, null); 890 891 Value fv = _opBin(ctx, tokid, first.getElement(0), v, reverse); 892 auto narr = createResultArray(ctx, fv, len); 893 for(int i = 1; i < len; i++) 894 { 895 fv = _opBin(ctx, tokid, first.getElement(i), v, reverse); 896 narr.first.getElement(i).opBin(ctx, TOK_assign, fv); 897 } 898 debug narr.sval = narr.toStr(); 899 return narr; 900 901 default: 902 if(reverse) 903 return super.opBin_r(ctx, tokid, v); 904 return super.opBin(ctx, tokid, v); 905 } 906 } 907 908 override Value opBin(Context ctx, int tokid, Value v) 909 { 910 switch(tokid) 911 { 912 case TOK_addass: 913 case TOK_minass: 914 case TOK_mulass: 915 case TOK_divass: 916 case TOK_modass: 917 case TOK_powass: 918 case TOK_shlass: 919 case TOK_shrass: 920 case TOK_ushrass: 921 case TOK_xorass: 922 case TOK_orass: 923 case TOK_andass: 924 //case TOK_catass: 925 if(auto tv = cast(ArrayValueBase) v) 926 { 927 if(tv.len != len) 928 return semanticErrorValue(tokenString(tokid), " on arrays of different length ", len, " and ", tv.len); 929 for(int i = 0; i < len; i++) 930 first.getElement(i).opBin(ctx, tokid, tv.first.getElement(i)); 931 } 932 else 933 { 934 for(int i = 0; i < len; i++) 935 first.getElement(i).opBin(ctx, tokid, v); 936 } 937 debug sval = toStr(); 938 return this; 939 940 default: 941 return _opBin(ctx, tokid, v, false); 942 } 943 } 944 945 override Value opBin_r(Context ctx, int tokid, Value v) 946 { 947 return _opBin(ctx, tokid, v, true); 948 } 949 950 override Value opUn(Context ctx, int tokid) 951 { 952 switch(tokid) 953 { 954 case TOK_add: 955 case TOK_min: 956 case TOK_not: 957 case TOK_tilde: 958 if(len == 0) 959 return getType().createValue(ctx, null); 960 961 Value fv = first.getElement(0).opUn(ctx, tokid); 962 auto narr = createResultArray(ctx, fv, len); 963 for(int i = 1; i < len; i++) 964 { 965 fv = first.getElement(i).opUn(ctx, tokid); 966 narr.first.getElement(i).opBin(ctx, TOK_assign, fv); 967 } 968 return narr; 969 default: 970 return super.opUn(ctx, tokid); 971 } 972 } 973 } 974 975 class ArrayValue(T) : ArrayValueBase 976 { 977 T type; 978 979 void setLength(Context ctx, size_t newlen) 980 { 981 if(newlen > len) 982 { 983 if(len == 0) 984 { 985 first = type.getNextType().createValue(ctx, null); 986 first.setElements(1, newlen); 987 } 988 else 989 first.setElements(len, newlen); 990 } 991 len = newlen; 992 // intermediate state, cannot set sval yet 993 } 994 995 override Value opSlice(Value b, Value e) 996 { 997 int idxb = b.toInt(); 998 int idxe = e.toInt(); 999 if(idxb < 0 || idxb > len || idxe < idxb || idxe > len) 1000 return semanticErrorValue("slice [", idxb, "..", idxe, "] out of bounds on value ", toStr()); 1001 auto nv = type.opSlice(idxb, idxe).createValue(nullContext, null); 1002 if(auto arr = cast(ArrayValueBase) nv) 1003 { 1004 if(idxb == 0) 1005 arr.first = first; 1006 else 1007 arr.first = first.getElement(idxb); 1008 arr.len = idxe - idxb; 1009 } 1010 debug nv.sval = nv.toStr(); 1011 return nv; 1012 } 1013 1014 } 1015 1016 class DynArrayValue : ArrayValue!TypeDynamicArray 1017 { 1018 this(TypeDynamicArray t) 1019 { 1020 type = t; 1021 debug sval = toStr(); 1022 } 1023 1024 override string toStr() 1025 { 1026 if(isString()) 1027 return "\"" ~ toMixin() ~ "\""; 1028 1029 return super.toStr(); 1030 } 1031 1032 override Type getType() 1033 { 1034 return type; 1035 } 1036 1037 override Value opBin(Context ctx, int tokid, Value v) 1038 { 1039 switch(tokid) 1040 { 1041 case TOK_assign: 1042 if(auto tv = cast(ArrayValueBase) v) 1043 { 1044 if(tv.len == 0) 1045 first = null; 1046 else 1047 first = tv.first.getElement(0); // create copy of "ptr" value 1048 len = tv.len; 1049 } 1050 else if(cast(NullValue) v) 1051 { 1052 first = null; 1053 len = 0; 1054 } 1055 else 1056 return semanticErrorValue("cannot assign ", v, " to ", this); 1057 debug sval = toStr(); 1058 return this; 1059 1060 case TOK_tilde: 1061 if(auto ev = cast(ErrorValue) v) 1062 return v; 1063 auto nv = new DynArrayValue(type); 1064 if(auto tv = cast(DynArrayValue) v) 1065 { 1066 nv.setLength(ctx, len + tv.len); 1067 for(size_t i = 0; i < len; i++) 1068 nv.setItem(ctx, i, getItem(i)); 1069 for(size_t i = 0; i < tv.len; i++) 1070 nv.setItem(ctx, len + i, tv.getItem(i)); 1071 } 1072 else 1073 { 1074 nv.setLength(ctx, len + 1); 1075 for(size_t i = 0; i < len; i++) 1076 nv.setItem(ctx, i, getItem(i)); 1077 nv.setItem(ctx, len, v); 1078 } 1079 debug nv.sval = nv.toStr(); 1080 return nv; 1081 1082 case TOK_catass: 1083 size_t oldlen = len; 1084 if(auto ev = cast(ErrorValue) v) 1085 return v; 1086 if(auto tv = cast(DynArrayValue) v) 1087 { 1088 setLength(ctx, len + tv.len); 1089 for(size_t i = 0; i < tv.len; i++) 1090 setItem(ctx, oldlen + i, tv.getItem(i)); 1091 } 1092 else 1093 { 1094 setLength(ctx, len + 1); 1095 setItem(ctx, oldlen, v); 1096 } 1097 debug sval = toStr(); 1098 return this; 1099 1100 default: 1101 return super.opBin(ctx, tokid, v); 1102 } 1103 } 1104 1105 bool isString() 1106 { 1107 auto t = type.getNextType().unqualified(); 1108 1109 if(auto bt = cast(BasicType) t) 1110 if(bt.id == TOK_char || bt.id == TOK_wchar || bt.id == TOK_dchar) 1111 return true; 1112 return false; 1113 } 1114 1115 override PointerValue toPointer(TypePointer to) 1116 { 1117 // TODO: implementation here just to satisfy string -> C const char* conversion 1118 if(isString()) 1119 { 1120 Value nfirst = first; 1121 auto nt = type.getNextType(); 1122 auto nto = to.getNextType(); 1123 if(literal) 1124 { 1125 // automatic conversion between string,wstring,dstring 1126 auto uto = nto.unqualified(); 1127 auto ut = nt.unqualified(); 1128 if(auto bt = cast(BasicType) ut) 1129 if(auto bto = cast(BasicType) uto) 1130 { 1131 if(bt.id != bto.id) 1132 { 1133 semanticErrorValue("literal string conversion not implemented!"); 1134 1135 DynArrayValue nv; 1136 switch(bto.id) 1137 { 1138 case TOK_char: 1139 string s; 1140 switch(bt.id) 1141 { 1142 case TOK_wchar: 1143 case TOK_dchar: 1144 default: 1145 break; 1146 } 1147 nv = createStringValue(s); 1148 break; 1149 case TOK_wchar: 1150 wstring s; 1151 switch(bt.id) 1152 { 1153 case TOK_char: 1154 case TOK_dchar: 1155 default: 1156 break; 1157 } 1158 nv = createStringValue(s); 1159 break; 1160 case TOK_dchar: 1161 dstring s; 1162 switch(bt.id) 1163 { 1164 case TOK_char: 1165 case TOK_wchar: 1166 default: 1167 break; 1168 } 1169 nv = createStringValue(s); 1170 break; 1171 default: 1172 assert(0); 1173 } 1174 nfirst = nv.first; 1175 } 1176 } 1177 } 1178 PointerValue pv = new PointerValue; 1179 auto tp = new TypePointer; 1180 tp.setNextType(nto); 1181 pv.type = tp; 1182 pv.pval = nfirst; 1183 debug pv.sval = pv.toStr(); 1184 return pv; 1185 } 1186 return super.toPointer(to); 1187 } 1188 1189 override string toMixin() 1190 { 1191 if(isString()) 1192 { 1193 if(len == 0) 1194 return ""; 1195 if(auto cv = cast(CharValue)first) 1196 return toUTF8Safe(cv.pval[0..len]); 1197 if(auto wv = cast(WCharValue)first) 1198 return toUTF8Safe(wv.pval[0..len]); 1199 if(auto dv = cast(DCharValue)first) 1200 return toUTF8Safe(dv.pval[0..len]); 1201 } 1202 return super.toMixin(); 1203 } 1204 1205 override Value _interpretProperty(Context ctx, string prop) 1206 { 1207 switch(prop) 1208 { 1209 case "length": 1210 return new SetLengthValue(this); 1211 default: 1212 return super._interpretProperty(ctx, prop); 1213 } 1214 } 1215 } 1216 1217 class SetLengthValue : UIntValue 1218 { 1219 DynArrayValue array; 1220 1221 this(DynArrayValue a) 1222 { 1223 array = a; 1224 super(); 1225 debug sval = toStr(); 1226 } 1227 1228 override string toStr() 1229 { 1230 return array.toStr() ~ ".length"; 1231 } 1232 1233 override Value opBin(Context ctx, int tokid, Value v) 1234 { 1235 switch(tokid) 1236 { 1237 case TOK_assign: 1238 int len = v.toInt(); 1239 array.setLength(ctx, len); 1240 debug array.sval = array.toStr(); 1241 return this; 1242 default: 1243 return super.opBin(ctx, tokid, v); 1244 } 1245 } 1246 1247 } 1248 1249 DynArrayValue createStringValue(C)(immutable(C)[] s) 1250 { 1251 DynArrayValue dav = new DynArrayValue(getTypeString!C()); 1252 auto cv = new BasicType2ValueType!C; 1253 cv.mutable = false; 1254 cv.pval = cast(C*) s.ptr; 1255 debug cv.sval = cv.toStr(); 1256 dav.first = cv; 1257 dav.len = s.length; 1258 dav.literal = true; 1259 debug dav.sval = dav.toStr(); 1260 return dav; 1261 } 1262 1263 class StaticArrayValue : ArrayValue!TypeStaticArray 1264 { 1265 this(TypeStaticArray t) 1266 { 1267 type = t; 1268 debug sval = toStr(); 1269 } 1270 1271 override Type getType() 1272 { 1273 return type; 1274 } 1275 1276 override Value opBin(Context ctx, int tokid, Value v) 1277 { 1278 switch(tokid) 1279 { 1280 case TOK_assign: 1281 if(auto tv = cast(ArrayValueBase) v) 1282 { 1283 if(tv.len != len) 1284 return semanticErrorValue("different length in assignment from ", v, " to ", this); 1285 1286 IntValue idxval = new IntValue; 1287 for(int i = 0; i < len; i++) 1288 { 1289 *(idxval.pval) = i; 1290 Value vidx = v.opIndex(idxval); 1291 auto idx = opIndex(idxval); 1292 idx.opBin(ctx, TOK_assign, vidx); 1293 } 1294 } 1295 else 1296 return semanticErrorValue("cannot assign ", v, " to ", this); 1297 debug sval = toStr(); 1298 return this; 1299 1300 default: 1301 return super.opBin(ctx, tokid, v); 1302 } 1303 } 1304 1305 } 1306 1307 alias AliasSeq!(CharValue, WCharValue, DCharValue, StringValue) StringTypeValues; 1308 1309 class StringValue : Value 1310 { 1311 alias string ValType; 1312 1313 ValType* pval; 1314 1315 this() 1316 { 1317 pval = (new string[1]).ptr; 1318 debug sval = toStr(); 1319 } 1320 1321 this(string s) 1322 { 1323 pval = (new string[1]).ptr; 1324 *pval = s; 1325 debug sval = toStr(); 1326 } 1327 1328 static StringValue _create(string s) 1329 { 1330 StringValue sv = new StringValue(s); 1331 return sv; 1332 } 1333 1334 override Type getType() 1335 { 1336 return getTypeString!char(); 1337 } 1338 1339 override string toStr() 1340 { 1341 return '"' ~ *pval ~ '"'; 1342 } 1343 1344 override string toMixin() 1345 { 1346 return *pval; 1347 } 1348 1349 override PointerValue toPointer(TypePointer to) 1350 { 1351 // TODO: implementation here just to satisfy string -> C const char* conversion 1352 PointerValue pv = new PointerValue; 1353 pv.type = new TypePointer; 1354 pv.type.addMember(createBasicType(TOK_char)); 1355 pv.pval = this; 1356 debug pv.sval = pv.toStr(); 1357 return pv; 1358 } 1359 1360 override bool toBool() 1361 { 1362 return *pval !is null; 1363 } 1364 1365 mixin mixinAssignOp!("=", StringTypeValues) ass_assign; 1366 mixin mixinAssignOp!("~=", StringTypeValues) ass_catass; 1367 mixin mixinBinaryOp!("~", StringTypeValues) bin_tilde; 1368 mixin mixinBinaryOp1!("<", StringValue) bin_lt; 1369 mixin mixinBinaryOp1!(">", StringValue) bin_gt; 1370 mixin mixinBinaryOp1!("<=", StringValue) bin_le; 1371 mixin mixinBinaryOp1!(">=", StringValue) bin_ge; 1372 mixin mixinBinaryOp1!("==", StringValue) bin_equal; 1373 mixin mixinBinaryOp1!("!=", StringValue) bin_notequal; 1374 1375 override Value opBin(Context ctx, int tokid, Value v) 1376 { 1377 switch(tokid) 1378 { 1379 case TOK_assign: 1380 auto rv = ass_assign.assOp(v); 1381 debug sval = toStr(); 1382 return rv; 1383 case TOK_catass: 1384 auto rv = ass_catass.assOp(v); 1385 debug sval = toStr(); 1386 return rv; 1387 case TOK_tilde: return bin_tilde.binOp(v); 1388 case TOK_lt: return bin_lt.binOp1(v); 1389 case TOK_gt: return bin_gt.binOp1(v); 1390 case TOK_le: return bin_le.binOp1(v); 1391 case TOK_ge: return bin_ge.binOp1(v); 1392 case TOK_equal: return bin_equal.binOp1(v); 1393 case TOK_notequal: return bin_notequal.binOp1(v); 1394 default: return super.opBin(ctx, tokid, v); 1395 } 1396 } 1397 1398 override Value opIndex(Value v) 1399 { 1400 int idx = v.toInt(); 1401 if(idx < 0 || idx >= (*pval).length) 1402 return semanticErrorValue("index ", idx, " out of bounds on ", *pval); 1403 return create((*pval)[idx]); 1404 } 1405 } 1406 1407 class PointerValue : Value 1408 { 1409 TypePointer type; // type of pointer 1410 Value pval; // Value is a class type, so its a reference, i.e. a pointer to the value 1411 1412 override string toStr() 1413 { 1414 return pval ? "&" ~ pval.toStr() : "null"; 1415 } 1416 1417 static PointerValue _create(TypePointer type, Value v) 1418 { 1419 PointerValue pv = new PointerValue; 1420 pv.type = type; 1421 pv.pval = v; 1422 debug pv.sval = pv.toStr(); 1423 return pv; 1424 } 1425 1426 override Type getType() 1427 { 1428 return type; 1429 } 1430 1431 override bool toBool() 1432 { 1433 return pval !is null; 1434 } 1435 1436 override PointerValue toPointer(TypePointer to) 1437 { 1438 return this; 1439 } 1440 1441 override Value opDerefPointer() 1442 { 1443 if(!pval) 1444 return semanticErrorValue("dereferencing a null pointer"); 1445 return pval; 1446 } 1447 1448 override Value opBin(Context ctx, int tokid, Value v) 1449 { 1450 switch(tokid) 1451 { 1452 case TOK_assign: 1453 auto pv = v.toPointer(type); 1454 if(!v) 1455 pval = null; 1456 else if(!pv) 1457 return semanticErrorValue("cannot convert value ", v, " to pointer of type ", type); 1458 else if(type.convertableFromImplicite(pv.type)) 1459 pval = pv.pval; 1460 else 1461 return semanticErrorValue("cannot convert pointer type ", pv.type, " to ", type); 1462 debug sval = toStr(); 1463 return this; 1464 case TOK_equal: 1465 case TOK_notequal: 1466 auto pv = cast(PointerValue)v; 1467 if(!pv || (!pv.type.convertableFromImplicite(type) && !type.convertableFromImplicite(pv.type))) 1468 return semanticErrorValue("cannot compare types ", v.getType(), " and ", type); 1469 if(tokid == TOK_equal) 1470 return Value.create(pv.pval is pval); 1471 else 1472 return Value.create(pv.pval !is pval); 1473 default: 1474 return super.opBin(ctx, tokid, v); 1475 } 1476 } 1477 1478 override Value _interpretProperty(Context ctx, string prop) 1479 { 1480 switch(prop) 1481 { 1482 case "init": 1483 return _create(type, null); 1484 default: 1485 if(!pval) 1486 return semanticErrorValue("dereferencing null pointer"); 1487 return pval._interpretProperty(ctx, prop); 1488 } 1489 } 1490 } 1491 1492 class TypeValue : Value 1493 { 1494 Type type; 1495 1496 this(Type t) 1497 { 1498 type = t; 1499 debug sval = toStr(); 1500 } 1501 1502 override Type getType() 1503 { 1504 return type; 1505 } 1506 1507 override string toStr() 1508 { 1509 return writeD(type); 1510 } 1511 1512 override Value opCall(Context sc, Value vargs) 1513 { 1514 return type.createValue(sc, vargs); 1515 } 1516 } 1517 1518 class AliasValue : Value 1519 { 1520 IdentifierList id; 1521 1522 this(IdentifierList _id) 1523 { 1524 id = _id; 1525 debug sval = toStr(); 1526 } 1527 1528 Node resolve() 1529 { 1530 return id.resolve(); 1531 } 1532 1533 override Type getType() 1534 { 1535 return id.calcType(); 1536 } 1537 1538 override string toStr() 1539 { 1540 return writeD(id); 1541 } 1542 } 1543 1544 class TupleValue : Value 1545 { 1546 private: 1547 Value[] _values; 1548 public: 1549 this() 1550 { 1551 debug sval = toStr(); 1552 } 1553 1554 @property Value[] values() 1555 { 1556 return _values; 1557 } 1558 @property void values(Value[] v) 1559 { 1560 _values = v; 1561 debug sval = toStr(); 1562 } 1563 void addValue(Value v) 1564 { 1565 _values ~= v; 1566 debug sval = toStr(); 1567 } 1568 void setValuesLength(size_t len) 1569 { 1570 _values.length = len; 1571 } 1572 1573 override string toStr() 1574 { 1575 return _toStr("(", ")"); 1576 } 1577 1578 string _toStr(string open, string close) 1579 { 1580 string s = open; 1581 foreach(i, v; values) 1582 { 1583 if(i > 0) 1584 s ~= ","; 1585 s ~= v.toStr(); 1586 } 1587 s ~= close; 1588 return s; 1589 } 1590 1591 override Value opIndex(Value v) 1592 { 1593 int idx = v.toInt(); 1594 if(idx < 0 || idx >= values.length) 1595 return semanticErrorValue("index ", idx, " out of bounds on value tuple"); 1596 return values[idx]; 1597 } 1598 1599 override Value opSlice(Value b, Value e) 1600 { 1601 int idxb = b.toInt(); 1602 int idxe = e.toInt(); 1603 if(idxb < 0 || idxb > values.length || idxe < idxb || idxe > values.length) 1604 return semanticErrorValue("slice [", idxb, "..", idxe, "] out of bounds on value tuple"); 1605 auto nv = new TupleValue; 1606 nv._values = _values[idxb..idxe]; 1607 return nv; 1608 } 1609 1610 override Value opBin(Context ctx, int tokid, Value v) 1611 { 1612 switch(tokid) 1613 { 1614 case TOK_equal: 1615 if(auto tv = cast(TupleValue) v) 1616 { 1617 if(tv.values.length != values.length) 1618 return Value.create(false); 1619 for(int i = 0; i < values.length; i++) 1620 if(!values[i].opBin(ctx, TOK_equal, tv.values[i]).toBool()) 1621 return Value.create(false); 1622 return Value.create(true); 1623 } 1624 return semanticErrorValue("cannot compare ", v, " to ", this); 1625 case TOK_notequal: 1626 return Value.create(!opBin(ctx, TOK_equal, v).toBool()); 1627 1628 case TOK_assign: 1629 if(auto tv = cast(TupleValue) v) 1630 values = tv.values; 1631 else 1632 return semanticErrorValue("cannot assign ", v, " to ", this); 1633 debug sval = toStr(); 1634 return this; 1635 1636 case TOK_tilde: 1637 auto nv = new TupleValue; 1638 if(auto tv = cast(TupleValue) v) 1639 nv._values = _values ~ tv._values; 1640 else 1641 nv._values = _values ~ v; 1642 return nv; 1643 1644 case TOK_catass: 1645 if(auto tv = cast(TupleValue) v) 1646 _values ~= tv._values; 1647 else 1648 _values ~= v; 1649 return this; 1650 1651 default: 1652 return super.opBin(ctx, tokid, v); 1653 } 1654 } 1655 1656 override Value _interpretProperty(Context ctx, string prop) 1657 { 1658 switch(prop) 1659 { 1660 case "length": 1661 return create(values.length); 1662 default: 1663 return super._interpretProperty(ctx, prop); 1664 } 1665 } 1666 } 1667 1668 Value doCall(CallableNode funcNode, Context sc, ParameterList params, Value vargs) 1669 { 1670 if(!funcNode) 1671 return semanticErrorValue("calling null reference"); 1672 1673 auto ctx = new Context(sc); 1674 1675 auto args = static_cast!TupleValue(vargs); 1676 auto numparams = params.members.length; 1677 auto numargs = args ? args.values.length : 0; 1678 if(params.anonymous_varargs) 1679 { 1680 if(numargs < numparams) 1681 return semanticErrorValue("too few arguments"); 1682 // TODO: add _arguments and _argptr variables 1683 } 1684 else if(params.varargs) 1685 { 1686 if(numargs < numparams - 1) 1687 return semanticErrorValue("too few arguments"); 1688 numparams--; 1689 } 1690 else if(numargs != numparams) 1691 return semanticErrorValue("incorrect number of arguments"); 1692 1693 for(size_t p = 0; p < numparams; p++) 1694 { 1695 if(auto decl = params.getParameter(p).getParameterDeclarator().getDeclarator()) 1696 { 1697 Value v = args.values[p]; 1698 Type t = v.getType(); 1699 if(!decl.isRef) 1700 v = decl.calcType().createValue(sc, v); // if not ref, always create copy 1701 else if(!t.compare(decl.calcType())) 1702 return semanticErrorValue("cannot create reference of incompatible type", v.getType()); 1703 ctx.setValue(decl, v); 1704 } 1705 } 1706 if(params.varargs) 1707 { 1708 // TODO: pack remaining arguments into array 1709 auto decl = params.getParameter(numparams).getParameterDeclarator(); 1710 auto vdecl = decl.getDeclarator(); 1711 if(!vdecl) 1712 return semanticErrorValue("cannot pack remaining arguments into parameter", decl); 1713 Value arr = vdecl.calcType().createValue(ctx, null); 1714 if(auto darr = cast(DynArrayValue) arr) 1715 { 1716 darr.setLength(ctx, args.values.length - numparams); 1717 for(size_t n = numparams; n < args.values.length; n++) 1718 { 1719 Value v = args.values[n]; 1720 Type t = v.getType(); 1721 v = t.createValue(sc, v); // if not ref, always create copy 1722 darr.setItem(ctx, n - numparams, v); 1723 } 1724 debug darr.sval = darr.toStr(); 1725 ctx.setValue(vdecl, darr); 1726 } 1727 else 1728 return semanticErrorValue("array type expected for variable argument parameter"); 1729 } 1730 Value retVal = funcNode.interpretCall(ctx); 1731 return retVal ? retVal : theVoidValue; 1732 } 1733 1734 class FunctionValue : Value 1735 { 1736 TypeFunction functype; 1737 bool adr; 1738 1739 override string toStr() 1740 { 1741 if(!functype.funcDecl) 1742 return "null"; 1743 if(!functype.funcDecl.ident) 1744 return "_funcliteral_"; 1745 return "&" ~ functype.funcDecl.ident; 1746 } 1747 1748 override Value opCall(Context sc, Value vargs) 1749 { 1750 return doCall(functype.funcDecl, threadContext, functype.getParameters(), vargs); 1751 } 1752 1753 override Value opBin(Context ctx, int tokid, Value v) 1754 { 1755 FunctionValue dg = cast(FunctionValue) v; 1756 if(!dg) 1757 return semanticErrorValue("cannot assign ", v, " to function"); 1758 //! TODO: verify compatibility of types 1759 switch(tokid) 1760 { 1761 case TOK_assign: 1762 functype = dg.functype; 1763 debug sval = toStr(); 1764 return this; 1765 case TOK_equal: 1766 return Value.create(functype.compare(dg.functype)); 1767 case TOK_notequal: 1768 return Value.create(!functype.compare(dg.functype)); 1769 default: 1770 return super.opBin(ctx, tokid, v); 1771 } 1772 } 1773 1774 override Type getType() 1775 { 1776 return functype; 1777 } 1778 1779 override Value opRefPointer() 1780 { 1781 adr = true; 1782 return this; 1783 } 1784 } 1785 1786 class DelegateValue : FunctionValue 1787 { 1788 Context context; 1789 1790 override Value opCall(Context sc, Value vargs) 1791 { 1792 return doCall(functype.funcDecl, context, functype.getParameters(), vargs); 1793 } 1794 1795 override Value opBin(Context ctx, int tokid, Value v) 1796 { 1797 DelegateValue dg = cast(DelegateValue) v; 1798 if(!dg) 1799 return semanticErrorValue("cannot assign ", v, " to delegate"); 1800 //! TODO: verify compatibility of types 1801 switch(tokid) 1802 { 1803 case TOK_assign: 1804 context = dg.context; 1805 functype = dg.functype; 1806 debug sval = toStr(); 1807 return this; 1808 case TOK_equal: 1809 return Value.create((context is dg.context) && functype.compare(dg.functype)); 1810 case TOK_notequal: 1811 return Value.create((context !is dg.context) || !functype.compare(dg.functype)); 1812 default: 1813 return super.opBin(ctx, tokid, v); 1814 } 1815 } 1816 } 1817 1818 class AggrValue : TupleValue 1819 { 1820 Context outer; 1821 AggrContext context; 1822 1823 abstract override Aggregate getType(); 1824 1825 override string toStr() 1826 { 1827 if(auto t = getType()) 1828 return t.ident ~ _toStr("{", "}"); 1829 return "<notype>" ~ _toStr("{", "}"); 1830 } 1831 1832 override Value _interpretProperty(Context ctx, string prop) 1833 { 1834 auto type = getType(); 1835 if(Value v = type.getProperty(this, prop, true)) 1836 return v; 1837 if(Value v = type.getStaticProperty(prop)) 1838 return v; 1839 if(!context) 1840 context = new AggrContext(outer, this); 1841 if(Value v = super._interpretProperty(context, prop)) 1842 return v; 1843 1844 //if(outer) // TODO: outer checked after super? 1845 // if(Value v = outer._interpretProperty(ctx, prop)) 1846 // return v; 1847 // 1848 return null; 1849 } 1850 1851 override Value opBin(Context ctx, int tokid, Value v) 1852 { 1853 switch(tokid) 1854 { 1855 case TOK_equal: 1856 if(Value fv = getType().getProperty(this, "opEquals", true)) 1857 { 1858 auto tctx = new AggrContext(ctx, this); 1859 auto tv = new TupleValue; 1860 tv.addValue(v); 1861 return fv.opCall(tctx, tv); 1862 } 1863 return super.opBin(ctx, tokid, v); 1864 case TOK_is: 1865 return Value.create(v is this); 1866 case TOK_notidentity: 1867 return Value.create(v !is this); 1868 default: 1869 return super.opBin(ctx, tokid, v); 1870 } 1871 } 1872 } 1873 1874 class AggrValueT(T) : AggrValue 1875 { 1876 T type; 1877 1878 this(T t) 1879 { 1880 type = t; 1881 debug sval = toStr(); 1882 } 1883 1884 override Aggregate getType() 1885 { 1886 return type; 1887 } 1888 } 1889 1890 class StructValue : AggrValueT!Struct 1891 { 1892 this(Struct t) 1893 { 1894 super(t); 1895 } 1896 } 1897 1898 class UnionValue : AggrValueT!Union 1899 { 1900 this(Union t) 1901 { 1902 super(t); 1903 } 1904 } 1905 1906 class ClassInstanceValue : AggrValueT!Class 1907 { 1908 this(Class t) 1909 { 1910 super(t); 1911 } 1912 } 1913 1914 class ReferenceValue : Value 1915 { 1916 ClassInstanceValue instance; 1917 bool insideToStr; 1918 1919 override string toStr() 1920 { 1921 if(!instance) 1922 return "null"; 1923 if(insideToStr) 1924 return "recursive-toStr"; 1925 insideToStr = true; 1926 scope(exit) insideToStr = false; 1927 return instance.toStr(); 1928 } 1929 1930 override Value opBin(Context ctx, int tokid, Value v) 1931 { 1932 ClassInstanceValue other; 1933 if(auto cv = cast(ReferenceValue) v) 1934 other = cv.instance; 1935 else if(!cast(NullValue) v) 1936 return super.opBin(ctx, tokid, v); 1937 1938 switch(tokid) 1939 { 1940 case TOK_assign: 1941 instance = other; 1942 debug sval = toStr(); 1943 return this; 1944 case TOK_equal: 1945 if(instance is other) 1946 return Value.create(true); 1947 if(!instance || !other) 1948 return Value.create(false); 1949 return instance.opBin(ctx, TOK_equal, other); 1950 case TOK_is: 1951 return Value.create(instance is other); 1952 case TOK_notidentity: 1953 return Value.create(instance !is other); 1954 default: 1955 return super.opBin(ctx, tokid, v); 1956 } 1957 } 1958 1959 } 1960 1961 class ReferenceValueT(T) : ReferenceValue 1962 { 1963 T type; 1964 1965 this(T t) 1966 { 1967 type = t; 1968 } 1969 1970 override T getType() 1971 { 1972 return type; 1973 } 1974 1975 override Value _interpretProperty(Context ctx, string prop) 1976 { 1977 if(instance) 1978 if(Value v = instance._interpretProperty(ctx, prop)) 1979 return v; 1980 if(Value v = type.getStaticProperty(prop)) 1981 return v; 1982 return super._interpretProperty(ctx, prop); 1983 } 1984 1985 override Value doCast(Value v) 1986 { 1987 if(cast(NullValue) v) 1988 { 1989 instance = null; 1990 return this; 1991 } 1992 if(auto cv = cast(ReferenceValue) v) 1993 { 1994 if(type.convertableFrom(cv.getType(), Type.ConversionFlags.kImpliciteConversion)) 1995 instance = cv.instance; 1996 else 1997 instance = null; 1998 return this; 1999 } 2000 return super.doCast(v); 2001 } 2002 } 2003 2004 class ClassValue : ReferenceValueT!Class 2005 { 2006 this(Class t, ClassInstanceValue inst = null) 2007 { 2008 super(t); 2009 instance = inst; 2010 validate(); 2011 } 2012 } 2013 2014 class InterfaceValue : ReferenceValueT!Intrface 2015 { 2016 this(Intrface t) 2017 { 2018 super(t); 2019 validate(); 2020 } 2021 } 2022 2023 class AnonymousClassInstanceValue : AggrValueT!AnonymousClass 2024 { 2025 this(AnonymousClass t) 2026 { 2027 super(t); 2028 validate(); 2029 } 2030 } 2031 2032 class AnonymousClassValue : ReferenceValueT!AnonymousClass 2033 { 2034 this(AnonymousClass t) 2035 { 2036 super(t); 2037 validate(); 2038 } 2039 } 2040 2041 //////////////////////////////////////////////////////////////////////// 2042 // program control 2043 class ProgramControlValue : Value 2044 { 2045 string label; 2046 } 2047 2048 class BreakValue : ProgramControlValue 2049 { 2050 this(string s) 2051 { 2052 label = s; 2053 } 2054 } 2055 2056 class ContinueValue : ProgramControlValue 2057 { 2058 this(string s) 2059 { 2060 label = s; 2061 } 2062 } 2063 2064 class GotoValue : ProgramControlValue 2065 { 2066 this(string s) 2067 { 2068 label = s; 2069 } 2070 } 2071 2072 class GotoCaseValue : ProgramControlValue 2073 { 2074 this(string s) 2075 { 2076 label = s; 2077 } 2078 }