1 /*
2 ** thingdef_expression.cpp
3 **
4 ** Expression evaluation
5 **
6 **---------------------------------------------------------------------------
7 ** Copyright 2008 Christoph Oelckers
8 ** All rights reserved.
9 **
10 ** Redistribution and use in source and binary forms, with or without
11 ** modification, are permitted provided that the following conditions
12 ** are met:
13 **
14 ** 1. Redistributions of source code must retain the above copyright
15 **    notice, this list of conditions and the following disclaimer.
16 ** 2. Redistributions in binary form must reproduce the above copyright
17 **    notice, this list of conditions and the following disclaimer in the
18 **    documentation and/or other materials provided with the distribution.
19 ** 3. The name of the author may not be used to endorse or promote products
20 **    derived from this software without specific prior written permission.
21 ** 4. When not used as part of ZDoom or a ZDoom derivative, this code will be
22 **    covered by the terms of the GNU General Public License as published by
23 **    the Free Software Foundation; either version 2 of the License, or (at
24 **    your option) any later version.
25 **
26 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27 ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28 ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30 ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35 ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 **---------------------------------------------------------------------------
37 **
38 */
39 
40 #include "actor.h"
41 #include "sc_man.h"
42 #include "tarray.h"
43 #include "templates.h"
44 #include "cmdlib.h"
45 #include "i_system.h"
46 #include "m_random.h"
47 #include "a_pickups.h"
48 #include "thingdef.h"
49 #include "p_lnspec.h"
50 #include "doomstat.h"
51 #include "thingdef_exp.h"
52 #include "m_fixed.h"
53 
54 int testglobalvar = 1337;	// just for having one global variable to test with
55 DEFINE_GLOBAL_VARIABLE(testglobalvar)
56 
57 // Accessible actor member variables
DEFINE_MEMBER_VARIABLE(alpha,AActor)58 DEFINE_MEMBER_VARIABLE(alpha, AActor)
59 DEFINE_MEMBER_VARIABLE(angle, AActor)
60 DEFINE_MEMBER_VARIABLE(args, AActor)
61 DEFINE_MEMBER_VARIABLE(ceilingz, AActor)
62 DEFINE_MEMBER_VARIABLE(floorz, AActor)
63 DEFINE_MEMBER_VARIABLE(health, AActor)
64 DEFINE_MEMBER_VARIABLE(Mass, AActor)
65 DEFINE_MEMBER_VARIABLE(pitch, AActor)
66 DEFINE_MEMBER_VARIABLE(special, AActor)
67 DEFINE_MEMBER_VARIABLE(special1, AActor)
68 DEFINE_MEMBER_VARIABLE(special2, AActor)
69 DEFINE_MEMBER_VARIABLE(tid, AActor)
70 DEFINE_MEMBER_VARIABLE(TIDtoHate, AActor)
71 DEFINE_MEMBER_VARIABLE(waterlevel, AActor)
72 DEFINE_MEMBER_VARIABLE_ALIAS(x, __pos.x, AActor)
73 DEFINE_MEMBER_VARIABLE_ALIAS(y, __pos.y, AActor)
74 DEFINE_MEMBER_VARIABLE_ALIAS(z, __pos.z, AActor)
75 DEFINE_MEMBER_VARIABLE(velx, AActor)
76 DEFINE_MEMBER_VARIABLE(vely, AActor)
77 DEFINE_MEMBER_VARIABLE(velz, AActor)
78 DEFINE_MEMBER_VARIABLE_ALIAS(momx, velx, AActor)
79 DEFINE_MEMBER_VARIABLE_ALIAS(momy, vely, AActor)
80 DEFINE_MEMBER_VARIABLE_ALIAS(momz, velz, AActor)
81 DEFINE_MEMBER_VARIABLE(scaleX, AActor)
82 DEFINE_MEMBER_VARIABLE(scaleY, AActor)
83 DEFINE_MEMBER_VARIABLE(Damage, AActor)
84 DEFINE_MEMBER_VARIABLE(Score, AActor)
85 DEFINE_MEMBER_VARIABLE(accuracy, AActor)
86 DEFINE_MEMBER_VARIABLE(stamina, AActor)
87 DEFINE_MEMBER_VARIABLE(height, AActor)
88 DEFINE_MEMBER_VARIABLE(radius, AActor)
89 DEFINE_MEMBER_VARIABLE(reactiontime, AActor)
90 DEFINE_MEMBER_VARIABLE(meleerange, AActor)
91 DEFINE_MEMBER_VARIABLE(Speed, AActor)
92 DEFINE_MEMBER_VARIABLE(roll, AActor)
93 
94 
95 //==========================================================================
96 //
97 // EvalExpression
98 // [GRB] Evaluates previously stored expression
99 //
100 //==========================================================================
101 
102 
103 int EvalExpressionI (DWORD xi, AActor *self)
104 {
105 	FxExpression *x = StateParams.Get(xi);
106 	if (x == NULL) return 0;
107 
108 	return x->EvalExpression (self).GetInt();
109 }
110 
EvalExpressionCol(DWORD xi,AActor * self)111 int EvalExpressionCol (DWORD xi, AActor *self)
112 {
113 	FxExpression *x = StateParams.Get(xi);
114 	if (x == NULL) return 0;
115 
116 	return x->EvalExpression (self).GetColor();
117 }
118 
EvalExpressionSnd(DWORD xi,AActor * self)119 FSoundID EvalExpressionSnd (DWORD xi, AActor *self)
120 {
121 	FxExpression *x = StateParams.Get(xi);
122 	if (x == NULL) return 0;
123 
124 	return x->EvalExpression (self).GetSoundID();
125 }
126 
EvalExpressionF(DWORD xi,AActor * self)127 double EvalExpressionF (DWORD xi, AActor *self)
128 {
129 	FxExpression *x = StateParams.Get(xi);
130 	if (x == NULL) return 0;
131 
132 	return x->EvalExpression (self).GetFloat();
133 }
134 
EvalExpressionFix(DWORD xi,AActor * self)135 fixed_t EvalExpressionFix (DWORD xi, AActor *self)
136 {
137 	FxExpression *x = StateParams.Get(xi);
138 	if (x == NULL) return 0;
139 
140 	ExpVal val = x->EvalExpression (self);
141 
142 	switch (val.Type)
143 	{
144 	default:
145 		return 0;
146 	case VAL_Int:
147 		return val.Int << FRACBITS;
148 	case VAL_Float:
149 		return fixed_t(val.Float*FRACUNIT);
150 	}
151 }
152 
EvalExpressionName(DWORD xi,AActor * self)153 FName EvalExpressionName (DWORD xi, AActor *self)
154 {
155 	FxExpression *x = StateParams.Get(xi);
156 	if (x == NULL) return 0;
157 
158 	return x->EvalExpression (self).GetName();
159 }
160 
EvalExpressionClass(DWORD xi,AActor * self)161 const PClass * EvalExpressionClass (DWORD xi, AActor *self)
162 {
163 	FxExpression *x = StateParams.Get(xi);
164 	if (x == NULL) return 0;
165 
166 	return x->EvalExpression (self).GetClass();
167 }
168 
EvalExpressionState(DWORD xi,AActor * self)169 FState *EvalExpressionState (DWORD xi, AActor *self)
170 {
171 	FxExpression *x = StateParams.Get(xi);
172 	if (x == NULL) return 0;
173 
174 	return x->EvalExpression (self).GetState();
175 }
176 
177 
178 //==========================================================================
179 //
180 //
181 //
182 //==========================================================================
183 
GetVariableValue(void * address,FExpressionType & type)184 static ExpVal GetVariableValue (void *address, FExpressionType &type)
185 {
186 	// NOTE: This cannot access native variables of types
187 	// char, short and float. These need to be redefined if necessary!
188 	ExpVal ret;
189 
190 	switch(type.Type)
191 	{
192 	case VAL_Int:
193 		ret.Type = VAL_Int;
194 		ret.Int = *(int*)address;
195 		break;
196 
197 	case VAL_Sound:
198 		ret.Type = VAL_Sound;
199 		ret.Int = *(FSoundID*)address;
200 		break;
201 
202 	case VAL_Name:
203 		ret.Type = VAL_Name;
204 		ret.Int = *(FName*)address;
205 		break;
206 
207 	case VAL_Color:
208 		ret.Type = VAL_Color;
209 		ret.Int = *(int*)address;
210 		break;
211 
212 	case VAL_Bool:
213 		ret.Type = VAL_Int;
214 		ret.Int = *(bool*)address;
215 		break;
216 
217 	case VAL_Float:
218 		ret.Type = VAL_Float;
219 		ret.Float = *(double*)address;
220 		break;
221 
222 	case VAL_Fixed:
223 		ret.Type = VAL_Float;
224 		ret.Float = (*(fixed_t*)address) / 65536.;
225 		break;
226 
227 	case VAL_Angle:
228 		ret.Type = VAL_Float;
229 		ret.Float = (*(angle_t*)address) * 90./ANGLE_90;	// intentionally not using ANGLE_1
230 		break;
231 
232 	case VAL_Object:
233 	case VAL_Class:
234 		ret.Type = ExpValType(type.Type);	// object and class pointers don't retain their specific class information as values
235 		ret.pointer = *(void**)address;
236 		break;
237 
238 	default:
239 		ret.Type = VAL_Unknown;
240 		ret.pointer = NULL;
241 		break;
242 	}
243 	return ret;
244 }
245 
246 //==========================================================================
247 //
248 //
249 //
250 //==========================================================================
251 
EvalExpression(AActor * self)252 ExpVal FxExpression::EvalExpression (AActor *self)
253 {
254 	ScriptPosition.Message(MSG_ERROR, "Unresolved expression found");
255 	ExpVal val;
256 
257 	val.Type = VAL_Int;
258 	val.Int = 0;
259 	return val;
260 }
261 
262 
263 //==========================================================================
264 //
265 //
266 //
267 //==========================================================================
268 
isConstant() const269 bool FxExpression::isConstant() const
270 {
271 	return false;
272 }
273 
274 //==========================================================================
275 //
276 //
277 //
278 //==========================================================================
279 
Resolve(FCompileContext & ctx)280 FxExpression *FxExpression::Resolve(FCompileContext &ctx)
281 {
282 	isresolved = true;
283 	return this;
284 }
285 
286 
287 //==========================================================================
288 //
289 //
290 //
291 //==========================================================================
292 
ResolveAsBoolean(FCompileContext & ctx)293 FxExpression *FxExpression::ResolveAsBoolean(FCompileContext &ctx)
294 {
295 	FxExpression *x = Resolve(ctx);
296 	if (x != NULL)
297 	{
298 		switch (x->ValueType.Type)
299 		{
300 		case VAL_Sound:
301 		case VAL_Color:
302 		case VAL_Name:
303 			x->ValueType = VAL_Int;
304 			break;
305 
306 		default:
307 			break;
308 		}
309 	}
310 	return x;
311 }
312 
313 //==========================================================================
314 //
315 //
316 //
317 //==========================================================================
318 
RequestAddress()319 void FxExpression::RequestAddress()
320 {
321 	ScriptPosition.Message(MSG_ERROR, "invalid dereference\n");
322 }
323 
324 
325 //==========================================================================
326 //
327 //
328 //
329 //==========================================================================
330 
EvalExpression(AActor * self)331 ExpVal FxConstant::EvalExpression (AActor *self)
332 {
333 	return value;
334 }
335 
336 //==========================================================================
337 //
338 //
339 //
340 //==========================================================================
341 
MakeConstant(PSymbol * sym,const FScriptPosition & pos)342 FxExpression *FxConstant::MakeConstant(PSymbol *sym, const FScriptPosition &pos)
343 {
344 	FxExpression *x;
345 	if (sym->SymbolType == SYM_Const)
346 	{
347 		PSymbolConst *csym = static_cast<PSymbolConst*>(sym);
348 		switch(csym->ValueType)
349 		{
350 		case VAL_Int:
351 			x = new FxConstant(csym->Value, pos);
352 			break;
353 
354 		case VAL_Float:
355 			x = new FxConstant(csym->Float, pos);
356 			break;
357 
358 		default:
359 			pos.Message(MSG_ERROR, "Invalid constant '%s'\n", csym->SymbolName.GetChars());
360 			return NULL;
361 		}
362 	}
363 	else
364 	{
365 		pos.Message(MSG_ERROR, "'%s' is not a constant\n", sym->SymbolName.GetChars());
366 		x = NULL;
367 	}
368 	return x;
369 }
370 
371 
372 
373 //==========================================================================
374 //
375 //
376 //
377 //==========================================================================
378 
FxIntCast(FxExpression * x)379 FxIntCast::FxIntCast(FxExpression *x)
380 : FxExpression(x->ScriptPosition)
381 {
382 	basex=x;
383 	ValueType = VAL_Int;
384 }
385 
386 //==========================================================================
387 //
388 //
389 //
390 //==========================================================================
391 
~FxIntCast()392 FxIntCast::~FxIntCast()
393 {
394 	SAFE_DELETE(basex);
395 }
396 
397 //==========================================================================
398 //
399 //
400 //
401 //==========================================================================
402 
Resolve(FCompileContext & ctx)403 FxExpression *FxIntCast::Resolve(FCompileContext &ctx)
404 {
405 	CHECKRESOLVED();
406 	SAFE_RESOLVE(basex, ctx);
407 
408 	if (basex->ValueType == VAL_Int)
409 	{
410 		FxExpression *x = basex;
411 		basex = NULL;
412 		delete this;
413 		return x;
414 	}
415 	else if (basex->ValueType == VAL_Float)
416 	{
417 		if (basex->isConstant())
418 		{
419 			ExpVal constval = basex->EvalExpression(NULL);
420 			FxExpression *x = new FxConstant(constval.GetInt(), ScriptPosition);
421 			delete this;
422 			return x;
423 		}
424 		return this;
425 	}
426 	else
427 	{
428 		ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
429 		delete this;
430 		return NULL;
431 	}
432 }
433 
434 //==========================================================================
435 //
436 //
437 //
438 //==========================================================================
439 
EvalExpression(AActor * self)440 ExpVal FxIntCast::EvalExpression (AActor *self)
441 {
442 	ExpVal baseval = basex->EvalExpression(self);
443 	baseval.Int = baseval.GetInt();
444 	baseval.Type = VAL_Int;
445 	return baseval;
446 }
447 
448 
449 //==========================================================================
450 //
451 //
452 //
453 //==========================================================================
454 
FxFloatCast(FxExpression * x)455 FxFloatCast::FxFloatCast(FxExpression *x)
456 : FxExpression(x->ScriptPosition)
457 {
458 	basex = x;
459 	ValueType = VAL_Float;
460 }
461 
462 //==========================================================================
463 //
464 //
465 //
466 //==========================================================================
467 
~FxFloatCast()468 FxFloatCast::~FxFloatCast()
469 {
470 	SAFE_DELETE(basex);
471 }
472 
473 //==========================================================================
474 //
475 //
476 //
477 //==========================================================================
478 
Resolve(FCompileContext & ctx)479 FxExpression *FxFloatCast::Resolve(FCompileContext &ctx)
480 {
481 	CHECKRESOLVED();
482 	SAFE_RESOLVE(basex, ctx);
483 
484 	if (basex->ValueType == VAL_Float)
485 	{
486 		FxExpression *x = basex;
487 		basex = NULL;
488 		delete this;
489 		return x;
490 	}
491 	else if (basex->ValueType == VAL_Int)
492 	{
493 		if (basex->isConstant())
494 		{
495 			ExpVal constval = basex->EvalExpression(NULL);
496 			FxExpression *x = new FxConstant(constval.GetFloat(), ScriptPosition);
497 			delete this;
498 			return x;
499 		}
500 		return this;
501 	}
502 	else
503 	{
504 		ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
505 		delete this;
506 		return NULL;
507 	}
508 }
509 
510 //==========================================================================
511 //
512 //
513 //
514 //==========================================================================
515 
EvalExpression(AActor * self)516 ExpVal FxFloatCast::EvalExpression (AActor *self)
517 {
518 	ExpVal baseval = basex->EvalExpression(self);
519 	baseval.Float = baseval.GetFloat();
520 	baseval.Type = VAL_Float;
521 	return baseval;
522 }
523 
524 
525 //==========================================================================
526 //
527 //
528 //
529 //==========================================================================
530 
FxPlusSign(FxExpression * operand)531 FxPlusSign::FxPlusSign(FxExpression *operand)
532 : FxExpression(operand->ScriptPosition)
533 {
534 	Operand=operand;
535 }
536 
537 //==========================================================================
538 //
539 //
540 //
541 //==========================================================================
542 
~FxPlusSign()543 FxPlusSign::~FxPlusSign()
544 {
545 	SAFE_DELETE(Operand);
546 }
547 
548 //==========================================================================
549 //
550 //
551 //
552 //==========================================================================
553 
Resolve(FCompileContext & ctx)554 FxExpression *FxPlusSign::Resolve(FCompileContext& ctx)
555 {
556 	CHECKRESOLVED();
557 	SAFE_RESOLVE(Operand, ctx);
558 
559 	if (Operand->ValueType.isNumeric())
560 	{
561 		FxExpression *e = Operand;
562 		Operand = NULL;
563 		delete this;
564 		return e;
565 	}
566 	else
567 	{
568 		ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
569 		delete this;
570 		return NULL;
571 	}
572 }
573 
574 //==========================================================================
575 //
576 //
577 //
578 //==========================================================================
579 
FxMinusSign(FxExpression * operand)580 FxMinusSign::FxMinusSign(FxExpression *operand)
581 : FxExpression(operand->ScriptPosition)
582 {
583 	Operand=operand;
584 }
585 
586 //==========================================================================
587 //
588 //
589 //
590 //==========================================================================
591 
~FxMinusSign()592 FxMinusSign::~FxMinusSign()
593 {
594 	SAFE_DELETE(Operand);
595 }
596 
597 //==========================================================================
598 //
599 //
600 //
601 //==========================================================================
602 
Resolve(FCompileContext & ctx)603 FxExpression *FxMinusSign::Resolve(FCompileContext& ctx)
604 {
605 	CHECKRESOLVED();
606 	SAFE_RESOLVE(Operand, ctx);
607 
608 	if (Operand->ValueType.isNumeric())
609 	{
610 		if (Operand->isConstant())
611 		{
612 			ExpVal val = Operand->EvalExpression(NULL);
613 			FxExpression *e = val.Type == VAL_Int?
614 				new FxConstant(-val.Int, ScriptPosition) :
615 				new FxConstant(-val.Float, ScriptPosition);
616 			delete this;
617 			return e;
618 		}
619 		ValueType = Operand->ValueType;
620 		return this;
621 	}
622 	else
623 	{
624 		ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
625 		delete this;
626 		return NULL;
627 	}
628 }
629 
630 //==========================================================================
631 //
632 //
633 //
634 //==========================================================================
635 
EvalExpression(AActor * self)636 ExpVal FxMinusSign::EvalExpression (AActor *self)
637 {
638 	ExpVal ret;
639 
640 	if (ValueType == VAL_Int)
641 	{
642 		ret.Int = -Operand->EvalExpression(self).GetInt();
643 		ret.Type = VAL_Int;
644 	}
645 	else
646 	{
647 		ret.Float = -Operand->EvalExpression(self).GetFloat();
648 		ret.Type = VAL_Float;
649 	}
650 	return ret;
651 }
652 
653 
654 //==========================================================================
655 //
656 //
657 //
658 //==========================================================================
659 
FxUnaryNotBitwise(FxExpression * operand)660 FxUnaryNotBitwise::FxUnaryNotBitwise(FxExpression *operand)
661 : FxExpression(operand->ScriptPosition)
662 {
663 	Operand=operand;
664 }
665 
666 //==========================================================================
667 //
668 //
669 //
670 //==========================================================================
671 
~FxUnaryNotBitwise()672 FxUnaryNotBitwise::~FxUnaryNotBitwise()
673 {
674 	SAFE_DELETE(Operand);
675 }
676 
677 //==========================================================================
678 //
679 //
680 //
681 //==========================================================================
682 
Resolve(FCompileContext & ctx)683 FxExpression *FxUnaryNotBitwise::Resolve(FCompileContext& ctx)
684 {
685 	CHECKRESOLVED();
686 	SAFE_RESOLVE(Operand, ctx);
687 
688 	if  (Operand->ValueType == VAL_Float && ctx.lax)
689 	{
690 		// DECORATE allows floats here so cast them to int.
691 		Operand = new FxIntCast(Operand);
692 		Operand = Operand->Resolve(ctx);
693 		if (Operand == NULL)
694 		{
695 			delete this;
696 			return NULL;
697 		}
698 	}
699 
700 	if (Operand->ValueType != VAL_Int)
701 	{
702 		ScriptPosition.Message(MSG_ERROR, "Integer type expected");
703 		delete this;
704 		return NULL;
705 	}
706 
707 	if (Operand->isConstant())
708 	{
709 		int result = ~Operand->EvalExpression(NULL).GetInt();
710 		FxExpression *e = new FxConstant(result, ScriptPosition);
711 		delete this;
712 		return e;
713 	}
714 	ValueType = VAL_Int;
715 	return this;
716 }
717 
718 //==========================================================================
719 //
720 //
721 //
722 //==========================================================================
723 
EvalExpression(AActor * self)724 ExpVal FxUnaryNotBitwise::EvalExpression (AActor *self)
725 {
726 	ExpVal ret;
727 
728 	ret.Int = ~Operand->EvalExpression(self).GetInt();
729 	ret.Type = VAL_Int;
730 	return ret;
731 }
732 
733 //==========================================================================
734 //
735 //
736 //
737 //==========================================================================
738 
FxUnaryNotBoolean(FxExpression * operand)739 FxUnaryNotBoolean::FxUnaryNotBoolean(FxExpression *operand)
740 : FxExpression(operand->ScriptPosition)
741 {
742 	Operand=operand;
743 }
744 
745 //==========================================================================
746 //
747 //
748 //
749 //==========================================================================
750 
~FxUnaryNotBoolean()751 FxUnaryNotBoolean::~FxUnaryNotBoolean()
752 {
753 	SAFE_DELETE(Operand);
754 }
755 
756 //==========================================================================
757 //
758 //
759 //
760 //==========================================================================
761 
Resolve(FCompileContext & ctx)762 FxExpression *FxUnaryNotBoolean::Resolve(FCompileContext& ctx)
763 {
764 	CHECKRESOLVED();
765 	if (Operand)
766 
767 	{
768 		Operand = Operand->ResolveAsBoolean(ctx);
769 	}
770 	if (!Operand)
771 	{
772 		delete this;
773 		return NULL;
774 	}
775 
776 	if (Operand->ValueType.isNumeric() || Operand->ValueType.isPointer())
777 	{
778 		if (Operand->isConstant())
779 		{
780 			bool result = !Operand->EvalExpression(NULL).GetBool();
781 			FxExpression *e = new FxConstant(result, ScriptPosition);
782 			delete this;
783 			return e;
784 		}
785 	}
786 	else
787 	{
788 		ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
789 		delete this;
790 		return NULL;
791 	}
792 	ValueType = VAL_Int;
793 	return this;
794 }
795 
796 //==========================================================================
797 //
798 //
799 //
800 //==========================================================================
801 
EvalExpression(AActor * self)802 ExpVal FxUnaryNotBoolean::EvalExpression (AActor *self)
803 {
804 	ExpVal ret;
805 
806 	ret.Int = !Operand->EvalExpression(self).GetBool();
807 	ret.Type = VAL_Int;
808 	return ret;
809 }
810 
811 //==========================================================================
812 //
813 //
814 //
815 //==========================================================================
816 
FxBinary(int o,FxExpression * l,FxExpression * r)817 FxBinary::FxBinary(int o, FxExpression *l, FxExpression *r)
818 : FxExpression(l->ScriptPosition)
819 {
820 	Operator=o;
821 	left=l;
822 	right=r;
823 }
824 
825 //==========================================================================
826 //
827 //
828 //
829 //==========================================================================
830 
~FxBinary()831 FxBinary::~FxBinary()
832 {
833 	SAFE_DELETE(left);
834 	SAFE_DELETE(right);
835 }
836 
837 //==========================================================================
838 //
839 //
840 //
841 //==========================================================================
842 
ResolveLR(FCompileContext & ctx,bool castnumeric)843 bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric)
844 {
845 	RESOLVE(left, ctx);
846 	RESOLVE(right, ctx);
847 	if (!left || !right)
848 	{
849 		delete this;
850 		return false;
851 	}
852 
853 	if (left->ValueType == VAL_Int && right->ValueType == VAL_Int)
854 	{
855 		ValueType = VAL_Int;
856 	}
857 	else if (left->ValueType.isNumeric() && right->ValueType.isNumeric())
858 	{
859 		ValueType = VAL_Float;
860 	}
861 	else if (left->ValueType == VAL_Object && right->ValueType == VAL_Object)
862 	{
863 		ValueType = VAL_Object;
864 	}
865 	else if (left->ValueType == VAL_Class && right->ValueType == VAL_Class)
866 	{
867 		ValueType = VAL_Class;
868 	}
869 	else
870 	{
871 		ValueType = VAL_Unknown;
872 	}
873 
874 	if (castnumeric)
875 	{
876 		// later!
877 	}
878 	return true;
879 }
880 
881 
882 //==========================================================================
883 //
884 //
885 //
886 //==========================================================================
887 
FxAddSub(int o,FxExpression * l,FxExpression * r)888 FxAddSub::FxAddSub(int o, FxExpression *l, FxExpression *r)
889 : FxBinary(o, l, r)
890 {
891 }
892 
893 //==========================================================================
894 //
895 //
896 //
897 //==========================================================================
898 
Resolve(FCompileContext & ctx)899 FxExpression *FxAddSub::Resolve(FCompileContext& ctx)
900 {
901 	CHECKRESOLVED();
902 	if (!ResolveLR(ctx, true)) return NULL;
903 
904 	if (!ValueType.isNumeric())
905 	{
906 		ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
907 		delete this;
908 		return NULL;
909 	}
910 	else if (left->isConstant() && right->isConstant())
911 	{
912 		if (ValueType == VAL_Float)
913 		{
914 			double v;
915 			double v1 = left->EvalExpression(NULL).GetFloat();
916 			double v2 = right->EvalExpression(NULL).GetFloat();
917 
918 			v =	Operator == '+'? v1 + v2 :
919 				Operator == '-'? v1 - v2 : 0;
920 
921 			FxExpression *e = new FxConstant(v, ScriptPosition);
922 			delete this;
923 			return e;
924 		}
925 		else
926 		{
927 			int v;
928 			int v1 = left->EvalExpression(NULL).GetInt();
929 			int v2 = right->EvalExpression(NULL).GetInt();
930 
931 			v =	Operator == '+'? v1 + v2 :
932 				Operator == '-'? v1 - v2 : 0;
933 
934 			FxExpression *e = new FxConstant(v, ScriptPosition);
935 			delete this;
936 			return e;
937 
938 		}
939 	}
940 	return this;
941 }
942 
943 //==========================================================================
944 //
945 //
946 //
947 //==========================================================================
948 
EvalExpression(AActor * self)949 ExpVal FxAddSub::EvalExpression (AActor *self)
950 {
951 	ExpVal ret;
952 
953 	if (ValueType == VAL_Float)
954 	{
955 		double v1 = left->EvalExpression(self).GetFloat();
956 		double v2 = right->EvalExpression(self).GetFloat();
957 
958 		ret.Type = VAL_Float;
959 		ret.Float = Operator == '+'? v1 + v2 :
960 			  		Operator == '-'? v1 - v2 : 0;
961 	}
962 	else
963 	{
964 		int v1 = left->EvalExpression(self).GetInt();
965 		int v2 = right->EvalExpression(self).GetInt();
966 
967 		ret.Type = VAL_Int;
968 		ret.Int = Operator == '+'? v1 + v2 :
969 				  Operator == '-'? v1 - v2 : 0;
970 
971 	}
972 	return ret;
973 }
974 
975 //==========================================================================
976 //
977 //
978 //
979 //==========================================================================
980 
FxMulDiv(int o,FxExpression * l,FxExpression * r)981 FxMulDiv::FxMulDiv(int o, FxExpression *l, FxExpression *r)
982 : FxBinary(o, l, r)
983 {
984 }
985 
986 //==========================================================================
987 //
988 //
989 //
990 //==========================================================================
991 
Resolve(FCompileContext & ctx)992 FxExpression *FxMulDiv::Resolve(FCompileContext& ctx)
993 {
994 	CHECKRESOLVED();
995 
996 	if (!ResolveLR(ctx, true)) return NULL;
997 
998 	if (!ValueType.isNumeric())
999 	{
1000 		ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
1001 		delete this;
1002 		return NULL;
1003 	}
1004 	else if (left->isConstant() && right->isConstant())
1005 	{
1006 		if (ValueType == VAL_Float)
1007 		{
1008 			double v;
1009 			double v1 = left->EvalExpression(NULL).GetFloat();
1010 			double v2 = right->EvalExpression(NULL).GetFloat();
1011 
1012 			if (Operator != '*' && v2 == 0)
1013 			{
1014 				ScriptPosition.Message(MSG_ERROR, "Division by 0");
1015 				delete this;
1016 				return NULL;
1017 			}
1018 
1019 			v =	Operator == '*'? v1 * v2 :
1020 				Operator == '/'? v1 / v2 :
1021 				Operator == '%'? fmod(v1, v2) : 0;
1022 
1023 			FxExpression *e = new FxConstant(v, ScriptPosition);
1024 			delete this;
1025 			return e;
1026 		}
1027 		else
1028 		{
1029 			int v;
1030 			int v1 = left->EvalExpression(NULL).GetInt();
1031 			int v2 = right->EvalExpression(NULL).GetInt();
1032 
1033 			if (Operator != '*' && v2 == 0)
1034 			{
1035 				ScriptPosition.Message(MSG_ERROR, "Division by 0");
1036 				delete this;
1037 				return NULL;
1038 			}
1039 
1040 			v =	Operator == '*'? v1 * v2 :
1041 				Operator == '/'? v1 / v2 :
1042 				Operator == '%'? v1 % v2 : 0;
1043 
1044 			FxExpression *e = new FxConstant(v, ScriptPosition);
1045 			delete this;
1046 			return e;
1047 
1048 		}
1049 	}
1050 	return this;
1051 }
1052 
1053 
1054 //==========================================================================
1055 //
1056 //
1057 //
1058 //==========================================================================
1059 
EvalExpression(AActor * self)1060 ExpVal FxMulDiv::EvalExpression (AActor *self)
1061 {
1062 	ExpVal ret;
1063 
1064 	if (ValueType == VAL_Float)
1065 	{
1066 		double v1 = left->EvalExpression(self).GetFloat();
1067 		double v2 = right->EvalExpression(self).GetFloat();
1068 
1069 		if (Operator != '*' && v2 == 0)
1070 		{
1071 			I_Error("Division by 0");
1072 		}
1073 
1074 		ret.Type = VAL_Float;
1075 		ret.Float = Operator == '*'? v1 * v2 :
1076 			  		Operator == '/'? v1 / v2 :
1077 					Operator == '%'? fmod(v1, v2) : 0;
1078 	}
1079 	else
1080 	{
1081 		int v1 = left->EvalExpression(self).GetInt();
1082 		int v2 = right->EvalExpression(self).GetInt();
1083 
1084 		if (Operator != '*' && v2 == 0)
1085 		{
1086 			I_Error("Division by 0");
1087 		}
1088 
1089 		ret.Type = VAL_Int;
1090 		ret.Int = Operator == '*'? v1 * v2 :
1091 				  Operator == '/'? v1 / v2 :
1092 				  Operator == '%'? v1 % v2 : 0;
1093 
1094 	}
1095 	return ret;
1096 }
1097 
1098 //==========================================================================
1099 //
1100 //
1101 //
1102 //==========================================================================
1103 
FxCompareRel(int o,FxExpression * l,FxExpression * r)1104 FxCompareRel::FxCompareRel(int o, FxExpression *l, FxExpression *r)
1105 : FxBinary(o, l, r)
1106 {
1107 }
1108 
1109 //==========================================================================
1110 //
1111 //
1112 //
1113 //==========================================================================
1114 
Resolve(FCompileContext & ctx)1115 FxExpression *FxCompareRel::Resolve(FCompileContext& ctx)
1116 {
1117 	CHECKRESOLVED();
1118 	if (!ResolveLR(ctx, true)) return NULL;
1119 
1120 	if (!ValueType.isNumeric())
1121 	{
1122 		ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
1123 		delete this;
1124 		return NULL;
1125 	}
1126 	else if (left->isConstant() && right->isConstant())
1127 	{
1128 		int v;
1129 
1130 		if (ValueType == VAL_Float)
1131 		{
1132 			double v1 = left->EvalExpression(NULL).GetFloat();
1133 			double v2 = right->EvalExpression(NULL).GetFloat();
1134 			v =	Operator == '<'? v1 < v2 :
1135 				Operator == '>'? v1 > v2 :
1136 				Operator == TK_Geq? v1 >= v2 :
1137 				Operator == TK_Leq? v1 <= v2 : 0;
1138 		}
1139 		else
1140 		{
1141 			int v1 = left->EvalExpression(NULL).GetInt();
1142 			int v2 = right->EvalExpression(NULL).GetInt();
1143 			v =	Operator == '<'? v1 < v2 :
1144 				Operator == '>'? v1 > v2 :
1145 				Operator == TK_Geq? v1 >= v2 :
1146 				Operator == TK_Leq? v1 <= v2 : 0;
1147 		}
1148 		FxExpression *e = new FxConstant(v, ScriptPosition);
1149 		delete this;
1150 		return e;
1151 	}
1152 	ValueType = VAL_Int;
1153 	return this;
1154 }
1155 
1156 
1157 //==========================================================================
1158 //
1159 //
1160 //
1161 //==========================================================================
1162 
EvalExpression(AActor * self)1163 ExpVal FxCompareRel::EvalExpression (AActor *self)
1164 {
1165 	ExpVal ret;
1166 
1167 	ret.Type = VAL_Int;
1168 
1169 	if (left->ValueType == VAL_Float || right->ValueType == VAL_Float)
1170 	{
1171 		double v1 = left->EvalExpression(self).GetFloat();
1172 		double v2 = right->EvalExpression(self).GetFloat();
1173 		ret.Int = Operator == '<'? v1 < v2 :
1174 				  Operator == '>'? v1 > v2 :
1175 				  Operator == TK_Geq? v1 >= v2 :
1176 				  Operator == TK_Leq? v1 <= v2 : 0;
1177 	}
1178 	else
1179 	{
1180 		int v1 = left->EvalExpression(self).GetInt();
1181 		int v2 = right->EvalExpression(self).GetInt();
1182 		ret.Int = Operator == '<'? v1 < v2 :
1183 				  Operator == '>'? v1 > v2 :
1184 				  Operator == TK_Geq? v1 >= v2 :
1185 				  Operator == TK_Leq? v1 <= v2 : 0;
1186 	}
1187 	return ret;
1188 }
1189 
1190 
1191 //==========================================================================
1192 //
1193 //
1194 //
1195 //==========================================================================
1196 
FxCompareEq(int o,FxExpression * l,FxExpression * r)1197 FxCompareEq::FxCompareEq(int o, FxExpression *l, FxExpression *r)
1198 : FxBinary(o, l, r)
1199 {
1200 }
1201 
1202 //==========================================================================
1203 //
1204 //
1205 //
1206 //==========================================================================
1207 
Resolve(FCompileContext & ctx)1208 FxExpression *FxCompareEq::Resolve(FCompileContext& ctx)
1209 {
1210 	CHECKRESOLVED();
1211 
1212 	if (!ResolveLR(ctx, true)) return NULL;
1213 
1214 	if (!left || !right)
1215 	{
1216 		delete this;
1217 		return NULL;
1218 	}
1219 
1220 	if (!ValueType.isNumeric() && !ValueType.isPointer())
1221 	{
1222 		if (left->ValueType.Type == right->ValueType.Type)
1223 		{
1224 			// compare other types?
1225 			if (left->ValueType == VAL_Sound || left->ValueType == VAL_Color || left->ValueType == VAL_Name)
1226 			{
1227 				left->ValueType = right->ValueType = VAL_Int;
1228 				goto cont;
1229 			}
1230 		}
1231 
1232 		ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
1233 		delete this;
1234 		return NULL;
1235 	}
1236 cont:
1237 	if (left->isConstant() && right->isConstant())
1238 	{
1239 		int v;
1240 
1241 		if (ValueType == VAL_Float)
1242 		{
1243 			double v1 = left->EvalExpression(NULL).GetFloat();
1244 			double v2 = right->EvalExpression(NULL).GetFloat();
1245 			v = Operator == TK_Eq? v1 == v2 : v1 != v2;
1246 		}
1247 		else
1248 		{
1249 			int v1 = left->EvalExpression(NULL).GetInt();
1250 			int v2 = right->EvalExpression(NULL).GetInt();
1251 			v = Operator == TK_Eq? v1 == v2 : v1 != v2;
1252 		}
1253 		FxExpression *e = new FxConstant(v, ScriptPosition);
1254 		delete this;
1255 		return e;
1256 	}
1257 	ValueType = VAL_Int;
1258 	return this;
1259 }
1260 
1261 //==========================================================================
1262 //
1263 //
1264 //
1265 //==========================================================================
1266 
EvalExpression(AActor * self)1267 ExpVal FxCompareEq::EvalExpression (AActor *self)
1268 {
1269 	ExpVal ret;
1270 
1271 	ret.Type = VAL_Int;
1272 
1273 	if (left->ValueType == VAL_Float || right->ValueType == VAL_Float)
1274 	{
1275 		double v1 = left->EvalExpression(self).GetFloat();
1276 		double v2 = right->EvalExpression(self).GetFloat();
1277 		ret.Int = Operator == TK_Eq? v1 == v2 : v1 != v2;
1278 	}
1279 	else if (ValueType == VAL_Int)
1280 	{
1281 		int v1 = left->EvalExpression(self).GetInt();
1282 		int v2 = right->EvalExpression(self).GetInt();
1283 		ret.Int = Operator == TK_Eq? v1 == v2 : v1 != v2;
1284 	}
1285 	else
1286 	{
1287 		// Implement pointer comparison
1288 		ret.Int = 0;
1289 	}
1290 	return ret;
1291 }
1292 
1293 
1294 //==========================================================================
1295 //
1296 //
1297 //
1298 //==========================================================================
1299 
FxBinaryInt(int o,FxExpression * l,FxExpression * r)1300 FxBinaryInt::FxBinaryInt(int o, FxExpression *l, FxExpression *r)
1301 : FxBinary(o, l, r)
1302 {
1303 	ValueType = VAL_Int;
1304 }
1305 
1306 //==========================================================================
1307 //
1308 //
1309 //
1310 //==========================================================================
1311 
Resolve(FCompileContext & ctx)1312 FxExpression *FxBinaryInt::Resolve(FCompileContext& ctx)
1313 {
1314 	CHECKRESOLVED();
1315 	if (!ResolveLR(ctx, false)) return NULL;
1316 
1317 	if (ctx.lax && ValueType == VAL_Float)
1318 	{
1319 		// For DECORATE which allows floats here.
1320 		if (left->ValueType != VAL_Int)
1321 		{
1322 			left = new FxIntCast(left);
1323 			left = left->Resolve(ctx);
1324 		}
1325 		if (right->ValueType != VAL_Int)
1326 		{
1327 			right = new FxIntCast(right);
1328 			right = right->Resolve(ctx);
1329 		}
1330 		if (left == NULL || right == NULL)
1331 		{
1332 			delete this;
1333 			return NULL;
1334 		}
1335 		ValueType = VAL_Int;
1336 	}
1337 
1338 	if (ValueType != VAL_Int)
1339 	{
1340 		ScriptPosition.Message(MSG_ERROR, "Integer type expected");
1341 		delete this;
1342 		return NULL;
1343 	}
1344 	else if (left->isConstant() && right->isConstant())
1345 	{
1346 		int v1 = left->EvalExpression(NULL).GetInt();
1347 		int v2 = right->EvalExpression(NULL).GetInt();
1348 
1349 		FxExpression *e = new FxConstant(
1350 			Operator == TK_LShift? v1 << v2 :
1351 			Operator == TK_RShift? v1 >> v2 :
1352 			Operator == TK_URShift? int((unsigned int)(v1) >> v2) :
1353 			Operator == '&'? v1 & v2 :
1354 			Operator == '|'? v1 | v2 :
1355 			Operator == '^'? v1 ^ v2 : 0, ScriptPosition);
1356 
1357 		delete this;
1358 		return e;
1359 	}
1360 	return this;
1361 }
1362 
1363 //==========================================================================
1364 //
1365 //
1366 //
1367 //==========================================================================
1368 
EvalExpression(AActor * self)1369 ExpVal FxBinaryInt::EvalExpression (AActor *self)
1370 {
1371 	int v1 = left->EvalExpression(self).GetInt();
1372 	int v2 = right->EvalExpression(self).GetInt();
1373 
1374 	ExpVal ret;
1375 
1376 	ret.Type = VAL_Int;
1377 	ret.Int =
1378 		Operator == TK_LShift? v1 << v2 :
1379 		Operator == TK_RShift? v1 >> v2 :
1380 		Operator == TK_URShift? int((unsigned int)(v1) >> v2) :
1381 		Operator == '&'? v1 & v2 :
1382 		Operator == '|'? v1 | v2 :
1383 		Operator == '^'? v1 ^ v2 : 0;
1384 
1385 	return ret;
1386 }
1387 
1388 //==========================================================================
1389 //
1390 //
1391 //
1392 //==========================================================================
1393 
FxBinaryLogical(int o,FxExpression * l,FxExpression * r)1394 FxBinaryLogical::FxBinaryLogical(int o, FxExpression *l, FxExpression *r)
1395 : FxExpression(l->ScriptPosition)
1396 {
1397 	Operator=o;
1398 	left=l;
1399 	right=r;
1400 	ValueType = VAL_Int;
1401 }
1402 
1403 //==========================================================================
1404 //
1405 //
1406 //
1407 //==========================================================================
1408 
~FxBinaryLogical()1409 FxBinaryLogical::~FxBinaryLogical()
1410 {
1411 	SAFE_DELETE(left);
1412 	SAFE_DELETE(right);
1413 }
1414 
1415 //==========================================================================
1416 //
1417 //
1418 //
1419 //==========================================================================
1420 
Resolve(FCompileContext & ctx)1421 FxExpression *FxBinaryLogical::Resolve(FCompileContext& ctx)
1422 {
1423 	CHECKRESOLVED();
1424 	if (left) left = left->ResolveAsBoolean(ctx);
1425 	if (right) right = right->ResolveAsBoolean(ctx);
1426 	if (!left || !right)
1427 	{
1428 		delete this;
1429 		return NULL;
1430 	}
1431 
1432 	int b_left=-1, b_right=-1;
1433 
1434 	if (left->isConstant()) b_left = left->EvalExpression(NULL).GetBool();
1435 	if (right->isConstant()) b_right = right->EvalExpression(NULL).GetBool();
1436 
1437 	// Do some optimizations. This will throw out all sub-expressions that are not
1438 	// needed to retrieve the final result.
1439 	if (Operator == TK_AndAnd)
1440 	{
1441 		if (b_left==0 || b_right==0)
1442 		{
1443 			FxExpression *x = new FxConstant(0, ScriptPosition);
1444 			delete this;
1445 			return x;
1446 		}
1447 		else if (b_left==1 && b_right==1)
1448 		{
1449 			FxExpression *x = new FxConstant(1, ScriptPosition);
1450 			delete this;
1451 			return x;
1452 		}
1453 		else if (b_left==1)
1454 		{
1455 			FxExpression *x = right;
1456 			right=NULL;
1457 			delete this;
1458 			return x;
1459 		}
1460 		else if (b_right==1)
1461 		{
1462 			FxExpression *x = left;
1463 			left=NULL;
1464 			delete this;
1465 			return x;
1466 		}
1467 	}
1468 	else if (Operator == TK_OrOr)
1469 	{
1470 		if (b_left==1 || b_right==1)
1471 		{
1472 			FxExpression *x = new FxConstant(1, ScriptPosition);
1473 			delete this;
1474 			return x;
1475 		}
1476 		if (b_left==0 && b_right==0)
1477 		{
1478 			FxExpression *x = new FxConstant(0, ScriptPosition);
1479 			delete this;
1480 			return x;
1481 		}
1482 		else if (b_left==0)
1483 		{
1484 			FxExpression *x = right;
1485 			right=NULL;
1486 			delete this;
1487 			return x;
1488 		}
1489 		else if (b_right==0)
1490 		{
1491 			FxExpression *x = left;
1492 			left=NULL;
1493 			delete this;
1494 			return x;
1495 		}
1496 	}
1497 	return this;
1498 }
1499 
1500 //==========================================================================
1501 //
1502 //
1503 //
1504 //==========================================================================
1505 
EvalExpression(AActor * self)1506 ExpVal FxBinaryLogical::EvalExpression (AActor *self)
1507 {
1508 	bool b_left = left->EvalExpression(self).GetBool();
1509 	ExpVal ret;
1510 
1511 	ret.Type = VAL_Int;
1512 	ret.Int = false;
1513 
1514 	if (Operator == TK_AndAnd)
1515 	{
1516 		ret.Int = (b_left && right->EvalExpression(self).GetBool());
1517 	}
1518 	else if (Operator == TK_OrOr)
1519 	{
1520 		ret.Int = (b_left || right->EvalExpression(self).GetBool());
1521 	}
1522 	return ret;
1523 }
1524 
1525 
1526 //==========================================================================
1527 //
1528 //
1529 //
1530 //==========================================================================
1531 
FxConditional(FxExpression * c,FxExpression * t,FxExpression * f)1532 FxConditional::FxConditional(FxExpression *c, FxExpression *t, FxExpression *f)
1533 : FxExpression(c->ScriptPosition)
1534 {
1535 	condition = c;
1536 	truex=t;
1537 	falsex=f;
1538 }
1539 
1540 //==========================================================================
1541 //
1542 //
1543 //
1544 //==========================================================================
1545 
~FxConditional()1546 FxConditional::~FxConditional()
1547 {
1548 	SAFE_DELETE(condition);
1549 	SAFE_DELETE(truex);
1550 	SAFE_DELETE(falsex);
1551 }
1552 
1553 //==========================================================================
1554 //
1555 //
1556 //
1557 //==========================================================================
1558 
Resolve(FCompileContext & ctx)1559 FxExpression *FxConditional::Resolve(FCompileContext& ctx)
1560 {
1561 	CHECKRESOLVED();
1562 	if (condition) condition = condition->ResolveAsBoolean(ctx);
1563 	RESOLVE(truex, ctx);
1564 	RESOLVE(falsex, ctx);
1565 	ABORT(condition && truex && falsex);
1566 
1567 	if (truex->ValueType == VAL_Int && falsex->ValueType == VAL_Int)
1568 		ValueType = VAL_Int;
1569 	else if (truex->ValueType.isNumeric() && falsex->ValueType.isNumeric())
1570 		ValueType = VAL_Float;
1571 	//else if (truex->ValueType != falsex->ValueType)
1572 
1573 	if (condition->isConstant())
1574 	{
1575 		ExpVal condval = condition->EvalExpression(NULL);
1576 		bool result = condval.GetBool();
1577 
1578 		FxExpression *e = result? truex:falsex;
1579 		delete (result? falsex:truex);
1580 		falsex = truex = NULL;
1581 		delete this;
1582 		return e;
1583 	}
1584 
1585 	return this;
1586 }
1587 
1588 //==========================================================================
1589 //
1590 //
1591 //
1592 //==========================================================================
1593 
EvalExpression(AActor * self)1594 ExpVal FxConditional::EvalExpression (AActor *self)
1595 {
1596 	ExpVal condval = condition->EvalExpression(self);
1597 	bool result = condval.GetBool();
1598 
1599 	FxExpression *e = result? truex:falsex;
1600 	return e->EvalExpression(self);
1601 }
1602 
1603 //==========================================================================
1604 //
1605 //
1606 //
1607 //==========================================================================
FxAbs(FxExpression * v)1608 FxAbs::FxAbs(FxExpression *v)
1609 : FxExpression(v->ScriptPosition)
1610 {
1611 	val = v;
1612 	ValueType = v->ValueType;
1613 }
1614 
1615 //==========================================================================
1616 //
1617 //
1618 //
1619 //==========================================================================
1620 
~FxAbs()1621 FxAbs::~FxAbs()
1622 {
1623 	SAFE_DELETE(val);
1624 }
1625 
1626 //==========================================================================
1627 //
1628 //
1629 //
1630 //==========================================================================
1631 
Resolve(FCompileContext & ctx)1632 FxExpression *FxAbs::Resolve(FCompileContext &ctx)
1633 {
1634 	CHECKRESOLVED();
1635 	SAFE_RESOLVE(val, ctx);
1636 
1637 
1638 	if (!val->ValueType.isNumeric())
1639 	{
1640 		ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
1641 		delete this;
1642 		return NULL;
1643 	}
1644 	else if (val->isConstant())
1645 	{
1646 		ExpVal value = val->EvalExpression(NULL);
1647 		switch (value.Type)
1648 		{
1649 		case VAL_Int:
1650 			value.Int = abs(value.Int);
1651 			break;
1652 
1653 		case VAL_Float:
1654 			value.Float = fabs(value.Float);
1655 			break;
1656 
1657 		default:
1658 			// shouldn't happen
1659 			delete this;
1660 			return NULL;
1661 		}
1662 		FxExpression *x = new FxConstant(value, ScriptPosition);
1663 		delete this;
1664 		return x;
1665 	}
1666 	ValueType = val->ValueType;
1667 	return this;
1668 }
1669 
1670 //==========================================================================
1671 //
1672 //
1673 //
1674 //==========================================================================
1675 
EvalExpression(AActor * self)1676 ExpVal FxAbs::EvalExpression (AActor *self)
1677 {
1678 	ExpVal value = val->EvalExpression(self);
1679 	switch (value.Type)
1680 	{
1681 	default:
1682 	case VAL_Int:
1683 		value.Int = abs(value.Int);
1684 		break;
1685 
1686 	case VAL_Float:
1687 		value.Float = fabs(value.Float);
1688 		break;
1689 	}
1690 	return value;
1691 }
1692 
1693 //==========================================================================
1694 //
1695 //
1696 //
1697 //==========================================================================
FxRandom(FRandom * r,FxExpression * mi,FxExpression * ma,const FScriptPosition & pos)1698 FxRandom::FxRandom(FRandom * r, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos)
1699 : FxExpression(pos)
1700 {
1701 	if (mi != NULL && ma != NULL)
1702 	{
1703 		min = new FxIntCast(mi);
1704 		max = new FxIntCast(ma);
1705 	}
1706 	else min = max = NULL;
1707 	rng = r;
1708 	ValueType = VAL_Int;
1709 }
1710 
1711 //==========================================================================
1712 //
1713 //
1714 //
1715 //==========================================================================
1716 
~FxRandom()1717 FxRandom::~FxRandom()
1718 {
1719 	SAFE_DELETE(min);
1720 	SAFE_DELETE(max);
1721 }
1722 
1723 //==========================================================================
1724 //
1725 //
1726 //
1727 //==========================================================================
1728 
Resolve(FCompileContext & ctx)1729 FxExpression *FxRandom::Resolve(FCompileContext &ctx)
1730 {
1731 	CHECKRESOLVED();
1732 	if (min && max)
1733 	{
1734 		RESOLVE(min, ctx);
1735 		RESOLVE(max, ctx);
1736 		ABORT(min && max);
1737 	}
1738 	return this;
1739 };
1740 
1741 
1742 //==========================================================================
1743 //
1744 //
1745 //
1746 //==========================================================================
1747 
EvalExpression(AActor * self)1748 ExpVal FxRandom::EvalExpression (AActor *self)
1749 {
1750 	ExpVal val;
1751 	val.Type = VAL_Int;
1752 
1753 	if (min != NULL && max != NULL)
1754 	{
1755 		int minval = min->EvalExpression (self).GetInt();
1756 		int maxval = max->EvalExpression (self).GetInt();
1757 
1758 		if (maxval < minval)
1759 		{
1760 			swapvalues (maxval, minval);
1761 		}
1762 
1763 		val.Int = (*rng)(maxval - minval + 1) + minval;
1764 	}
1765 	else
1766 	{
1767 		val.Int = (*rng)();
1768 	}
1769 	return val;
1770 }
1771 
1772 //==========================================================================
1773 //
1774 //
1775 //
1776 //==========================================================================
FxRandomPick(FRandom * r,TArray<FxExpression * > mi,bool floaty,const FScriptPosition & pos)1777 FxRandomPick::FxRandomPick(FRandom * r, TArray<FxExpression*> mi, bool floaty, const FScriptPosition &pos)
1778 : FxExpression(pos)
1779 {
1780 	for (unsigned int index = 0; index < mi.Size(); index++)
1781 	{
1782 		FxExpression *casted;
1783 		if (floaty)
1784 		{
1785 			casted = new FxFloatCast(mi[index]);
1786 		}
1787 		else
1788 		{
1789 			casted = new FxIntCast(mi[index]);
1790 		}
1791 		min.Push(casted);
1792 	}
1793 	rng = r;
1794 	ValueType = floaty ? VAL_Float : VAL_Int;
1795 }
1796 
1797 //==========================================================================
1798 //
1799 //
1800 //
1801 //==========================================================================
1802 
~FxRandomPick()1803 FxRandomPick::~FxRandomPick()
1804 {
1805 }
1806 
1807 //==========================================================================
1808 //
1809 //
1810 //
1811 //==========================================================================
1812 
Resolve(FCompileContext & ctx)1813 FxExpression *FxRandomPick::Resolve(FCompileContext &ctx)
1814 {
1815 	CHECKRESOLVED();
1816 	for (unsigned int index = 0; index < min.Size(); index++)
1817 	{
1818 		RESOLVE(min[index], ctx);
1819 		ABORT(min[index]);
1820 	}
1821 	return this;
1822 };
1823 
1824 
1825 //==========================================================================
1826 //
1827 //
1828 //
1829 //==========================================================================
1830 
EvalExpression(AActor * self)1831 ExpVal FxRandomPick::EvalExpression(AActor *self)
1832 {
1833 	ExpVal val;
1834 	int max = min.Size();
1835 	if (max > 0)
1836 	{
1837 		int select = (*rng)(max);
1838 		val = min[select]->EvalExpression(self);
1839 	}
1840 	/* Is a default even important when the parser requires at least one
1841 	 * choice? Why do we do this? */
1842 	else if (ValueType == VAL_Int)
1843 	{
1844 		val.Type = VAL_Int;
1845 		val.Int = (*rng)();
1846 	}
1847 	else
1848 	{
1849 		val.Type = VAL_Float;
1850 		val.Float = (*rng)(0x40000000) / double(0x40000000);
1851 	}
1852 	assert(val.Type == ValueType.Type);
1853 	return val;
1854 }
1855 
1856 //==========================================================================
1857 //
1858 //
1859 //
1860 //==========================================================================
FxFRandom(FRandom * r,FxExpression * mi,FxExpression * ma,const FScriptPosition & pos)1861 FxFRandom::FxFRandom(FRandom *r, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos)
1862 : FxRandom(r, NULL, NULL, pos)
1863 {
1864 	if (mi != NULL && ma != NULL)
1865 	{
1866 		min = mi;
1867 		max = ma;
1868 	}
1869 	ValueType = VAL_Float;
1870 }
1871 
1872 //==========================================================================
1873 //
1874 //
1875 //
1876 //==========================================================================
1877 
EvalExpression(AActor * self)1878 ExpVal FxFRandom::EvalExpression (AActor *self)
1879 {
1880 	ExpVal val;
1881 	val.Type = VAL_Float;
1882 	int random = (*rng)(0x40000000);
1883 	double frandom = random / double(0x40000000);
1884 
1885 	if (min != NULL && max != NULL)
1886 	{
1887 		double minval = min->EvalExpression (self).GetFloat();
1888 		double maxval = max->EvalExpression (self).GetFloat();
1889 
1890 		if (maxval < minval)
1891 		{
1892 			swapvalues (maxval, minval);
1893 		}
1894 
1895 		val.Float = frandom * (maxval - minval) + minval;
1896 	}
1897 	else
1898 	{
1899 		val.Float = frandom;
1900 	}
1901 	return val;
1902 }
1903 
1904 //==========================================================================
1905 //
1906 //
1907 //
1908 //==========================================================================
1909 
FxRandom2(FRandom * r,FxExpression * m,const FScriptPosition & pos)1910 FxRandom2::FxRandom2(FRandom *r, FxExpression *m, const FScriptPosition &pos)
1911 : FxExpression(pos)
1912 {
1913 	rng = r;
1914 	if (m) mask = new FxIntCast(m);
1915 	else mask = new FxConstant(-1, pos);
1916 	ValueType = VAL_Int;
1917 }
1918 
1919 //==========================================================================
1920 //
1921 //
1922 //
1923 //==========================================================================
1924 
~FxRandom2()1925 FxRandom2::~FxRandom2()
1926 {
1927 	SAFE_DELETE(mask);
1928 }
1929 
1930 //==========================================================================
1931 //
1932 //
1933 //
1934 //==========================================================================
1935 
Resolve(FCompileContext & ctx)1936 FxExpression *FxRandom2::Resolve(FCompileContext &ctx)
1937 {
1938 	CHECKRESOLVED();
1939 	SAFE_RESOLVE(mask, ctx);
1940 	return this;
1941 }
1942 
1943 //==========================================================================
1944 //
1945 //
1946 //
1947 //==========================================================================
1948 
EvalExpression(AActor * self)1949 ExpVal FxRandom2::EvalExpression (AActor *self)
1950 {
1951 	ExpVal maskval = mask->EvalExpression(self);
1952 	int imaskval = maskval.GetInt();
1953 
1954 	maskval.Type = VAL_Int;
1955 	maskval.Int = rng->Random2(imaskval);
1956 	return maskval;
1957 }
1958 
1959 //==========================================================================
1960 //
1961 //
1962 //
1963 //==========================================================================
1964 
FxIdentifier(FName name,const FScriptPosition & pos)1965 FxIdentifier::FxIdentifier(FName name, const FScriptPosition &pos)
1966 : FxExpression(pos)
1967 {
1968 	Identifier = name;
1969 }
1970 
1971 //==========================================================================
1972 //
1973 //
1974 //
1975 //==========================================================================
1976 
Resolve(FCompileContext & ctx)1977 FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
1978 {
1979 	PSymbol * sym;
1980 	FxExpression *newex = NULL;
1981 	//FBaseCVar * cv = NULL;
1982 	//FString s;
1983 	int num;
1984 	//const PClass *Class;
1985 
1986 	CHECKRESOLVED();
1987 	// see if the current class (if valid) defines something with this name.
1988 	if ((sym = ctx.FindInClass(Identifier)) != NULL)
1989 	{
1990 		if (sym->SymbolType == SYM_Const)
1991 		{
1992 			ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as class constant\n", Identifier.GetChars());
1993 			newex = FxConstant::MakeConstant(sym, ScriptPosition);
1994 		}
1995 		else if (sym->SymbolType == SYM_Variable)
1996 		{
1997 			PSymbolVariable *vsym = static_cast<PSymbolVariable*>(sym);
1998 			ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as member variable, index %d\n", Identifier.GetChars(), vsym->offset);
1999 			newex = new FxClassMember((new FxSelf(ScriptPosition))->Resolve(ctx), vsym, ScriptPosition);
2000 		}
2001 		else
2002 		{
2003 			ScriptPosition.Message(MSG_ERROR, "Invalid member identifier '%s'\n", Identifier.GetChars());
2004 		}
2005 	}
2006 	// now check the global identifiers.
2007 	else if ((sym = ctx.FindGlobal(Identifier)) != NULL)
2008 	{
2009 		if (sym->SymbolType == SYM_Const)
2010 		{
2011 			ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as global constant\n", Identifier.GetChars());
2012 			newex = FxConstant::MakeConstant(sym, ScriptPosition);
2013 		}
2014 		else if (sym->SymbolType == SYM_Variable)	// global variables will always be native
2015 		{
2016 			PSymbolVariable *vsym = static_cast<PSymbolVariable*>(sym);
2017 			ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as global variable, address %d\n", Identifier.GetChars(), vsym->offset);
2018 			newex = new FxGlobalVariable(vsym, ScriptPosition);
2019 		}
2020 		else
2021 		{
2022 			ScriptPosition.Message(MSG_ERROR, "Invalid global identifier '%s'\n", Identifier.GetChars());
2023 		}
2024 	}
2025 	/*
2026 	else if ((Class = PClass::FindClass(Identifier)))
2027 	{
2028 		pos.Message(MSG_DEBUGLOG, "Resolving name '%s' as class name\n", Identifier.GetChars());
2029 			newex = new FxClassType(Class, ScriptPosition);
2030 		}
2031 	}
2032 	*/
2033 
2034 	// also check for CVars
2035 	/*
2036 	else if ((cv = FindCVar(Identifier, NULL)) != NULL)
2037 	{
2038 		CLOG(CL_RESOLVE, LPrintf("Resolving name '%s' as cvar\n", Identifier.GetChars()));
2039 		newex = new FxCVar(cv, ScriptPosition);
2040 	}
2041 	*/
2042 	// and line specials
2043 	else if ((num = P_FindLineSpecial(Identifier, NULL, NULL)))
2044 	{
2045 		ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as line special %d\n", Identifier.GetChars(), num);
2046 		newex = new FxConstant(num, ScriptPosition);
2047 	}
2048 	else
2049 	{
2050 		ScriptPosition.Message(MSG_ERROR, "Unknown identifier '%s'", Identifier.GetChars());
2051 		newex = new FxConstant(0, ScriptPosition);
2052 	}
2053 	delete this;
2054 	return newex? newex->Resolve(ctx) : NULL;
2055 }
2056 
2057 
2058 //==========================================================================
2059 //
2060 //
2061 //
2062 //==========================================================================
2063 
FxSelf(const FScriptPosition & pos)2064 FxSelf::FxSelf(const FScriptPosition &pos)
2065 : FxExpression(pos)
2066 {
2067 }
2068 
2069 //==========================================================================
2070 //
2071 //
2072 //
2073 //==========================================================================
2074 
Resolve(FCompileContext & ctx)2075 FxExpression *FxSelf::Resolve(FCompileContext& ctx)
2076 {
2077 	CHECKRESOLVED();
2078 	if (!ctx.cls)
2079 	{
2080 		// can't really happen with DECORATE's expression evaluator.
2081 		ScriptPosition.Message(MSG_ERROR, "self used outside of a member function");
2082 		delete this;
2083 		return NULL;
2084 	}
2085 	ValueType = ctx.cls;
2086 	ValueType.Type = VAL_Object;
2087 	return this;
2088 }
2089 
2090 //==========================================================================
2091 //
2092 //
2093 //
2094 //==========================================================================
2095 
EvalExpression(AActor * self)2096 ExpVal FxSelf::EvalExpression (AActor *self)
2097 {
2098 	ExpVal ret;
2099 
2100 	ret.Type = VAL_Object;
2101 	ret.pointer = self;
2102 	return ret;
2103 }
2104 
2105 //==========================================================================
2106 //
2107 //
2108 //
2109 //==========================================================================
2110 
FxGlobalVariable(PSymbolVariable * mem,const FScriptPosition & pos)2111 FxGlobalVariable::FxGlobalVariable(PSymbolVariable *mem, const FScriptPosition &pos)
2112 : FxExpression(pos)
2113 {
2114 	var = mem;
2115 	AddressRequested = false;
2116 }
2117 
2118 //==========================================================================
2119 //
2120 //
2121 //
2122 //==========================================================================
2123 
RequestAddress()2124 void FxGlobalVariable::RequestAddress()
2125 {
2126 	AddressRequested = true;
2127 }
2128 
2129 //==========================================================================
2130 //
2131 //
2132 //
2133 //==========================================================================
2134 
Resolve(FCompileContext &)2135 FxExpression *FxGlobalVariable::Resolve(FCompileContext&)
2136 {
2137 	CHECKRESOLVED();
2138 	switch (var->ValueType.Type)
2139 	{
2140 	case VAL_Int:
2141 	case VAL_Bool:
2142 		ValueType = VAL_Int;
2143 		break;
2144 
2145 	case VAL_Float:
2146 	case VAL_Fixed:
2147 	case VAL_Angle:
2148 		ValueType = VAL_Float;
2149 		break;
2150 
2151 	case VAL_Object:
2152 	case VAL_Class:
2153 		ValueType = var->ValueType;
2154 		break;
2155 
2156 	default:
2157 		ScriptPosition.Message(MSG_ERROR, "Invalid type for global variable");
2158 		delete this;
2159 		return NULL;
2160 	}
2161 	return this;
2162 }
2163 
2164 //==========================================================================
2165 //
2166 //
2167 //
2168 //==========================================================================
2169 
EvalExpression(AActor * self)2170 ExpVal FxGlobalVariable::EvalExpression (AActor *self)
2171 {
2172 	ExpVal ret;
2173 
2174 	if (!AddressRequested)
2175 	{
2176 		ret = GetVariableValue((void*)var->offset, var->ValueType);
2177 	}
2178 	else
2179 	{
2180 		ret.pointer = (void*)var->offset;
2181 		ret.Type = VAL_Pointer;
2182 	}
2183 	return ret;
2184 }
2185 
2186 
2187 //==========================================================================
2188 //
2189 //
2190 //
2191 //==========================================================================
2192 
FxClassMember(FxExpression * x,PSymbolVariable * mem,const FScriptPosition & pos)2193 FxClassMember::FxClassMember(FxExpression *x, PSymbolVariable* mem, const FScriptPosition &pos)
2194 : FxExpression(pos)
2195 {
2196 	classx = x;
2197 	membervar = mem;
2198 	AddressRequested = false;
2199 	//if (classx->IsDefaultObject()) Readonly=true;
2200 }
2201 
2202 //==========================================================================
2203 //
2204 //
2205 //
2206 //==========================================================================
2207 
~FxClassMember()2208 FxClassMember::~FxClassMember()
2209 {
2210 	SAFE_DELETE(classx);
2211 }
2212 
2213 //==========================================================================
2214 //
2215 //
2216 //
2217 //==========================================================================
2218 
RequestAddress()2219 void FxClassMember::RequestAddress()
2220 {
2221 	AddressRequested = true;
2222 }
2223 
2224 //==========================================================================
2225 //
2226 //
2227 //
2228 //==========================================================================
2229 
Resolve(FCompileContext & ctx)2230 FxExpression *FxClassMember::Resolve(FCompileContext &ctx)
2231 {
2232 	CHECKRESOLVED();
2233 	SAFE_RESOLVE(classx, ctx);
2234 
2235 	if (classx->ValueType != VAL_Object && classx->ValueType != VAL_Class)
2236 	{
2237 		ScriptPosition.Message(MSG_ERROR, "Member variable requires a class or object");
2238 		delete this;
2239 		return NULL;
2240 	}
2241 	switch (membervar->ValueType.Type)
2242 	{
2243 	case VAL_Int:
2244 	case VAL_Bool:
2245 		ValueType = VAL_Int;
2246 		break;
2247 
2248 	case VAL_Float:
2249 	case VAL_Fixed:
2250 	case VAL_Angle:
2251 		ValueType = VAL_Float;
2252 		break;
2253 
2254 	case VAL_Object:
2255 	case VAL_Class:
2256 	case VAL_Array:
2257 		ValueType = membervar->ValueType;
2258 		break;
2259 
2260 	default:
2261 		ScriptPosition.Message(MSG_ERROR, "Invalid type for member variable %s", membervar->SymbolName.GetChars());
2262 		delete this;
2263 		return NULL;
2264 	}
2265 	return this;
2266 }
2267 
2268 //==========================================================================
2269 //
2270 //
2271 //
2272 //==========================================================================
2273 
EvalExpression(AActor * self)2274 ExpVal FxClassMember::EvalExpression (AActor *self)
2275 {
2276 	char *object = NULL;
2277 	if (classx->ValueType == VAL_Class)
2278 	{
2279 		// not implemented yet
2280 	}
2281 	else
2282 	{
2283 		object = classx->EvalExpression(self).GetPointer<char>();
2284 	}
2285 	if (object == NULL)
2286 	{
2287 		I_Error("Accessing member variable without valid object");
2288 	}
2289 
2290 	ExpVal ret;
2291 
2292 	if (!AddressRequested)
2293 	{
2294 		ret = GetVariableValue(object + membervar->offset, membervar->ValueType);
2295 	}
2296 	else
2297 	{
2298 		ret.pointer = object + membervar->offset;
2299 		ret.Type = VAL_Pointer;
2300 	}
2301 	return ret;
2302 }
2303 
2304 
2305 
2306 //==========================================================================
2307 //
2308 //
2309 //
2310 //==========================================================================
2311 
FxArrayElement(FxExpression * base,FxExpression * _index)2312 FxArrayElement::FxArrayElement(FxExpression *base, FxExpression *_index)
2313 :FxExpression(base->ScriptPosition)
2314 {
2315 	Array=base;
2316 	index = _index;
2317 	//AddressRequested = false;
2318 }
2319 
2320 //==========================================================================
2321 //
2322 //
2323 //
2324 //==========================================================================
2325 
~FxArrayElement()2326 FxArrayElement::~FxArrayElement()
2327 {
2328 	SAFE_DELETE(Array);
2329 	SAFE_DELETE(index);
2330 }
2331 
2332 //==========================================================================
2333 //
2334 //
2335 //
2336 //==========================================================================
2337 
2338 /*
2339 void FxArrayElement::RequestAddress()
2340 {
2341 	AddressRequested = true;
2342 }
2343 */
2344 
2345 //==========================================================================
2346 //
2347 //
2348 //
2349 //==========================================================================
2350 
Resolve(FCompileContext & ctx)2351 FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
2352 {
2353 	CHECKRESOLVED();
2354 	SAFE_RESOLVE(Array,ctx);
2355 	SAFE_RESOLVE(index,ctx);
2356 
2357 	if (index->ValueType == VAL_Float && ctx.lax)
2358 	{
2359 		// DECORATE allows floats here so cast them to int.
2360 		index = new FxIntCast(index);
2361 		index = index->Resolve(ctx);
2362 		if (index == NULL)
2363 		{
2364 			delete this;
2365 			return NULL;
2366 		}
2367 	}
2368 	if (index->ValueType != VAL_Int)
2369 	{
2370 		ScriptPosition.Message(MSG_ERROR, "Array index must be integer");
2371 		delete this;
2372 		return NULL;
2373 	}
2374 
2375 	if (Array->ValueType != VAL_Array)
2376 	{
2377 		ScriptPosition.Message(MSG_ERROR, "'[]' can only be used with arrays.");
2378 		delete this;
2379 		return NULL;
2380 	}
2381 
2382 	ValueType = Array->ValueType.GetBaseType();
2383 	if (ValueType != VAL_Int)
2384 	{
2385 		// int arrays only for now
2386 		ScriptPosition.Message(MSG_ERROR, "Only integer arrays are supported.");
2387 		delete this;
2388 		return NULL;
2389 	}
2390 	Array->RequestAddress();
2391 	return this;
2392 }
2393 
2394 //==========================================================================
2395 //
2396 // in its current state this won't be able to do more than handle the args array.
2397 //
2398 //==========================================================================
2399 
EvalExpression(AActor * self)2400 ExpVal FxArrayElement::EvalExpression (AActor *self)
2401 {
2402 	int * arraystart = Array->EvalExpression(self).GetPointer<int>();
2403 	int indexval = index->EvalExpression(self).GetInt();
2404 
2405 	if (indexval < 0 || indexval >= Array->ValueType.size)
2406 	{
2407 		I_Error("Array index out of bounds");
2408 	}
2409 
2410 	ExpVal ret;
2411 
2412 	ret.Int = arraystart[indexval];
2413 	ret.Type = VAL_Int;
2414 	return ret;
2415 }
2416 
2417 
2418 //==========================================================================
2419 //
2420 //
2421 //
2422 //==========================================================================
2423 
FxFunctionCall(FxExpression * self,FName methodname,FArgumentList * args,const FScriptPosition & pos)2424 FxFunctionCall::FxFunctionCall(FxExpression *self, FName methodname, FArgumentList *args, const FScriptPosition &pos)
2425 : FxExpression(pos)
2426 {
2427 	Self = self;
2428 	MethodName = methodname;
2429 	ArgList = args;
2430 }
2431 
2432 //==========================================================================
2433 //
2434 //
2435 //
2436 //==========================================================================
2437 
~FxFunctionCall()2438 FxFunctionCall::~FxFunctionCall()
2439 {
2440 	SAFE_DELETE(Self);
2441 	SAFE_DELETE(ArgList);
2442 }
2443 
2444 //==========================================================================
2445 //
2446 //
2447 //
2448 //==========================================================================
2449 
Resolve(FCompileContext & ctx)2450 FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
2451 {
2452 	int min, max, special;
2453 	if (MethodName == NAME_ACS_NamedExecuteWithResult || MethodName == NAME_CallACS)
2454 	{
2455 		special = -ACS_ExecuteWithResult;
2456 		min = 1;
2457 		max = 5;
2458 	}
2459 	else
2460 	{
2461 		special = P_FindLineSpecial(MethodName.GetChars(), &min, &max);
2462 	}
2463 	if (special != 0 && min >= 0)
2464 	{
2465 		int paramcount = ArgList? ArgList->Size() : 0;
2466 		if (paramcount < min)
2467 		{
2468 			ScriptPosition.Message(MSG_ERROR, "Not enough parameters for '%s' (expected %d, got %d)",
2469 				MethodName.GetChars(), min, paramcount);
2470 			delete this;
2471 			return NULL;
2472 		}
2473 		else if (paramcount > max)
2474 		{
2475 			ScriptPosition.Message(MSG_ERROR, "too many parameters for '%s' (expected %d, got %d)",
2476 				MethodName.GetChars(), max, paramcount);
2477 			delete this;
2478 			return NULL;
2479 		}
2480 		FxExpression *x = new FxActionSpecialCall(Self, special, ArgList, ScriptPosition);
2481 		ArgList = NULL;
2482 		delete this;
2483 		return x->Resolve(ctx);
2484 	}
2485 	else
2486 	{
2487 		if (Self != NULL)
2488 		{
2489 			ScriptPosition.Message(MSG_ERROR, "Global variables cannot have a self pointer");
2490 			delete this;
2491 			return NULL;
2492 		}
2493 		FxExpression *x = FxGlobalFunctionCall::StaticCreate(MethodName, ArgList, ScriptPosition);
2494 		ArgList = NULL;
2495 		delete this;
2496 		return x->Resolve(ctx);
2497 	}
2498 
2499 	ScriptPosition.Message(MSG_ERROR, "Call to unknown function '%s'", MethodName.GetChars());
2500 	delete this;
2501 	return NULL;
2502 }
2503 
2504 
2505 //==========================================================================
2506 //
2507 // FxActionSpecialCall
2508 //
2509 // If special is negative, then the first argument will be treated as a
2510 // name for ACS_NamedExecuteWithResult.
2511 //
2512 //==========================================================================
2513 
FxActionSpecialCall(FxExpression * self,int special,FArgumentList * args,const FScriptPosition & pos)2514 FxActionSpecialCall::FxActionSpecialCall(FxExpression *self, int special, FArgumentList *args, const FScriptPosition &pos)
2515 : FxExpression(pos)
2516 {
2517 	Self = self;
2518 	Special = special;
2519 	ArgList = args;
2520 }
2521 
2522 //==========================================================================
2523 //
2524 //
2525 //
2526 //==========================================================================
2527 
~FxActionSpecialCall()2528 FxActionSpecialCall::~FxActionSpecialCall()
2529 {
2530 	SAFE_DELETE(Self);
2531 	SAFE_DELETE(ArgList);
2532 }
2533 
2534 //==========================================================================
2535 //
2536 //
2537 //
2538 //==========================================================================
2539 
Resolve(FCompileContext & ctx)2540 FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx)
2541 {
2542 	CHECKRESOLVED();
2543 	bool failed = false;
2544 
2545 	if (ArgList != NULL)
2546 	{
2547 		for(unsigned i = 0; i < ArgList->Size(); i++)
2548 		{
2549 			(*ArgList)[i] = (*ArgList)[i]->Resolve(ctx);
2550 			if ((*ArgList)[i] == NULL) failed = true;
2551 			if (Special < 0 && i == 0)
2552 			{
2553 				if ((*ArgList)[i]->ValueType != VAL_Name)
2554 				{
2555 					ScriptPosition.Message(MSG_ERROR, "Name expected for parameter %d", i);
2556 					failed = true;
2557 				}
2558 			}
2559 			else if ((*ArgList)[i]->ValueType != VAL_Int)
2560 			{
2561 				if (ctx.lax && ((*ArgList)[i]->ValueType == VAL_Float))
2562 				{
2563 					(*ArgList)[i] = new FxIntCast((*ArgList)[i]);
2564 				}
2565 				else
2566 				{
2567 					ScriptPosition.Message(MSG_ERROR, "Integer expected for parameter %d", i);
2568 					failed = true;
2569 				}
2570 			}
2571 		}
2572 		if (failed)
2573 		{
2574 			delete this;
2575 			return NULL;
2576 		}
2577 	}
2578 	ValueType = VAL_Int;
2579 	return this;
2580 }
2581 
2582 
2583 //==========================================================================
2584 //
2585 //
2586 //
2587 //==========================================================================
2588 
EvalExpression(AActor * self)2589 ExpVal FxActionSpecialCall::EvalExpression (AActor *self)
2590 {
2591 	int v[5] = {0,0,0,0,0};
2592 	int special = Special;
2593 
2594 	if (Self != NULL)
2595 	{
2596 		self = Self->EvalExpression(self).GetPointer<AActor>();
2597 	}
2598 
2599 	if (ArgList != NULL)
2600 	{
2601 		for(unsigned i = 0; i < ArgList->Size(); i++)
2602 		{
2603 			if (special < 0)
2604 			{
2605 				special = -special;
2606 				v[i] = -(*ArgList)[i]->EvalExpression(self).GetName();
2607 			}
2608 			else
2609 			{
2610 				v[i] = (*ArgList)[i]->EvalExpression(self).GetInt();
2611 			}
2612 		}
2613 	}
2614 	ExpVal ret;
2615 	ret.Type = VAL_Int;
2616 	ret.Int = P_ExecuteSpecial(special, NULL, self, false, v[0], v[1], v[2], v[3], v[4]);
2617 	return ret;
2618 }
2619 
2620 //==========================================================================
2621 //
2622 //
2623 //
2624 //==========================================================================
2625 
FxGlobalFunctionCall(FName fname,FArgumentList * args,const FScriptPosition & pos)2626 FxGlobalFunctionCall::FxGlobalFunctionCall(FName fname, FArgumentList *args, const FScriptPosition &pos)
2627 : FxExpression(pos)
2628 {
2629 	Name = fname;
2630 	ArgList = args;
2631 }
2632 
2633 //==========================================================================
2634 //
2635 //
2636 //
2637 //==========================================================================
2638 
~FxGlobalFunctionCall()2639 FxGlobalFunctionCall::~FxGlobalFunctionCall()
2640 {
2641 	SAFE_DELETE(ArgList);
2642 }
2643 
2644 
2645 //==========================================================================
2646 //
2647 //
2648 //
2649 //==========================================================================
2650 
FxClassTypeCast(const PClass * dtype,FxExpression * x)2651 FxClassTypeCast::FxClassTypeCast(const PClass *dtype, FxExpression *x)
2652 : FxExpression(x->ScriptPosition)
2653 {
2654 	desttype = dtype;
2655 	basex=x;
2656 }
2657 
2658 //==========================================================================
2659 //
2660 //
2661 //
2662 //==========================================================================
2663 
~FxClassTypeCast()2664 FxClassTypeCast::~FxClassTypeCast()
2665 {
2666 	SAFE_DELETE(basex);
2667 }
2668 
2669 //==========================================================================
2670 //
2671 //
2672 //
2673 //==========================================================================
2674 
Resolve(FCompileContext & ctx)2675 FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
2676 {
2677 	CHECKRESOLVED();
2678 	SAFE_RESOLVE(basex, ctx);
2679 
2680 	if (basex->ValueType != VAL_Name)
2681 	{
2682 		ScriptPosition.Message(MSG_ERROR, "Cannot convert to class type");
2683 		delete this;
2684 		return NULL;
2685 	}
2686 
2687 	if (basex->isConstant())
2688 	{
2689 		FName clsname = basex->EvalExpression(NULL).GetName();
2690 		const PClass *cls = NULL;
2691 
2692 		if (clsname != NAME_None)
2693 		{
2694 			cls = PClass::FindClass(clsname);
2695 			if (cls == NULL)
2696 			{
2697 				if (!ctx.lax)
2698 				{
2699 					ScriptPosition.Message(MSG_ERROR,"Unknown class name '%s'", clsname.GetChars());
2700 					delete this;
2701 					return NULL;
2702 				}
2703 				// Since this happens in released WADs it must pass without a terminal error... :(
2704 				ScriptPosition.Message(MSG_WARNING,
2705 					"Unknown class name '%s'",
2706 					clsname.GetChars(), desttype->TypeName.GetChars());
2707 			}
2708 			else
2709 			{
2710 				if (!cls->IsDescendantOf(desttype))
2711 				{
2712 					ScriptPosition.Message(MSG_ERROR,"class '%s' is not compatible with '%s'", clsname.GetChars(), desttype->TypeName.GetChars());
2713 					delete this;
2714 					return NULL;
2715 				}
2716 			}
2717 			ScriptPosition.Message(MSG_DEBUG,"resolving '%s' as class name", clsname.GetChars());
2718 		}
2719 		FxExpression *x = new FxConstant(cls, ScriptPosition);
2720 		delete this;
2721 		return x;
2722 	}
2723 	return this;
2724 }
2725 
2726 //==========================================================================
2727 //
2728 //
2729 //
2730 //==========================================================================
2731 
EvalExpression(AActor * self)2732 ExpVal FxClassTypeCast::EvalExpression (AActor *self)
2733 {
2734 	FName clsname = basex->EvalExpression(NULL).GetName();
2735 	const PClass *cls = PClass::FindClass(clsname);
2736 
2737 	if (!cls->IsDescendantOf(desttype))
2738 	{
2739 		Printf("class '%s' is not compatible with '%s'", clsname.GetChars(), desttype->TypeName.GetChars());
2740 		cls = NULL;
2741 	}
2742 
2743 	ExpVal ret;
2744 	ret.Type = VAL_Class;
2745 	ret.pointer = (void*)cls;
2746 	return ret;
2747 }
2748 
2749 
2750 //==========================================================================
2751 //
2752 //
2753 //
2754 //==========================================================================
2755 
Resolve(FCompileContext & ctx)2756 FxExpression *FxStateByIndex::Resolve(FCompileContext &ctx)
2757 {
2758 	CHECKRESOLVED();
2759 	if (ctx.cls->ActorInfo == NULL || ctx.cls->ActorInfo->NumOwnedStates == 0)
2760 	{
2761 		// This can't really happen
2762 		assert(false);
2763 	}
2764 	if (ctx.cls->ActorInfo->NumOwnedStates <= index)
2765 	{
2766 		ScriptPosition.Message(MSG_ERROR, "%s: Attempt to jump to non existing state index %d",
2767 			ctx.cls->TypeName.GetChars(), index);
2768 		delete this;
2769 		return NULL;
2770 	}
2771 	FxExpression *x = new FxConstant(ctx.cls->ActorInfo->OwnedStates + index, ScriptPosition);
2772 	delete this;
2773 	return x;
2774 }
2775 
2776 
2777 //==========================================================================
2778 //
2779 //
2780 //
2781 //==========================================================================
2782 
FxMultiNameState(const char * _statestring,const FScriptPosition & pos)2783 FxMultiNameState::FxMultiNameState(const char *_statestring, const FScriptPosition &pos)
2784 	:FxExpression(pos)
2785 {
2786 	FName scopename;
2787 	FString statestring = _statestring;
2788 	int scopeindex = statestring.IndexOf("::");
2789 
2790 	if (scopeindex >= 0)
2791 	{
2792 		scopename = FName(statestring, scopeindex, false);
2793 		statestring = statestring.Right(statestring.Len() - scopeindex - 2);
2794 	}
2795 	else
2796 	{
2797 		scopename = NULL;
2798 	}
2799 	names = MakeStateNameList(statestring);
2800 	names.Insert(0, scopename);
2801 	scope = NULL;
2802 }
2803 
2804 //==========================================================================
2805 //
2806 //
2807 //
2808 //==========================================================================
2809 
Resolve(FCompileContext & ctx)2810 FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx)
2811 {
2812 	CHECKRESOLVED();
2813 	if (names[0] == NAME_None)
2814 	{
2815 		scope = NULL;
2816 	}
2817 	else if (names[0] == NAME_Super)
2818 	{
2819 		scope = ctx.cls->ParentClass;
2820 	}
2821 	else
2822 	{
2823 		scope = PClass::FindClass(names[0]);
2824 		if (scope == NULL)
2825 		{
2826 			ScriptPosition.Message(MSG_ERROR, "Unknown class '%s' in state label", names[0].GetChars());
2827 			delete this;
2828 			return NULL;
2829 		}
2830 		else if (!scope->IsDescendantOf(ctx.cls))
2831 		{
2832 			ScriptPosition.Message(MSG_ERROR, "'%s' is not an ancestor of '%s'", names[0].GetChars(),ctx.cls->TypeName.GetChars());
2833 			delete this;
2834 			return NULL;
2835 		}
2836 	}
2837 	if (scope != NULL)
2838 	{
2839 		FState *destination = NULL;
2840 		// If the label is class specific we can resolve it right here
2841 		if (names[1] != NAME_None)
2842 		{
2843 			if (scope->ActorInfo == NULL)
2844 			{
2845 				ScriptPosition.Message(MSG_ERROR, "'%s' has no actorinfo", names[0].GetChars());
2846 				delete this;
2847 				return NULL;
2848 			}
2849 			destination = scope->ActorInfo->FindState(names.Size()-1, &names[1], false);
2850 			if (destination == NULL)
2851 			{
2852 				ScriptPosition.Message(ctx.lax? MSG_WARNING:MSG_ERROR, "Unknown state jump destination");
2853 				if (!ctx.lax)
2854 				{
2855 					delete this;
2856 					return NULL;
2857 				}
2858 				return this;
2859 			}
2860 		}
2861 		FxExpression *x = new FxConstant(destination, ScriptPosition);
2862 		delete this;
2863 		return x;
2864 	}
2865 	names.Delete(0);
2866 	names.ShrinkToFit();
2867 	ValueType = VAL_State;
2868 	return this;
2869 }
2870 
2871 //==========================================================================
2872 //
2873 //
2874 //
2875 //==========================================================================
2876 
EvalExpression(AActor * self)2877 ExpVal FxMultiNameState::EvalExpression (AActor *self)
2878 {
2879 	ExpVal ret;
2880 	ret.Type = VAL_State;
2881 	ret.pointer = self->GetClass()->ActorInfo->FindState(names.Size(), &names[0]);
2882 	if (ret.pointer == NULL)
2883 	{
2884 		const char *dot="";
2885 		Printf("Jump target '");
2886 		for (unsigned int i=0;i<names.Size();i++)
2887 		{
2888 			Printf("%s%s", dot, names[i].GetChars());
2889 			dot = ".";
2890 		}
2891 		Printf("' not found in %s\n", self->GetClass()->TypeName.GetChars());
2892 	}
2893 	return ret;
2894 }
2895 
2896 
2897 
2898 //==========================================================================
2899 //
2900 // NOTE: I don't expect any of the following to survive Doomscript ;)
2901 //
2902 //==========================================================================
2903 
2904 FStateExpressions StateParams;
2905 
2906 
2907 //==========================================================================
2908 //
2909 //
2910 //
2911 //==========================================================================
2912 
Clear()2913 void FStateExpressions::Clear()
2914 {
2915 	for(unsigned i=0; i<Size(); i++)
2916 	{
2917 		if (expressions[i].expr != NULL && !expressions[i].cloned)
2918 		{
2919 			delete expressions[i].expr;
2920 		}
2921 	}
2922 	expressions.Clear();
2923 }
2924 
2925 //==========================================================================
2926 //
2927 //
2928 //
2929 //==========================================================================
2930 
Add(FxExpression * x,const PClass * o,bool c)2931 int FStateExpressions::Add(FxExpression *x, const PClass *o, bool c)
2932 {
2933 	int idx = expressions.Reserve(1);
2934 	FStateExpression &exp = expressions[idx];
2935 	exp.expr = x;
2936 	exp.owner = o;
2937 	exp.constant = c;
2938 	exp.cloned = false;
2939 	return idx;
2940 }
2941 
2942 //==========================================================================
2943 //
2944 //
2945 //
2946 //==========================================================================
2947 
Reserve(int num,const PClass * cls)2948 int FStateExpressions::Reserve(int num, const PClass *cls)
2949 {
2950 	int idx = expressions.Reserve(num);
2951 	FStateExpression *exp = &expressions[idx];
2952 	for(int i=0; i<num; i++)
2953 	{
2954 		exp[i].expr = NULL;
2955 		exp[i].owner = cls;
2956 		exp[i].constant = false;
2957 		exp[i].cloned = false;
2958 	}
2959 	return idx;
2960 }
2961 
2962 //==========================================================================
2963 //
2964 //
2965 //
2966 //==========================================================================
2967 
Set(int num,FxExpression * x,bool cloned)2968 void FStateExpressions::Set(int num, FxExpression *x, bool cloned)
2969 {
2970 	if (num >= 0 && num < int(Size()))
2971 	{
2972 		assert(expressions[num].expr == NULL || expressions[num].cloned);
2973 		expressions[num].expr = x;
2974 		expressions[num].cloned = cloned;
2975 	}
2976 }
2977 
2978 //==========================================================================
2979 //
2980 //
2981 //
2982 //==========================================================================
2983 
Copy(int dest,int src,int cnt)2984 void FStateExpressions::Copy(int dest, int src, int cnt)
2985 {
2986 	for(int i=0; i<cnt; i++)
2987 	{
2988 		// For now set only a reference because these expressions may change when being resolved
2989 		expressions[dest+i].expr = (FxExpression*)intptr_t(src+i);
2990 		expressions[dest+i].cloned = true;
2991 	}
2992 }
2993 
2994 //==========================================================================
2995 //
2996 //
2997 //
2998 //==========================================================================
2999 
ResolveAll()3000 int FStateExpressions::ResolveAll()
3001 {
3002 	int errorcount = 0;
3003 
3004 	FCompileContext ctx;
3005 	ctx.lax = true;
3006 	for(unsigned i=0; i<Size(); i++)
3007 	{
3008 		if (expressions[i].cloned)
3009 		{
3010 			// Now that everything coming before has been resolved we may copy the actual pointer.
3011 			unsigned ii = unsigned((intptr_t)expressions[i].expr);
3012 			expressions[i].expr = expressions[ii].expr;
3013 		}
3014 		else if (expressions[i].expr != NULL)
3015 		{
3016 			ctx.cls = expressions[i].owner;
3017 			ctx.isconst = expressions[i].constant;
3018 			expressions[i].expr = expressions[i].expr->Resolve(ctx);
3019 			if (expressions[i].expr == NULL)
3020 			{
3021 				errorcount++;
3022 			}
3023 			else if (expressions[i].constant && !expressions[i].expr->isConstant())
3024 			{
3025 				expressions[i].expr->ScriptPosition.Message(MSG_ERROR, "Constant expression expected");
3026 				errorcount++;
3027 			}
3028 		}
3029 	}
3030 
3031 	for(unsigned i=0; i<Size(); i++)
3032 	{
3033 		if (expressions[i].expr != NULL)
3034 		{
3035 			if (!expressions[i].expr->isresolved)
3036 			{
3037 				expressions[i].expr->ScriptPosition.Message(MSG_ERROR, "Expression at index %d not resolved\n", i);
3038 				errorcount++;
3039 			}
3040 		}
3041 	}
3042 
3043 	return errorcount;
3044 }
3045 
3046 //==========================================================================
3047 //
3048 //
3049 //
3050 //==========================================================================
3051 
Get(int num)3052 FxExpression *FStateExpressions::Get(int num)
3053 {
3054 	if (num >= 0 && num < int(Size()))
3055 		return expressions[num].expr;
3056 	return NULL;
3057 }
3058 
3059