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