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