TorqueScript  0.2
instructions.hpp
1 
15 #pragma once
16 
17 #include <vector>
18 #include <assert.h>
19 #include <iostream>
20 #include <sstream>
21 
22 #include <torquescript/function.hpp>
23 #include <torquescript/interpreter.hpp>
24 #include <torquescript/executionscope.hpp>
25 #include <torquescript/storedvalue.hpp>
26 #include <torquescript/storedvaluestack.hpp>
27 #include <torquescript/executionstate.hpp>
28 #include <torquescript/instructionsequence.hpp>
29 
30 namespace TorqueScript
31 {
32  namespace Instructions
33  {
39  {
40  public:
46  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) = 0;
47 
51  virtual std::string disassemble() = 0;
52 
54  std::string mComment;
55  };
56 
62  {
63  public:
64  PushFloatInstruction(const float value) : mParameter(value)
65  {
66 
67  }
68 
69  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
70  {
71  StoredValueStack& stack = state->mExecutionScope.getStack();
72  stack.push_back(StoredValue(mParameter));
73  return 1;
74  };
75 
76  virtual std::string disassemble() override
77  {
78  std::ostringstream out;
79  out << "PushFloat " << mParameter;
80  return out.str();
81  }
82 
83  private:
85  float mParameter;
86  };
87 
93  {
94  public:
95  PushIntegerInstruction(const int value) : mParameter(value)
96  {
97 
98  }
99 
100  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
101  {
102  StoredValueStack& stack = state->mExecutionScope.getStack();
103  stack.push_back(StoredValue(mParameter));
104  return 1;
105  };
106 
107  virtual std::string disassemble() override
108  {
109  std::ostringstream out;
110  out << "PushInteger " << mParameter;
111  return out.str();
112  }
113 
114  private:
116  int mParameter;
117  };
118 
124  {
125  public:
126  PushStringInstruction(const std::size_t value) : mStringID(value)
127  {
128 
129  }
130 
131  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
132  {
133  StoredValueStack& stack = state->mExecutionScope.getStack();
134  stack.push_back(StoredValue(mStringID, StoredValueType::String));
135  return 1;
136  };
137 
138  virtual std::string disassemble() override
139  {
140  std::ostringstream out;
141  out << "PushString " << mStringID;
142  return out.str();
143  }
144 
145  private:
147  std::size_t mStringID;
148  };
149 
155  {
156  public:
157  PushLocalReferenceInstruction(const std::size_t value) : mStringID(value)
158  {
159 
160  }
161 
162  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
163  {
164  StoredValueStack& stack = state->mExecutionScope.getStack();
165  stack.push_back(StoredValue(mStringID, StoredValueType::LocalReference));
166  return 1;
167  };
168 
169  virtual std::string disassemble() override
170  {
171  std::ostringstream out;
172  out << "PushLocalReference " << mStringID;
173  return out.str();
174  }
175 
176  private:
178  std::size_t mStringID;
179  };
180 
186  {
187  public:
188  PushGlobalReferenceInstruction(const std::size_t value) : mStringID(value)
189  {
190 
191  }
192 
193  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
194  {
195  StoredValueStack& stack = state->mExecutionScope.getStack();
196  stack.push_back(StoredValue(mStringID, StoredValueType::GlobalReference));
197  return 1;
198  };
199 
200  virtual std::string disassemble() override
201  {
202  std::ostringstream out;
203  out << "PushGlobalReference " << mStringID;
204  return out.str();
205  }
206 
207  private:
209  std::size_t mStringID;
210  };
211 
216  {
217  public:
218  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
219  {
220  StoredValueStack& stack = state->mExecutionScope.getStack();
221 
222  assert(stack.size() >= 2);
223 
224  // Pull two values off the stack
225  StoredValue rhsStored = stack.back();
226  stack.pop_back();
227  StoredValue lhsStored = stack.back();
228  stack.pop_back();
229 
230  float resultRaw = 0.0f;
231  resultRaw = lhsStored.toFloat(state);
232  resultRaw += rhsStored.toFloat(state);
233 
234  StoredValue result = StoredValue(resultRaw);
235  if (!lhsStored.setValue(result, state))
236  {
237  state->mInterpreter->mConfig.mPlatform->logError("Attempted to perform no-op assignment!");
238  }
239 
240  // In Torque, the result of the assignment is pushed to stack
241  stack.push_back(result);
242  return 1;
243  };
244 
245  virtual std::string disassemble() override
246  {
247  return "AddAssignment";
248  }
249  };
250 
255  {
256  public:
257  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
258  {
259  StoredValueStack& stack = state->mExecutionScope.getStack();
260 
261  assert(stack.size() >= 2);
262 
263  // Pull two values off the stack
264  StoredValue rhsStored = stack.back();
265  stack.pop_back();
266  StoredValue lhsStored = stack.back();
267  stack.pop_back();
268 
269  if (!lhsStored.setValue(rhsStored, state))
270  {
271  state->mInterpreter->mConfig.mPlatform->logError("Attempted to perform no-op assignment!");
272  }
273 
274  // In Torque, the result of the assignment is pushed to stack
275  stack.push_back(rhsStored);
276  return 1;
277  };
278 
279  virtual std::string disassemble() override
280  {
281  return "Assignment";
282  }
283  };
284 
290  {
291  public:
292  ConcatInstruction(const std::string& seperator) : mSeperator(seperator)
293  {
294 
295  }
296 
297  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
298  {
299  StoredValueStack& stack = state->mExecutionScope.getStack();
300 
301  assert(stack.size() >= 2);
302 
303  // Pull two values off the stack
304  StoredValue rhsStored = stack.back();
305  stack.pop_back();
306  StoredValue lhsStored = stack.back();
307  stack.pop_back();
308 
309  std::string lhs = lhsStored.toString(state);
310  std::string rhs = rhsStored.toString(state);
311 
312  // Generate a new string ID
313  const std::size_t requestedStringID = state->mInterpreter->mStringTable.getOrAssign(lhs + mSeperator + rhs);
314  stack.push_back(StoredValue(requestedStringID, StoredValueType::String));
315  return 1;
316  };
317 
318  virtual std::string disassemble() override
319  {
320  std::ostringstream result;
321  result << "Concat " << mSeperator;
322  return result.str();
323  }
324 
325  private:
326  std::string mSeperator;
327  };
328 
333  {
334  public:
335  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
336  {
337  StoredValueStack& stack = state->mExecutionScope.getStack();
338 
339  assert(stack.size() >= 1);
340 
341  // Pull two values off the stack
342  StoredValue storedTarget = stack.back();
343  stack.pop_back();
344 
345  stack.push_back(StoredValue(-storedTarget.toFloat(state)));
346  return 1;
347  };
348 
349  virtual std::string disassemble() override
350  {
351  return "Negate";
352  }
353  };
354 
359  {
360  public:
361  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
362  {
363  StoredValueStack& stack = state->mExecutionScope.getStack();
364 
365  assert(stack.size() >= 1);
366 
367  // Pull two values off the stack
368  StoredValue storedTarget = stack.back();
369  stack.pop_back();
370 
371  stack.push_back(StoredValue(!storedTarget.toBoolean(state) ? 1 : 0));
372  return 1;
373  };
374 
375  virtual std::string disassemble() override
376  {
377  return "Not";
378  }
379  };
380 
385  {
386  public:
393  CallFunctionInstruction(const std::string& space, const std::string& name, const std::size_t argc) : mNameSpace(space), mName(name), mArgc(argc)
394  {
395 
396  }
397 
398  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
399  {
400  const std::string namespaceName = toLowerCase(mNameSpace);
401  StoredValueStack& stack = state->mExecutionScope.getStack();
402 
403  // If we're calling a parent function, perform an alternative lookup
404  if (namespaceName == "parent")
405  {
406  Function* currentFunction = state->mExecutionScope.getCurrentFunction();
407  if (currentFunction == nullptr)
408  {
409  state->mInterpreter->mConfig.mPlatform->logError("Attempted to call parent:: function at root!");
410  stack.push_back(StoredValue(0));
411  return 1;
412  }
413 
414  // Once we have a valid function pointer, ask the interpreter to find a super function higher up the chain
415  std::shared_ptr<Function> parentFunction = state->mInterpreter->getFunctionParent(currentFunction);
416  if (!parentFunction)
417  {
418  std::ostringstream stream;
419 
420  stream << "Could not find parent function '" << mName << "' for calling! Placing 0 on the stack.";
421  state->mInterpreter->mConfig.mPlatform->logError(stream.str());
422 
423  stack.push_back(StoredValue(0));
424  return 1;
425  }
426 
427  // Otherwise, call it
428  parentFunction->execute(nullptr, state, mArgc);
429 
430  return 1;
431  }
432 
433  std::shared_ptr<Function> functionLookup = state->mInterpreter->getFunction(mNameSpace, mName);
434  if (functionLookup)
435  {
436  functionLookup->execute(nullptr, state, mArgc);
437  }
438  else
439  {
440  std::ostringstream stream;
441 
442  stream << "Could not find function '" << mName << "' for calling! Placing 0 on the stack.";
443  state->mInterpreter->mConfig.mPlatform->logError(stream.str());
444 
445  stack.push_back(StoredValue(0));
446  }
447  return 1;
448  };
449 
450  virtual std::string disassemble() override
451  {
452  std::ostringstream out;
453 
454  if (mNameSpace == "")
455  {
456  out << "CallFunction " << mName << " argc=" << mArgc;
457  }
458  else
459  {
460  out << "CallFunction " << mNameSpace << "::" << mName << " argc=" << mArgc;
461  }
462  return out.str();
463  }
464 
465  private:
467  std::string mNameSpace;
468 
470  std::string mName;
471 
473  std::size_t mArgc;
474  };
475 
480  {
481  public:
482  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
483  {
484  StoredValueStack& stack = state->mExecutionScope.getStack();
485 
486  assert(stack.size() >= 2);
487 
488  StoredValue rhsStored = stack.back();
489  stack.pop_back();
490  StoredValue lhsStored = stack.back();
491  stack.pop_back();
492 
493  // NOTE: For now we normalize to floats
494  float lhs = lhsStored.toFloat(state);
495  float rhs = rhsStored.toFloat(state);
496 
497  const float result = lhs + rhs;
498  stack.push_back(StoredValue(result));
499  return 1;
500  };
501 
502  virtual std::string disassemble() override
503  {
504  return "Add";
505  }
506  };
507 
512  {
513  public:
514  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
515  {
516  StoredValueStack& stack = state->mExecutionScope.getStack();
517 
518  assert(stack.size() >= 2);
519 
520  StoredValue rhsStored = stack.back();
521  stack.pop_back();
522  StoredValue lhsStored = stack.back();
523  stack.pop_back();
524 
525  // NOTE: For now we normalize to floats
526  float lhs = lhsStored.toFloat(state);
527  float rhs = rhsStored.toFloat(state);
528 
529  const int result = lhs < rhs ? 1 : 0;
530  stack.push_back(StoredValue(result));
531  return 1;
532  };
533 
534  virtual std::string disassemble() override
535  {
536  return "LessThan";
537  }
538  };
539 
544  {
545  public:
546  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
547  {
548  StoredValueStack& stack = state->mExecutionScope.getStack();
549 
550  assert(stack.size() >= 2);
551 
552  StoredValue rhsStored = stack.back();
553  stack.pop_back();
554  StoredValue lhsStored = stack.back();
555  stack.pop_back();
556 
557  // NOTE: For now we normalize to floats
558  float lhs = lhsStored.toFloat(state);
559  float rhs = rhsStored.toFloat(state);
560 
561  const int result = lhs == rhs ? 1 : 0;
562  stack.push_back(StoredValue(result));
563  return 1;
564  };
565 
566  virtual std::string disassemble() override
567  {
568  return "Equals";
569  }
570  };
571 
576  {
577  public:
578  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
579  {
580  StoredValueStack& stack = state->mExecutionScope.getStack();
581 
582  assert(stack.size() >= 2);
583 
584  StoredValue rhsStored = stack.back();
585  stack.pop_back();
586  StoredValue lhsStored = stack.back();
587  stack.pop_back();
588 
589  // NOTE: For now we normalize to floats
590  int lhs = lhsStored.toInteger(state);
591  int rhs = rhsStored.toInteger(state);
592 
593  const int result = lhs & rhs;
594  stack.push_back(StoredValue(result));
595  return 1;
596  };
597 
598  virtual std::string disassemble() override
599  {
600  return "BitwiseAnd";
601  }
602  };
603 
609  {
610  public:
611  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
612  {
613  StoredValueStack& stack = state->mExecutionScope.getStack();
614 
615  assert(stack.size() >= 2);
616 
617  StoredValue lhsStored = stack.back();
618  stack.pop_back();
619  StoredValue rhsStored = stack.back();
620  stack.pop_back();
621 
622  // NOTE: For now we normalize to floats
623 
624  float lhs = lhsStored.toFloat(state);
625  float rhs = rhsStored.toFloat(state);
626 
627  const float result = lhs * rhs;
628  stack.push_back(StoredValue(result));
629  return 1;
630  };
631 
632  virtual std::string disassemble() override
633  {
634  return "Multiply";
635  }
636  };
637 
643  {
644  public:
645  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
646  {
647  StoredValueStack& stack = state->mExecutionScope.getStack();
648 
649  assert(stack.size() >= 2);
650 
651  StoredValue rhsStored = stack.back();
652  stack.pop_back();
653  StoredValue lhsStored = stack.back();
654  stack.pop_back();
655 
656  // NOTE: For now we normalize to floats
657 
658  float lhs = lhsStored.toFloat(state);
659  float rhs = rhsStored.toFloat(state);
660 
661  const float result = lhs / rhs;
662  stack.push_back(StoredValue(result));
663  return 1;
664  };
665 
666  virtual std::string disassemble() override
667  {
668  return "Divide";
669  }
670  };
671 
676  {
677  public:
678  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
679  {
680  StoredValueStack& stack = state->mExecutionScope.getStack();
681 
682  assert(stack.size() >= 1);
683  stack.pop_back();
684 
685  return 1;
686  };
687 
688  virtual std::string disassemble() override
689  {
690  return "Pop";
691  }
692  };
693 
698  {
699  public:
704  JumpInstruction(const AddressType offset) : mOffset(offset)
705  {
706 
707  }
708 
709  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
710  {
711  return mOffset;
712  };
713 
714  virtual std::string disassemble() override
715  {
716  std::ostringstream out;
717  out << "Jump " << mOffset;
718  return out.str();
719  }
720 
721  private:
723  AddressType mOffset;
724  };
725 
732  {
733  public:
738  JumpTrueInstruction(const AddressType offset) : mOffset(offset)
739  {
740 
741  }
742 
743  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
744  {
745  StoredValueStack& stack = state->mExecutionScope.getStack();
746 
747  assert(stack.size() >= 1);
748 
749  StoredValue booleanStored = stack.back();
750  stack.pop_back();
751 
752  if (booleanStored.toBoolean(state))
753  {
754  return mOffset;
755  }
756  return 1;
757  };
758 
759  virtual std::string disassemble() override
760  {
761  std::ostringstream out;
762  out << "JumpTrue " << mOffset;
763  return out.str();
764  }
765 
766  private:
768  AddressType mOffset;
769  };
770 
777  {
778  public:
783  JumpFalseInstruction(const AddressType offset) : mOffset(offset)
784  {
785 
786  }
787 
788  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
789  {
790  StoredValueStack& stack = state->mExecutionScope.getStack();
791 
792  assert(stack.size() >= 1);
793 
794  StoredValue booleanStored = stack.back();
795  stack.pop_back();
796 
797  if (!booleanStored.toBoolean(state))
798  {
799  return mOffset;
800  }
801  return 1;
802  };
803 
804  virtual std::string disassemble() override
805  {
806  std::ostringstream out;
807  out << "JumpFalse " << mOffset;
808  return out.str();
809  }
810 
811  private:
813  AddressType mOffset;
814  };
815 
821  {
822  public:
823  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
824  {
825  return 1;
826  };
827 
828  virtual std::string disassemble() override
829  {
830  return "NOP";
831  }
832  };
833 
838  {
839  public:
848  FunctionDeclarationInstruction(const std::string package, const std::string& space, const std::string& name, const std::vector<std::string> parameterNames, const InstructionSequence& instructions) : mPackageName(package), mNameSpace(space), mName(name), mParameterNames(parameterNames), mInstructions(instructions)
849  {
850 
851  }
852 
853  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
854  {
855  // Register the function
856  std::shared_ptr<Function> newFunction = std::shared_ptr<Function>(new Function(mPackageName, mNameSpace, mName, mParameterNames));
857  newFunction->addInstructions(mInstructions);
858  state->mInterpreter->addFunction(newFunction);
859 
860  return 1;
861  };
862 
863  virtual std::string disassemble() override
864  {
865  std::ostringstream out;
866 
867  if (mNameSpace == NAMESPACE_EMPTY)
868  {
869  out << "FunctionDeclaration " << mName;
870  }
871  else
872  {
873  out << "FunctionDeclaration " << mNameSpace << "::" << mName;
874  }
875 
876  if (mPackageName != PACKAGE_EMPTY)
877  {
878  out << "[in Package " << mPackageName << "] ";
879  }
880 
881  out << "(";
882 
883  // Generate parameter list
884  for (auto iterator = mParameterNames.begin(); iterator != mParameterNames.end(); ++iterator)
885  {
886  if (iterator != mParameterNames.begin())
887  {
888  out << ", ";
889  }
890 
891  out << *iterator;
892  }
893 
894  // Output all instructions
895  out << ")" << std::endl;
896  for (auto&& instruction : mInstructions)
897  {
898  out << " " << instruction->disassemble();
899  if (instruction->mComment != "")
900  {
901  out << " // " << instruction->mComment;
902  }
903  out << std::endl;
904  }
905  return out.str();
906  }
907 
908  private:
909  std::string mPackageName;
910  std::string mNameSpace;
911  std::string mName;
912  std::vector<std::string> mParameterNames;
913  InstructionSequence mInstructions;
914  };
915 
917  {
918  public:
919  SubReferenceInstruction(const std::size_t value, const std::size_t arrayIndices) : mStringID(value), mArrayIndices(arrayIndices)
920  {
921 
922  }
923 
924  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
925  {
926  StoredValueStack& stack = state->mExecutionScope.getStack();
927 
928  assert(stack.size() >= 1);
929 
930  const std::string arrayName = resolveArrayNameFromStack(stack, state, state->mInterpreter->mStringTable.getString(mStringID), mArrayIndices);
931 
932  StoredValue targetStored = stack.back();
933  stack.pop_back();
934  std::shared_ptr<ConsoleObject> referenced = targetStored.toConsoleObject(state);
935 
936  if (referenced)
937  {
938  const std::size_t stringID = state->mInterpreter->mStringTable.getOrAssign(arrayName);
939 
940  stack.push_back(StoredValue(referenced, mStringID));
941  return 1;
942  }
943 
944  stack.push_back(StoredValue(0));
945  return 1;
946  };
947 
948  virtual std::string disassemble() override
949  {
950  std::ostringstream out;
951  out << "SubReference " << mStringID << " argc=" << mArrayIndices;
952  return out.str();
953  }
954 
955  private:
956  std::size_t mStringID;
957  std::size_t mArrayIndices;
958  };
959 
965  {
966  public:
967  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
968  {
969  StoredValueStack& stack = state->mExecutionScope.getStack();
970 
971  assert(stack.size() >= 1);
972 
973  StoredValue targetStored = stack.back();
974  stack.pop_back();
975 
976  // For if we return a variable reference, we want to pass back a copy
977  StoredValueStack& returnStack = state->mExecutionScope.getReturnStack();
978  returnStack.push_back(targetStored.getReferencedValueCopy(state));
979  return 0;
980  };
981 
982  virtual std::string disassemble() override
983  {
984  std::ostringstream out;
985  out << "Return";
986  return out.str();
987  }
988  };
989 
995  {
996  public:
1001  PushLoopInstruction(const std::size_t loopSize) : mLoopSize(loopSize)
1002  {
1003 
1004  }
1005 
1006  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
1007  {
1008  const AddressType loopPosition = state->mInstructionPointer;
1009  state->mExecutionScope.pushLoop(loopPosition, mLoopSize);
1010  return 1;
1011  };
1012 
1013  virtual std::string disassemble() override
1014  {
1015  std::ostringstream out;
1016  out << "PushLoop " << mLoopSize;
1017  return out.str();
1018  }
1019 
1020  private:
1021  std::size_t mLoopSize;
1022  };
1023 
1029  {
1030  public:
1031  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
1032  {
1033  state->mExecutionScope.popLoop();
1034  return 1;
1035  };
1036 
1037  virtual std::string disassemble() override
1038  {
1039  return "PopLoop";
1040  }
1041  };
1042 
1047  {
1048  public:
1049  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
1050  {
1051  if (state->mExecutionScope.isLoopStackEmpty())
1052  {
1053  state->mInterpreter->mConfig.mPlatform->logWarning("Break outside of loop, ignoring ...");
1054  return 1;
1055  }
1056 
1057  LoopDescriptor descriptor = state->mExecutionScope.currentLoopDescriptor();
1058  // This should lead to a PopLoop instruction so we don't pop here
1059  const AddressType loopProgress = state->mInstructionPointer - descriptor.mInstructionPointer;
1060  return descriptor.mLoopSize - loopProgress;
1061  };
1062 
1063  virtual std::string disassemble() override
1064  {
1065  return "Break";
1066  }
1067  };
1068 
1074  {
1075  public:
1082  AccessArrayInstruction(const std::string& name, const std::size_t argc, bool global) : mName(name), mArgc(argc), mGlobal(global)
1083  {
1084 
1085  }
1086 
1087  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
1088  {
1089  StoredValueStack& stack = state->mExecutionScope.getStack();
1090 
1091  // When we encounter this instruction, we generate a new variable reference by appending all string representations together
1092  // This is what T2 does - it has no concept of arrays despite pretending to
1093 
1094  // FIXME: With more clever use of the ostream we might be able to make this work without the vector
1095  std::vector<std::string> variableComponents;
1096  for (unsigned int iteration = 0; iteration < mArgc; ++iteration)
1097  {
1098  variableComponents.push_back(stack.popString(state));
1099  }
1100 
1101  std::ostringstream out;
1102  out << mName;
1103  for (auto iterator = variableComponents.rbegin(); iterator != variableComponents.rend(); ++iterator)
1104  {
1105  if (iterator != variableComponents.rbegin())
1106  {
1107  out << "_";
1108  }
1109  out << *iterator;
1110  }
1111 
1112  const std::size_t stringID = state->mInterpreter->mStringTable.getOrAssign(out.str());
1113  if (mGlobal)
1114  {
1115  stack.push_back(StoredValue(stringID, StoredValueType::GlobalReference));
1116  }
1117  else
1118  {
1119  stack.push_back(StoredValue(stringID, StoredValueType::LocalReference));
1120  }
1121  return 1;
1122  };
1123 
1124  virtual std::string disassemble() override
1125  {
1126  std::ostringstream out;
1127  out << "AccessArray " << mName << " argc=" << mArgc << " global=" << mGlobal;
1128  return out.str();
1129  }
1130 
1131  private:
1132  std::string mName;
1133  std::size_t mArgc;
1134  bool mGlobal;
1135  };
1136 
1141  {
1142  public:
1148  CallBoundFunctionInstruction(const std::string& name, const std::size_t argc) : mName(name), mArgc(argc)
1149  {
1150 
1151  }
1152 
1153  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
1154  {
1155  StoredValueStack& stack = state->mExecutionScope.getStack();
1156 
1157  assert(stack.size() >= 1);
1158 
1159  StoredValue targetStored = stack.back();
1160  stack.pop_back();
1161 
1162  // Retrieve the referenced ConsoleObject
1163  std::shared_ptr<ConsoleObject> targetObject = targetStored.toConsoleObject(state);
1164  if (!targetObject)
1165  {
1166  std::ostringstream output;
1167  output << "Cannot find object '" << targetStored.toString(state) << "' to call function '" << mName << "'!";
1168  state->mInterpreter->mConfig.mPlatform->logWarning(output.str());
1169 
1170  stack.push_back(StoredValue(0));
1171  return 1;
1172  }
1173 
1174  // Walk the class hierarchy
1175  ConsoleObjectDescriptor* descriptor = sConsoleObjectDescriptors->at(targetObject->getClassName());
1176  assert(descriptor->mHierarchy.size() != 0);
1177 
1178  for (const std::string& className : descriptor->mHierarchy)
1179  {
1180  // Ask the interpreter to lookup the function
1181  std::shared_ptr<Function> calledFunction = state->mInterpreter->getFunction(className, mName);
1182  if (calledFunction)
1183  {
1184  calledFunction->execute(targetObject, state, mArgc);
1185  return 1;
1186  }
1187  }
1188 
1189  stack.push_back(StoredValue(0));
1190  return 1;
1191  };
1192 
1193  virtual std::string disassemble() override
1194  {
1195  std::ostringstream out;
1196  out << "CallBoundFunctionInstruction " << mName << " argc=" << mArgc;
1197  return out.str();
1198  }
1199 
1200  private:
1201  std::string mName;
1202  std::size_t mArgc;
1203  };
1204 
1206  {
1207  public:
1208  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
1209  {
1210  StoredValueStack& stack = state->mExecutionScope.getStack();
1211  assert(stack.size() >= 2);
1212 
1213  StoredValue objectName = stack.back();
1214  stack.pop_back();
1215  StoredValue objectTypeName = stack.back();
1216  stack.pop_back();
1217 
1218  state->mExecutionScope.pushObjectInstantiation(objectTypeName.toString(state), objectName.toString(state));
1219 
1220  return 1;
1221  };
1222 
1223  virtual std::string disassemble() override
1224  {
1225  return "PushObjectInstantiation";
1226  }
1227  };
1228 
1230  {
1231  public:
1232  PushObjectFieldInstruction(const std::size_t fieldComponentCount) : mFieldComponentCount(fieldComponentCount)
1233  {
1234 
1235  }
1236 
1237  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
1238  {
1239  StoredValueStack& stack = state->mExecutionScope.getStack();
1240 
1241  StoredValue rvalue = stack.back();
1242  stack.pop_back();
1243 
1244  // Load array components
1245  std::vector<std::string> arrayComponents;
1246  for (unsigned int iteration = 0; iteration < mFieldComponentCount; ++iteration)
1247  {
1248  arrayComponents.push_back(stack.popString(state));
1249  }
1250 
1251  // Load base name
1252  StoredValue fieldBaseName = stack.back();
1253  stack.pop_back();
1254 
1255  std::ostringstream out;
1256  out << fieldBaseName.toString(state);
1257  for (auto iterator = arrayComponents.rbegin(); iterator != arrayComponents.rend(); ++iterator)
1258  {
1259  if (iterator != arrayComponents.rbegin())
1260  {
1261  out << "_";
1262  }
1263  out << *iterator;
1264  }
1265 
1266  // Final field assignment
1267  ObjectInstantiationDescriptor& descriptor = state->mExecutionScope.currentObjectInstantiation();
1268 
1269  auto search = descriptor.mFieldAssignments.find(out.str());
1270  if (search != descriptor.mFieldAssignments.end())
1271  {
1272  search->second = rvalue;
1273  }
1274  else
1275  {
1276  descriptor.mFieldAssignments.insert(std::make_pair(out.str(), rvalue));
1277  }
1278  //descriptor.mFieldAssignments[out.str()] = rvalue;
1279 
1280  return 1;
1281  };
1282 
1283  virtual std::string disassemble() override
1284  {
1285  std::ostringstream out;
1286  out << "PushObjectField argc=" << mFieldComponentCount;
1287  return out.str();
1288  }
1289 
1290  private:
1291  std::size_t mFieldComponentCount;
1292  };
1293 
1295  {
1296  public:
1297  virtual AddressOffsetType execute(std::shared_ptr<ExecutionState> state) override
1298  {
1299  StoredValueStack& stack = state->mExecutionScope.getStack();
1300  ObjectInstantiationDescriptor descriptor = state->mExecutionScope.popObjectInstantiation();
1301 
1302  // Track parent/child relationships so we can walk the tree later
1303  if (state->mExecutionScope.isAwaitingParentInstantiation())
1304  {
1305  ObjectInstantiationDescriptor& parentDescriptor = state->mExecutionScope.currentObjectInstantiation();
1306  parentDescriptor.mChildren.push_back(descriptor);
1307  }
1308  else
1309  {
1310  // Ask the interpreter to initialize the resulting tree
1311  std::shared_ptr<ConsoleObject> result = state->mInterpreter->initializeConsoleObjectTree(descriptor);
1312 
1313  if (result)
1314  {
1315  stack.push_back(StoredValue((int)state->mInterpreter->mConsoleObjectRegistry.getConsoleObjectID(result)));
1316  }
1317  else
1318  {
1319  stack.push_back(StoredValue(-1));
1320  }
1321  }
1322 
1323 
1324  return 1;
1325  };
1326 
1327  virtual std::string disassemble() override
1328  {
1329  return "PopObjectInstantiation";
1330  }
1331  };
1332  }
1333 }
Definition: consoleobject.hpp:45
A function is callable subroutine from anywhere in the language, defined by a script....
Definition: function.hpp:40
Storage class for a sequence of instructions to be executed. Also implements the primary execution co...
Definition: instructionsequence.hpp:39
Accesses an array on a local or global variable. Technically, we just take all array indices and use ...
Definition: instructions.hpp:1074
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:1124
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:1087
AccessArrayInstruction(const std::string &name, const std::size_t argc, bool global)
Constructs a new instance of AccessArrayInstruction.
Definition: instructions.hpp:1082
Performs an addition of two values on the stack and assigns the result.
Definition: instructions.hpp:216
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:245
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:218
Adds together two values on the stack and pushes the sum.
Definition: instructions.hpp:480
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:482
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:502
Assign to lhs with whatever is on rhs.
Definition: instructions.hpp:255
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:279
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:257
Performs a bitwise AND against two values.
Definition: instructions.hpp:576
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:598
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:578
Breaks out of the current loop, ending all possible loop iterations immediately.
Definition: instructions.hpp:1047
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:1063
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:1049
Calls a function that is bound to an object identified on the stack.
Definition: instructions.hpp:1141
CallBoundFunctionInstruction(const std::string &name, const std::size_t argc)
Constructs a new instance of CallBoundFunctionInstruction.
Definition: instructions.hpp:1148
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:1153
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:1193
Calls a function registered within the current interpreter.
Definition: instructions.hpp:385
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:450
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:398
CallFunctionInstruction(const std::string &space, const std::string &name, const std::size_t argc)
Constructs a new CallFunctionInstruction instance.
Definition: instructions.hpp:393
Concatenates two values at the top of the stack and pushes back the result.
Definition: instructions.hpp:290
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:297
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:318
Performs a divide on two values at the top of the stack, pushing the result back.
Definition: instructions.hpp:643
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:645
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:666
Compares two values on the stack using an equality.
Definition: instructions.hpp:544
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:546
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:566
Registers a callable function to the registry in the current interpreter.
Definition: instructions.hpp:838
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:863
FunctionDeclarationInstruction(const std::string package, const std::string &space, const std::string &name, const std::vector< std::string > parameterNames, const InstructionSequence &instructions)
Constructs a new instance of FunctionDeclarationInstruction.
Definition: instructions.hpp:848
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:853
Base instruction class. All instructions in the interpreter should dervive from this class and implem...
Definition: instructions.hpp:39
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state)=0
Main execution method of the instruction. This serves as our switching statement that determines how ...
std::string mComment
Compiler generated comment, used for generating easier to follow disassembly.
Definition: instructions.hpp:54
virtual std::string disassemble()=0
Helper routine to produce a disassembly for this instruction.
Jumps to the specified instruction offset if a condition is false. The condition checked is the value...
Definition: instructions.hpp:777
JumpFalseInstruction(const AddressType offset)
Constructs a new instance of JumpFalseInstruction.
Definition: instructions.hpp:783
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:788
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:804
Unconditionally jumps to the specified instruction offset.
Definition: instructions.hpp:698
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:714
JumpInstruction(const AddressType offset)
Constructs a new JumpInstruction instance.
Definition: instructions.hpp:704
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:709
Jumps to the specified instruction offset if a condition is true. The condition checked is the value ...
Definition: instructions.hpp:732
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:743
JumpTrueInstruction(const AddressType offset)
Constructs a new instance of JumpTrueInstruction.
Definition: instructions.hpp:738
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:759
Compares two values on the stack using a less than relation.
Definition: instructions.hpp:512
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:514
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:534
Multiplies together two values on the stack and pushes the result back to the stack.
Definition: instructions.hpp:609
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:611
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:632
Instruction that does nothing. It usually is used to pad jumps in order to provide safe jump targets ...
Definition: instructions.hpp:821
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:823
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:828
Negate a value on the stack.
Definition: instructions.hpp:333
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:349
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:335
Invert the truthfulness of a value on the stack.
Definition: instructions.hpp:359
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:361
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:375
Pops a value from the stack, discarding it.
Definition: instructions.hpp:676
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:678
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:688
Used to keep track of loops in the virtual instructions. This instruction marks the end of a loop con...
Definition: instructions.hpp:1029
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:1031
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:1037
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:1327
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:1297
Push float instruction. This will push a floating point value to the system stack for later use in ex...
Definition: instructions.hpp:62
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:76
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:69
Push a reference to a named global variable. The parameter provided here should be excluding the '$' ...
Definition: instructions.hpp:186
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:193
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:200
Push integer instruction. This will push an integer value to the system stack for later use in execut...
Definition: instructions.hpp:93
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:100
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:107
Push a reference to a named local variable. The parameter provided here should be excluding the '' pr...
Definition: instructions.hpp:155
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:169
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:162
Used to keep track of loops in the virtual instructions. This instruction marks the start of a loop c...
Definition: instructions.hpp:995
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:1006
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:1013
PushLoopInstruction(const std::size_t loopSize)
Constructs a new instance of PushLoopInstruction.
Definition: instructions.hpp:1001
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:1237
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:1283
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:1208
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:1223
Push string instruction. This will push a string value to the system stack for later use in execution...
Definition: instructions.hpp:124
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:138
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:131
Ends execution in the current function immediately. It will take one value from the top of the stack ...
Definition: instructions.hpp:965
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:982
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:967
virtual AddressOffsetType execute(std::shared_ptr< ExecutionState > state) override
Main execution method of the instruction. This serves as our switching statement that determines how ...
Definition: instructions.hpp:924
virtual std::string disassemble() override
Helper routine to produce a disassembly for this instruction.
Definition: instructions.hpp:948
Storage class used to keep variable values in-memory of arbitrary data types. This is the base class ...
Definition: storedvaluestack.hpp:32
Storage class used to keep variable values in-memory of arbitrary data types. The data types supporte...
Definition: storedvalue.hpp:80
float toFloat(std::shared_ptr< ExecutionState > state)
Converts the value in question to a native floating point type.
bool setValue(StoredValue newValue, std::shared_ptr< ExecutionState > state)
Sets the value of this object. Only has an effect if this object is a reference to a local or global ...
std::string toString(std::shared_ptr< ExecutionState > state)
Converts the value in question to a native sting type.
Definition: ast.hpp:28
long long int AddressType
Typedef for the signed integer type to be used when calculating addresses.
Definition: instructionsequence.hpp:28
Definition: executionscope.hpp:34
Struct describing a tree of console object initializations.
Definition: executionscope.hpp:48
std::vector< ObjectInstantiationDescriptor > mChildren
All children of this object. These will not be initialized until the parent is initialized.
Definition: executionscope.hpp:66
std::map< std::string, StoredValue > mFieldAssignments
All resolved field names mapped to the values to set.
Definition: executionscope.hpp:69