1 #ifndef THINGDEF_EXP_H 2 #define THINGDEF_EXP_H 3 4 /* 5 ** thingdef_exp.h 6 ** 7 ** Expression evaluation 8 ** 9 **--------------------------------------------------------------------------- 10 ** Copyright 2008 Christoph Oelckers 11 ** All rights reserved. 12 ** 13 ** Redistribution and use in source and binary forms, with or without 14 ** modification, are permitted provided that the following conditions 15 ** are met: 16 ** 17 ** 1. Redistributions of source code must retain the above copyright 18 ** notice, this list of conditions and the following disclaimer. 19 ** 2. Redistributions in binary form must reproduce the above copyright 20 ** notice, this list of conditions and the following disclaimer in the 21 ** documentation and/or other materials provided with the distribution. 22 ** 3. The name of the author may not be used to endorse or promote products 23 ** derived from this software without specific prior written permission. 24 ** 4. When not used as part of ZDoom or a ZDoom derivative, this code will be 25 ** covered by the terms of the GNU General Public License as published by 26 ** the Free Software Foundation; either version 2 of the License, or (at 27 ** your option) any later version. 28 ** 29 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 30 ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 31 ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 32 ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 33 ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 34 ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 38 ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 **--------------------------------------------------------------------------- 40 ** 41 */ 42 43 #include "m_random.h" 44 45 #define CHECKRESOLVED() if (isresolved) return this; isresolved=true; 46 #define SAFE_DELETE(p) if (p!=NULL) { delete p; p=NULL; } 47 #define RESOLVE(p,c) if (p!=NULL) p = p->Resolve(c) 48 #define ABORT(p) if (!(p)) { delete this; return NULL; } 49 #define SAFE_RESOLVE(p,c) RESOLVE(p,c); ABORT(p) 50 51 extern PSymbolTable GlobalSymbols; 52 53 //========================================================================== 54 // 55 // 56 // 57 //========================================================================== 58 59 struct FCompileContext 60 { 61 const PClass *cls; 62 bool lax; 63 bool isconst; 64 65 FCompileContext(const PClass *_cls = NULL, bool _lax = false, bool _isconst = false) 66 { 67 cls = _cls; 68 lax = _lax; 69 isconst = _isconst; 70 } 71 FindInClassFCompileContext72 PSymbol *FindInClass(FName identifier) 73 { 74 return cls? cls->Symbols.FindSymbol(identifier, true) : NULL; 75 } FindGlobalFCompileContext76 PSymbol *FindGlobal(FName identifier) 77 { 78 return GlobalSymbols.FindSymbol(identifier, true); 79 } 80 }; 81 82 //========================================================================== 83 // 84 // 85 // 86 //========================================================================== 87 88 struct ExpVal 89 { 90 ExpValType Type; 91 union 92 { 93 int Int; 94 double Float; 95 void *pointer; 96 }; 97 GetIntExpVal98 int GetInt() const 99 { 100 return Type == VAL_Int? Int : Type == VAL_Float? int(Float) : 0; 101 } 102 GetFloatExpVal103 double GetFloat() const 104 { 105 return Type == VAL_Int? double(Int) : Type == VAL_Float? Float : 0; 106 } 107 GetBoolExpVal108 bool GetBool() const 109 { 110 return (Type == VAL_Int || Type == VAL_Sound) ? !!Int : Type == VAL_Float? Float!=0. : false; 111 } 112 GetPointerExpVal113 template<class T> T *GetPointer() const 114 { 115 return Type == VAL_Object || Type == VAL_Pointer? (T*)pointer : NULL; 116 } 117 GetSoundIDExpVal118 FSoundID GetSoundID() const 119 { 120 return Type == VAL_Sound? Int : 0; 121 } 122 GetColorExpVal123 int GetColor() const 124 { 125 return Type == VAL_Color? Int : 0; 126 } 127 GetNameExpVal128 FName GetName() const 129 { 130 return Type == VAL_Name? ENamedName(Int) : NAME_None; 131 } 132 GetStateExpVal133 FState *GetState() const 134 { 135 return Type == VAL_State? (FState*)pointer : NULL; 136 } 137 GetClassExpVal138 const PClass *GetClass() const 139 { 140 return Type == VAL_Class? (const PClass *)pointer : NULL; 141 } 142 143 }; 144 145 146 //========================================================================== 147 // 148 // 149 // 150 //========================================================================== 151 152 class FxExpression 153 { 154 protected: FxExpression(const FScriptPosition & pos)155 FxExpression(const FScriptPosition &pos) 156 : ScriptPosition(pos) 157 { 158 isresolved = false; 159 ScriptPosition = pos; 160 } 161 public: ~FxExpression()162 virtual ~FxExpression() {} 163 virtual FxExpression *Resolve(FCompileContext &ctx); 164 FxExpression *ResolveAsBoolean(FCompileContext &ctx); 165 166 virtual ExpVal EvalExpression (AActor *self); 167 virtual bool isConstant() const; 168 virtual void RequestAddress(); 169 170 FScriptPosition ScriptPosition; 171 FExpressionType ValueType; 172 173 bool isresolved; 174 }; 175 176 //========================================================================== 177 // 178 // FxIdentifier 179 // 180 //========================================================================== 181 182 class FxIdentifier : public FxExpression 183 { 184 FName Identifier; 185 186 public: 187 FxIdentifier(FName i, const FScriptPosition &p); 188 FxExpression *Resolve(FCompileContext&); 189 }; 190 191 192 //========================================================================== 193 // 194 // FxDotIdentifier 195 // 196 //========================================================================== 197 198 class FxDotIdentifier : public FxExpression 199 { 200 FxExpression *container; 201 FName Identifier; 202 203 public: 204 FxDotIdentifier(FxExpression*, FName, const FScriptPosition &); 205 ~FxDotIdentifier(); 206 FxExpression *Resolve(FCompileContext&); 207 }; 208 209 //========================================================================== 210 // 211 // FxClassDefaults 212 // 213 //========================================================================== 214 215 class FxClassDefaults : public FxExpression 216 { 217 FxExpression *obj; 218 219 public: 220 FxClassDefaults(FxExpression*, const FScriptPosition &); 221 ~FxClassDefaults(); 222 FxExpression *Resolve(FCompileContext&); 223 bool IsDefaultObject() const; 224 }; 225 226 //========================================================================== 227 // 228 // FxConstant 229 // 230 //========================================================================== 231 232 class FxConstant : public FxExpression 233 { 234 ExpVal value; 235 236 public: FxConstant(int val,const FScriptPosition & pos)237 FxConstant(int val, const FScriptPosition &pos) : FxExpression(pos) 238 { 239 ValueType = value.Type = VAL_Int; 240 value.Int = val; 241 isresolved = true; 242 } 243 FxConstant(double val,const FScriptPosition & pos)244 FxConstant(double val, const FScriptPosition &pos) : FxExpression(pos) 245 { 246 ValueType = value.Type = VAL_Float; 247 value.Float = val; 248 isresolved = true; 249 } 250 FxConstant(FSoundID val,const FScriptPosition & pos)251 FxConstant(FSoundID val, const FScriptPosition &pos) : FxExpression(pos) 252 { 253 ValueType = value.Type = VAL_Sound; 254 value.Int = val; 255 isresolved = true; 256 } 257 FxConstant(FName val,const FScriptPosition & pos)258 FxConstant(FName val, const FScriptPosition &pos) : FxExpression(pos) 259 { 260 ValueType = value.Type = VAL_Name; 261 value.Int = val; 262 isresolved = true; 263 } 264 FxConstant(ExpVal cv,const FScriptPosition & pos)265 FxConstant(ExpVal cv, const FScriptPosition &pos) : FxExpression(pos) 266 { 267 value = cv; 268 ValueType = cv.Type; 269 isresolved = true; 270 } 271 FxConstant(const PClass * val,const FScriptPosition & pos)272 FxConstant(const PClass *val, const FScriptPosition &pos) : FxExpression(pos) 273 { 274 value.pointer = (void*)val; 275 ValueType = val; 276 value.Type = VAL_Class; 277 isresolved = true; 278 } 279 FxConstant(FState * state,const FScriptPosition & pos)280 FxConstant(FState *state, const FScriptPosition &pos) : FxExpression(pos) 281 { 282 value.pointer = state; 283 ValueType = value.Type = VAL_State; 284 isresolved = true; 285 } 286 287 static FxExpression *MakeConstant(PSymbol *sym, const FScriptPosition &pos); 288 isConstant()289 bool isConstant() const 290 { 291 return true; 292 } 293 ExpVal EvalExpression (AActor *self); 294 }; 295 296 297 //========================================================================== 298 // 299 // 300 // 301 //========================================================================== 302 303 class FxIntCast : public FxExpression 304 { 305 FxExpression *basex; 306 307 public: 308 309 FxIntCast(FxExpression *x); 310 ~FxIntCast(); 311 FxExpression *Resolve(FCompileContext&); 312 313 ExpVal EvalExpression (AActor *self); 314 }; 315 316 317 //========================================================================== 318 // 319 // 320 // 321 //========================================================================== 322 323 class FxFloatCast : public FxExpression 324 { 325 FxExpression *basex; 326 327 public: 328 329 FxFloatCast(FxExpression *x); 330 ~FxFloatCast(); 331 FxExpression *Resolve(FCompileContext&); 332 333 ExpVal EvalExpression (AActor *self); 334 }; 335 336 //========================================================================== 337 // 338 // FxSign 339 // 340 //========================================================================== 341 342 class FxPlusSign : public FxExpression 343 { 344 FxExpression *Operand; 345 346 public: 347 FxPlusSign(FxExpression*); 348 ~FxPlusSign(); 349 FxExpression *Resolve(FCompileContext&); 350 }; 351 352 //========================================================================== 353 // 354 // FxSign 355 // 356 //========================================================================== 357 358 class FxMinusSign : public FxExpression 359 { 360 FxExpression *Operand; 361 362 public: 363 FxMinusSign(FxExpression*); 364 ~FxMinusSign(); 365 FxExpression *Resolve(FCompileContext&); 366 ExpVal EvalExpression (AActor *self); 367 }; 368 369 //========================================================================== 370 // 371 // FxUnaryNot 372 // 373 //========================================================================== 374 375 class FxUnaryNotBitwise : public FxExpression 376 { 377 FxExpression *Operand; 378 379 public: 380 FxUnaryNotBitwise(FxExpression*); 381 ~FxUnaryNotBitwise(); 382 FxExpression *Resolve(FCompileContext&); 383 ExpVal EvalExpression (AActor *self); 384 }; 385 386 //========================================================================== 387 // 388 // FxUnaryNot 389 // 390 //========================================================================== 391 392 class FxUnaryNotBoolean : public FxExpression 393 { 394 FxExpression *Operand; 395 396 public: 397 FxUnaryNotBoolean(FxExpression*); 398 ~FxUnaryNotBoolean(); 399 FxExpression *Resolve(FCompileContext&); 400 ExpVal EvalExpression (AActor *self); 401 }; 402 403 //========================================================================== 404 // 405 // FxBinary 406 // 407 //========================================================================== 408 409 class FxBinary : public FxExpression 410 { 411 public: 412 int Operator; 413 FxExpression *left; 414 FxExpression *right; 415 416 FxBinary(int, FxExpression*, FxExpression*); 417 ~FxBinary(); 418 bool ResolveLR(FCompileContext& ctx, bool castnumeric); 419 }; 420 421 //========================================================================== 422 // 423 // FxBinary 424 // 425 //========================================================================== 426 427 class FxAddSub : public FxBinary 428 { 429 public: 430 431 FxAddSub(int, FxExpression*, FxExpression*); 432 FxExpression *Resolve(FCompileContext&); 433 ExpVal EvalExpression (AActor *self); 434 }; 435 436 //========================================================================== 437 // 438 // FxBinary 439 // 440 //========================================================================== 441 442 class FxMulDiv : public FxBinary 443 { 444 public: 445 446 FxMulDiv(int, FxExpression*, FxExpression*); 447 FxExpression *Resolve(FCompileContext&); 448 ExpVal EvalExpression (AActor *self); 449 }; 450 451 //========================================================================== 452 // 453 // FxBinary 454 // 455 //========================================================================== 456 457 class FxCompareRel : public FxBinary 458 { 459 public: 460 461 FxCompareRel(int, FxExpression*, FxExpression*); 462 FxExpression *Resolve(FCompileContext&); 463 ExpVal EvalExpression (AActor *self); 464 }; 465 466 //========================================================================== 467 // 468 // FxBinary 469 // 470 //========================================================================== 471 472 class FxCompareEq : public FxBinary 473 { 474 public: 475 476 FxCompareEq(int, FxExpression*, FxExpression*); 477 FxExpression *Resolve(FCompileContext&); 478 ExpVal EvalExpression (AActor *self); 479 }; 480 481 //========================================================================== 482 // 483 // FxBinary 484 // 485 //========================================================================== 486 487 class FxBinaryInt : public FxBinary 488 { 489 public: 490 491 FxBinaryInt(int, FxExpression*, FxExpression*); 492 FxExpression *Resolve(FCompileContext&); 493 ExpVal EvalExpression (AActor *self); 494 }; 495 496 //========================================================================== 497 // 498 // FxBinaryLogical 499 // 500 //========================================================================== 501 502 class FxBinaryLogical : public FxExpression 503 { 504 public: 505 int Operator; 506 FxExpression *left; 507 FxExpression *right; 508 509 FxBinaryLogical(int, FxExpression*, FxExpression*); 510 ~FxBinaryLogical(); 511 FxExpression *Resolve(FCompileContext&); 512 513 ExpVal EvalExpression (AActor *self); 514 }; 515 516 //========================================================================== 517 // 518 // FxConditional 519 // 520 //========================================================================== 521 522 class FxConditional : public FxExpression 523 { 524 public: 525 FxExpression *condition; 526 FxExpression *truex; 527 FxExpression *falsex; 528 529 FxConditional(FxExpression*, FxExpression*, FxExpression*); 530 ~FxConditional(); 531 FxExpression *Resolve(FCompileContext&); 532 533 ExpVal EvalExpression (AActor *self); 534 }; 535 536 //========================================================================== 537 // 538 // 539 // 540 //========================================================================== 541 542 class FxAbs : public FxExpression 543 { 544 FxExpression *val; 545 546 public: 547 548 FxAbs(FxExpression *v); 549 ~FxAbs(); 550 FxExpression *Resolve(FCompileContext&); 551 552 ExpVal EvalExpression (AActor *self); 553 }; 554 555 //========================================================================== 556 // 557 // 558 // 559 //========================================================================== 560 561 class FxRandom : public FxExpression 562 { 563 protected: 564 FRandom * rng; 565 FxExpression *min, *max; 566 567 public: 568 569 FxRandom(FRandom *, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos); 570 ~FxRandom(); 571 FxExpression *Resolve(FCompileContext&); 572 573 ExpVal EvalExpression (AActor *self); 574 }; 575 576 //========================================================================== 577 // 578 // 579 // 580 //========================================================================== 581 582 class FxRandomPick : public FxExpression 583 { 584 protected: 585 FRandom * rng; 586 TDeletingArray<FxExpression*> min; 587 588 public: 589 590 FxRandomPick(FRandom *, TArray<FxExpression*> mi, bool floaty, const FScriptPosition &pos); 591 ~FxRandomPick(); 592 FxExpression *Resolve(FCompileContext&); 593 594 ExpVal EvalExpression(AActor *self); 595 }; 596 597 //========================================================================== 598 // 599 // 600 // 601 //========================================================================== 602 603 class FxFRandom : public FxRandom 604 { 605 public: 606 FxFRandom(FRandom *, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos); 607 ExpVal EvalExpression (AActor *self); 608 }; 609 610 //========================================================================== 611 // 612 // 613 // 614 //========================================================================== 615 616 class FxRandom2 : public FxExpression 617 { 618 FRandom * rng; 619 FxExpression *mask; 620 621 public: 622 623 FxRandom2(FRandom *, FxExpression *m, const FScriptPosition &pos); 624 ~FxRandom2(); 625 FxExpression *Resolve(FCompileContext&); 626 627 ExpVal EvalExpression (AActor *self); 628 }; 629 630 631 //========================================================================== 632 // 633 // FxGlobalVariable 634 // 635 //========================================================================== 636 637 class FxGlobalVariable : public FxExpression 638 { 639 public: 640 PSymbolVariable *var; 641 bool AddressRequested; 642 643 FxGlobalVariable(PSymbolVariable*, const FScriptPosition&); 644 FxExpression *Resolve(FCompileContext&); 645 void RequestAddress(); 646 ExpVal EvalExpression (AActor *self); 647 }; 648 649 //========================================================================== 650 // 651 // FxClassMember 652 // 653 //========================================================================== 654 655 class FxClassMember : public FxExpression 656 { 657 public: 658 FxExpression *classx; 659 PSymbolVariable *membervar; 660 bool AddressRequested; 661 662 FxClassMember(FxExpression*, PSymbolVariable*, const FScriptPosition&); 663 ~FxClassMember(); 664 FxExpression *Resolve(FCompileContext&); 665 void RequestAddress(); 666 ExpVal EvalExpression (AActor *self); 667 }; 668 669 //========================================================================== 670 // 671 // FxSelf 672 // 673 //========================================================================== 674 675 class FxSelf : public FxExpression 676 { 677 public: 678 FxSelf(const FScriptPosition&); 679 FxExpression *Resolve(FCompileContext&); 680 ExpVal EvalExpression (AActor *self); 681 }; 682 683 //========================================================================== 684 // 685 // FxArrayElement 686 // 687 //========================================================================== 688 689 class FxArrayElement : public FxExpression 690 { 691 public: 692 FxExpression *Array; 693 FxExpression *index; 694 //bool AddressRequested; 695 696 FxArrayElement(FxExpression*, FxExpression*); 697 ~FxArrayElement(); 698 FxExpression *Resolve(FCompileContext&); 699 //void RequestAddress(); 700 ExpVal EvalExpression (AActor *self); 701 }; 702 703 704 //========================================================================== 705 // 706 // FxFunctionCall 707 // 708 //========================================================================== 709 710 typedef TDeletingArray<FxExpression*> FArgumentList; 711 712 class FxFunctionCall : public FxExpression 713 { 714 FxExpression *Self; 715 FName MethodName; 716 FArgumentList *ArgList; 717 718 public: 719 720 FxFunctionCall(FxExpression *self, FName methodname, FArgumentList *args, const FScriptPosition &pos); 721 ~FxFunctionCall(); 722 FxExpression *Resolve(FCompileContext&); 723 }; 724 725 726 //========================================================================== 727 // 728 // FxActionSpecialCall 729 // 730 //========================================================================== 731 732 class FxActionSpecialCall : public FxExpression 733 { 734 FxExpression *Self; 735 int Special; 736 FArgumentList *ArgList; 737 738 public: 739 740 FxActionSpecialCall(FxExpression *self, int special, FArgumentList *args, const FScriptPosition &pos); 741 ~FxActionSpecialCall(); 742 FxExpression *Resolve(FCompileContext&); 743 ExpVal EvalExpression (AActor *self); 744 }; 745 746 //========================================================================== 747 // 748 // FxGlobalFunctionCall 749 // 750 //========================================================================== 751 752 class FxGlobalFunctionCall : public FxExpression 753 { 754 public: 755 typedef FxExpression *(*Creator)(FName, FArgumentList *, const FScriptPosition &); 756 struct CreatorAdder 757 { CreatorAdderCreatorAdder758 CreatorAdder(FName methodname, Creator creator) 759 { 760 FxGlobalFunctionCall::AddCreator(methodname, creator); 761 } 762 }; 763 764 static void AddCreator(FName methodname, Creator creator); 765 static FxExpression *StaticCreate(FName methodname, FArgumentList *args, const FScriptPosition &pos); 766 767 protected: 768 FName Name; 769 FArgumentList *ArgList; 770 771 FxGlobalFunctionCall(FName fname, FArgumentList *args, const FScriptPosition &pos); 772 ~FxGlobalFunctionCall(); 773 774 FxExpression *ResolveArgs(FCompileContext &, unsigned min, unsigned max, bool numeric); 775 }; 776 777 #define GLOBALFUNCTION_DEFINE(CLASS) \ 778 FxGlobalFunctionCall_##CLASS(FName methodname, FArgumentList *args, const FScriptPosition &pos) \ 779 : FxGlobalFunctionCall(methodname, args, pos) {} \ 780 static FxExpression *StaticCreate(FName methodname, FArgumentList *args, const FScriptPosition &pos) \ 781 {return new FxGlobalFunctionCall_##CLASS(methodname, args, pos);} 782 783 #define GLOBALFUNCTION_ADDER(CLASS) GLOBALFUNCTION_ADDER_NAMED(CLASS, CLASS) 784 785 #define GLOBALFUNCTION_ADDER_NAMED(CLASS,NAME) \ 786 static FxGlobalFunctionCall::CreatorAdder FxGlobalFunctionCall_##NAME##Adder \ 787 (NAME_##NAME, FxGlobalFunctionCall_##CLASS::StaticCreate) 788 789 790 //========================================================================== 791 // 792 // 793 // 794 //========================================================================== 795 796 class FxClassTypeCast : public FxExpression 797 { 798 const PClass *desttype; 799 FxExpression *basex; 800 801 public: 802 803 FxClassTypeCast(const PClass *dtype, FxExpression *x); 804 ~FxClassTypeCast(); 805 FxExpression *Resolve(FCompileContext&); 806 ExpVal EvalExpression (AActor *self); 807 }; 808 809 //========================================================================== 810 // 811 // Only used to resolve the old jump by index feature of DECORATE 812 // 813 //========================================================================== 814 815 class FxStateByIndex : public FxExpression 816 { 817 int index; 818 819 public: 820 FxStateByIndex(int i,const FScriptPosition & pos)821 FxStateByIndex(int i, const FScriptPosition &pos) : FxExpression(pos) 822 { 823 index = i; 824 } 825 FxExpression *Resolve(FCompileContext&); 826 }; 827 828 //========================================================================== 829 // 830 // 831 // 832 //========================================================================== 833 834 class FxMultiNameState : public FxExpression 835 { 836 const PClass *scope; 837 TArray<FName> names; 838 public: 839 840 FxMultiNameState(const char *statestring, const FScriptPosition &pos); 841 FxExpression *Resolve(FCompileContext&); 842 ExpVal EvalExpression (AActor *self); 843 }; 844 845 846 847 FxExpression *ParseExpression (FScanner &sc, PClass *cls); 848 849 850 #endif 851