MinitScript  0.9.31 PRE-BETA
MinitScript.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <algorithm>
4 #include <array>
5 #include <memory>
6 #include <span>
7 #include <stack>
8 #include <string>
9 #include <string_view>
10 #include <unordered_map>
11 #include <unordered_set>
12 #include <utility>
13 #include <vector>
14 
28 
29 using std::array;
30 using std::exchange;
31 using std::find;
32 using std::make_unique;
33 using std::move;
34 using std::pair;
35 using std::remove;
36 using std::sort;
37 using std::span;
38 using std::stack;
39 using std::string;
40 using std::string_view;
41 using std::to_string;
42 using std::unique_ptr;
43 using std::unordered_map;
44 using std::unordered_set;
45 using std::vector;
46 
58 
59 #define MINITSCRIPT_METHODUSAGE_COMPLAIN(methodName) { minitScript->complain(methodName, subStatement); minitScript->startErrorScript(); }
60 #define MINITSCRIPT_METHODUSAGE_COMPLAINM(methodName, message) { minitScript->complain(methodName, subStatement, message); minitScript->startErrorScript(); }
61 #define MINITSCRIPT_METHODUSAGE_COMPLAINO(methodName, operatorString) { minitScript->complainOperator(methodName, operatorString, subStatement); minitScript->startErrorScript(); }
62 #define MINITSCRIPT_METHODUSAGE_COMPLAINOM(methodName, operatorString, message) { minitScript->complainOperator(methodName, operatorString, subStatement, message); minitScript->startErrorScript(); }
63 
64 /**
65  * MinitScript
66  * @author Andreas Drewke
67  */
69  friend class ApplicationMethods;
70  friend class BaseMethods;
71  friend class JSONMethods;
72  friend class MathMethods;
73  friend class ScriptMethods;
74  friend class Transpiler;
75 
76 public:
77  enum Operator {
78  // see: https://en.cppreference.com/w/cpp/language/operator_precedence
80  // priority 2
83  // priority 3
88  // priority 5
92  // priority 6
95  // priority 9
100  // priority 10
103  // priority 11
105  // priority 12
107  // priority 12
109  // priority 14
111  // priority 15
113  // priority 16
115  //
117  };
118 
124  };
125 
126  /**
127  * Statement
128  */
129  struct Statement {
130  /**
131  * Constructor
132  * @param line line
133  * @param statementIdx statement index
134  * @param statement statement
135  * @param executableStatement executable statement
136  * @param gotoStatementIdx goto statement index
137  */
138  inline Statement(
139  int line,
140  int statementIdx,
141  const string& statement,
142  const string& executableStatement,
143  int gotoStatementIdx
144  ):
145  line(line),
150  {}
151  //
152  int line;
154  string statement;
157  };
158 
159  /**
160  * Sub statement
161  */
162  struct SubStatement {
163  /**
164  * Sub statement
165  */
167  statement(nullptr),
168  subLineIdx(-1)
169  {}
170  /**
171  * Sub statement
172  * @param statement statement
173  * @param subLineIdx sub line index
174  */
178  {}
179  //
182  };
183 
185  // primitives
190  // special
194  // pseudo
197  // classes
201  TYPE_MAP = 12,
202  TYPE_SET = 13,
206  };
207 
208  //
209  class SyntaxTreeNode;
210  class Variable;
211 
212  /**
213  * Data type
214  */
215  class DataType {
216  friend class MinitScript;
217  friend class MathMethods;
218 
219  protected:
220  /**
221  * Script context
222  */
224  friend class MinitScript;
225  public:
226  /**
227  * Constructor
228  */
229  inline ScriptContext() {}
230 
231  /**
232  * Destructor
233  */
234  virtual ~ScriptContext() {}
235 
236  /**
237  * Set MinitScript instance
238  * @param minitScript MinitScript instance
239  */
241  this->minitScript = minitScript;
242  }
243 
244  /**
245  * Set garbage collection type index
246  * @param index garbage collection type index
247  */
248  inline void setIndex(int index) {
249  this->index = index;
250  }
251 
252  /**
253  * Set requires garbage collection
254  */
257  }
258 
259  /**
260  * Unset requires garbage collection
261  */
264  }
265 
266  private:
267  int index { -1 };
268  MinitScript* minitScript { nullptr };
269  };
270 
271  //
272  bool mathDataType { false };
274  //
276 
277  /**
278  * Set type
279  * @param type type
280  */
282  this->type = type;
283  }
284 
285  /**
286  * @return is math data type
287  */
288  inline bool isMathDataType() {
289  return mathDataType;
290  }
291 
292  /**
293  * @return is requiring garbage collection
294  */
297  }
298 
299  /**
300  * Register constants
301  * @param minitScript MinitScript instance
302  */
303  virtual void registerConstants(MinitScript* minitScript) const = 0;
304 
305  /**
306  * Register methods
307  * @param minitScript MinitScript instance
308  */
309  virtual void registerMethods(MinitScript* minitScript) const = 0;
310 
311  /**
312  * Unset variable value
313  * @param variable variable
314  */
315  virtual void unsetVariableValue(Variable& variable) const = 0;
316 
317  /**
318  * Set variable value
319  * @param variable variable
320  */
321  virtual void setVariableValue(Variable& variable) const = 0;
322 
323  /**
324  * Set variable value
325  * @param variable variable
326  * @param value value
327  */
328  virtual void setVariableValue(Variable& variable, const void* value) const = 0;
329 
330  /**
331  * Copy variable
332  * @param to to
333  * @param from from
334  */
335  virtual void copyVariable(Variable& to, const Variable& from) const = 0;
336 
337  /**
338  * Multiply
339  * @param minitScript MinitScript instance
340  * @param arguments argument values
341  * @param returnValue return value
342  * @param subStatement sub statement
343  * @return mul was executed
344  */
345  virtual bool mul(MinitScript* minitScript, const span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) const = 0;
346 
347  /**
348  * Division
349  * @param minitScript MinitScript instance
350  * @param arguments argument values
351  * @param returnValue return value
352  * @param subStatement sub statement
353  * @return div was executed
354  */
355  virtual bool div(MinitScript* minitScript, const span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) const = 0;
356 
357  /**
358  * Addition
359  * @param minitScript MinitScript instance
360  * @param arguments argument values
361  * @param returnValue return value
362  * @param subStatement sub statement
363  * @return add was executed
364  */
365  virtual bool add(MinitScript* minitScript, const span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) const = 0;
366 
367  /**
368  * Subtraction
369  * @param minitScript MinitScript instance
370  * @param arguments argument values
371  * @param returnValue return value
372  * @param subStatement sub statement
373  * @return sub was executed
374  */
375  virtual bool sub(MinitScript* minitScript, const span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) const = 0;
376 
377  /**
378  * Create script context
379  * @return script context
380  */
381  virtual ScriptContext* createScriptContext() const = 0;
382 
383  /**
384  * Delete script context
385  * @param context script context
386  */
387  virtual void deleteScriptContext(ScriptContext* context) const = 0;
388 
389  /**
390  * Issue garbage collection
391  * @param context script context
392  */
393  virtual void garbageCollection(ScriptContext* context) const = 0;
394 
395  public:
396  // forbid class copy
398 
399  /**
400  * Data type
401  * @param mathDataType is math data type and provides math methods
402  * @param requiresGarbageCollection requires garbage collection
403  */
405  //
406  }
407 
408  virtual ~DataType() {
409  //
410  }
411 
412  /**
413  * @return type
414  */
416  return type;
417  }
418 
419  /**
420  * @return type as string
421  */
422  virtual const string& getTypeAsString() const = 0;
423 
424  /**
425  * Returns value as string
426  * @param variable variable
427  * @return value as string
428  */
429  virtual const string getValueAsString(const Variable& variable) const = 0;
430 
431  };
432 
433  /**
434  * Variable
435  */
436  class Variable {
437  friend class MinitScript;
438  friend class BaseMethods;
439 
440  private:
441  /**
442  * Variable initializer
443  */
444  class Initializer {
445  public:
446  /**
447  * Constructor
448  */
449  inline Initializer():
450  statement(
454  string(),
455  string(),
457  )
458  ),
459  syntaxTree(new SyntaxTreeNode()) {
460  //
461  }
462 
463  /**
464  * Constructor
465  * @param initializerString initializer string
466  * @param statement statement
467  * @param syntaxTree syntax tree
468  */
470 
471  /**
472  * Destructor
473  */
474  inline ~Initializer() { delete syntaxTree; }
475 
476  /**
477  * Copy from initializer
478  * @param initializer initializer
479  */
480  inline void copy(Initializer* initializer) {
481  this->initializerString = initializer->initializerString;
482  this->statement = initializer->statement;
483  if (syntaxTree != nullptr && initializer->syntaxTree != nullptr) {
484  *syntaxTree = *initializer->syntaxTree;
485  }
486  }
487 
488  /**
489  * @return initializer string
490  */
491  inline const string& getInitializerString() const {
492  return initializerString;
493  }
494 
495  /**
496  * @return statement
497  */
498  inline const Statement& getStatement() const {
499  return statement;
500  }
501 
502  /**
503  * @return syntax tree node
504  */
505  inline const SyntaxTreeNode* getSyntaxTree() const {
506  return syntaxTree;
507  }
508 
509  private:
513  };
514 
515  //
516  static constexpr uint32_t TYPE_BITS_VALUE { 268435455 }; // 2 ^ 28 - 1
517  static constexpr uint32_t CONSTANT_BIT_VALUE { 268435456 }; // 2 ^ 28
518  static constexpr uint32_t REFERENCE_BIT_VALUE { 536870912 }; // 2 ^ 29
519  static constexpr uint32_t PRIVATE_BIT_VALUE { 1073741824 }; // 2 ^ 30
520  static constexpr uint32_t PRIVATESCOPE_BIT_VALUE { 2147483648 }; // 2 ^ 31
521 
522  //
526  };
527 
528  /**
529  * String value
530  */
531  class StringValue {
532  friend class Variable;
533  public:
534  /**
535  * Constructor
536  */
537  inline StringValue(): cache(_UTF8CharacterIterator::UTF8PositionCache()) {}
538 
539  /**
540  * Constructor
541  * @param value value
542  */
543  inline StringValue(const string& value): value(value) {}
544 
545  /**
546  * @return value
547  */
548  inline const string& getValue() const {
549  return value;
550  }
551 
552  /**
553  * Set value
554  * @param value value
555  */
556  inline void setValue(const string& value) {
557  this->value = value;
558  cache.removeCache();
559  }
560 
561  /**
562  * @return const cache
563  */
565  return cache;
566  }
567 
568  /**
569  * @return cache
570  */
572  return cache;
573  }
574 
575  /**
576  * Set cache
577  * @param cache cache
578  */
580  this->cache = cache;
581  }
582 
583  private:
584  string value;
586  };
587 
588  /**
589  * Function value
590  */
591  struct FunctionValue {
592  string name;
594  };
595 
596  /**
597  * ByteArray value
598  */
599  struct ByteArrayValue {
600  int64_t readPtr { 0ll };
601  int64_t writePtr { 0ll };
602  vector<uint8_t> value;
603  };
604 
605  // 24 bytes
606  uint32_t typeBits { TYPE_NULL }; // 4 bytes
607  int32_t referenceCounter { 1 }; // 4 bytes
608  uint64_t valuePtr { 0LL }; // 8 bytes
610 
611  /**
612  * Set constant
613  */
614  inline void setConstant() {
616  }
617 
618  /**
619  * Unset constant
620  */
621  inline void unsetConstant() {
623  }
624 
625  /**
626  * @return unset reference
627  */
628  inline void unsetReference() {
631  }
632 
633  /**
634  * Set private
635  */
636  inline void setPrivate() {
638  }
639 
640  /**
641  * Set private scope
642  */
643  inline void setPrivateScope() {
645  }
646 
647  /**
648  * Unset private scope
649  */
650  inline void unsetPrivateScope() {
652  }
653 
654  /**
655  * Acquire reference
656  */
657  inline void acquireReference() {
659  }
660 
661  /**
662  * Release reference
663  */
664  inline void releaseReference() {
665  if (--referenceCounter == 0) {
666  if (isReference() == true) {
668  unsetReference();
669  }
671  delete this;
672  }
673  }
674 
675  /**
676  * Return initializer
677  * @return initializer
678  */
681  }
682 
683  /**
684  * Return const value pointer
685  * @return value ptr
686  */
687  inline const uint64_t& getValuePtrReference() const {
689  }
690 
691  /**
692  * Return value pointer
693  * @return value ptr
694  */
695  inline uint64_t& getValuePtrReference() {
697  }
698 
699  /**
700  * @return boolean value reference
701  */
702  inline bool& getBooleanValueReference() {
703  return *(bool*)(&getValuePtrReference());
704  }
705 
706  /**
707  * @return const boolean value reference
708  */
709  inline const bool& getBooleanValueReference() const {
710  return *(bool*)(&getValuePtrReference());
711  }
712 
713  /**
714  * @return integer value reference
715  */
716  inline int64_t& getIntegerValueReference() {
717  return *(int64_t*)(&getValuePtrReference());
718  }
719 
720  /**
721  * @return const integer value reference
722  */
723  inline const int64_t& getIntegerValueReference() const {
724  return *(int64_t*)(&getValuePtrReference());
725  }
726 
727  /**
728  * @return float value reference
729  */
730  inline float& getFloatValueReference() {
731  return *(float*)(&getValuePtrReference());
732  }
733 
734  /**
735  * @return const float value reference
736  */
737  inline const float& getFloatValueReference() const {
738  return *(float*)(&getValuePtrReference());
739  }
740 
741  /**
742  * @return function value reference
743  */
745  return *static_cast<FunctionValue*>((void*)getValuePtrReference());
746  }
747 
748  /**
749  * @return const function value reference
750  */
751  inline const FunctionValue& getFunctionValueReference() const {
752  return *static_cast<FunctionValue*>((void*)getValuePtrReference());
753  }
754 
755  /**
756  * @return string value reference
757  */
759  return *static_cast<StringValue*>((void*)getValuePtrReference());
760  }
761 
762  /**
763  * @return const string value reference
764  */
765  inline const StringValue& getStringValueReference() const {
766  return *static_cast<StringValue*>((void*)getValuePtrReference());
767  }
768 
769  /**
770  * @return byte array value reference
771  */
773  return *static_cast<ByteArrayValue*>((void*)getValuePtrReference());
774  }
775 
776  /**
777  * @return const byte array value reference
778  */
780  return *static_cast<ByteArrayValue*>((void*)getValuePtrReference());
781  }
782 
783  /**
784  * @return array value reference
785  */
786  inline vector<Variable*>& getArrayValueReference() {
787  return *static_cast<vector<Variable*>*>((void*)getValuePtrReference());
788  }
789 
790  /**
791  * @return const array value reference
792  */
793  inline const vector<Variable*>& getArrayValueReference() const {
794  return *static_cast<vector<Variable*>*>((void*)getValuePtrReference());
795  }
796 
797  /**
798  * @return map value reference
799  */
800  inline unordered_map<string, Variable*>& getMapValueReference() {
801  return *static_cast<unordered_map<string, Variable*>*>((void*)getValuePtrReference());
802  }
803 
804  /**
805  * @return const map value reference
806  */
807  inline const unordered_map<string, Variable*>& getMapValueReference() const {
808  return *static_cast<unordered_map<string, Variable*>*>((void*)getValuePtrReference());
809  }
810 
811  /**
812  * @return set value reference
813  */
814  inline unordered_set<string>& getSetValueReference() {
815  return *static_cast<unordered_set<string>*>((void*)getValuePtrReference());
816  }
817 
818  /**
819  * @return const set value reference
820  */
821  inline const unordered_set<string>& getSetValueReference() const {
822  return *static_cast<unordered_set<string>*>((void*)getValuePtrReference());
823  }
824 
825  public:
826  // class names
841 
842  /**
843  * @return is constant
844  */
845  inline bool isConstant() const {
846  return
849  }
850 
851  /**
852  * @return is reference
853  */
854  inline bool isReference() const {
856  }
857 
858  /**
859  * @return is private
860  */
861  inline bool isPrivate() const {
862  return
865  }
866 
867  /**
868  * @return is private scope
869  */
870  inline bool isPrivateScope() const {
871  return
874  }
875 
876  /**
877  * Unset variable
878  */
879  inline void unset() {
880  if (isReference() == true) {
882  unsetReference();
883  }
885  }
886 
887  /**
888  * Set reference
889  * @param variable variable
890  */
891  inline void setReference(const Variable* variable) {
892  unset();
894  if (variable->isReference() == true) {
897  } else {
900  }
901  // we need to copy those properties
902  // as we can tag a reference variable instance (which points to the original)
903  // as private, private scope and constant itself too
904  // no matter which properties the original variable has
905  if (variable->isConstant() == true) setConstant();
906  if (variable->isPrivate() == true) setPrivate();
907  if (variable->isPrivateScope() == true) setPrivateScope();
908  }
909 
910  /**
911  * Create variable optimized for method argument usage
912  * @param variable variable
913  * @returns reference/non reference variable based on data type
914  */
915  inline static Variable createMethodArgumentVariable(const Variable* variable) {
916  auto createReference = false;
917  switch(variable->getType()) {
918  case(TYPE_FUNCTION_CALL):
921  case(TYPE_STRING):
922  case(TYPE_BYTEARRAY):
923  case(TYPE_ARRAY):
924  case(TYPE_MAP):
925  case(TYPE_SET):
926  createReference = true;
927  break;
928  default:
929  createReference = variable->getType() >= TYPE_PSEUDO_DATATYPES;
930  break;
931  }
932  //
933  return createReference == true?createReferenceVariable(variable):createNonReferenceVariable(variable);
934  }
935 
936  /**
937  * Create non const/reference variable
938  * @param variable variable
939  * @return non const/reference variable
940  */
941  inline static Variable createNonConstVariable(const Variable* variable) {
942  auto nonConstVariable = createNonReferenceVariable(variable);
943  MinitScript::unsetConstant(nonConstVariable);
944  return nonConstVariable;
945  }
946 
947  /**
948  * Create reference variable
949  * @param variable variable
950  * @returns reference variable
951  */
952  inline static Variable createReferenceVariable(const Variable* variable) {
953  Variable referenceVariable;
954  referenceVariable.setReference((Variable*)variable);
955  return referenceVariable;
956  }
957 
958  /**
959  * Create reference variable pointer
960  * @param variable variable
961  * @returns reference variable
962  */
963  inline static Variable* createReferenceVariablePointer(const Variable* variable) {
964  auto referenceVariable = new Variable();
965  referenceVariable->setReference((Variable*)variable);
966  return referenceVariable;
967  }
968 
969  /**
970  * Create none reference variable
971  * @param variable variable
972  * @returns reference variable
973  */
974  inline static Variable createNonReferenceVariable(const Variable* variable) {
975  Variable nonReferenceVariable;
976  //
977  copyVariable(nonReferenceVariable, *variable, true);
978  //
979  return nonReferenceVariable;
980  }
981 
982  /**
983  * Create none reference variable pointer
984  * @param variable variable
985  * @returns reference variable
986  */
987  inline static Variable* createNonReferenceVariablePointer(const Variable* variable) {
988  auto nonReferenceVariable = new Variable();
989  //
990  copyVariable(*nonReferenceVariable, *variable, true);
991  //
992  return nonReferenceVariable;
993  }
994 
995  /**
996  * Copy variable
997  * @param from from
998  * @param to to
999  * @param properties copy also properties
1000  */
1001  inline static void copyVariable(Variable& to, const Variable& from, bool properties) {
1002  // initial setup
1003  to.setType(from.getType());
1004  // do the copy
1005  switch(from.getType()) {
1006  case TYPE_NULL:
1007  // no op
1008  break;
1009  case TYPE_BOOLEAN:
1011  break;
1012  case TYPE_INTEGER:
1014  break;
1015  case TYPE_FLOAT:
1016  to.setValue(from.getFloatValueReference());
1017  break;
1018  case TYPE_FUNCTION_CALL:
1021  // copy initializer if we have any
1022  to.getInitializer()->copy(from.getInitializer());
1023  //
1024  break;
1026  {
1027  const auto& functionValue = from.getFunctionValueReference();
1028  to.setFunctionAssignment(functionValue.name, functionValue.scriptIdx);
1029  break;
1030  }
1032  {
1033  const auto& functionValue = from.getFunctionValueReference();
1034  to.setStackletAssignment(functionValue.name, functionValue.scriptIdx);
1035  break;
1036  }
1037  case TYPE_PSEUDO_NUMBER: break;
1038  case TYPE_PSEUDO_MIXED: break;
1039  case TYPE_STRING:
1040  {
1041  const auto& stringValue = from.getStringValueReference();
1042  to.getStringValueReference().setValue(stringValue.getValue());
1043  to.getStringValueReference().setCache(stringValue.getCache());
1044  break;
1045  }
1046  case TYPE_BYTEARRAY:
1048  break;
1049  case TYPE_ARRAY:
1050  to.setValue(from.getArrayValueReference());
1051  // copy initializer if we have any
1052  to.getInitializer()->copy(from.getInitializer());
1053  //
1054  break;
1055  case TYPE_MAP:
1056  to.setValue(from.getMapValueReference());
1057  // copy initializer if we have any
1058  to.getInitializer()->copy(from.getInitializer());
1059  //
1060  break;
1061  case TYPE_SET:
1062  to.setValue(from.getSetValueReference());
1063  // copy initializer if we have any
1064  to.getInitializer()->copy(from.getInitializer());
1065  //
1066  break;
1067  default:
1068  // custom data type
1069  auto dataTypeIdx = static_cast<int>(from.getType()) - TYPE_PSEUDO_DATATYPES;
1070  if (dataTypeIdx < 0 || dataTypeIdx >= MinitScript::dataTypes.size()) {
1071  _Console::printLine("ScriptVariable::copyScriptVariable(): unknown data type with id " + to_string(dataTypeIdx));
1072  return;
1073  }
1074  MinitScript::dataTypes[dataTypeIdx]->copyVariable(to, from);
1075  }
1076  //
1077  if (properties == true) {
1078  if (from.isConstant() == true) to.setConstant();
1079  if (from.isPrivate() == true) to.setPrivate();
1080  if (from.isPrivateScope() == true) to.setPrivateScope();
1081  }
1082  }
1083 
1084  /**
1085  * Swap variables
1086  * @param a a
1087  * @param b b
1088  */
1089  inline static void swap(Variable& a, Variable& b) {
1090  auto& _a = a.isReference() == true?*a.initializerReferenceUnion.reference:a;
1091  auto& _b = b.isReference() == true?*b.initializerReferenceUnion.reference:b;
1092  std::swap(_a.typeBits, _b.typeBits);
1093  std::swap(_a.valuePtr, _b.valuePtr);
1094  std::swap(_a.initializerReferenceUnion, _b.initializerReferenceUnion);
1095  std::swap(_a.referenceCounter, _b.referenceCounter);
1096  }
1097 
1098  /**
1099  * Copy constructor
1100  * @param variable variable to copy
1101  */
1102  inline Variable(const Variable& variable) {
1103  if (variable.isReference() == true) {
1104  setReference(&variable);
1105  } else {
1106  copyVariable(*this, variable, true);
1107  }
1108  }
1109 
1110  /**
1111  * Move constructor
1112  * @param variable variable to move from
1113  */
1114  inline Variable(Variable&& variable):
1115  typeBits(exchange(variable.typeBits, static_cast<int>(MinitScript::TYPE_NULL))),
1116  valuePtr(exchange(variable.valuePtr, 0ll)),
1117  referenceCounter(exchange(variable.referenceCounter, 1)) {
1118  // TODO: improve me
1119  initializerReferenceUnion.initializer = variable.initializerReferenceUnion.initializer;
1120  variable.initializerReferenceUnion.initializer = nullptr;
1121  }
1122 
1123  /**
1124  * Assignment operator
1125  * @param variable variable to copy
1126  * @return this variable
1127  */
1128  inline Variable& operator=(const Variable& variable) {
1129  // set up new variable
1130  unset();
1131  //
1132  if (variable.isReference() == true) {
1133  setReference(&variable);
1134  } else {
1135  copyVariable(*this, variable, true);
1136  }
1137  //
1138  return *this;
1139  }
1140 
1141  /**
1142  * Move operator
1143  * @param variable variable to move from
1144  * @return this variable
1145  */
1146  inline Variable& operator=(Variable&& variable) {
1147  std::swap(typeBits, variable.typeBits);
1148  std::swap(valuePtr, variable.valuePtr);
1149  std::swap(initializerReferenceUnion, variable.initializerReferenceUnion);
1150  std::swap(referenceCounter, variable.referenceCounter);
1151  //
1152  return *this;
1153  }
1154 
1155  /**
1156  * Constructor
1157  */
1158  inline Variable() {
1159  }
1160 
1161  /**
1162  * Destructor
1163  */
1164  inline ~Variable() {
1165  if (isReference() == true) {
1167  unsetReference();
1168  }
1169  setType(TYPE_NULL);
1170  }
1171 
1172  /**
1173  * Constructor
1174  * @param value value
1175  */
1176  inline Variable(bool value) {
1177  setValue(value);
1178  }
1179 
1180  /**
1181  * Constructor
1182  * @param value value
1183  */
1184  inline Variable(int64_t value) {
1185  setValue(value);
1186  }
1187 
1188  /**
1189  * Constructor
1190  * @param value value
1191  */
1192  inline Variable(float value) {
1193  setValue(value);
1194  }
1195 
1196  /**
1197  * Constructor
1198  * @param type type
1199  * @param value value
1200  * @param scriptIdx script index
1201  */
1202  inline Variable(VariableType type, const string& value, int scriptIdx = SCRIPTIDX_NONE) {
1203  switch (type) {
1205  setFunctionAssignment(value, scriptIdx);
1206  break;
1208  setStackletAssignment(value, scriptIdx);
1209  break;
1211  setValue(value);
1212  break;
1213  default:
1214  _Console::printLine("Variable::Variable(VariableType, const string&): invalid type: " + getTypeAsString(type));
1215  }
1216  }
1217 
1218  /**
1219  * Constructor
1220  * @param value value
1221  */
1222  inline Variable(const string& value) {
1223  setValue(value);
1224  }
1225 
1226  /**
1227  * Constructor
1228  * @param value value
1229  */
1230  inline Variable(const vector<Variable*>& value) {
1231  setValue(value);
1232  }
1233 
1234  /**
1235  * Constructor
1236  * @param value value
1237  */
1238  inline Variable(const unordered_map<string, Variable*>& value) {
1239  setValue(value);
1240  }
1241 
1242  /**
1243  * @return type
1244  */
1245  inline VariableType getType() const {
1247  }
1248 
1249  /**
1250  * Set type
1251  * @param newType new type
1252  */
1253  inline void setType(VariableType newType) {
1254  if (getType() == newType) return;
1255  switch(getType()) {
1256  case TYPE_NULL:
1257  break;
1258  case TYPE_BOOLEAN:
1259  break;
1260  case TYPE_INTEGER:
1261  break;
1262  case TYPE_FLOAT:
1263  break;
1264  case TYPE_FUNCTION_CALL:
1265  delete static_cast<StringValue*>((void*)getValuePtrReference());
1266  delete getInitializerReference();
1267  getInitializerReference() = nullptr;
1268  break;
1269  case TYPE_PSEUDO_NUMBER: break;
1270  case TYPE_PSEUDO_MIXED: break;
1271  case TYPE_STRING:
1272  delete static_cast<StringValue*>((void*)getValuePtrReference());
1273  break;
1276  delete static_cast<FunctionValue*>((void*)getValuePtrReference());
1277  break;
1278  case TYPE_BYTEARRAY:
1279  delete static_cast<ByteArrayValue*>((void*)getValuePtrReference());
1280  break;
1281  case TYPE_ARRAY:
1282  for (auto arrayValue: getArrayValueReference()) arrayValue->releaseReference();
1283  delete static_cast<vector<Variable*>*>((void*)getValuePtrReference());
1284  delete getInitializerReference();
1285  getInitializerReference() = nullptr;
1286  break;
1287  case TYPE_MAP:
1288  for (const auto& [mapEntryName, mapEntryValue]: getMapValueReference()) mapEntryValue->releaseReference();
1289  delete static_cast<unordered_map<string, Variable*>*>((void*)getValuePtrReference());
1290  delete getInitializerReference();
1291  getInitializerReference() = nullptr;
1292  break;
1293  case TYPE_SET:
1294  delete static_cast<unordered_set<string>*>((void*)getValuePtrReference());
1295  delete getInitializerReference();
1296  getInitializerReference() = nullptr;
1297  break;
1298  default:
1299  // custom data type
1300  auto dataTypeIdx = static_cast<int>(this->getType()) - TYPE_PSEUDO_DATATYPES;
1301  if (dataTypeIdx < 0 || dataTypeIdx >= MinitScript::dataTypes.size()) {
1302  _Console::printLine("ScriptVariable::setType(): unknown data type with id " + to_string(dataTypeIdx));
1303  return;
1304  }
1305  MinitScript::dataTypes[dataTypeIdx]->unsetVariableValue(*this);
1306 
1307  }
1308  this->getValuePtrReference() = 0LL;
1309  //
1310  if (isReference() == true) {
1312  static_cast<uint32_t>(newType) |
1316  } else {
1317  typeBits =
1318  static_cast<uint32_t>(newType) |
1322  }
1323  //
1324  switch(getType()) {
1325  case TYPE_NULL:
1326  break;
1327  case TYPE_BOOLEAN:
1328  break;
1329  case TYPE_INTEGER:
1330  break;
1331  case TYPE_FLOAT:
1332  break;
1333  case TYPE_PSEUDO_NUMBER: break;
1334  case TYPE_PSEUDO_MIXED: break;
1337  getValuePtrReference() = (uint64_t)(new FunctionValue());
1338  break;
1339  case TYPE_STRING:
1340  getValuePtrReference() = (uint64_t)(new StringValue());
1341  break;
1342  case TYPE_BYTEARRAY:
1343  getValuePtrReference() = (uint64_t)(new ByteArrayValue());
1344  break;
1345  case TYPE_ARRAY:
1346  getValuePtrReference() = (uint64_t)(new vector<Variable*>());
1348  break;
1349  case TYPE_MAP:
1350  getValuePtrReference() = (uint64_t)(new unordered_map<string, Variable*>());
1352  break;
1353  case TYPE_SET:
1354  getValuePtrReference() = (uint64_t)(new unordered_set<string>());
1356  break;
1357  case TYPE_FUNCTION_CALL:
1358  getValuePtrReference() = (uint64_t)(new StringValue());
1360  break;
1361  default:
1362  // custom data type
1363  auto dataTypeIdx = static_cast<int>(this->getType()) - TYPE_PSEUDO_DATATYPES;
1364  if (dataTypeIdx < 0 || dataTypeIdx >= MinitScript::dataTypes.size()) {
1365  _Console::printLine("ScriptVariable::setType(): unknown data type with id " + to_string(dataTypeIdx));
1366  return;
1367  }
1368  MinitScript::dataTypes[dataTypeIdx]->setVariableValue(*this);
1369  }
1370  }
1371 
1372  /**
1373  * Return initializer
1374  * @return initializer
1375  */
1376  inline Initializer* getInitializer() const {
1378  }
1379 
1380  /**
1381  * @return value pointer
1382  */
1383  inline void* getValuePtr() const {
1385  }
1386 
1387  /**
1388  * Set value pointer
1389  * @param valuePtr value pointer
1390  */
1391  inline void setValuePtr(void* valuePtr) {
1392  if (isReference() == true) {
1394  } else {
1395  this->valuePtr = (uint64_t)valuePtr;
1396  }
1397  }
1398 
1399  /**
1400  * Get boolean value from given variable
1401  * @param value value
1402  * @param optional optionalfalse
1403  * @return success
1404  */
1405  inline bool getBooleanValue(bool& value, bool optional = false) const {
1406  switch(getType()) {
1407  case TYPE_BOOLEAN:
1408  value = getBooleanValueReference();
1409  return true;
1410  break;
1411  case TYPE_INTEGER:
1412  value = getIntegerValueReference() != 0;
1413  return true;
1414  case TYPE_FLOAT:
1415  value = getFloatValueReference() != 0.0f;
1416  return true;
1417  case TYPE_STRING:
1418  {
1419  auto lowerCaseString = _StringTools::toLowerCase(getStringValueReference().getValue());
1420  if (lowerCaseString != "false" && lowerCaseString != "true" && lowerCaseString != "1" && lowerCaseString != "0") return optional;
1421  value = lowerCaseString == "true" || lowerCaseString == "1";
1422  return true;
1423  }
1424  default:
1425  return optional;
1426  }
1427  return false;
1428  }
1429 
1430  /**
1431  * Get integer value from given variable
1432  * @param value value
1433  * @param optional optional
1434  * @return success
1435  */
1436  inline bool getIntegerValue(int64_t& value, bool optional = false) const {
1437  switch(getType()) {
1438  case TYPE_BOOLEAN:
1439  value = getBooleanValueReference() == true?1:0;
1440  return true;
1441  break;
1442  case TYPE_INTEGER:
1443  value = getIntegerValueReference();
1444  return true;
1445  case TYPE_FLOAT:
1446  value = getFloatValueReference();
1447  return true;
1448  case TYPE_STRING:
1449  {
1450  const auto& stringValue = getStringValueReference().getValue();
1451  if (_Integer::is(stringValue) == true) {
1452  value = _Integer::parse(stringValue);
1453  return true;
1454  } else
1455  if (_Float::is(stringValue) == true) {
1456  value = static_cast<int64_t>(_Float::parse(stringValue));
1457  return true;
1458  } else {
1459  return optional;
1460  }
1461  }
1462  default:
1463  return optional;
1464  }
1465  return false;
1466  }
1467 
1468  /**
1469  * Get float value from given variable
1470  * @param value value
1471  * @param optional optional
1472  * @return success
1473  */
1474  inline bool getFloatValue(float& value, bool optional = false) const {
1475  switch(getType()) {
1476  case TYPE_BOOLEAN:
1477  value = getBooleanValueReference() == true?1.0f:0.0f;
1478  return true;
1479  break;
1480  case TYPE_INTEGER:
1481  value = getIntegerValueReference();
1482  return true;
1483  case TYPE_FLOAT:
1484  value = getFloatValueReference();
1485  return true;
1486  case TYPE_STRING:
1487  {
1488  const auto& stringValue = getStringValueReference().getValue();
1489  if (_Float::is(stringValue) == false) return optional;
1490  value = _Float::parse(stringValue);
1491  }
1492  return true;
1493  default:
1494  return optional;
1495  }
1496  return false;
1497  }
1498 
1499  /**
1500  * Get function values from given variable
1501  * @param function function
1502  * @param scriptIdx script index
1503  * @param optional optional
1504  * @return success
1505  */
1506  inline bool getFunctionValue(string& function, int& scriptIdx, bool optional = false) const {
1507  switch(getType()) {
1509  {
1510  const auto& functionValue = getFunctionValueReference();
1511  function = functionValue.name;
1512  scriptIdx = functionValue.scriptIdx;
1513  return true;
1514  }
1515  default:
1516  return false;
1517  }
1518  return false;
1519  }
1520 
1521  /**
1522  * Get stacklet values from given variable
1523  * @param stacklet stacklet
1524  * @param scriptIdx script index
1525  * @param optional optional
1526  * @return success
1527  */
1528  inline bool getStackletValue(string& stacklet, int& scriptIdx, bool optional = false) const {
1529  switch(getType()) {
1531  {
1532  const auto& functionValue = getFunctionValueReference();
1533  stacklet = functionValue.name;
1534  scriptIdx = functionValue.scriptIdx;
1535  return true;
1536  }
1537  default:
1538  return false;
1539  }
1540  return false;
1541  }
1542 
1543  /**
1544  * Get string value from given variable
1545  * @param value value
1546  * @param optional optional
1547  * @return success
1548  */
1549  inline bool getStringValue(string& value, bool optional = false) const {
1550  switch(getType()) {
1551  case TYPE_BOOLEAN:
1552  value = getBooleanValueReference() == true?"true":"false";
1553  return true;
1554  case TYPE_INTEGER:
1555  value = to_string(getIntegerValueReference());
1556  return true;
1557  case TYPE_FLOAT:
1558  value = to_string(getFloatValueReference());
1559  return true;
1560  case TYPE_STRING:
1561  value = getStringValueReference().getValue();
1562  return true;
1563  default:
1564  return false;
1565  }
1566  return false;
1567  }
1568 
1569  /**
1570  * Get byte value from given variable
1571  * @param minitScript mini script
1572  * @param value value
1573  * @param statement statement
1574  * @return success
1575  */
1576  inline bool getByteValue(MinitScript* minitScript, uint8_t& value, const Statement* statement = nullptr) const {
1577  int64_t intValue;
1578  if (getIntegerValue(intValue, false) == true && value >= 0 && value <= 255) {
1579  value = intValue;
1580  return true;
1581  } else {
1582  if (statement != nullptr) {
1583  _Console::printLine(minitScript->getStatementInformation(*statement) + ": Expected byte integer value (0 <= value <= 255), but got " + getValueAsString());
1584  } else {
1585  _Console::printLine(minitScript->getScriptFileName() + ": Expected byte integer value (0 <= value <= 255), but got " + getValueAsString());
1586  }
1587  }
1588  return false;
1589  }
1590 
1591  /**
1592  * Get string value UTF8 position cache from given variable
1593  * @return UTF8 position cache or nullptr if not available
1594  */
1596  switch(getType()) {
1597  case TYPE_STRING:
1600  return &getStringValueReference().getCache();
1601  default:
1602  return nullptr;
1603  }
1604  }
1605 
1606  /**
1607  * Set boolean value from given value into variable
1608  * @param value value
1609  */
1610  inline void setNullValue() {
1611  setType(TYPE_NULL);
1612  }
1613 
1614  /**
1615  * Set value from given variable into variable
1616  * @param variable variable
1617  */
1618  inline void setValue(const Variable& variable) {
1619  setType(TYPE_NULL);
1620  copyVariable(*this, variable, false);
1621  }
1622 
1623  /**
1624  * Set boolean value from given value into variable
1625  * @param value value
1626  */
1627  inline void setValue(bool value) {
1629  getBooleanValueReference() = value;
1630  }
1631 
1632  /**
1633  * Set integer value from given value into variable
1634  * @param value value
1635  */
1636  inline void setValue(int64_t value) {
1638  getIntegerValueReference() = value;
1639  }
1640 
1641  /**
1642  * Set float value from given value into variable
1643  * @param value value
1644  */
1645  inline void setValue(float value) {
1647  getFloatValueReference() = value;
1648  }
1649 
1650  /**
1651  * Set string value from given value into variable
1652  * @param value value
1653  */
1654  inline void setValue(const string& value) {
1657  }
1658 
1659  /**
1660  * Set array value from given value into variable
1661  * @param value value
1662  */
1663  inline void setValue(const vector<uint8_t>& value) {
1665  auto& byteArrayValue = getByteArrayValueReference().value;
1666  for (const auto arrayEntry: value) {
1667  byteArrayValue.push_back(arrayEntry);
1668  }
1669  }
1670 
1671  /**
1672  * Set array value from given value into variable
1673  * @param value value
1674  */
1675  inline void setValue(const vector<Variable*>& value) {
1677  auto& arrayValue = getArrayValueReference();
1678  for (const auto arrayEntry: value) {
1679  arrayValue.push_back(new Variable(*arrayEntry));
1680  }
1681  }
1682 
1683  /**
1684  * Set map value from given value into variable
1685  * @param value value
1686  */
1687  inline void setValue(const unordered_map<string, Variable*>& value) {
1688  setType(TYPE_MAP);
1689  auto& mapValue = getMapValueReference();
1690  for (const auto& [mapEntryName, mapEntryValue]: value) {
1691  mapValue[mapEntryName] = new Variable(*mapEntryValue);
1692  }
1693  }
1694 
1695  /**
1696  * Set set value from given value into variable
1697  * @param value value
1698  */
1699  inline void setValue(const unordered_set<string>& value) {
1700  setType(TYPE_SET);
1701  getSetValueReference() = value;
1702  }
1703 
1704  /**
1705  * Set value for custom data types
1706  * @param value value
1707  */
1708  inline void setValue(const void* value) {
1709  // custom data type
1710  auto dataTypeIdx = static_cast<int>(this->getType()) - TYPE_PSEUDO_DATATYPES;
1711  if (dataTypeIdx < 0 || dataTypeIdx >= MinitScript::dataTypes.size()) {
1712  _Console::printLine("ScriptVariable::setValue(): unknown data type with id " + to_string(dataTypeIdx));
1713  return;
1714  }
1715  MinitScript::dataTypes[dataTypeIdx]->setVariableValue(*this, value);
1716  }
1717 
1718  /**
1719  * @return return const pointer to underlying byte vector or nullptr
1720  */
1721  inline const vector<uint8_t>* getByteArrayPointer() const {
1722  if (getType() != TYPE_BYTEARRAY) return nullptr;
1723  auto& byteArrayValue = getByteArrayValueReference().value;
1724  return &byteArrayValue;
1725  }
1726 
1727  /**
1728  * @return pointer to underlying byte vector or nullptr
1729  */
1730  inline vector<uint8_t>* getByteArrayPointer() {
1731  if (getType() != TYPE_BYTEARRAY) return nullptr;
1732  auto& byteArrayValue = getByteArrayValueReference().value;
1733  return &byteArrayValue;
1734  }
1735 
1736  /**
1737  * Get byte array size
1738  * @return byte array size
1739  */
1740  inline int64_t getByteArraySize() const {
1741  if (getType() != TYPE_BYTEARRAY) return 0;
1742  return getByteArrayValueReference().value.size();
1743  }
1744 
1745  /**
1746  * Get const byte array read pointer
1747  * @return const pointer to byte array read pointer
1748  */
1749  inline const int64_t* getByteArrayReadPointer() const {
1750  if (getType() != TYPE_BYTEARRAY) return nullptr;
1752  }
1753 
1754  /**
1755  * Get byte array read pointer
1756  * @return pointer to byte array read pointer
1757  */
1758  inline int64_t* getByteArrayReadPointer() {
1759  if (getType() != TYPE_BYTEARRAY) return nullptr;
1761  }
1762 
1763  /**
1764  * Get const byte array write pointer
1765  * @return const pointer to byte array write pointer
1766  */
1767  inline const int64_t* getByteArrayWritePointer() const {
1768  if (getType() != TYPE_BYTEARRAY) return nullptr;
1770  }
1771 
1772  /**
1773  * Get byte array write pointer
1774  * @return pointer to byte array write pointer
1775  */
1776  inline int64_t* getByteArrayWritePointer() {
1777  if (getType() != TYPE_BYTEARRAY) return nullptr;
1779  }
1780 
1781  /**
1782  * Get entry from byte array with given index
1783  * @param idx index
1784  * @return entry from byte array with given index
1785  */
1786  inline const uint8_t getByteArrayEntry(int64_t idx) const {
1787  if (getType() != TYPE_BYTEARRAY) return 0;
1788  const auto& byteArrayValue = getByteArrayValueReference().value;
1789  if (idx >= 0 && idx < byteArrayValue.size()) return byteArrayValue[idx];
1790  return 0;
1791  }
1792 
1793  /**
1794  * Set entry in byte array with given index
1795  * @param idx index
1796  */
1797  inline void setByteArrayEntry(int64_t idx, uint8_t value) {
1799  if (idx < 0) return;
1800  auto& byteArrayValue = getByteArrayValueReference().value;
1801  while (byteArrayValue.size() <= idx) pushByteArrayEntry(0);
1802  byteArrayValue[idx] = value;
1803  }
1804 
1805  /**
1806  * Push entry to byte array
1807  * @param value value
1808  */
1809  inline void pushByteArrayEntry(uint8_t value) {
1811  getByteArrayValueReference().value.push_back(value);
1812  }
1813 
1814  /**
1815  * Remove byte array entries at given index and size
1816  * @param idx index
1817  * @param size size
1818  */
1819  inline void removeByteArray(int64_t idx, int64_t size) {
1820  if (getType() != TYPE_BYTEARRAY) return;
1821  auto& byteArrayValue = getByteArrayValueReference().value;
1822  if (idx >= 0 && idx < byteArrayValue.size()) {
1823  byteArrayValue.erase(byteArrayValue.begin() + idx, byteArrayValue.begin() + idx + size);
1824  }
1825  }
1826 
1827  /**
1828  * Clear byte array
1829  */
1830  inline void clearByteArray() {
1831  if (getType() != TYPE_BYTEARRAY) return;
1832  auto& byteArrayValue = getByteArrayValueReference().value;
1833  byteArrayValue.clear();
1834  }
1835 
1836  /**
1837  * @return return const pointer to underlying vector or nullptr
1838  */
1839  inline const vector<Variable*>* getArrayPointer() const {
1840  if (getType() != TYPE_ARRAY) return nullptr;
1841  auto& arrayValue = getArrayValueReference();
1842  return &arrayValue;
1843  }
1844 
1845  /**
1846  * @return pointer to underlying vector or nullptr
1847  */
1848  inline vector<Variable*>* getArrayPointer() {
1849  if (getType() != TYPE_ARRAY) return nullptr;
1850  auto& arrayValue = getArrayValueReference();
1851  return &arrayValue;
1852  }
1853 
1854  /**
1855  * Get array size
1856  * @return array size
1857  */
1858  inline int64_t getArraySize() const {
1859  if (getType() != TYPE_ARRAY) return 0;
1860  return getArrayValueReference().size();
1861  }
1862 
1863  /**
1864  * Get entry from array with given index
1865  * @param idx index
1866  * @return entry from array with given index
1867  */
1868  inline const Variable getArrayEntry(int64_t idx) const {
1869  if (getType() != TYPE_ARRAY) return Variable();
1870  const auto& arrayValue = getArrayValueReference();
1871  if (idx >= 0 && idx < arrayValue.size()) return *arrayValue[idx];
1872  return Variable();
1873  }
1874 
1875  /**
1876  * Set entry in array with given index
1877  * @param idx index
1878  */
1879  inline void setArrayEntry(int64_t idx, const Variable& value) {
1881  if (idx < 0) return;
1882  auto& arrayValue = getArrayValueReference();
1883  while (arrayValue.size() <= idx) pushArrayEntry(Variable());
1884  arrayValue[idx]->releaseReference();
1885  arrayValue[idx] = new Variable(value);
1886  }
1887 
1888  /**
1889  * Push entry to array
1890  * @param value value
1891  */
1892  inline void pushArrayEntry(const Variable& value) {
1894  getArrayValueReference().push_back(new Variable(value));
1895  }
1896 
1897  /**
1898  * Remove array entry at given index
1899  * @param idx index
1900  */
1901  inline void removeArrayEntry(int64_t idx) {
1902  if (getType() != TYPE_ARRAY) return;
1903  auto& arrayValue = getArrayValueReference();
1904  if (idx >= 0 && idx < arrayValue.size()) {
1905  arrayValue[idx]->releaseReference();
1906  arrayValue.erase(arrayValue.begin() + idx);
1907  }
1908  return;
1909  }
1910 
1911  /**
1912  * Clear array
1913  */
1914  inline void clearArray() {
1915  if (getType() != TYPE_ARRAY) return;
1916  auto& arrayValue = getArrayValueReference();
1917  for (auto i = 0; i < arrayValue.size(); i++) arrayValue[i]->releaseReference();
1918  arrayValue.clear();
1919  }
1920 
1921  /**
1922  * @return return const pointer to underlying unordered_map or nullptr
1923  */
1924  inline const unordered_map<string, Variable*>* getMapPointer() const {
1925  if (getType() != TYPE_MAP) return nullptr;
1926  auto& mapValue = getMapValueReference();
1927  return &mapValue;
1928  }
1929 
1930  /**
1931  * @return pointer to underlying unordered_map or nullptr
1932  */
1933  inline unordered_map<string, Variable*>* getMapPointer() {
1934  if (getType() != TYPE_MAP) return nullptr;
1935  auto& mapValue = getMapValueReference();
1936  return &mapValue;
1937  }
1938 
1939  /**
1940  * Get map size
1941  */
1942  inline int64_t getMapSize() const {
1943  if (getType() != TYPE_MAP) return 0;
1944  return getMapValueReference().size();
1945  }
1946 
1947  /**
1948  * Map has entry with given key
1949  * @param key key
1950  * @return key exists
1951  */
1952  inline bool hasMapEntry(const string& key) const {
1953  if (getType() != TYPE_MAP) return false;
1954  const auto& mapValue = getMapValueReference();
1955  auto it = mapValue.find(key);
1956  if (it != mapValue.end()) return true;
1957  return false;
1958  }
1959 
1960  /**
1961  * Get entry from map with given key
1962  * @param key key
1963  * @return map entry from given key
1964  */
1965  inline const Variable getMapEntry(const string& key) const {
1966  if (getType() != TYPE_MAP) return Variable();
1967  const auto& mapValue = getMapValueReference();
1968  auto it = mapValue.find(key);
1969  if (it != mapValue.end()) return *it->second;
1970  return Variable();
1971  }
1972 
1973  /**
1974  * Get entry pointer from map with given key
1975  * @param key key
1976  * @return map entry from given key
1977  */
1978  inline const Variable* getMapEntryPtr(const string& key) const {
1979  if (getType() != TYPE_MAP) return nullptr;
1980  const auto& mapValue = getMapValueReference();
1981  auto it = mapValue.find(key);
1982  if (it != mapValue.end()) return it->second;
1983  return nullptr;
1984  }
1985 
1986  /**
1987  * Set entry in map with given key
1988  * @param key key
1989  * @param value value
1990  * @param _private private entry
1991  *
1992  */
1993  inline void setMapEntry(const string& key, const Variable& value, bool _private = false) {
1994  setType(TYPE_MAP);
1995  auto mapValueIt = getMapValueReference().find(key);
1996  if (mapValueIt != getMapValueReference().end()) mapValueIt->second->releaseReference();
1997  auto variablePtr = new Variable(value);
1998  if (_private == true) variablePtr->setPrivate();
1999  getMapValueReference()[key] = variablePtr;
2000  }
2001 
2002  /**
2003  * Remove entry in map with given key
2004  * @param key key
2005  */
2006  inline void removeMapEntry(const string& key) {
2007  if (getType() != TYPE_MAP) return;
2008  auto& mapValue = getMapValueReference();
2009  auto mapValueIt = mapValue.find(key);
2010  if (mapValueIt != mapValue.end()) {
2011  mapValueIt->second->releaseReference();
2012  mapValue.erase(mapValueIt);
2013  }
2014  }
2015 
2016  /**
2017  * Get map keys
2018  * @return keys
2019  */
2020  inline const vector<string> getMapKeys() const {
2021  vector<string> keys;
2022  if (getType() != TYPE_MAP) return keys;
2023  const auto& mapValue = getMapValueReference();
2024  for (const auto& [mapEntryName, mapEntryValue]: mapValue) {
2025  keys.push_back(mapEntryName);
2026  }
2027  return keys;
2028  }
2029 
2030  /**
2031  * Get map values
2032  * @return values
2033  */
2034  inline const vector<Variable*> getMapValues() const {
2035  vector<Variable*> values;
2036  if (getType() != TYPE_MAP) return values;
2037  const auto& mapValue = getMapValueReference();
2038  for (const auto& [mapEntryKey, mapEntryValue]: mapValue) {
2039  values.push_back(mapEntryValue);
2040  }
2041  return values;
2042  }
2043 
2044  /**
2045  * Clear array
2046  */
2047  inline void clearMap() {
2048  if (getType() != TYPE_MAP) return;
2049  auto& mapValue = getMapValueReference();
2050  for (const auto& [mapEntryName, mapEntryValue]: mapValue) {
2051  mapEntryValue->releaseReference();
2052  }
2053  mapValue.clear();
2054  }
2055 
2056  /**
2057  * @return const pointer to underlying unordered_set or nullptr
2058  */
2059  inline const unordered_set<string>* getSetPointer() const {
2060  if (getType() != TYPE_SET) return nullptr;
2061  auto& setValue = getSetValueReference();
2062  return &setValue;
2063  }
2064 
2065  /**
2066  * @return pointer to underlying unordered_set or nullptr
2067  */
2068  inline unordered_set<string>* getSetPointer() {
2069  if (getType() != TYPE_SET) return nullptr;
2070  auto& setValue = getSetValueReference();
2071  return &setValue;
2072  }
2073 
2074  /**
2075  * Get set size
2076  */
2077  inline int64_t getSetSize() const {
2078  if (getType() != TYPE_SET) return 0;
2079  return getSetValueReference().size();
2080  }
2081 
2082  /**
2083  * Set has given key
2084  * @param key key
2085  * @return key exists
2086  */
2087  inline bool hasSetKey(const string& key) const {
2088  if (getType() != TYPE_SET) return false;
2089  const auto& setValue = getSetValueReference();
2090  auto it = setValue.find(key);
2091  if (it != setValue.end()) return true;
2092  return false;
2093  }
2094 
2095  /**
2096  * Insert given key in set
2097  * @param key key
2098  */
2099  inline void insertSetKey(const string& key) {
2100  setType(TYPE_SET);
2101  getSetValueReference().insert(key);
2102  }
2103 
2104  /**
2105  * Remove key in set with given key
2106  * @param key key
2107  */
2108  inline void removeSetKey(const string& key) {
2109  if (getType() != TYPE_SET) return;
2110  auto& setValue = getSetValueReference();
2111  auto it = setValue.find(key);
2112  if (it != setValue.end()) {
2113  setValue.erase(it);
2114  }
2115  }
2116 
2117  /**
2118  * Get set keys
2119  * @return keys
2120  */
2121  inline const vector<string> getSetKeys() const {
2122  vector<string> keys;
2123  if (getType() != TYPE_SET) return keys;
2124  const auto& setValue = getSetValueReference();
2125  for (const auto& key: setValue) {
2126  keys.push_back(key);
2127  }
2128  return keys;
2129  }
2130 
2131  /**
2132  * Clear set
2133  */
2134  inline void clearSet() {
2135  if (getType() != TYPE_SET) return;
2136  auto& setValue = getSetValueReference();
2137  setValue.clear();
2138  }
2139 
2140  /**
2141  * Set array/map values initializer function call statement
2142  * @param initializerStatement initializer statement
2143  * @param minitScript minitscript instance
2144  * @param scriptIdx script index
2145  * @param statement statement
2146  */
2147  void setFunctionCallStatement(const string& initializerStatement, MinitScript* minitScript, int scriptIdx, const Statement& statement);
2148 
2149  /**
2150  * Set function assignment from given value into variable
2151  * @param function function
2152  * @param scriptIdx script index
2153  */
2154  inline void setFunctionAssignment(const string& function, int scriptIdx = MinitScript::SCRIPTIDX_NONE) {
2156  auto& functionValue = getFunctionValueReference();
2157  functionValue.name = function;
2158  functionValue.scriptIdx = scriptIdx;
2159  }
2160 
2161  /**
2162  * Set stacklet assignment from given value into variable
2163  * @param stacklet stacklet
2164  * @param scriptIdx script index
2165  */
2166  inline void setStackletAssignment(const string& stacklet, int scriptIdx = MinitScript::SCRIPTIDX_NONE) {
2168  auto& functionValue = getFunctionValueReference();
2169  functionValue.name = stacklet;
2170  functionValue.scriptIdx = scriptIdx;
2171  }
2172 
2173  /**
2174  * Set implicit typed value given by value string
2175  * @param value value
2176  * @param minitScript mini script
2177  * @param scriptIdx script index
2178  * @param statement statement
2179  */
2180  inline void setImplicitTypedValue(const string& value, MinitScript* minitScript, int scriptIdx, const Statement& statement) {
2181  setImplicitTypedValueFromStringView(string_view(value), minitScript, scriptIdx, statement);
2182  }
2183 
2184  /**
2185  * Set implicit typed value given by value string
2186  * @param value value
2187  * @param minitScript mini script
2188  * @param scriptIdx script index
2189  * @param statement statement
2190  */
2191  inline void setImplicitTypedValueFromStringView(const string_view& value, MinitScript* minitScript, int scriptIdx, const Statement& statement) {
2192  //
2193  auto viewIsFunctionAssignment = [](const string_view& candidate, string_view& function) -> bool {
2194  if (candidate.size() == 0) return false;
2195  //
2196  auto i = 0;
2197  // (
2198  if (candidate[i++] != '(') return false;
2199  //
2200  if (i >= candidate.size()) return false;
2201  // )
2202  if (candidate[i++] != ')') return false;
2203  // spaces
2204  for (; i < candidate.size() && _Character::isSpace(candidate[i]) == true; i++);
2205  if (i >= candidate.size()) return false;
2206  // -
2207  if (candidate[i++] != '-') return false;
2208  //
2209  if (i >= candidate.size()) return false;
2210  // >
2211  if (candidate[i++] != '>') return false;
2212  // spaces
2213  for (; i < candidate.size() && _Character::isSpace(candidate[i]) == true; i++);
2214  if (i >= candidate.size()) return false;
2215  //
2216  auto functionStartIdx = i;
2217  for (; i < candidate.size(); i++) {
2218  auto c = candidate[i];
2219  if (_Character::isAlphaNumeric(c) == false && c != '_') {
2220  return false;
2221  }
2222  }
2223  //
2224  function = string_view(&candidate[functionStartIdx], i - functionStartIdx);
2225  //
2226  return true;
2227  };
2228  //
2229  auto viewIsStackletAssignment = [](const string_view& candidate, string_view& stacklet) -> bool {
2230  if (candidate.size() == 0) return false;
2231  //
2232  auto i = 0;
2233  // spaces
2234  for (; i < candidate.size() && _Character::isSpace(candidate[i]) == true; i++);
2235  if (i >= candidate.size()) return false;
2236  // -
2237  if (candidate[i++] != '-') return false;
2238  //
2239  if (i >= candidate.size()) return false;
2240  // >
2241  if (candidate[i++] != '>') return false;
2242  // spaces
2243  for (; i < candidate.size() && _Character::isSpace(candidate[i]) == true; i++);
2244  if (i >= candidate.size()) return false;
2245  //
2246  auto stackletStartIdx = i;
2247  for (; i < candidate.size(); i++) {
2248  auto c = candidate[i];
2249  if (_Character::isAlphaNumeric(c) == false && c != '_') {
2250  return false;
2251  }
2252  }
2253  //
2254  stacklet = string_view(&candidate[stackletStartIdx], i - stackletStartIdx);
2255  //
2256  return true;
2257  };
2258  //
2259  string_view functionOrStacklet;
2260  //
2261  if (value == "null") {
2262  setNullValue();
2263  } else
2264  if (value == "true") {
2265  setValue(true);
2266  } else
2267  if (value == "false") {
2268  setValue(false);
2269  } else
2270  if (_Integer::viewIs(value) == true) {
2271  setValue(static_cast<int64_t>(_Integer::viewParse(value)));
2272  } else
2273  if (_Float::viewIs(value) == true) {
2274  setValue(_Float::viewParse(value));
2275  } else
2276  if (viewIsStringLiteral(value) == true) {
2277  setValue(minitScript->deescape(dequote(value), statement));
2278  } else
2279  if (_StringTools::viewStartsWith(value, "{") == true &&
2280  _StringTools::viewEndsWith(value, "}") == true) {
2281  *this = initializeMapSet(value, minitScript, scriptIdx, statement);
2282  } else
2283  if (_StringTools::viewStartsWith(value, "[") == true &&
2284  _StringTools::viewEndsWith(value, "]") == true) {
2285  *this = initializeArray(value, minitScript, scriptIdx, statement);
2286  } else
2287  if (viewIsFunctionAssignment(value, functionOrStacklet) == true) {
2288  setFunctionAssignment(string(functionOrStacklet));
2289  } else
2290  if (viewIsStackletAssignment(value, functionOrStacklet) == true) {
2291  setStackletAssignment(string(functionOrStacklet));
2292  } else
2293  if (viewIsCall(value) == true) {
2294  setFunctionCallStatement(minitScript->doStatementPreProcessing(string(value), statement), minitScript, scriptIdx, statement);
2295  } else
2296  if (viewIsVariableAccess(value) == true) {
2297  setFunctionCallStatement("getVariable(\"" + string(value) + "\")", minitScript, scriptIdx, statement);
2298  } else {
2299  setValue(minitScript->deescape(value, statement));
2300  }
2301  }
2302 
2303  /**
2304  * Check if given variable type does match expected variable type
2305  * @param type type
2306  * @param expectedType expected type
2307  * @return given variable type does match expected variable type
2308  */
2309  inline static bool isExpectedType(VariableType type, VariableType expectedType) {
2310  if (type == expectedType) return true;
2311  switch(expectedType) {
2312  case TYPE_PSEUDO_NUMBER:
2313  return type == TYPE_INTEGER || type == TYPE_FLOAT || type == TYPE_BOOLEAN;
2314  case TYPE_PSEUDO_MIXED:
2315  return true;
2316  default:
2317  return false;
2318  }
2319  }
2320 
2321  /**
2322  * Returns given variable type as string
2323  * @param type type
2324  * @return variable type as string
2325  */
2326  inline static const string& getTypeAsString(VariableType type) {
2327  switch(type) {
2328  case TYPE_NULL: return TYPENAME_NULL;
2329  case TYPE_BOOLEAN: return TYPENAME_BOOLEAN;
2330  case TYPE_INTEGER: return TYPENAME_INTEGER;
2331  case TYPE_FLOAT: return TYPENAME_FLOAT;
2332  case TYPE_FUNCTION_CALL: return TYPENAME_NONE;
2335  case TYPE_PSEUDO_NUMBER: return TYPENAME_NUMBER;
2336  case TYPE_PSEUDO_MIXED: return TYPENAME_MIXED;
2337  case TYPE_STRING: return TYPENAME_STRING;
2338  case TYPE_BYTEARRAY: return TYPENAME_BYTEARRAY;
2339  case TYPE_ARRAY: return TYPENAME_ARRAY;
2340  case TYPE_MAP: return TYPENAME_MAP;
2341  case TYPE_SET: return TYPENAME_SET;
2342  default:
2343  // custom data types
2344  auto dataTypeIdx = static_cast<int>(type) - TYPE_PSEUDO_DATATYPES;
2345  if (dataTypeIdx < 0 || dataTypeIdx >= MinitScript::dataTypes.size()) {
2346  return TYPENAME_NONE;
2347  }
2348  return MinitScript::dataTypes[dataTypeIdx]->getTypeAsString();
2349  }
2350  return TYPENAME_NONE;
2351  }
2352 
2353  /**
2354  * @return this variable type as string
2355  */
2356  inline const string getTypeAsString() const {
2357  return getTypeAsString(getType());
2358  }
2359 
2360  /**
2361  * Returns given return value variable type string representation
2362  * @param type type
2363  * @param nullable nullable
2364  * @return return value variable type string representation
2365  */
2366  inline static const string getReturnTypeAsString(VariableType type, bool nullable) {
2367  switch(type) {
2368  case TYPE_NULL: return "Null";
2369  default: return string(nullable?"?":"") + getTypeAsString(type);
2370  }
2371  return string();
2372  }
2373 
2374  /**
2375  * Returns given return value variable type string representation
2376  * @param nullable nullable
2377  * @return return value variable type string representation
2378  */
2379  inline const string getReturnTypeAsString(bool nullable) const {
2380  return getReturnTypeAsString(getType(), nullable);
2381  }
2382 
2383  /**
2384  * @return string representation of variable type
2385  */
2386  inline const string getAsString() const {
2387  string result;
2388  result+= getTypeAsString();
2389  result+= "(";
2390  if (getType() == TYPE_STRING) result+= "\"";
2391  result+= getValueAsString();
2392  if (getType() == TYPE_STRING) result+= "\"";
2393  result+= ")";
2394  return result;
2395  }
2396 
2397  /**
2398  * Print string representation of variable
2399  * @param formatted formatted
2400  * @param jsonCompatible json compatible
2401  * @param depth recursion depth
2402  * @return string representation of variable type
2403  */
2404  inline const string getValueAsString(bool formatted = false, bool jsonCompatible = false, int depth = 0) const {
2405  auto escapeString = [](const string& str) -> const string {
2406  const array<char, 11> escapeSequences = {'0', 'a', 'b', 'f', 'n', 'r', 't', 'v', 'U', '"'};
2407  //
2408  auto result = str;
2409  //
2410  result = _StringTools::replace(result, "\0", "\\0");
2411  result = _StringTools::replace(result, "\a", "\\a");
2412  result = _StringTools::replace(result, "\b", "\\b");
2413  result = _StringTools::replace(result, "\f", "\\f");
2414  result = _StringTools::replace(result, "\n", "\\n");
2415  result = _StringTools::replace(result, "\r", "\\r");
2416  result = _StringTools::replace(result, "\t", "\\t");
2417  result = _StringTools::replace(result, "\v", "\\v");
2418  result = _StringTools::replace(result, "\"", "\\\"");
2419  //
2420  string result2;
2421  auto lc = '\0';
2422  auto llc = '\0';
2423  for (auto i = 0; i < result.size(); i++) {
2424  //
2425  auto c = result[i];
2426  auto nc = i < result.size() - 1?result[i + 1]:'\0';
2427  if (c == '\\' && lc != '\\' && nc != '\\' && find(escapeSequences.begin(), escapeSequences.end(), nc) == escapeSequences.end()) {
2428  result2+= "\\\\";
2429  } else {
2430  result2+= c;
2431  }
2432  //
2433  auto lc = c;
2434  auto llc = lc;
2435  }
2436  //
2437  return result2;
2438  };
2439  //
2440  string result;
2441  switch (getType()) {
2442  case TYPE_NULL:
2443  result+= "<Null>";
2444  break;
2445  case TYPE_BOOLEAN:
2446  result+= getBooleanValueReference() == true?"true":"false";
2447  break;
2448  case TYPE_INTEGER:
2449  result+= to_string(getIntegerValueReference());
2450  break;
2451  case TYPE_FLOAT:
2452  result+= to_string(getFloatValueReference());
2453  break;
2454  case TYPE_FUNCTION_CALL:
2455  result+= "{" + getStringValueReference().getValue() + "}";
2456  break;
2458  {
2459  const auto& functionValue = getFunctionValueReference();
2460  result+= "() -> " + functionValue.name + "(" + to_string(functionValue.scriptIdx) + ")";
2461  break;
2462  }
2464  {
2465  const auto& functionValue = getFunctionValueReference();
2466  result+= "-> " + functionValue.name + "(" + to_string(functionValue.scriptIdx) + ")";
2467  break;
2468  }
2469  case TYPE_PSEUDO_NUMBER:
2470  result+= "Number";
2471  break;
2472  case TYPE_PSEUDO_MIXED:
2473  result+= "Mixed";
2474  break;
2475  case TYPE_STRING:
2476  result+= getStringValueReference().getValue();
2477  break;
2478  case TYPE_BYTEARRAY:
2479  {
2480  const auto& byteArrayValue = getByteArrayValueReference().value;
2481  vector<string> values;
2482  for (const auto arrayEntry: byteArrayValue) {
2483  values.push_back(to_string(arrayEntry));
2484  }
2485  auto i = 0;
2486  for (const auto& valueString: values) {
2487  result+= valueString;
2488  if (i != values.size() - 1) result+= ", ";
2489  i++;
2490  }
2491  result =
2492  "ByteArray([" + result + "], " +
2493  "size: " + to_string(byteArrayValue.size()) +
2494  ", capacity: " + to_string(byteArrayValue.capacity()) +
2495  ", read position: " + to_string(getByteArrayValueReference().readPtr) +
2496  ", write position: " + to_string(getByteArrayValueReference().writePtr) +
2497  ")";
2498  break;
2499  }
2500  case TYPE_ARRAY:
2501  {
2502  const auto& arrayValue = getArrayValueReference();
2503  vector<string> values;
2504  for (const auto arrayEntry: arrayValue) {
2505  if (arrayEntry->getType() == TYPE_STRING) {
2506  values.push_back("\"" + escapeString(arrayEntry->getValueAsString(formatted, jsonCompatible, depth + 1)) + "\"");
2507  } else {
2508  values.push_back(arrayEntry->getValueAsString(formatted, jsonCompatible, depth + 1));
2509  }
2510  }
2511  if (formatted == true) {
2512  auto i = 0;
2513  for (auto& value: values) {
2514  if (i != values.size() - 1) value+= ",";
2515  i++;
2516  }
2517  for (const auto& valueString: values) {
2518  result+= _StringTools::indent(valueString, "\t" , depth + 1);
2519  result+= "\n";
2520  }
2521  result = (depth == 0?_StringTools::indent("[", "\t", depth):"[") + "\n" + result;
2522  result+= _StringTools::indent("]", "\t", depth) + (depth == 0?"\n":"");
2523  } else {
2524  auto i = 0;
2525  for (const auto& valueString: values) {
2526  result+= valueString;
2527  if (i != values.size() - 1) result+= ", ";
2528  i++;
2529  }
2530  result = "[" + result + "]";
2531  }
2532  break;
2533  }
2534  case TYPE_MAP:
2535  {
2536  const auto& mapValue = getMapValueReference();
2537  vector<string> values;
2538  for (const auto& [mapEntryName, mapEntryValue]: mapValue) {
2539  string value;
2540  value+= "\"" + escapeString(mapEntryName) + "\": ";
2541  if (mapEntryValue->getType() == TYPE_STRING) {
2542  value+= "\"";
2543  value+= escapeString(mapEntryValue->getValueAsString(formatted, jsonCompatible, depth + 1));
2544  value+= "\"";
2545  } else {
2546  value+= mapEntryValue->getValueAsString(formatted, jsonCompatible, depth + 1);
2547  }
2548  values.push_back(value);
2549  }
2550  sort(values.begin(), values.end());
2551  if (formatted == true) {
2552  auto i = 0;
2553  for (auto& value: values) {
2554  if (i != values.size() - 1) value+= ",";
2555  i++;
2556  }
2557  for (const auto& valueString: values) {
2558  result+= _StringTools::indent(valueString, "\t" , depth + 1);
2559  result+= "\n";
2560  }
2561  result = (depth == 0?_StringTools::indent("{", "\t", depth):"{") + "\n" + result;
2562  result+= _StringTools::indent("}", "\t", depth) + (depth == 0?"\n":"");
2563  } else {
2564  auto i = 0;
2565  for (const auto& valueString: values) {
2566  result+= valueString;
2567  if (i != values.size() - 1) result+= ", ";
2568  i++;
2569  }
2570  result = "{" + result + "}";
2571  }
2572  break;
2573  }
2574  case TYPE_SET:
2575  {
2576  const auto& setValue = getSetValueReference();
2577  vector<string> values;
2578  for (const auto& key: setValue) {
2579  values.push_back(
2580  "\"" + escapeString(key) + "\""
2581  );
2582  if (jsonCompatible == true) {
2583  values.back() += ": true";
2584  }
2585  }
2586  sort(values.begin(), values.end());
2587  if (formatted == true) {
2588  auto i = 0;
2589  for (auto& value: values) {
2590  if (i != values.size() - 1) value+= ",";
2591  i++;
2592  }
2593  for (const auto& valueString: values) {
2594  result+= _StringTools::indent(valueString, "\t" , depth + 1);
2595  result+= "\n";
2596  }
2597  result = (depth == 0?_StringTools::indent("{", "\t", depth):"{") + "\n" + result;
2598  result+= _StringTools::indent("}", "\t", depth) + (depth == 0?"\n":"");
2599  } else {
2600  auto i = 0;
2601  for (const auto& valueString: values) {
2602  result+= valueString;
2603  if (i != values.size() - 1) result+= ", ";
2604  i++;
2605  }
2606  result = "{" + result + "}";
2607  }
2608  break;
2609  }
2610  default:
2611  // custom data types
2612  auto dataTypeIdx = static_cast<int>(getType()) - TYPE_PSEUDO_DATATYPES;
2613  if (dataTypeIdx < 0 || dataTypeIdx >= MinitScript::dataTypes.size()) {
2614  _Console::printLine("ScriptVariable::getValueAsString(): unknown data type with id " + to_string(dataTypeIdx));
2615  return result;
2616  }
2617  return MinitScript::dataTypes[dataTypeIdx]->getValueAsString(*this);
2618 
2619  }
2620  return result;
2621  }
2622  };
2623 
2624  /**
2625  * State Machine State
2626  */
2628  public:
2629  // forbid class copy
2631 
2632  /**
2633  * Constructor
2634  */
2635  inline StateMachineState() {}
2636 
2637  /**
2638  * Destructor
2639  */
2640  virtual ~StateMachineState() {}
2641 
2642  /**
2643  * @return name
2644  */
2645  virtual const string getName() = 0;
2646 
2647  /**
2648  * @return id
2649  */
2650  virtual int getId() = 0;
2651 
2652  /**
2653  * Execute state machine state
2654  */
2655  virtual void execute() = 0;
2656  };
2657 
2658  /**
2659  * Method
2660  */
2661  class Method {
2662  public:
2663  struct ArgumentType {
2665  string name;
2666  bool optional;
2668  bool nullable;
2669  };
2670 
2671  // forbid class copy
2673 
2674  /**
2675  * Constructor
2676  * @param argumentTypes argument types
2677  * @param returnValueType return value type
2678  * @param returnValueNullable true if return value can also be a null value
2679  */
2680  inline Method(
2681  const vector<ArgumentType>& argumentTypes = {},
2682  VariableType returnValueType = VariableType::TYPE_NULL,
2683  bool returnValueNullable = false
2684  ):
2688  //
2689  }
2690 
2691  /**
2692  * Destructor
2693  */
2694  virtual ~Method() {}
2695 
2696  /**
2697  * @return method name
2698  */
2699  virtual const string getMethodName() = 0;
2700 
2701  /**
2702  * Execute method
2703  * @param arguments argument values
2704  * @param returnValue return value
2705  * @param subStatement sub statement
2706  */
2707  virtual void executeMethod(span<Variable>& arguments, Variable& returnValue, const SubStatement& subStatement) = 0;
2708 
2709  /**
2710  * @return arguments
2711  */
2712  inline const vector<ArgumentType>& getArgumentTypes() const {
2713  return argumentTypes;
2714  }
2715 
2716  /**
2717  * Get arguments information
2718  * @param beginIdx begin index
2719  * @return arguments information
2720  */
2721  inline const string getArgumentsInformation(int beginIdx = 0) const {
2722  string result;
2723  auto optionalArgumentCount = 0;
2724  auto argumentIdx = 0;
2725  for (const auto& argumentType: argumentTypes) {
2726  string argumentResult;
2727  if (argumentType.optional == true) {
2728  result+= "[";
2729  optionalArgumentCount++;
2730  }
2731  if (argumentIdx > beginIdx) result+= ", ";
2732  if (optionalArgumentCount > 0 || argumentIdx >= beginIdx) {
2733  if (argumentType.reference == true) {
2734  result+= "&";
2735  }
2736  result+= "$" + argumentType.name + ": " + (argumentType.nullable == true?"?":"") + Variable::getTypeAsString(argumentType.type);
2737  }
2738  argumentIdx++;
2739  }
2740  if (isVariadic() == true) {
2741  if (argumentIdx > beginIdx) result+= ", ";
2742  result+="...";
2743  }
2744  for (auto i = 0; i < optionalArgumentCount; i++) result+= "]";
2745  return result;
2746  }
2747 
2748  /**
2749  * @return return value type
2750  */
2751  inline const VariableType& getReturnValueType() const {
2752  return returnValueType;
2753  }
2754 
2755  /**
2756  * @return if return value can be null
2757  */
2758  inline bool isReturnValueNullable() const {
2759  return returnValueNullable;
2760  }
2761 
2762  /**
2763  * @return if variadic method
2764  */
2765  virtual bool isVariadic() const {
2766  return false;
2767  }
2768 
2769  /**
2770  * @return if private
2771  */
2772  virtual bool isPrivate() const {
2773  return false;
2774  }
2775 
2776  /**
2777  * @return operator
2778  */
2779  virtual Operator getOperator() const {
2780  return OPERATOR_NONE;
2781  }
2782 
2783  /**
2784  * @return context function
2785  */
2786  virtual const vector<string>& getContextFunctions() {
2787  return CONTEXTFUNCTIONS_ALL;
2788  }
2789 
2790  protected:
2792 
2793  private:
2794  vector<ArgumentType> argumentTypes;
2797  };
2798 
2799  /**
2800  * Syntax Tree Node
2801  */
2803  enum Type {
2809  };
2810  /**
2811  * Constructor
2812  */
2813  inline SyntaxTreeNode():
2815  value(Variable()),
2816  pointer(0ll),
2817  arguments({}),
2819  {}
2820  /**
2821  * Constructor
2822  * @param type type
2823  * @param value value
2824  * @param pointer pointer to method
2825  * @param arguments arguments
2826  * @param subLineIdx sub line index
2827  */
2829  Type type,
2830  const Variable& value,
2831  Method* method,
2832  const vector<SyntaxTreeNode>& arguments,
2833  int subLineIdx
2834  ):
2835  type(type),
2836  value(value),
2837  pointer((uint64_t)method),
2840  {}
2841  /**
2842  * Constructor
2843  * @param type type
2844  * @param value value
2845  * @param scriptIdx script index
2846  * @param arguments arguments
2847  * @param subLineIdx sub line index
2848  */
2850  Type type,
2851  const Variable& value,
2852  uint64_t scriptIdx,
2853  const vector<SyntaxTreeNode>& arguments,
2854  int subLineIdx
2855  ):
2856  type(type),
2857  value(value),
2858  pointer(scriptIdx),
2861  {}
2862  /**
2863  * @return method
2864  */
2865  inline Method* getMethod() const {
2866  return (Method*)pointer;
2867  }
2868  /**
2869  * Set method
2870  * @param method method
2871  */
2872  inline void setMethod(Method* method) {
2873  pointer = (uint64_t)method;
2874  }
2875  /**
2876  * @return function/stacklet script index
2877  */
2878  inline int64_t getScriptIdx() const {
2879  return pointer;
2880  }
2881  /**
2882  * Set function/stacklet script index
2883  * @param scriptIdx script index
2884  */
2885  inline void setScriptIdx(uint64_t scriptIdx) {
2886  pointer = scriptIdx;
2887  }
2888  //
2891  uint64_t pointer;
2892  vector<SyntaxTreeNode> arguments;
2894  };
2895 
2896  /**
2897  * Script
2898  */
2899  struct Script {
2900  /**
2901  * Argument
2902  */
2903  struct Argument {
2904  /**
2905  * Constructor
2906  * @param name name
2907  * @param reference reference
2908  * @param privateScope private scope
2909  */
2911  const string& name,
2912  bool reference,
2913  bool privateScope
2914  ):
2915  name(name),
2918  {}
2919  //
2920  string name;
2923  };
2924  //
2926  /**
2927  * Constructor
2928  * @param type type
2929  * @param line line
2930  * @param condition condition
2931  * @param executableCondition executable condition
2932  * @param conditionStatement condition statement
2933  * @param conditionSyntaxTree condition syntax tree
2934  * @param name name
2935  * @param emitCondition emit condition
2936  * @param statements statements
2937  * @param syntaxTree syntax tree
2938  * @param callableFunction callable function
2939  * @param functionArguments function arguments
2940  */
2941  inline Script(
2942  Type type,
2943  int line,
2944  // applies only for on and on-enabled
2945  const string& condition,
2946  const string& executableCondition,
2949  // applies only for on-enabled
2950  const string& name,
2951  bool emitCondition,
2952  const vector<Statement>& statements,
2953  const vector<SyntaxTreeNode>& syntaxTree,
2954  // applies only for functions/stacklets
2955  bool callable,
2956  const vector<Argument>& arguments
2957  ):
2958  type(type),
2959  line(line),
2964  name(name),
2968  callable(callable),
2970  {}
2971  //
2973  int line;
2974  // condition, condition name or function/stacklet/callable name
2975  string condition;
2979  // if condition holds a condition, name is the additional condition name if given
2980  string name;
2982  vector<Statement> statements;
2983  vector<SyntaxTreeNode> syntaxTree;
2984  bool callable;
2985  vector<Argument> arguments;
2986  };
2987 
2988  static constexpr int SCRIPTIDX_NONE { -1 };
2989  static constexpr int LINE_NONE { -1 };
2990  static constexpr int STATEMENTIDX_NONE { -1 };
2991  static constexpr int STATEMENTIDX_FIRST { 0 };
2992  static constexpr int ARGUMENTIDX_NONE { -1 };
2993 
3000 
3001  /**
3002  * Returns arguments as string
3003  * @param arguments arguments
3004  * @return arguments as string
3005  */
3006  inline const string getArgumentsAsString(const vector<SyntaxTreeNode>& arguments) {
3007  string argumentsString;
3008  for (const auto& argument: arguments) {
3009  switch (argument.type) {
3011  switch(argument.value.getType()) {
3012  case TYPE_NULL:
3013  {
3014  argumentsString+= (argumentsString.empty() == false?", ":"") + string("<Null>");
3015  break;
3016  }
3017  case TYPE_BOOLEAN:
3018  case TYPE_INTEGER:
3019  case TYPE_FLOAT:
3020  {
3021  argumentsString+= (argumentsString.empty() == false?", ":"") + argument.value.getValueAsString();
3022  break;
3023  }
3024  case TYPE_STRING:
3025  {
3026  argumentsString+= (argumentsString.empty() == false?", ":"") + string("\"") + escapeString(argument.value.getValueAsString()) + string("\"");
3027  break;
3028  }
3029  default:
3030  {
3031  argumentsString+= (argumentsString.empty() == false?", ":"") + string("<COMPLEX DATATYPE>");
3032  break;
3033  }
3034  }
3035  break;
3038  argumentsString+= (argumentsString.empty() == false?", ":"") + argument.value.getValueAsString() + string("(") + getArgumentsAsString(argument.arguments) + string(")");
3039  break;
3040  default:
3041  break;
3042  }
3043  }
3044  return argumentsString;
3045  }
3046 
3047 protected:
3048  static constexpr int SETACCESSBOOL_NONE { -1 };
3049  static constexpr int SETACCESSBOOL_TRUE { 0 };
3050  static constexpr int SETACCESSBOOL_FALSE { 1 };
3051  static constexpr int ARRAYIDX_NONE { -1 };
3052  static constexpr int ARRAYIDX_ADD { -2 };
3053  static constexpr int ARRAYIDX_FIRST { 0 };
3054  static constexpr int STATE_NONE { -1 };
3055  static constexpr int OPERATORIDX_NONE { -1 };
3056  static constexpr int LINE_FIRST { 1 };
3057  static constexpr int64_t TIME_NONE { -1LL };
3058 
3059  /**
3060  * Script state
3061  */
3062  struct ScriptState {
3063  /**
3064  * Block
3065  */
3066  struct Block {
3068  /**
3069  * Constructor
3070  * @param type block type
3071  * @param match match
3072  * @param continueStatement continue statement
3073  * @param breakStatement break statement
3074  * @param parameter switch variable / iteration function
3075  */
3076  inline Block(
3077  Type type,
3078  bool match,
3080  const Statement* breakStatement,
3081  const Variable& parameter
3082  ):
3083  type(type),
3084  match(match),
3088  {}
3089  //
3091  bool match;
3095  };
3099  };
3103  bool running { false };
3109  unordered_map<string, Variable*> variables;
3110  unordered_map<int, int64_t> forTimeStarted;
3111  vector<Block> blockStack;
3112  // applies for functions only
3114  };
3115 
3116  bool native;
3117  _Context* context { nullptr };
3118  _Library* library { nullptr };
3119  vector<Script> scripts;
3120  string nativeHash;
3121  vector<Script> nativeScripts;
3122  vector<unique_ptr<ScriptState>> scriptStateStack;
3123 
3124  // root context variables
3125  vector<string> enabledNamedConditions;
3127 
3128  vector<string> parseErrors;
3129  vector<pair<int, string>> deferredInlineScriptCodes;
3130 
3133 
3134  unique_ptr<MathMethods> minitScriptMath;
3135 
3138 
3140  bool emitted { false };
3141 
3142  /**
3143  * Escape string variable
3144  * @param str string
3145  * @return escaped string
3146  */
3147  inline static const string escapeString(const string& str) {
3148  //
3149  auto result = str;
3150  const array<char, 11> escapeSequences = {'0', 'a', 'b', 'f', 'n', 'r', 't', 'v', 'U', '"'};
3151  for (const auto c: escapeSequences) {
3152  result = _StringTools::replace(result, string("\\") + c, string("\\\\") + c);
3153  }
3154  //
3155  result = _StringTools::replace(result, "\0", "\\0");
3156  result = _StringTools::replace(result, "\a", "\\a");
3157  result = _StringTools::replace(result, "\b", "\\b");
3158  result = _StringTools::replace(result, "\f", "\\f");
3159  result = _StringTools::replace(result, "\n", "\\n");
3160  result = _StringTools::replace(result, "\r", "\\r");
3161  result = _StringTools::replace(result, "\t", "\\t");
3162  result = _StringTools::replace(result, "\v", "\\v");
3163  result = _StringTools::replace(result, "\"", "\\\"");
3164  //
3165  string result2;
3166  auto lc = '\0';
3167  auto llc = '\0';
3168  for (auto i = 0; i < result.size(); i++) {
3169  //
3170  auto c = result[i];
3171  auto nc = i < result.size() - 1?result[i + 1]:'\0';
3172  if (c == '\\' && lc != '\\' && nc != '\\' && find(escapeSequences.begin(), escapeSequences.end(), nc) == escapeSequences.end()) {
3173  result2+= "\\\\";
3174  } else {
3175  result2+= c;
3176  }
3177  //
3178  auto lc = c;
3179  auto llc = lc;
3180  }
3181  //
3182  return result2;
3183  }
3184 
3185  /**
3186  * Decode operator
3187  * @param arguments arguments
3188  * @param operatorValueIdx operator value index
3189  * @param defaultOperatorString default operator string
3190  * @return operator string
3191  */
3192  static const string decodeOperator(const span<MinitScript::Variable>& arguments, int operatorValueIdx, const string& defaultOperatorString) {
3193  //
3194  int64_t operatorValue;
3195  if (MinitScript::getIntegerValue(arguments, operatorValueIdx, operatorValue) == false) return defaultOperatorString;
3196  //
3197  string result;
3198  auto c1 = (operatorValue & 255);
3199  auto c2 = ((operatorValue >> 8) & 255);
3200  if (c1 != 0ll) result+= (char)c1;
3201  if (c2 != 0ll) result+= (char)c2;
3202  //
3203  return result;
3204  }
3205 
3206  /**
3207  * @return if script has emitted a condition like error
3208  */
3209  inline bool hasEmitted() {
3210  return emitted;
3211  }
3212 
3213  /**
3214  * Initialize native mini script
3215  */
3216  virtual void initializeNative();
3217 
3218  /**
3219  * Set native
3220  * @param native native
3221  */
3222  inline void setNative(bool native) {
3223  this->native = native;
3224  }
3225 
3226  /**
3227  * Set native hash
3228  * @param nativeHash native hash
3229  */
3230  inline void setNativeHash(const string& nativeHash) {
3231  this->nativeHash = nativeHash;
3232  }
3233 
3234  /**
3235  * Go to statement
3236  * @param statement statement
3237  */
3238  inline void gotoStatement(const Statement& statement) {
3241  }
3242 
3243  /**
3244  * Go to statement goto from given statement
3245  * @param statement statement
3246  */
3247  inline void gotoStatementGoto(const Statement& statement) {
3250  }
3251 
3252  /**
3253  * @return native script
3254  */
3255  inline vector<Script> getNativeScripts() {
3256  return nativeScripts;
3257  }
3258 
3259  /**
3260  * Set native scripts
3261  * @param nativeScripts native scripts
3262  */
3263  inline void setNativeScripts(const vector<Script>& nativeScripts) {
3264  this->nativeScripts = nativeScripts;
3265  }
3266 
3267  /**
3268  * Set native functions
3269  * @param nativeFunctions native functions
3270  */
3271  inline void setNativeFunctions(const unordered_map<string, int>& nativeFunctions) {
3272  this->functions = nativeFunctions;
3273  }
3274 
3275  /**
3276  * Execute state machine
3277  */
3278  void executeStateMachine();
3279 
3280  /**
3281  * Dump script state
3282  * @param scriptState script state
3283  * @param message message
3284  */
3285  void dumpScriptState(ScriptState& scriptState, const string& message = string());
3286 
3287  /**
3288  * Push a new script state
3289  */
3290  inline void pushScriptState() {
3291  scriptStateStack.push_back(make_unique<ScriptState>());
3292  }
3293 
3294  /**
3295  * Pop script state
3296  */
3297  inline void popScriptState() {
3298  if (scriptStateStack.empty() == true) return;
3299  auto& scriptState = getScriptState();
3300  // we need to delete references first
3301  unordered_set<string> deletedVariables;
3302  for (const auto& [variableName, variable]: scriptState.variables) {
3303  if (variable->isReference() == false) continue;
3304  deletedVariables.insert(variableName);
3305  delete variable;
3306  }
3307  // next ordinary variables
3308  for (const auto& [variableName, variable]: scriptState.variables) {
3309  if (deletedVariables.contains(variableName) == true) continue;
3310  delete variable;
3311  }
3312  scriptState.variables.clear();
3313  scriptStateStack.erase(scriptStateStack.begin() + scriptStateStack.size() - 1);
3314  }
3315 
3316  /**
3317  * @return is function/stacklet running
3318  */
3319  inline bool isFunctionRunning() {
3320  // function?
3321  if (scriptStateStack.size() > 1) return true;
3322  // stacklet?
3323  for (const auto& block: getRootScriptState().blockStack) {
3324  if (block.type == ScriptState::Block::TYPE_STACKLET) return true;
3325  }
3326  // nope
3327  return false;
3328  }
3329 
3330  /**
3331  * Reset script execution state
3332  * @param scriptIdx script index
3333  * @param stateMachineState state machine state
3334  */
3335  inline void resetScriptExecutationState(int scriptIdx, StateMachineStateId stateMachineState) {
3336  auto& scriptState = getScriptState();
3337  if (isFunctionRunning() == false) enabledNamedConditions.clear();
3338  scriptState.forTimeStarted.clear();
3339  scriptState.blockStack.clear();
3340  if (scriptIdx != SCRIPTIDX_NONE) {
3341  scriptState.blockStack.emplace_back(
3342  scripts[scriptIdx].type == Script::TYPE_FUNCTION?
3345  false,
3346  nullptr,
3347  nullptr,
3348  Variable()
3349  );
3350  } else {
3351  scriptState.blockStack.emplace_back(
3353  false,
3354  nullptr,
3355  nullptr,
3356  Variable()
3357  );
3358  }
3359  scriptState.scriptIdx = scriptIdx;
3360  scriptState.statementIdx = STATEMENTIDX_FIRST;
3361  scriptState.gotoStatementIdx = STATEMENTIDX_NONE;
3362  scriptState.timeWaitStarted = _Time::getCurrentMillis();
3363  scriptState.timeWaitTime = 0LL;
3364  scriptState.returnValue.setNullValue();
3365  setScriptStateState(stateMachineState);
3366  }
3367 
3368  /**
3369  * Reset stacklet script execution state
3370  * @param scriptIdx script index
3371  * @param stateMachineState state machine state
3372  */
3373  inline void resetStackletScriptExecutationState(int scriptIdx, StateMachineStateId stateMachineState) {
3374  auto& scriptState = getScriptState();
3375  scriptState.blockStack.emplace_back(
3377  false,
3378  nullptr,
3379  nullptr,
3380  Variable()
3381  );
3382  scriptState.scriptIdx = scriptIdx;
3383  scriptState.statementIdx = STATEMENTIDX_FIRST;
3384  scriptState.gotoStatementIdx = STATEMENTIDX_NONE;
3385  scriptState.returnValue.setNullValue();
3386  setScriptStateState(stateMachineState);
3387  }
3388 
3389  /**
3390  * Set running flag to false
3391  */
3392  inline void stopRunning() {
3393  getScriptState().running = false;
3394  }
3395 
3396  /**
3397  * Stop script execution
3398  */
3399  inline void stopScriptExecution() {
3400  while (scriptStateStack.size() > 1) popScriptState();
3401  //
3403  //
3404  auto& scriptState = getScriptState();
3405  //
3406  scriptState.running = false;
3407  //
3410  }
3411 
3412  /**
3413  * Set script state machine state
3414  * @param state state
3415  */
3416  inline void setScriptStateState(int state) {
3417  auto& scriptState = getScriptState();
3418  scriptState.state = state;
3419  scriptState.lastState = STATE_NONE;
3420  scriptState.lastStateMachineState = nullptr;
3421  }
3422 
3423  /**
3424  * Determine script index to start
3425  * @return script index or SCRIPTIDX_NONE if no script to start
3426  */
3427  virtual int determineScriptIdxToStart();
3428 
3429  /**
3430  * Determine named script index to start
3431  * @return script index or SCRIPTIDX_NONE if no script to start
3432  */
3433  virtual int determineNamedScriptIdxToStart();
3434 
3435  /***
3436  * Create lamda function for given variable
3437  * @param variable variable
3438  * @param arguments arguments
3439  * @param functionScriptCode function script code
3440  * @param lineIdx start line index of lamda function
3441  * @param populateThis populate this variable, which applies to lamda member function of maps/objects
3442  * @param statement statement
3443  * @param nameHint name hint
3444  */
3445  void createLamdaFunction(Variable& variable, const vector<string_view>& arguments, const string_view& functionScriptCode, int lineIdx, bool populateThis, const Statement& statement, const string& nameHint = string());
3446 
3447  /***
3448  * Create stacklet for given variable
3449  * @param variable variable
3450  * @param scopeName scope name
3451  * @param arguments arguments
3452  * @param stackletScriptCode stacklet script code
3453  * @param lineIdx start line index of lamda function
3454  * @param statement statement
3455  */
3456  void createStacklet(Variable& variable, const string& scopeName, const vector<string_view>& arguments, const string_view& stackletScriptCode, int lineIdx, const Statement& statement);
3457 
3458  /**
3459  * Initialize array by initializer string
3460  * @param initializerString initializer string
3461  * @param minitScript mini script
3462  * @param scriptIdx script index
3463  * @param statement statement
3464  * @return initialized variable
3465  */
3466  static const Variable initializeArray(const string_view& initializerString, MinitScript* minitScript, int scriptIdx, const Statement& statement);
3467 
3468  /**
3469  * Initialize map/set by initializer string
3470  * @param initializerString initializer string
3471  * @param minitScript mini script
3472  * @param scriptIdx script index
3473  * @param statement statement
3474  * @return initialized variable
3475  */
3476  static const Variable initializeMapSet(const string_view& initializerString, MinitScript* minitScript, int scriptIdx, const Statement& statement);
3477 
3478  /**
3479  * Try garbage collection
3480  */
3481  inline void tryGarbageCollection() {
3482  auto now = _Time::getCurrentMillis();
3485  dataTypesGCTime = now;
3486  }
3487  }
3488 
3489  /**
3490  * Issue garbage collection
3491  */
3492  void garbageCollection();
3493 
3494 private:
3495  static constexpr bool VERBOSE { false };
3496  static constexpr bool VALIDATION { false };
3497  static constexpr int64_t GARBAGE_COLLECTION_INTERVAL { 1000ll };
3498 
3499  /**
3500  * Shutdown RAII
3501  */
3503  public:
3504  /**
3505  * Constructor
3506  * @param dataTypes data types
3507  */
3508  inline ShutdownRAII(vector<DataType*>& dataTypes): dataTypes(dataTypes) {}
3509 
3510  /**
3511  * Destructor
3512  */
3513  inline ~ShutdownRAII() {
3514  for (const auto dataType: dataTypes) delete dataType;
3515  dataTypes.clear();
3516  }
3517  private:
3518  vector<DataType*>& dataTypes;
3519  };
3520 
3521  //
3523  MINITSCRIPT_STATIC_DLL_IMPEXT static vector<DataType*> dataTypes;
3525 
3526  //
3527  int64_t dataTypesGCTime { -1ll };
3528 
3529  // TODO: maybe we need a better naming for this
3530  // functions/stacklets/callables defined by script itself
3531  unordered_map<string, int> functions;
3532  // registered methods
3533  unordered_map<string, Method*> methods;
3534  // registered state machine states
3535  unordered_map<int, StateMachineState*> stateMachineStates;
3536  // operators
3537  unordered_map<uint8_t, Method*> operators;
3538  //
3541  //
3542  bool scriptValid { false };
3543 
3544  /**
3545  * Garbage collection data type
3546  */
3548  /**
3549  * Constructor
3550  * @param dataType data type
3551  * @param context script context
3552  */
3554  DataType* dataType,
3556  dataType(dataType),
3557  context(context) {
3558  //
3559  }
3560  //
3563  };
3564 
3565  //
3566  vector<GarbageCollectionDataType> garbageCollectionDataTypes;
3567  unordered_map<VariableType, DataType::ScriptContext*> garbageCollectionScriptContextsByDataType;
3569 
3570  /**
3571  * Parser argument
3572  */
3574  /**
3575  * Constructor
3576  * @param argument argument
3577  * @param subLineIdx sub line index
3578  */
3580  const string_view& argument,
3581  int subLineIdx
3582  ):
3583  argument(argument),
3585  {}
3586  //
3587  string_view argument;
3589  };
3590 
3591  /**
3592  * Parse script code into this MinitScript instance
3593  * @param scriptCode script code
3594  * @param lineIdxOffset line index offset
3595  * @return success
3596  */
3597  bool parseScriptInternal(const string& scriptCode, int lineIdxOffset = 0);
3598 
3599 
3600  /**
3601  * Execute next statement
3602  */
3603  void executeNextStatement();
3604 
3605  /**
3606  * Get next statement from script code
3607  * @param scriptCode script code
3608  * @param i character index
3609  * @param line line
3610  * @param statement statement
3611  * @return success
3612  */
3613  bool getNextStatement(const string& scriptCode, int& i, int& line, string& statement);
3614 
3615  /**
3616  * Parse a statement
3617  * @param executableStatement executable statement
3618  * @param methodName method name
3619  * @param arguments arguments
3620  * @param statement statment
3621  * @param accessObjectMember generated access object member statement
3622  * @return success
3623  */
3624  bool parseStatement(const string_view& executableStatement, string_view& methodName, vector<ParserArgument>& arguments, const Statement& statement, string& accessObjectMemberStatement);
3625 
3626  /**
3627  * Execute a statement
3628  * @param syntaxTree syntax tree
3629  * @param statement statement
3630  * @return return value as variable
3631  */
3632  Variable executeStatement(const SyntaxTreeNode& syntaxTree, const Statement& statement);
3633 
3634  /**
3635  * Create statement syntax tree
3636  * @param scriptIdx script index
3637  * @param methodName method name
3638  * @param arguments arguments
3639  * @param statement statement
3640  * @param syntaxTree syntax tree
3641  * @param subLineIdx sub line index
3642  * @return success
3643  */
3644  bool createStatementSyntaxTree(int scriptIdx, const string_view& methodName, const vector<ParserArgument>& arguments, const Statement& statement, SyntaxTreeNode& syntaxTree, int subLineIdx = 0);
3645 
3646  /**
3647  * Setup function and stacket script indices
3648  * @param scriptIdx script index
3649  */
3650  bool setupFunctionAndStackletScriptIndices(int scriptIdx);
3651 
3652  /**
3653  * Setup function and stacket script indices
3654  * @param syntaxTreeNode syntax tree node
3655  * @param statement statement
3656  */
3657  bool setupFunctionAndStackletScriptIndices(SyntaxTreeNode& syntaxTreeNode, const Statement& statement);
3658 
3659  /**
3660  * Setup function and stacket script indices
3661  * @param variable variable
3662  * @param statement statement
3663  * @param subLineIdx sub line index
3664  * @return success
3665  */
3666  bool setupFunctionAndStackletScriptIndices(Variable& variable, const Statement& statement, int subLineIdx);
3667 
3668  /**
3669  * Return stacklet scope script index
3670  * @param scriptIdx stacklet script index
3671  * @return stacklet scope script index
3672  */
3673  int getStackletScopeScriptIdx(int scriptIdx);
3674 
3675  /**
3676  * Validate stacklets
3677  * @param scriptIdx script index
3678  * @return success
3679  */
3680  bool validateStacklets(int scriptIdx);
3681 
3682  /**
3683  * Validate stacklets
3684  * @param function function
3685  * @param scopeScriptIdx scope script index or MinitScript::SCRIPTIDX_NONE for the function itself
3686  * @return success
3687  */
3688  bool validateStacklets(const string& function, int scopeScriptIdx = MinitScript::SCRIPTIDX_NONE);
3689 
3690  /**
3691  * Validate stacklets
3692  * @param scopeScriptIdx scope script index
3693  * @param syntaxTreeNode syntax tree node
3694  * @param statement statement
3695  * @return success
3696  */
3697  bool validateStacklets(int scopeScriptIdx, const SyntaxTreeNode& syntaxTreeNode, const Statement& statement);
3698 
3699  /**
3700  * Validate callabe
3701  * @param function function
3702  * @return success
3703  */
3704  bool validateCallable(const string& function);
3705 
3706  /**
3707  * Validate callable
3708  * @param syntaxTreeNode syntax tree node
3709  * @param statement statement
3710  * @return success
3711  */
3712  bool validateCallable(const SyntaxTreeNode& syntaxTreeNode, const Statement& statement);
3713 
3714  /**
3715  * Validate context functions
3716  * @param function function
3717  * @param functionStack function stack
3718  * @return success
3719  */
3720  bool validateContextFunctions(const string& function, vector<string>& functionStack);
3721 
3722  /**
3723  * Validate context functions
3724  * @param syntaxTreeNode syntax tree node
3725  * @param functionStack function stack
3726  * @param statement statement
3727  * @return success
3728  */
3729  bool validateContextFunctions(const SyntaxTreeNode& syntaxTreeNode, vector<string>& functionStack, const Statement& statement);
3730 
3731  /**
3732  * Returns if char is operator char
3733  * @param c char to test
3734  * @return if char is operator char
3735  */
3736  static inline const bool isOperatorChar(char c) {
3737  return OPERATOR_CHARS.find(c) != string::npos;
3738  }
3739 
3740  /**
3741  * Do statement pre processing, 1) replace operators with corresponding methods
3742  * @param processedStatement statement that is currently being processed
3743  * @param statement statement
3744  */
3745  const string doStatementPreProcessing(const string& processedStatement, const Statement& statement);
3746 
3747  /**
3748  * Returns if statement has a object member access
3749  * @param executableStatement executable statement
3750  * @param object object
3751  * @param method method
3752  * @param methodStartIdx method start index
3753  * @param statement statement
3754  * @return statement has a object member access
3755  */
3756  bool getObjectMemberAccess(const string_view& executableStatement, string_view& object, string_view& method, int& methodStartIdx, const Statement& statement);
3757 
3758  /**
3759  * Get access operator left and right indices
3760  * @param variableStatement variable statement
3761  * @param callerMethod caller method
3762  * @param accessOperatorLeftIdx access operator left idx
3763  * @param accessOperatorRightIdx access operator right idx
3764  * @param subStatement sub statement
3765  * @param startIdx startIdx
3766  */
3767  bool getVariableAccessOperatorLeftRightIndices(const string& variableStatement, const string& callerMethod, string::size_type& accessOperatorLeftIdx, string::size_type& accessOperatorRightIdx, const SubStatement* subStatement = nullptr, int startIdx = 0);
3768 
3769  /**
3770  * Evaluate access
3771  * @param variableStatement variable statement
3772  * @param callerMethod caller method
3773  * @param arrayAccessOperatorLeftIdx array access operator left idx
3774  * @param arrayAccessOperatorRightIdx array access operator right idx
3775  * @param arrayIdx array index
3776  * @param key map key
3777  * @param subStatement sub statement
3778  */
3779  bool evaluateAccess(const string& variableStatement, const string& callerMethod, string::size_type& arrayAccessOperatorLeftIdx, string::size_type& arrayAccessOperatorRightIdx, int64_t& arrayIdx, string& key, const SubStatement* subStatement = nullptr);
3780 
3781  /**
3782  * Returns pointer of variable with given name or nullptr
3783  * @param variablePtr pointer to variable
3784  * @param variableStatement variable statement
3785  * @param callerMethod caller method
3786  * @param parentVariable parent variable
3787  * @param arrayIdx array index whereas there is ARRAYIDX_ADD for [] or ARRAYIDX_NONE for no array access
3788  * @param key key
3789  * @param setAccessBool set access bool which returns one of SETACCESSBOOL_NONE, *_TRUE, *_FALSE
3790  * @param subStatement optional sub statement the variable is read in
3791  * @param expectVariable expect variable which controls verbosity
3792  * @return pointer to variable
3793  */
3794  Variable* evaluateVariableAccessIntern(Variable* variablePtr, const string& variableStatement, const string& callerMethod, Variable*& parentVariable, int64_t& arrayIdx, string& key, int& setAccessBool, const SubStatement* subStatement = nullptr, bool expectVariable = true);
3795 
3796  /**
3797  * Returns pointer of variable with given name or nullptr
3798  * @param variableStatement variable statement
3799  * @param callerMethod caller method
3800  * @param variableName variable name
3801  * @param parentVariable parent variable
3802  * @param arrayIdx array index whereas there is ARRAYIDX_ADD for [] or ARRAYIDX_NONE for no array access
3803  * @param key key
3804  * @param setAccessBool set access bool which returns one of SETACCESSBOOL_NONE, *_TRUE, *_FALSE
3805  * @param subStatement optional sub statement the variable is read in
3806  * @param expectVariable expect variable which controls verbosity
3807  * @param global use global context instead of current context
3808  * @return pointer to variable
3809  */
3810  inline Variable* getVariableIntern(const string& variableStatement, const string& callerMethod, string& variableName, Variable*& parentVariable, int64_t& arrayIdx, string& key, int& setAccessBool, const SubStatement* subStatement = nullptr, bool expectVariable = true, bool global = false) {
3811  // determine variable name
3812  {
3813  auto dotIdx = string::npos;
3814  auto squareBracketIdx = string::npos;
3815  auto lc = '\0';
3816  for (auto i = 0; i < variableStatement.size(); i++) {
3817  auto c = variableStatement[i];
3818  if (c == '.') {
3819  if (dotIdx == string::npos) dotIdx = i;
3820  } else
3821  if (c == '[') {
3822  if (squareBracketIdx == string::npos) squareBracketIdx = i;
3823  } else
3824  if (lc == ':' && c == ':') {
3825  dotIdx = string::npos;
3826  squareBracketIdx = string::npos;
3827  }
3828  //
3829  lc = c;
3830  }
3831  if (dotIdx == string::npos) dotIdx = variableStatement.size();
3832  if (squareBracketIdx == string::npos) squareBracketIdx = variableStatement.size();
3833  variableName = _StringTools::substring(
3834  variableStatement,
3835  0,
3836  dotIdx < squareBracketIdx?
3837  dotIdx:
3838  squareBracketIdx
3839  );
3840  }
3841  // retrieve variable from script state
3842  Variable* variablePtr = nullptr;
3843  const auto& scriptState = global == false?getScriptState():getRootScriptState();
3844  auto variableIt = scriptState.variables.find(variableName);
3845  if (variableIt == scriptState.variables.end()) {
3846  if (expectVariable == true) {
3847  _Console::printLine((subStatement != nullptr?getSubStatementInformation(*subStatement):scriptFileName) + ": Variable: " + variableStatement + " does not exist");
3848  }
3849  return nullptr;
3850  } else {
3851  variablePtr = variableIt->second;
3852  }
3853  //
3854  return evaluateVariableAccessIntern(variablePtr, variableStatement, callerMethod, parentVariable, arrayIdx, key, setAccessBool, subStatement, expectVariable);
3855  }
3856 
3857  /**
3858  * Set variable internal
3859  * @param variableStatement variable statement
3860  * @param parentVariable parent variable
3861  * @param variablePtr variable pointer
3862  * @param arrayIdx array index
3863  * @param key key
3864  * @param variable variable
3865  * @param subStatement optional sub statement the variable is written in
3866  * @param createReference optional flag for creating variable references
3867  */
3868  void setVariableInternal(const string& variableStatement, Variable* parentVariable, Variable* variablePtr, int64_t arrayIdx, const string& key, const Variable& variable, const SubStatement* subStatement = nullptr, bool createReference = false);
3869 
3870  /**
3871  * Evaluate given statement without executing preprocessor run
3872  * @param statement statement
3873  * @param executableStatement executable statement
3874  * @param returnValue return value
3875  * @param pushScriptState push script state
3876  * @return success
3877  */
3878  bool evaluateInternal(const string& statement, const string& executableStatement, Variable& returnValue, bool pushScriptState = true);
3879 
3880  /**
3881  * Call function
3882  * @param scriptIdx script index
3883  * @param arguments argument values
3884  * @param returnValue return value
3885  * @param pushScriptState push script state
3886  * @return success
3887  */
3888  bool call(int scriptIdx, span<Variable>& arguments, Variable& returnValue, bool pushScriptState);
3889 
3890  /**
3891  * Call function
3892  * @param function function
3893  * @param arguments argument values
3894  * @param returnValue return value
3895  * @param pushScriptState push script state
3896  * @return success
3897  */
3898  inline bool call(const string& function, span<Variable>& arguments, Variable& returnValue, bool pushScriptState) {
3899  // lookup function
3900  auto functionIt = functions.find(function);
3901  if (functionIt == functions.end()) {
3902  return false;
3903  }
3904  //
3905  auto scriptIdx = functionIt->second;
3906  // call it
3907  return call(scriptIdx, arguments, returnValue, pushScriptState);
3908  }
3909 
3910  /**
3911  * Initialize variable
3912  * @param variable variable
3913  * @return initialized variable
3914  */
3915  const Variable initializeVariable(const Variable& variable);
3916 
3917  /**
3918  * Deescape string
3919  * @param str string
3920  * @param statement statement
3921  * @return deescaped string
3922  */
3923  inline const string deescape(const string_view& str, const Statement& statement) {
3924  string deescapedStr;
3925  auto lc = '\0';
3926  for (auto i = 0; i < str.size(); i++) {
3927  auto c = str[i];
3928  if (c != '\\' || lc == '\\') {
3929  // escape sequences
3930  // see: https://en.cppreference.com/w/cpp/language/escape
3931  // \0 null character
3932  if (lc == '\\' && c == '0') deescapedStr+= '\0'; else
3933  // \a audible bell
3934  if (lc == '\\' && c == 'a') deescapedStr+= '\a'; else
3935  // \b backspace
3936  if (lc == '\\' && c == 'b') deescapedStr+= '\b'; else
3937  // \f form feed - new page
3938  if (lc == '\\' && c == 'f') deescapedStr+= '\f'; else
3939  // \n line feed - new line
3940  if (lc == '\\' && c == 'n') deescapedStr+= '\n'; else
3941  // \r carriage return
3942  if (lc == '\\' && c == 'r') deescapedStr+= '\r'; else
3943  // \t horizontal tab
3944  if (lc == '\\' && c == 't') deescapedStr+= '\t'; else
3945  // \v vertical tab
3946  if (lc == '\\' && c == 'v') deescapedStr+= '\v'; else
3947  // unicode \Unnnnnnnn
3948  if (lc == '\\' && c == 'U') {
3949  string unicodeHexadecimalSequence;
3950  auto j = 0;
3951  auto valid = true;
3952  for (i++; i < str.size() && j < 8; i++ && j++) {
3953  c = str[i];
3954  unicodeHexadecimalSequence+= c;
3955  if (((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) == false) break;
3956  }
3957  i--;
3958  if (valid == false || j != 8) {
3959  _Console::printLine(getStatementInformation(statement) + ": Invalid hexadecimal unicode character sequence: " + unicodeHexadecimalSequence);
3960  } else {
3961  _Character::appendToString(deescapedStr, _Hex::decodeInt(unicodeHexadecimalSequence));
3962  }
3963  } else
3964  deescapedStr+= c;
3965  //
3966  lc = '\0';
3967  continue;
3968  }
3969  lc = c;
3970  }
3971  return deescapedStr;
3972  }
3973 
3974  /**
3975  * Returns if a given string is a lambda function
3976  * @param candidate candidate
3977  * @param arguments arguments
3978  * @param functionScriptCode function script code
3979  * @param lineIdx start line index
3980  * @return if candidate is a lambda function
3981  */
3982  inline static bool viewIsLamdaFunction(const string_view& candidate, vector<string_view>& arguments, string_view& functionScriptCode, int& lineIdx) {
3983  if (candidate.size() == 0) return false;
3984  //
3985  auto i = 0;
3986  // (
3987  if (candidate[i++] != '(') return false;
3988  // spaces
3989  for (; i < candidate.size() && _Character::isSpace(candidate[i]) == true; i++);
3990  if (i >= candidate.size()) return false;
3991  //
3992  auto argumentStartIdx = string::npos;
3993  auto argumentEndIdx = string::npos;
3994  //
3995  for (; i < candidate.size(); i++) {
3996  auto c = candidate[i];
3997  if (c == '&') {
3998  if (argumentStartIdx == string::npos) {
3999  argumentStartIdx = i;
4000  } else {
4001  return false;
4002  }
4003  } else
4004  if (c == '$') {
4005  if (argumentStartIdx == string::npos) {
4006  argumentStartIdx = i;
4007  } else
4008  if (argumentStartIdx == i - 1 && candidate[argumentStartIdx] == '&') {
4009  // no op
4010  } else {
4011  return false;
4012  }
4013  } else
4014  if (c == ',' || c == ')') {
4015  if (argumentEndIdx == string::npos) {
4016  if (argumentStartIdx != string::npos) {
4017  argumentEndIdx = i;
4018  arguments.push_back(string_view(&candidate[argumentStartIdx], argumentEndIdx - argumentStartIdx));
4019  }
4020  //
4021  argumentStartIdx = string::npos;
4022  argumentEndIdx = string::npos;
4023  } else {
4024  return false;
4025  }
4026  if (c == ')') {
4027  i++;
4028  break;
4029  }
4030  } else
4031  if (argumentStartIdx != string::npos && _Character::isAlphaNumeric(candidate[i]) == false && c != '_') {
4032  return false;
4033  }
4034  }
4035  //
4036  if (i >= candidate.size()) return false;
4037  // spaces
4038  for (; i < candidate.size() && _Character::isSpace(candidate[i]) == true; i++);
4039  if (i >= candidate.size()) return false;
4040  // -
4041  if (candidate[i++] != '-') return false;
4042  //
4043  if (i >= candidate.size()) return false;
4044  // >
4045  if (candidate[i++] != '>') return false;
4046  // spaces
4047  for (; i < candidate.size() && _Character::isSpace(candidate[i]) == true; i++);
4048  if (i >= candidate.size()) return false;
4049  //
4050  if (candidate[i++] != '{') return false;
4051  //
4052  for (auto j = 0; j < i - 1; j++) {
4053  if (candidate[j] == '\n') lineIdx++;
4054  }
4055  //
4056  auto scriptCodeStartIdx = i;
4057  auto scriptCodeEndIdx = string::npos;
4058  //
4059  for (auto j = candidate.size() - 1; j > i; j--) {
4060  if (candidate[j] == '}') {
4061  scriptCodeEndIdx = j;
4062  break;
4063  } else
4064  if (_Character::isSpace(candidate[j]) == false) {
4065  return false;
4066  }
4067  }
4068  //
4069  if (scriptCodeEndIdx == string::npos) return false;
4070  //
4071  functionScriptCode = string_view(&candidate[scriptCodeStartIdx], scriptCodeEndIdx - scriptCodeStartIdx);
4072  //
4073  return true;
4074  }
4075 
4076  /**
4077  * Returns if a given string is a stacklet
4078  * @param candidate candidate
4079  * @param arguments arguments
4080  * @param stackletScriptCode stacklet script code
4081  * @param lineIdx start line index
4082  * @return if candidate is a stacklet function
4083  */
4084  inline static bool viewIsStacklet(const string_view& candidate, vector<string_view>& arguments, string_view& stackletScriptCode, int& lineIdx) {
4085  if (candidate.size() == 0) return false;
4086  //
4087  auto i = 0;
4088  // spaces
4089  for (; i < candidate.size() && _Character::isSpace(candidate[i]) == true; i++);
4090  if (i >= candidate.size()) return false;
4091  // -
4092  if (candidate[i++] != '-') return false;
4093  //
4094  if (i >= candidate.size()) return false;
4095  // >
4096  if (candidate[i++] != '>') return false;
4097  // spaces
4098  for (; i < candidate.size() && _Character::isSpace(candidate[i]) == true; i++);
4099  if (i >= candidate.size()) return false;
4100  //
4101  if (candidate[i++] != '{') return false;
4102  //
4103  for (auto j = 0; j < i - 1; j++) {
4104  if (candidate[j] == '\n') lineIdx++;
4105  }
4106  //
4107  auto scriptCodeStartIdx = i;
4108  auto scriptCodeEndIdx = string::npos;
4109  //
4110  for (auto j = candidate.size() - 1; j > i; j--) {
4111  if (candidate[j] == '}') {
4112  scriptCodeEndIdx = j;
4113  break;
4114  } else
4115  if (_Character::isSpace(candidate[j]) == false) {
4116  return false;
4117  }
4118  }
4119  //
4120  if (scriptCodeEndIdx == string::npos) return false;
4121  //
4122  stackletScriptCode = string_view(&candidate[scriptCodeStartIdx], scriptCodeEndIdx - scriptCodeStartIdx);
4123  //
4124  return true;
4125  }
4126 
4127  /**
4128  * Returns if a given string is a variable name
4129  * @param candidate candidate
4130  * @return if string is a variable name
4131  */
4132  inline static bool viewIsVariableAccess(const string_view& candidate) {
4133  if (candidate.size() < 2) return false;
4134  auto i = 0;
4135  if (candidate[i++] != '$') return false;
4136  if (candidate[i] == '$') i++;
4137  auto squareBracketCount = 0;
4138  for (; i < candidate.size(); i++) {
4139  auto c = candidate[i];
4140  if (c == '[') {
4141  squareBracketCount++;
4142  } else
4143  if (c == ']') {
4144  squareBracketCount--;
4145  } else
4146  if (squareBracketCount == 0 && _Character::isAlphaNumeric(c) == false && c != '_' && c != '.' && c != ':') {
4147  return false;
4148  }
4149  }
4150  return true;
4151  }
4152 
4153  /**
4154  * Returns if a given string is a valid map key name
4155  * @param candidate candidate
4156  * @return if string is a valid map key name
4157  */
4158  static bool viewIsKey(const string_view& candidate);
4159 
4160  /**
4161  * Returns if a given key candidate is marked as private by head '-'
4162  * @param candidate candidate
4163  * @return if key candidate is marked as private
4164  */
4165  static bool viewIsKeyPrivate(const string_view& candidate);
4166 
4167  /**
4168  * Returns private key
4169  * @param candidate candidate
4170  * @return private key
4171  */
4172  static const string_view viewGetPrivateKey(const string_view& candidate);
4173 
4174  /**
4175  * Returns if a given string is a string literal
4176  * @param candidate candidate
4177  * @return if string is a string literal
4178  */
4179  inline static bool viewIsStringLiteral(const string_view& candidate) {
4180  // we need a " or ' and a " or ' :DDD
4181  if (candidate.size() < 2) return false;
4182  auto i = 0;
4183  // check for head quote
4184  if (candidate[i] != '"' && candidate[i] != '\'') return false;
4185  // detect quote
4186  auto quote = candidate[i++];
4187  // check for tail quote
4188  if (candidate[candidate.size() - 1] != quote) return false;
4189  //
4190  auto lc = '\0';
4191  for (; i < candidate.size() - 1; i++) {
4192  auto c = candidate[i];
4193  if (c == quote && lc != '\\') return false;
4194  lc = c;
4195  }
4196  //
4197  return true;
4198  }
4199 
4200  /**
4201  * Dequote a string
4202  * @param str string
4203  * @return dequoted string
4204  */
4205  inline static string_view dequote(const string_view& str) {
4206  return _StringTools::viewSubstring(str, 1, str.size() - 1);
4207  }
4208 
4209  /**
4210  * Returns if a given string is a array/map/set initializer
4211  * @param candidate candidate
4212  * @return if string is a array/map/set initializer
4213  */
4214  inline static bool viewIsInitializer(const string_view& candidate) {
4215  return
4216  (_StringTools::viewStartsWith(candidate, "[") == true && _StringTools::viewEndsWith(candidate, "]") == true) ||
4217  (_StringTools::viewStartsWith(candidate, "{") == true && _StringTools::viewEndsWith(candidate, "}") == true);
4218 
4219  }
4220 
4221  /**
4222  * Returns if a given string is a method/function call
4223  * @param candidate candidate
4224  * @return if string is a method/function call
4225  */
4226  inline static bool viewIsCall(const string_view& candidate) {
4227  // TODO: improve me!
4228  auto leftBracketIdx = candidate.find('(');
4229  auto rightBracketIdx = candidate.rfind(')');
4230  return leftBracketIdx > 0 && rightBracketIdx > leftBracketIdx;
4231  }
4232 
4233  /**
4234  * Set variable recursively to be a constant
4235  * @param variable variable
4236  */
4237  static void setConstantInternal(Variable& variable);
4238 
4239  /**
4240  * Set variable recursively to be a non constant
4241  * @param variable variable
4242  */
4243  static void unsetConstantInternal(Variable& variable);
4244 
4245 public:
4246  /**
4247  * Initialize
4248  */
4249  static void initialize();
4250 
4251  /**
4252  * Set variable recursively to be a constant
4253  * @param variable variable
4254  */
4255  inline static void setConstant(Variable& variable) {
4256  if (variable.isConstant() == true) return;
4257  setConstantInternal(variable);
4258  }
4259 
4260  /**
4261  * Set variable recursively to be a non constant
4262  * @param variable variable
4263  */
4264  inline static void unsetConstant(Variable& variable) {
4265  if (variable.isConstant() == false) return;
4266  unsetConstantInternal(variable);
4267  }
4268 
4269  /**
4270  * Return data type script context
4271  * @param type data type
4272  * @return data type script context
4273  */
4275  auto garbageCollectionScriptContextsByDataTypeIt = garbageCollectionScriptContextsByDataType.find(type);
4276  if (garbageCollectionScriptContextsByDataTypeIt != garbageCollectionScriptContextsByDataType.end()) {
4277  return garbageCollectionScriptContextsByDataTypeIt->second;
4278  }
4279  return nullptr;
4280  }
4281 
4282  /**
4283  * @return context
4284  */
4285  inline _Context* getContext() {
4286  return context;
4287  }
4288 
4289  /**
4290  * Set context
4291  * @param context context
4292  */
4293  inline void setContext(_Context* context) {
4294  this->context = context;
4295  }
4296 
4297  /**
4298  * @return library
4299  */
4300  inline _Library* getLibrary() {
4301  return library;
4302  }
4303 
4304  /**
4305  * Set library
4306  * @param library library
4307  */
4308  inline void setLibrary(_Library* library) {
4309  this->library = library;
4310  }
4311 
4312  /**
4313  * Returns string representation of given argument indices
4314  * @param argumentIndices argument indices
4315  * @param delimiter delimiter
4316  * @return string representation of given argument indices
4317  */
4318  inline static const string getArgumentIndicesAsString(const vector<int>& argumentIndices, const string& delimiter) {
4319  string result;
4320  for (const auto argumentIdx: argumentIndices) {
4321  if (result.empty() == false) result+= delimiter;
4322  result+= to_string(argumentIdx);
4323  }
4324  return result;
4325  }
4326 
4327  /**
4328  * @return error message
4329  */
4330  const string& getErrorMessage() {
4331  return errorMessage;
4332  }
4333 
4334  /**
4335  * @return error sub statement
4336  */
4338  return errorSubStatement;
4339  }
4340 
4341  /**
4342  * Complain about method usage
4343  * @param methodName method mame
4344  * @param subStatement sub statement
4345  */
4346  void complain(const string& methodName, const SubStatement& subStatement);
4347 
4348  /**
4349  * Complain about method usage
4350  * @param methodName method mame
4351  * @param subStatement sub statement
4352  * @param message message
4353  */
4354  void complain(const string& methodName, const SubStatement& subStatement, const string& message);
4355 
4356  /**
4357  * Complain about operator usage
4358  * @param methodName method mame
4359  * @param operatorString operator string
4360  * @param subStatement sub statement
4361  */
4362  void complainOperator(const string& methodName, const string& operatorString, const SubStatement& subStatement);
4363 
4364  /**
4365  * Complain about operator usage
4366  * @param methodName method mame
4367  * @param operatorString operator string
4368  * @param subStatement sub statement
4369  * @param message message
4370  */
4371  void complainOperator(const string& methodName, const string& operatorString, const SubStatement& subStatement, const string& message);
4372 
4373  /**
4374  * @return data types
4375  */
4376  inline static const vector<DataType*>& getDataTypes() {
4377  return dataTypes;
4378  }
4379 
4380  /**
4381  * Returns data type by class name or nullptr
4382  * @param className class name
4383  * @return data type
4384  */
4385  inline static DataType* getDataTypeByClassName(const string& className) {
4386  for (const auto dataType: dataTypes) {
4387  if (dataType->getTypeAsString() == className) return dataType;
4388  }
4389  return nullptr;
4390  }
4391 
4392  /**
4393  * Register data type
4394  * @param dataType data type
4395  */
4396  static void registerDataType(DataType* dataType);
4397 
4398  // forbid class copy
4400 
4401  /**
4402  * Default constructor
4403  */
4404  MinitScript();
4405 
4406  /**
4407  * Destructor
4408  */
4409  virtual ~MinitScript();
4410 
4411  /**
4412  * @return base class header
4413  */
4414  virtual const string getBaseClassHeader();
4415 
4416  /**
4417  * @return base class
4418  */
4419  virtual const string getBaseClass();
4420 
4421  /**
4422  * @return transpilation units
4423  */
4424  virtual const vector<string> getTranspilationUnits();
4425 
4426  /**
4427  * @return parse errors
4428  */
4429  inline const vector<string>& getParseErrors() {
4430  return parseErrors;
4431  }
4432 
4433  /**
4434  * @return if this script is valid to be executed
4435  */
4436  inline bool isValid() {
4437  return scriptValid;
4438  }
4439 
4440  /**
4441  * @return if this script was compiled to C++ and is executed natively
4442  */
4443  inline bool isNative() {
4444  return native;
4445  }
4446 
4447  /**
4448  * @return native script hash
4449  */
4450  inline const string& getNativeHash() {
4451  return nativeHash;
4452  }
4453 
4454  /**
4455  * @return script path name
4456  */
4457  inline const string& getScriptPathName() {
4458  return scriptPathName;
4459  }
4460 
4461  /**
4462  * @return script file name
4463  */
4464  inline const string& getScriptFileName() {
4465  return scriptFileName;
4466  }
4467 
4468  /**
4469  * @return scripts
4470  */
4471  inline const vector<Script>& getScripts() {
4472  return scripts;
4473  }
4474 
4475  /**
4476  * @return root script state
4477  */
4479  return *(scriptStateStack[0].get());
4480  }
4481 
4482  /**
4483  * @return script state
4484  */
4486  return *(scriptStateStack[scriptStateStack.size() - 1].get());
4487  }
4488 
4489  /**
4490  * @return math methods
4491  */
4493  return minitScriptMath.get();
4494  }
4495 
4496  /**
4497  * Start error script
4498  */
4499  inline void startErrorScript() {
4500  emit("error");
4501  }
4502 
4503  /**
4504  * Returns if method with given name does exist
4505  * @param methodName method name
4506  * @return method exists
4507  */
4508  inline bool hasMethod(const string& methodName) {
4509  return methods.find(methodName) != methods.end();
4510  }
4511 
4512  /**
4513  * Returns if function with given name does exist
4514  * @param functionName function name
4515  * @return function exists
4516  */
4517  inline bool hasFunction(const string& functionName) {
4518  return functions.find(functionName) != functions.end();
4519  }
4520 
4521  /**
4522  * Register state machine states
4523  */
4524  virtual void registerStateMachineStates();
4525 
4526  /**
4527  * Register methods
4528  */
4529  virtual void registerMethods();
4530 
4531  /**
4532  * Register variables
4533  */
4534  virtual void registerVariables();
4535 
4536  /**
4537  * Get statement sub line index
4538  * @param statement statement
4539  * @param idx index
4540  * @return sub line index
4541  */
4542  inline int getStatementSubLineIdx(const string& statement, int idx) {
4543  auto subLineIdx = 0;
4544  for (auto i = 0; i < statement.size() && i <= idx; i++) {
4545  if (statement[i] == '\n') subLineIdx++;
4546  }
4547  return subLineIdx;
4548  }
4549 
4550  /**
4551  * Return statement information
4552  * @param statement statement
4553  * @param subLineIdx sub line index
4554  * @return statement information
4555  */
4556  inline const string getStatementInformation(const Statement& statement, int subLineIdx = -1) {
4557  //
4558  auto statementCode = statement.statement;
4559  auto statementLine = statement.line;
4560  if (subLineIdx != -1) {
4561  auto statementCodeLines = _StringTools::tokenize(statementCode, "\n", true);
4562  if (subLineIdx >= 0 && subLineIdx < statementCodeLines.size()) {
4563  statementCode = statementCodeLines[subLineIdx];
4564  statementLine+= subLineIdx;
4565  }
4566  }
4567  //
4568  return scriptFileName + ":" + to_string(statementLine) + ": " + statementCode;
4569  }
4570 
4571  /**
4572  * Return sub statement information
4573  * @param subStatement sub statement
4574  * @return sub statement information
4575  */
4576  inline const string getSubStatementInformation(const SubStatement& subStatement) {
4577  return getStatementInformation(*subStatement.statement, subStatement.subLineIdx);
4578  }
4579 
4580  /**
4581  * Get arguments information
4582  * @param methodName method name
4583  * @return arguments information
4584  */
4585  inline const string getArgumentsInformation(const string& methodName) {
4586  auto scriptMethod = getMethod(methodName);
4587  if (scriptMethod == nullptr) {
4588  _Console::printLine("MinitScript::getArgumentInformation(): method not found: " + methodName);
4589  return "No information available";
4590  }
4591  return scriptMethod->getArgumentsInformation();
4592  }
4593 
4594  /**
4595  * Get operator as string
4596  * @param operator_ operator
4597  * @return operator as string
4598  */
4599  inline static string getOperatorAsString(Operator operator_) {
4600  switch(operator_) {
4601  case(OPERATOR_NONE): return "NONE";
4602  case(OPERATOR_POSTFIX_INCREMENT): return "++";
4603  case(OPERATOR_POSTFIX_DECREMENT): return "--";
4604  case(OPERATOR_PREFIX_INCREMENT): return "++";
4605  case(OPERATOR_PREFIX_DECREMENT): return "--";
4606  case(OPERATOR_NOT): return "!";
4607  case(OPERATOR_BITWISENOT): return "~";
4608  case(OPERATOR_MULTIPLICATION): return "*";
4609  case(OPERATOR_DIVISION): return "/";
4610  case(OPERATOR_MODULO): return "%";
4611  case(OPERATOR_ADDITION): return "+";
4612  case(OPERATOR_SUBTRACTION): return "-";
4613  case(OPERATOR_LESSER): return "<";
4614  case(OPERATOR_LESSEREQUALS): return "<=";
4615  case(OPERATOR_GREATER): return ">";
4616  case(OPERATOR_GREATEREQUALS): return ">=";
4617  case(OPERATOR_EQUALS): return "==";
4618  case(OPERATOR_NOTEQUAL): return "!=";
4619  case(OPERATOR_BITWISEAND): return "&";
4620  case(OPERATOR_BITWISEXOR): return "^";
4621  case(OPERATOR_BITWISEOR): return "|";
4622  case(OPERATOR_AND): return "&&";
4623  case(OPERATOR_OR): return "||";
4624  case(OPERATOR_SET): return "=";
4625  case(OPERATOR_MAX): return "MAX";
4626  default: return "INVALID";
4627  }
4628  }
4629 
4630  /**
4631  * Is given candidate a operator string
4632  * @param candidate candidate
4633  * @return operator
4634  */
4635  inline static bool isOperator(const string& candidate) {
4636  for (int i = OPERATOR_NONE + 1; i < OPERATOR_MAX; i++) {
4637  if (candidate == getOperatorAsString(static_cast<Operator>(i))) return true;
4638  }
4639  return false;
4640  }
4641 
4642  /**
4643  * Check if arguments contain argument with given type
4644  * @param arguments arguments
4645  * @param type type
4646  * @return has type
4647  */
4648  inline static bool hasType(const span<Variable>& arguments, VariableType type) {
4649  for (const auto& argument: arguments) if (argument.getType() == type) return true;
4650  return false;
4651  }
4652 
4653  /**
4654  * Checks if left and right operator arguments have given type
4655  * @param arguments arguments
4656  * @param type type
4657  * @return has type
4658  */
4659  inline static bool hasTypeForOperatorArguments(const span<Variable>& arguments, VariableType type) {
4660  for (auto i = 0; i < arguments.size() - (arguments.size() == 3?1:0); i++) {
4661  if (arguments[i].getType() == type) return true;
4662  }
4663  return false;
4664  }
4665 
4666  /**
4667  * Get boolean value from given variable
4668  * @param arguments arguments
4669  * @param idx argument index
4670  * @param value value
4671  * @param optional optionalfalse
4672  * @return success
4673  */
4674  inline static bool getBooleanValue(const span<Variable>& arguments, int idx, bool& value, bool optional = false) {
4675  if (idx >= arguments.size()) return optional;
4676  const auto& argument = arguments[idx];
4677  return argument.getBooleanValue(value, optional);
4678  }
4679 
4680  /**
4681  * Get integer value from given variable
4682  * @param arguments arguments
4683  * @param idx argument index
4684  * @param value value
4685  * @param optional optional
4686  * @return success
4687  */
4688  inline static bool getIntegerValue(const span<Variable>& arguments, int idx, int64_t& value, bool optional = false) {
4689  if (idx >= arguments.size()) return optional;
4690  const auto& argument = arguments[idx];
4691  return argument.getIntegerValue(value, optional);
4692  }
4693 
4694  /**
4695  * Get float value from given variable
4696  * @param arguments arguments
4697  * @param idx argument index
4698  * @param value value
4699  * @param optional optional
4700  * @return success
4701  */
4702  inline static bool getFloatValue(const span<Variable>& arguments, int idx, float& value, bool optional = false) {
4703  if (idx >= arguments.size()) return optional;
4704  const auto& argument = arguments[idx];
4705  return argument.getFloatValue(value, optional);
4706  }
4707 
4708  /**
4709  * Get function value from given variable
4710  * @param arguments arguments
4711  * @param idx argument index
4712  * @param function function
4713  * @param scriptIdx script index
4714  * @param optional optional
4715  * @return success
4716  */
4717  inline static bool getFunctionValue(const span<Variable>& arguments, int idx, string& function, int& scriptIdx, bool optional = false) {
4718  if (idx >= arguments.size()) return optional;
4719  const auto& argument = arguments[idx];
4720  return argument.getFunctionValue(function, scriptIdx, optional);
4721  }
4722 
4723  /**
4724  * Get stacklet value from given variable
4725  * @param arguments arguments
4726  * @param idx argument index
4727  * @param stacklet stacklet
4728  * @param scriptIdx script index
4729  * @param optional optional
4730  * @return success
4731  */
4732  inline static bool getStackletValue(const span<Variable>& arguments, int idx, string& stacklet, int& scriptIdx, bool optional = false) {
4733  if (idx >= arguments.size()) return optional;
4734  const auto& argument = arguments[idx];
4735  return argument.getStackletValue(stacklet, scriptIdx, optional);
4736  }
4737 
4738  /**
4739  * Get string value from given variable
4740  * @param arguments arguments
4741  * @param idx argument index
4742  * @param value value
4743  * @param optional optional
4744  * @return success
4745  */
4746  inline static bool getStringValue(const span<Variable>& arguments, int idx, string& value, bool optional = false) {
4747  if (idx >= arguments.size()) return optional;
4748  const auto& argument = arguments[idx];
4749  return argument.getStringValue(value, optional);
4750  }
4751 
4752  /**
4753  * Register state machine state
4754  * @param state state
4755  */
4756  void registerStateMachineState(StateMachineState* state);
4757 
4758  /**
4759  * Register method
4760  * @param method method
4761  */
4762  void registerMethod(Method* method);
4763 
4764  /**
4765  * Returns if a given string is a variable name
4766  * @param candidate candidate
4767  * @param statement statement
4768  * @return if string is a variable name
4769  */
4770  inline bool isVariableAccess(const string& candidate, const SubStatement* subStatement = nullptr) {
4771  if (candidate.size() < 2) {
4772  _Console::printLine((subStatement != nullptr?getSubStatementInformation(*subStatement):scriptFileName) + ": Variable: " + candidate + ": empty variable statement");
4773  return false;
4774  }
4775  auto i = 0;
4776  if (candidate[i++] != '$') {
4777  _Console::printLine((subStatement != nullptr?getSubStatementInformation(*subStatement):scriptFileName) + ": Variable: " + candidate + ": variable statement must begin with an $");
4778  return false;
4779  }
4780  if (candidate[i] == '$') i++;
4781  //
4782  auto squareBracketCount = 0;
4783  for (; i < candidate.size(); i++) {
4784  auto c = candidate[i];
4785  if (c == '[') {
4786  squareBracketCount++;
4787  } else
4788  if (c == ']') {
4789  squareBracketCount--;
4790  } else
4791  if (squareBracketCount == 0 && _Character::isAlphaNumeric(c) == false && c != '_' && c != '.' && c != ':') {
4792  _Console::printLine((subStatement != nullptr?getSubStatementInformation(*subStatement):scriptFileName) + ": Variable: " + candidate + ": invalid character in variable statement: '" + c + "'");
4793  return false;
4794  }
4795  }
4796  if (candidate.size() == 2 && string_view(candidate) == string_view("$$", 2)) {
4797  _Console::printLine((subStatement != nullptr?getSubStatementInformation(*subStatement):scriptFileName) + ": Variable: " + candidate + ": variable statement must not be $$");
4798  return false;
4799  }
4800  if (candidate.size() == 7 && string_view(candidate) == string_view("$GLOBAL", 7)) {
4801  _Console::printLine((subStatement != nullptr?getSubStatementInformation(*subStatement):scriptFileName) + ": Variable: " + candidate + ": variable statement must not be $GLOBAL");
4802  return false;
4803  }
4804  return true;
4805  }
4806 
4807  /**
4808  * Returns if variable determined by given variable statement exists
4809  * @param variableStatement variable statement
4810  * @param subStatement optional sub statement the variable is read in
4811  * @return variable exists
4812  */
4813  inline bool hasVariable(const string& variableStatement, const SubStatement* subStatement = nullptr) {
4814  //
4815  string variableName;
4816  // global accessor
4817  string globalVariableStatement;
4818  if (_StringTools::viewStartsWith(string_view(variableStatement), string_view("$$.", 3)) == true) {
4819  globalVariableStatement = "$" + _StringTools::substring(variableStatement, 3);
4820  } else
4821  if (_StringTools::viewStartsWith(string_view(variableStatement), string_view("$GLOBAL.", 8)) == true) {
4822  globalVariableStatement = "$" + _StringTools::substring(variableStatement, 8);
4823  }
4824  //
4825  Variable* parentVariable = nullptr;
4826  string key;
4827  int64_t arrayIdx = ARRAYIDX_NONE;
4828  int setAccessBool = SETACCESSBOOL_NONE;
4829  auto variablePtr = getVariableIntern(globalVariableStatement.empty() == true?variableStatement:globalVariableStatement, __FUNCTION__, variableName, parentVariable, arrayIdx, key, setAccessBool, subStatement, false, globalVariableStatement.empty() == false);
4830  // set '.' operator
4831  if (setAccessBool != SETACCESSBOOL_NONE) {
4832  return true;
4833  } else
4834  // we have a pointer to a ordinary variable
4835  if (variablePtr != nullptr) {
4836  return true;
4837  }
4838  //
4839  return false;
4840  }
4841 
4842  /**
4843  * Returns variable determined by given variable statement optimized for method argument usage
4844  * @param variableStatement variable statement
4845  * @param subStatement optional sub statement the variable is read in
4846  * @return variable
4847  */
4848  inline const Variable getMethodArgumentVariable(const string& variableStatement, const SubStatement* subStatement = nullptr) {
4849  //
4850  if (isVariableAccess(variableStatement, subStatement) == false) return Variable();
4851  //
4852  string variableName;
4853  // global accessor
4854  string globalVariableStatement;
4855  if (_StringTools::viewStartsWith(string_view(variableStatement), string_view("$$.", 3)) == true) {
4856  globalVariableStatement = "$" + _StringTools::substring(variableStatement, 3);
4857  } else
4858  if (_StringTools::viewStartsWith(string_view(variableStatement), string_view("$GLOBAL.", 8)) == true) {
4859  globalVariableStatement = "$" + _StringTools::substring(variableStatement, 8);
4860  }
4861 
4862  //
4863  Variable* parentVariable = nullptr;
4864  string key;
4865  int64_t arrayIdx = ARRAYIDX_NONE;
4866  int setAccessBool = SETACCESSBOOL_NONE;
4867  auto variablePtr = getVariableIntern(globalVariableStatement.empty() == true?variableStatement:globalVariableStatement, __FUNCTION__, variableName, parentVariable, arrayIdx, key, setAccessBool, subStatement, true, globalVariableStatement.empty() == false);
4868  // set '.' operator
4869  if (setAccessBool != SETACCESSBOOL_NONE) {
4870  return Variable(setAccessBool == SETACCESSBOOL_TRUE);
4871  } else
4872  // we have a pointer to a ordinary variable
4873  if (variablePtr != nullptr) {
4874  // if we return any variable we can safely remove the constness, a reference can of course keep its constness
4875  auto variable = Variable::createMethodArgumentVariable(variablePtr);
4876  if (variable.isReference() == false) variable.unsetConstant();
4877  return variable;
4878  } else {
4879  // nothing to return
4880  return Variable();
4881  }
4882  }
4883 
4884  /**
4885  * Returns variable determined by given variable statement and variable pointer optimized for method argument usage
4886  * @param variablePtr variable pointer
4887  * @param variableStatement variable statement
4888  * @param subStatement optional sub statement the variable is read in
4889  * @return variable
4890  */
4891  inline const Variable getMethodArgumentVariable(Variable* variablePtr, const string& variableStatement, const SubStatement* subStatement = nullptr) {
4892  //
4893  if (isVariableAccess(variableStatement, subStatement) == false) return Variable();
4894  //
4895  Variable* parentVariable = nullptr;
4896  string key;
4897  int64_t arrayIdx = ARRAYIDX_NONE;
4898  int setAccessBool = SETACCESSBOOL_NONE;
4899  variablePtr = evaluateVariableAccessIntern(variablePtr, variableStatement, __FUNCTION__, parentVariable, arrayIdx, key, setAccessBool, subStatement, true);
4900  // set '.' operator
4901  if (setAccessBool != SETACCESSBOOL_NONE) {
4902  return Variable(setAccessBool == SETACCESSBOOL_TRUE);
4903  } else
4904  // we have a pointer to a ordinary variable
4905  if (variablePtr != nullptr) {
4906  // if we return any variable we can safely remove the constness, a reference can of course keep its constness
4907  auto variable = Variable::createMethodArgumentVariable(variablePtr);
4908  if (variable.isReference() == false) variable.unsetConstant();
4909  return variable;
4910  } else {
4911  // nothing to return
4912  return Variable();
4913  }
4914  }
4915 
4916  /**
4917  * Returns variable determined by given variable statement
4918  * @param variableStatement variable statement
4919  * @param subStatement optional sub statement the variable is read in
4920  * @param createReference optional flag for creating variable references
4921  * @return variable
4922  */
4923  inline const Variable getVariable(const string& variableStatement, const SubStatement* subStatement = nullptr, bool createReference = false) {
4924  //
4925  if (isVariableAccess(variableStatement, subStatement) == false) return Variable();
4926  //
4927  string variableName;
4928  // global accessor
4929  string globalVariableStatement;
4930  if (_StringTools::viewStartsWith(string_view(variableStatement), string_view("$$.", 3)) == true) {
4931  globalVariableStatement = "$" + _StringTools::substring(variableStatement, 3);
4932  } else
4933  if (_StringTools::viewStartsWith(string_view(variableStatement), string_view("$GLOBAL.", 8)) == true) {
4934  globalVariableStatement = "$" + _StringTools::substring(variableStatement, 8);
4935  }
4936 
4937  //
4938  Variable* parentVariable = nullptr;
4939  string key;
4940  int64_t arrayIdx = ARRAYIDX_NONE;
4941  int setAccessBool = SETACCESSBOOL_NONE;
4942  auto variablePtr = getVariableIntern(globalVariableStatement.empty() == true?variableStatement:globalVariableStatement, __FUNCTION__, variableName, parentVariable, arrayIdx, key, setAccessBool, subStatement, true, globalVariableStatement.empty() == false);
4943  // set '.' operator
4944  if (setAccessBool != SETACCESSBOOL_NONE) {
4945  return Variable(setAccessBool == SETACCESSBOOL_TRUE);
4946  } else
4947  // we have a pointer to a ordinary variable
4948  if (variablePtr != nullptr) {
4949  // if we return any variable we can safely remove the constness, a reference can of course keep its constness
4950  auto variable = createReference == false?Variable::createNonReferenceVariable(variablePtr):Variable::createReferenceVariable(variablePtr);
4951  if (createReference == false) variable.unsetConstant();
4952  return variable;
4953  } else {
4954  // nothing to return
4955  return Variable();
4956  }
4957  }
4958 
4959  /**
4960  * Returns variable determined by given variable statement and variable pointer
4961  * @param variablePtr variable pointer
4962  * @param variableStatement variable statement
4963  * @param subStatement optional sub statement the variable is read in
4964  * @param createReference optional flag for creating variable references
4965  * @return variable
4966  */
4967  inline const Variable getVariable(Variable* variablePtr, const string& variableStatement, const SubStatement* subStatement = nullptr, bool createReference = false) {
4968  //
4969  if (isVariableAccess(variableStatement, subStatement) == false) return Variable();
4970  //
4971  Variable* parentVariable = nullptr;
4972  string key;
4973  int64_t arrayIdx = ARRAYIDX_NONE;
4974  int setAccessBool = SETACCESSBOOL_NONE;
4975  variablePtr = evaluateVariableAccessIntern(variablePtr, variableStatement, __FUNCTION__, parentVariable, arrayIdx, key, setAccessBool, subStatement, true);
4976  // set '.' operator
4977  if (setAccessBool != SETACCESSBOOL_NONE) {
4978  return Variable(setAccessBool == SETACCESSBOOL_TRUE);
4979  } else
4980  // we have a pointer to a ordinary variable
4981  if (variablePtr != nullptr) {
4982  // if we return any variable we can safely remove the constness, a reference can of course keep its constness
4983  auto variable = createReference == false?Variable::createNonReferenceVariable(variablePtr):Variable::createReferenceVariable(variablePtr);
4984  if (createReference == false) variable.unsetConstant();
4985  return variable;
4986  } else {
4987  // nothing to return
4988  return Variable();
4989  }
4990  }
4991 
4992  /**
4993  * Unsets variable determined by given variable statement and variable pointer
4994  * @param variablePtr variable pointer
4995  * @param variableStatement variable statement
4996  * @param subStatement optional sub statement the variable is read in
4997  * @param createReference optional flag for creating variable references
4998  * @return variable
4999  */
5000  inline void unsetVariable(Variable* variablePtr, const string& variableStatement, const SubStatement* subStatement = nullptr) {
5001  //
5002  if (isVariableAccess(variableStatement, subStatement) == false) return;
5003  //
5004  Variable* parentVariable = nullptr;
5005  string key;
5006  int64_t arrayIdx = ARRAYIDX_NONE;
5007  int setAccessBool = SETACCESSBOOL_NONE;
5008  variablePtr = evaluateVariableAccessIntern(variablePtr, variableStatement, __FUNCTION__, parentVariable, arrayIdx, key, setAccessBool, subStatement, true);
5009  // set '.' operator
5010  if (setAccessBool != SETACCESSBOOL_NONE) {
5011  return;
5012  } else
5013  // we have a pointer to a ordinary variable
5014  if (variablePtr != nullptr) {
5015  //
5016  variablePtr->unset();
5017  }
5018  }
5019 
5020  /**
5021  * Unsets variable determined by given variable statement
5022  * @param variableStatement variable statement
5023  * @param subStatement optional sub statement the variable is read in
5024  */
5025  inline void unsetVariable(const string& variableStatement, const SubStatement* subStatement = nullptr) {
5026  //
5027  if (isVariableAccess(variableStatement, subStatement) == false) return;
5028  //
5029  string variableName;
5030  // global accessor
5031  string globalVariableStatement;
5032  if (_StringTools::viewStartsWith(string_view(variableStatement), string_view("$$.", 3)) == true) {
5033  globalVariableStatement = "$" + _StringTools::substring(variableStatement, 3);
5034  } else
5035  if (_StringTools::viewStartsWith(string_view(variableStatement), string_view("$GLOBAL.", 8)) == true) {
5036  globalVariableStatement = "$" + _StringTools::substring(variableStatement, 8);
5037  }
5038 
5039  //
5040  Variable* parentVariable = nullptr;
5041  string key;
5042  int64_t arrayIdx = ARRAYIDX_NONE;
5043  int setAccessBool = SETACCESSBOOL_NONE;
5044  auto variablePtr = getVariableIntern(globalVariableStatement.empty() == true?variableStatement:globalVariableStatement, __FUNCTION__, variableName, parentVariable, arrayIdx, key, setAccessBool, subStatement, true, globalVariableStatement.empty() == false);
5045  // set '.' operator
5046  if (setAccessBool != SETACCESSBOOL_NONE) {
5047  // no op
5048  } else
5049  // we have a pointer to a ordinary variable
5050  if (variablePtr != nullptr) {
5051  variablePtr->unset();
5052  }
5053  }
5054 
5055  /**
5056  * Set constant by given variable statement and variable
5057  * @param variableStatement variable statement
5058  * @param variable variable
5059  */
5060  inline void setConstant(const string& variableStatement, const Variable& variable) {
5061  auto constVariable = variable;
5062  setConstant(constVariable);
5063  setVariable(variableStatement, constVariable);
5064  }
5065 
5066  /**
5067  * Set variable by given variable statement and variable
5068  * @param variableStatement variable statement
5069  * @param variable variable
5070  * @param subStatement optional sub statement the variable is written in
5071  * @param createReference optional flag for creating variable references
5072  */
5073  inline void setVariable(const string& variableStatement, const Variable& variable, const SubStatement* subStatement = nullptr, bool createReference = false) {
5074  //
5075  if (isVariableAccess(variableStatement, subStatement) == false) return;
5076  //
5077  string variableName;
5078  // global accessor
5079  string globalVariableStatement;
5080  if (_StringTools::viewStartsWith(string_view(variableStatement), string_view("$$.", 3)) == true) {
5081  globalVariableStatement = "$" + _StringTools::substring(variableStatement, 3);
5082  } else
5083  if (_StringTools::viewStartsWith(string_view(variableStatement), string_view("$GLOBAL.", 8)) == true) {
5084  globalVariableStatement = "$" + _StringTools::substring(variableStatement, 8);
5085  }
5086 
5087  //
5088  Variable* parentVariable = nullptr;
5089  string key;
5090  int64_t arrayIdx = ARRAYIDX_NONE;
5091  int setAccessBool = SETACCESSBOOL_NONE;
5092  auto variablePtr = getVariableIntern(globalVariableStatement.empty() == true?variableStatement:globalVariableStatement, __FUNCTION__, variableName, parentVariable, arrayIdx, key, setAccessBool, subStatement, false, globalVariableStatement.empty() == false);
5093 
5094  // set variable if not yet done
5095  if (variablePtr == nullptr && parentVariable == nullptr) {
5096  // default
5097  auto& scriptState = globalVariableStatement.empty() == true?getScriptState():getRootScriptState();
5098  auto variableIt = scriptState.variables.find(globalVariableStatement.empty() == true?variableStatement:globalVariableStatement);
5099  if (variableIt != scriptState.variables.end()) {
5100  auto& existingVariable = variableIt->second;
5101  if (existingVariable->isConstant() == false) {
5102  // if we set a variable in variable scope that did exist before, we can safely remove the constness
5103  if (createReference == true) {
5104  existingVariable->setReference(&variable);
5105  } else {
5106  existingVariable->setValue(variable);
5107  }
5108  } else {
5109  _Console::printLine(getSubStatementInformation(*subStatement) + ": Constant: " + variableStatement + ": assignment of constant is not allowed");
5110  }
5111  return;
5112  } else {
5113  // if we set a variable in variable scope that did not exist before, we keep things as they are regarding constness
5114  scriptState.variables[globalVariableStatement.empty() == true?variableStatement:globalVariableStatement] =
5115  createReference == false?Variable::createNonReferenceVariablePointer(&variable):Variable::createReferenceVariablePointer(&variable);
5116  }
5117  } else {
5118  setVariableInternal(variableStatement, parentVariable, variablePtr, arrayIdx, key, variable, subStatement, createReference);
5119  }
5120  }
5121 
5122  /**
5123  * Set variable by given variable pointer, variable statement and variable
5124  * @param variablePtr variable pointer
5125  * @param variableStatement variable statement
5126  * @param variable variable
5127  * @param subStatement optional sub statement the variable is written in
5128  * @param createReference optional flag for creating variable references
5129  */
5130  inline void setVariable(Variable* variablePtr, const string& variableStatement, const Variable& variable, const SubStatement* subStatement = nullptr, bool createReference = false) {
5131  //
5132  if (isVariableAccess(variableStatement, subStatement) == false) return;
5133  //
5134  string variableName;
5135  // global accessor
5136  string globalVariableStatement;
5137  if (_StringTools::viewStartsWith(string_view(variableStatement), string_view("$$.", 3)) == true) {
5138  globalVariableStatement = "$" + _StringTools::substring(variableStatement, 3);
5139  } else
5140  if (_StringTools::viewStartsWith(string_view(variableStatement), string_view("$GLOBAL.", 8)) == true) {
5141  globalVariableStatement = "$" + _StringTools::substring(variableStatement, 8);
5142  }
5143 
5144  //
5145  Variable* parentVariable = nullptr;
5146  string key;
5147  int64_t arrayIdx = ARRAYIDX_NONE;
5148  int setAccessBool = SETACCESSBOOL_NONE;
5149  variablePtr = evaluateVariableAccessIntern(variablePtr, globalVariableStatement.empty() == true?variableStatement:globalVariableStatement, __FUNCTION__, parentVariable, arrayIdx, key, setAccessBool, subStatement, false);
5150 
5151  // set variable if not yet done
5152  setVariableInternal(variableStatement, parentVariable, variablePtr, arrayIdx, key, variable, subStatement, createReference);
5153  }
5154 
5155  /**
5156  * Parse script
5157  * @param pathName path name
5158  * @param fileName file name
5159  * @param nativeOnly native only
5160  */
5161  void parseScript(const string& pathName, const string& fileName, bool nativeOnly = false);
5162 
5163  /**
5164  * Start script
5165  */
5166  virtual void startScript();
5167 
5168  /**
5169  * Check if condition with given name exists
5170  * @param condition condition
5171  * @return condition with given name exists
5172  */
5173  inline bool hasCondition(const string& condition) {
5174  // iterate scripts to find out if condition exists
5175  for (const auto& script: scripts) {
5176  if (script.type != Script::TYPE_ON) {
5177  // no op
5178  } else
5179  if (script.emitCondition == true && script.condition == condition) {
5180  // no op
5181  return true;
5182  }
5183  }
5184  //
5185  return false;
5186  }
5187 
5188  /**
5189  * Emit
5190  * @param condition condition
5191  */
5192  virtual void emit(const string& condition);
5193 
5194  /**
5195  * Execute
5196  */
5197  virtual void execute();
5198 
5199  /**
5200  * Return function script index by function name
5201  * @param function function
5202  * @return function script index
5203  */
5204  inline int getFunctionScriptIdx(const string& function) {
5205  // lookup function
5206  auto functionIt = functions.find(function);
5207  if (functionIt == functions.end()) {
5208  return SCRIPTIDX_NONE;
5209  }
5210  //
5211  auto scriptIdx = functionIt->second;
5212  //
5213  return scriptIdx;
5214  }
5215 
5216  /**
5217  * Call function
5218  * @param scriptIdx script index
5219  * @param arguments argument values
5220  * @param returnValue return value
5221  * @return success
5222  */
5223  inline bool call(int scriptIdx, span<Variable>& arguments, Variable& returnValue) {
5224  return call(scriptIdx, arguments, returnValue, true);
5225  }
5226 
5227  /**
5228  * Call function
5229  * @param function function
5230  * @param arguments argument values
5231  * @param returnValue return value
5232  * @return success
5233  */
5234  inline bool call(const string& function, span<Variable>& arguments, Variable& returnValue) {
5235  return call(function, arguments, returnValue, true);
5236  }
5237 
5238  /**
5239  * Call stacklet
5240  * @param scriptIdx script index
5241  * @param arguments argument values
5242  * @param returnValue return value
5243  * @return success
5244  */
5245  inline bool callStacklet(int scriptIdx, span<Variable>& arguments, Variable& returnValue) {
5246  return call(scriptIdx, arguments, returnValue, false);
5247  }
5248 
5249  /**
5250  * Call stacklet
5251  * @param stacklet stacklet
5252  * @param arguments argument values
5253  * @param returnValue return value
5254  * @return success
5255  */
5256  inline bool callStacklet(const string& stacklet, span<Variable>& arguments, Variable& returnValue) {
5257  return call(stacklet, arguments, returnValue, false);
5258  }
5259 
5260  /**
5261  * Evaluate statement
5262  * @param evaluateStatement evaluate statement
5263  * @param returnValue return value
5264  * @return success
5265  */
5266  inline bool evaluate(const string& evaluateStatement, Variable& returnValue) {
5267  Statement evaluateScriptStatement(
5268  LINE_NONE,
5270  "internal.script.evaluate(" + _StringTools::replace(_StringTools::replace(evaluateStatement, "\\", "\\\\"), "\"", "\\\"") + ")",
5271  "internal.script.evaluate(" + _StringTools::replace(_StringTools::replace(evaluateStatement, "\\", "\\\\"), "\"", "\\\"") + ")",
5273  );
5274  return evaluateInternal(evaluateStatement, doStatementPreProcessing(evaluateStatement, evaluateScriptStatement), returnValue);
5275  }
5276 
5277  /**
5278  * @return is running
5279  */
5280  inline bool isRunning() {
5281  return getScriptState().running;
5282  }
5283 
5284  /**
5285  * Get method by method name
5286  * @param methodName method name
5287  * @return method or nullptr
5288  */
5289  inline Method* getMethod(const string& methodName) {
5290  auto methodIt = methods.find(methodName);
5291  if (methodIt != methods.end()) {
5292  return methodIt->second;
5293  } else {
5294  return nullptr;
5295  }
5296  }
5297 
5298  /**
5299  * @return methods
5300  */
5301  const vector<Method*> getMethods();
5302 
5303  /**
5304  * Get method by operator
5305  * @param operator_ operator
5306  * @return method or nullptr
5307  */
5308  inline Method* getOperatorMethod(Operator operator_) {
5309  auto methodIt = operators.find(operator_);
5310  if (methodIt != operators.end()) {
5311  return methodIt->second;
5312  } else {
5313  return nullptr;
5314  }
5315  }
5316 
5317  /**
5318  * @return operator methods
5319  */
5320  const vector<Method*> getOperatorMethods();
5321 
5322  /**
5323  * Get script information for a specific script index
5324  * @param scriptIdx script index
5325  * @param includeStatements include statements
5326  * @return information as string
5327  */
5328  const string getScriptInformation(int scriptIdx, bool includeStatements = true);
5329 
5330  /**
5331  * Get MinitScript instance information
5332  * @return information as string
5333  */
5334  const string getInformation();
5335 
5336 };
minitscript::utilities::Exception _Exception
MinitScript script application methods.
MinitScript script base methods.
Definition: BaseMethods.h:13
MinitScript script JSON methods.
Definition: JSONMethods.h:12
MinitScript math methods.
Definition: MathMethods.h:16
void setIndex(int index)
Set garbage collection type index.
Definition: MinitScript.h:248
void setRequiresGarbageCollection()
Set requires garbage collection.
Definition: MinitScript.h:255
void setMinitScript(MinitScript *minitScript)
Set MinitScript instance.
Definition: MinitScript.h:240
void unsetRequiresGarbageCollection()
Unset requires garbage collection.
Definition: MinitScript.h:262
virtual void setVariableValue(Variable &variable, const void *value) const =0
Set variable value.
virtual void setVariableValue(Variable &variable) const =0
Set variable value.
virtual bool add(MinitScript *minitScript, const span< MinitScript::Variable > &arguments, MinitScript::Variable &returnValue, const MinitScript::SubStatement &subStatement) const =0
Addition.
virtual void copyVariable(Variable &to, const Variable &from) const =0
Copy variable.
void setType(MinitScript::VariableType type)
Set type.
Definition: MinitScript.h:281
virtual ScriptContext * createScriptContext() const =0
Create script context.
virtual const string getValueAsString(const Variable &variable) const =0
Returns value as string.
virtual bool mul(MinitScript *minitScript, const span< MinitScript::Variable > &arguments, MinitScript::Variable &returnValue, const MinitScript::SubStatement &subStatement) const =0
Multiply.
virtual const string & getTypeAsString() const =0
MinitScript::VariableType getType() const
Definition: MinitScript.h:415
virtual bool div(MinitScript *minitScript, const span< MinitScript::Variable > &arguments, MinitScript::Variable &returnValue, const MinitScript::SubStatement &subStatement) const =0
Division.
virtual bool sub(MinitScript *minitScript, const span< MinitScript::Variable > &arguments, MinitScript::Variable &returnValue, const MinitScript::SubStatement &subStatement) const =0
Subtraction.
virtual void registerMethods(MinitScript *minitScript) const =0
Register methods.
virtual void unsetVariableValue(Variable &variable) const =0
Unset variable value.
virtual void registerConstants(MinitScript *minitScript) const =0
Register constants.
virtual void deleteScriptContext(ScriptContext *context) const =0
Delete script context.
virtual void garbageCollection(ScriptContext *context) const =0
Issue garbage collection.
virtual const vector< string > & getContextFunctions()
Definition: MinitScript.h:2786
virtual void executeMethod(span< Variable > &arguments, Variable &returnValue, const SubStatement &subStatement)=0
Execute method.
const string getArgumentsInformation(int beginIdx=0) const
Get arguments information.
Definition: MinitScript.h:2721
const VariableType & getReturnValueType() const
Definition: MinitScript.h:2751
const vector< ArgumentType > & getArgumentTypes() const
Definition: MinitScript.h:2712
static MINITSCRIPT_STATIC_DLL_IMPEXT const vector< string > CONTEXTFUNCTIONS_ALL
Definition: MinitScript.h:2791
ShutdownRAII(vector< DataType * > &dataTypes)
Constructor.
Definition: MinitScript.h:3508
virtual void execute()=0
Execute state machine state.
Initializer(const string &initializerString, const Statement &statement, SyntaxTreeNode *syntaxTree)
Constructor.
Definition: MinitScript.h:469
void copy(Initializer *initializer)
Copy from initializer.
Definition: MinitScript.h:480
const _UTF8CharacterIterator::UTF8PositionCache & getCache() const
Definition: MinitScript.h:564
_UTF8CharacterIterator::UTF8PositionCache & getCache()
Definition: MinitScript.h:571
_UTF8CharacterIterator::UTF8PositionCache cache
Definition: MinitScript.h:585
void setCache(const _UTF8CharacterIterator::UTF8PositionCache &cache)
Set cache.
Definition: MinitScript.h:579
static MINITSCRIPT_STATIC_DLL_IMPEXT const string TYPENAME_NUMBER
Definition: MinitScript.h:834
static const string getReturnTypeAsString(VariableType type, bool nullable)
Returns given return value variable type string representation.
Definition: MinitScript.h:2366
const vector< string > getMapKeys() const
Get map keys.
Definition: MinitScript.h:2020
const string getReturnTypeAsString(bool nullable) const
Returns given return value variable type string representation.
Definition: MinitScript.h:2379
static void copyVariable(Variable &to, const Variable &from, bool properties)
Copy variable.
Definition: MinitScript.h:1001
InitializerReferenceUnion initializerReferenceUnion
Definition: MinitScript.h:609
bool getIntegerValue(int64_t &value, bool optional=false) const
Get integer value from given variable.
Definition: MinitScript.h:1436
static Variable * createReferenceVariablePointer(const Variable *variable)
Create reference variable pointer.
Definition: MinitScript.h:963
int64_t getByteArraySize() const
Get byte array size.
Definition: MinitScript.h:1740
Variable & operator=(const Variable &variable)
Assignment operator.
Definition: MinitScript.h:1128
static constexpr uint32_t CONSTANT_BIT_VALUE
Definition: MinitScript.h:517
void setImplicitTypedValueFromStringView(const string_view &value, MinitScript *minitScript, int scriptIdx, const Statement &statement)
Set implicit typed value given by value string.
Definition: MinitScript.h:2191
const FunctionValue & getFunctionValueReference() const
Definition: MinitScript.h:751
void setValue(const string &value)
Set string value from given value into variable.
Definition: MinitScript.h:1654
Variable(const vector< Variable * > &value)
Constructor.
Definition: MinitScript.h:1230
static void swap(Variable &a, Variable &b)
Swap variables.
Definition: MinitScript.h:1089
static Variable createNonReferenceVariable(const Variable *variable)
Create none reference variable.
Definition: MinitScript.h:974
static MINITSCRIPT_STATIC_DLL_IMPEXT const string TYPENAME_SET
Definition: MinitScript.h:840
void setValue(const vector< uint8_t > &value)
Set array value from given value into variable.
Definition: MinitScript.h:1663
void setValue(const vector< Variable * > &value)
Set array value from given value into variable.
Definition: MinitScript.h:1675
static MINITSCRIPT_STATIC_DLL_IMPEXT const string TYPENAME_NULL
Definition: MinitScript.h:828
static MINITSCRIPT_STATIC_DLL_IMPEXT const string TYPENAME_BYTEARRAY
Definition: MinitScript.h:837
bool getStackletValue(string &stacklet, int &scriptIdx, bool optional=false) const
Get stacklet values from given variable.
Definition: MinitScript.h:1528
static Variable createMethodArgumentVariable(const Variable *variable)
Create variable optimized for method argument usage.
Definition: MinitScript.h:915
_UTF8CharacterIterator::UTF8PositionCache * getStringValueCache()
Get string value UTF8 position cache from given variable.
Definition: MinitScript.h:1595
static MINITSCRIPT_STATIC_DLL_IMPEXT const string TYPENAME_ARRAY
Definition: MinitScript.h:838
static MINITSCRIPT_STATIC_DLL_IMPEXT const string TYPENAME_FUNCTION
Definition: MinitScript.h:832
void setFunctionCallStatement(const string &initializerStatement, MinitScript *minitScript, int scriptIdx, const Statement &statement)
Set array/map values initializer function call statement.
bool getStringValue(string &value, bool optional=false) const
Get string value from given variable.
Definition: MinitScript.h:1549
const StringValue & getStringValueReference() const
Definition: MinitScript.h:765
const Variable getArrayEntry(int64_t idx) const
Get entry from array with given index.
Definition: MinitScript.h:1868
void setFunctionAssignment(const string &function, int scriptIdx=MinitScript::SCRIPTIDX_NONE)
Set function assignment from given value into variable.
Definition: MinitScript.h:2154
void pushByteArrayEntry(uint8_t value)
Push entry to byte array.
Definition: MinitScript.h:1809
bool hasMapEntry(const string &key) const
Map has entry with given key.
Definition: MinitScript.h:1952
const unordered_map< string, Variable * > * getMapPointer() const
Definition: MinitScript.h:1924
const vector< Variable * > getMapValues() const
Get map values.
Definition: MinitScript.h:2034
void setValue(float value)
Set float value from given value into variable.
Definition: MinitScript.h:1645
static const string & getTypeAsString(VariableType type)
Returns given variable type as string.
Definition: MinitScript.h:2326
unordered_map< string, Variable * > & getMapValueReference()
Definition: MinitScript.h:800
static MINITSCRIPT_STATIC_DLL_IMPEXT const string TYPENAME_STACKLET
Definition: MinitScript.h:833
const ByteArrayValue & getByteArrayValueReference() const
Definition: MinitScript.h:779
void setMapEntry(const string &key, const Variable &value, bool _private=false)
Set entry in map with given key.
Definition: MinitScript.h:1993
Variable(Variable &&variable)
Move constructor.
Definition: MinitScript.h:1114
void setValue(const void *value)
Set value for custom data types.
Definition: MinitScript.h:1708
const int64_t * getByteArrayReadPointer() const
Get const byte array read pointer.
Definition: MinitScript.h:1749
static Variable createNonConstVariable(const Variable *variable)
Create non const/reference variable.
Definition: MinitScript.h:941
static constexpr uint32_t PRIVATESCOPE_BIT_VALUE
Definition: MinitScript.h:520
bool hasSetKey(const string &key) const
Set has given key.
Definition: MinitScript.h:2087
bool getByteValue(MinitScript *minitScript, uint8_t &value, const Statement *statement=nullptr) const
Get byte value from given variable.
Definition: MinitScript.h:1576
vector< Variable * > & getArrayValueReference()
Definition: MinitScript.h:786
uint64_t & getValuePtrReference()
Return value pointer.
Definition: MinitScript.h:695
static MINITSCRIPT_STATIC_DLL_IMPEXT const string TYPENAME_NONE
Definition: MinitScript.h:827
static MINITSCRIPT_STATIC_DLL_IMPEXT const string TYPENAME_FLOAT
Definition: MinitScript.h:831
void insertSetKey(const string &key)
Insert given key in set.
Definition: MinitScript.h:2099
Variable(const Variable &variable)
Copy constructor.
Definition: MinitScript.h:1102
void pushArrayEntry(const Variable &value)
Push entry to array.
Definition: MinitScript.h:1892
const Variable * getMapEntryPtr(const string &key) const
Get entry pointer from map with given key.
Definition: MinitScript.h:1978
static constexpr uint32_t REFERENCE_BIT_VALUE
Definition: MinitScript.h:518
static Variable * createNonReferenceVariablePointer(const Variable *variable)
Create none reference variable pointer.
Definition: MinitScript.h:987
unordered_map< string, Variable * > * getMapPointer()
Definition: MinitScript.h:1933
const vector< string > getSetKeys() const
Get set keys.
Definition: MinitScript.h:2121
void setValue(int64_t value)
Set integer value from given value into variable.
Definition: MinitScript.h:1636
static MINITSCRIPT_STATIC_DLL_IMPEXT const string TYPENAME_MAP
Definition: MinitScript.h:839
void setStackletAssignment(const string &stacklet, int scriptIdx=MinitScript::SCRIPTIDX_NONE)
Set stacklet assignment from given value into variable.
Definition: MinitScript.h:2166
const unordered_set< string > * getSetPointer() const
Definition: MinitScript.h:2059
void setValue(const unordered_map< string, Variable * > &value)
Set map value from given value into variable.
Definition: MinitScript.h:1687
unordered_set< string > & getSetValueReference()
Definition: MinitScript.h:814
const vector< Variable * > * getArrayPointer() const
Definition: MinitScript.h:1839
bool getFloatValue(float &value, bool optional=false) const
Get float value from given variable.
Definition: MinitScript.h:1474
bool getBooleanValue(bool &value, bool optional=false) const
Get boolean value from given variable.
Definition: MinitScript.h:1405
void setValue(const unordered_set< string > &value)
Set set value from given value into variable.
Definition: MinitScript.h:1699
void removeMapEntry(const string &key)
Remove entry in map with given key.
Definition: MinitScript.h:2006
void setArrayEntry(int64_t idx, const Variable &value)
Set entry in array with given index.
Definition: MinitScript.h:1879
void setValuePtr(void *valuePtr)
Set value pointer.
Definition: MinitScript.h:1391
int64_t * getByteArrayWritePointer()
Get byte array write pointer.
Definition: MinitScript.h:1776
const vector< uint8_t > * getByteArrayPointer() const
Definition: MinitScript.h:1721
int64_t getArraySize() const
Get array size.
Definition: MinitScript.h:1858
void removeByteArray(int64_t idx, int64_t size)
Remove byte array entries at given index and size.
Definition: MinitScript.h:1819
Variable(VariableType type, const string &value, int scriptIdx=SCRIPTIDX_NONE)
Constructor.
Definition: MinitScript.h:1202
static MINITSCRIPT_STATIC_DLL_IMPEXT const string TYPENAME_STRING
Definition: MinitScript.h:836
static MINITSCRIPT_STATIC_DLL_IMPEXT const string TYPENAME_INTEGER
Definition: MinitScript.h:830
static Variable createReferenceVariable(const Variable *variable)
Create reference variable.
Definition: MinitScript.h:952
const uint8_t getByteArrayEntry(int64_t idx) const
Get entry from byte array with given index.
Definition: MinitScript.h:1786
static bool isExpectedType(VariableType type, VariableType expectedType)
Check if given variable type does match expected variable type.
Definition: MinitScript.h:2309
const unordered_set< string > & getSetValueReference() const
Definition: MinitScript.h:821
const unordered_map< string, Variable * > & getMapValueReference() const
Definition: MinitScript.h:807
Initializer * getInitializer() const
Return initializer.
Definition: MinitScript.h:1376
const int64_t & getIntegerValueReference() const
Definition: MinitScript.h:723
const string getValueAsString(bool formatted=false, bool jsonCompatible=false, int depth=0) const
Print string representation of variable.
Definition: MinitScript.h:2404
Variable(const string &value)
Constructor.
Definition: MinitScript.h:1222
void setReference(const Variable *variable)
Set reference.
Definition: MinitScript.h:891
void setType(VariableType newType)
Set type.
Definition: MinitScript.h:1253
static MINITSCRIPT_STATIC_DLL_IMPEXT const string TYPENAME_MIXED
Definition: MinitScript.h:835
void removeArrayEntry(int64_t idx)
Remove array entry at given index.
Definition: MinitScript.h:1901
void setNullValue()
Set boolean value from given value into variable.
Definition: MinitScript.h:1610
int64_t * getByteArrayReadPointer()
Get byte array read pointer.
Definition: MinitScript.h:1758
void removeSetKey(const string &key)
Remove key in set with given key.
Definition: MinitScript.h:2108
void setImplicitTypedValue(const string &value, MinitScript *minitScript, int scriptIdx, const Statement &statement)
Set implicit typed value given by value string.
Definition: MinitScript.h:2180
void setByteArrayEntry(int64_t idx, uint8_t value)
Set entry in byte array with given index.
Definition: MinitScript.h:1797
Variable(const unordered_map< string, Variable * > &value)
Constructor.
Definition: MinitScript.h:1238
bool getFunctionValue(string &function, int &scriptIdx, bool optional=false) const
Get function values from given variable.
Definition: MinitScript.h:1506
Initializer *& getInitializerReference()
Return initializer.
Definition: MinitScript.h:679
static MINITSCRIPT_STATIC_DLL_IMPEXT const string TYPENAME_BOOLEAN
Definition: MinitScript.h:829
const vector< Variable * > & getArrayValueReference() const
Definition: MinitScript.h:793
void setValue(const Variable &variable)
Set value from given variable into variable.
Definition: MinitScript.h:1618
void setValue(bool value)
Set boolean value from given value into variable.
Definition: MinitScript.h:1627
const uint64_t & getValuePtrReference() const
Return const value pointer.
Definition: MinitScript.h:687
void unsetPrivateScope()
Unset private scope.
Definition: MinitScript.h:650
Variable & operator=(Variable &&variable)
Move operator.
Definition: MinitScript.h:1146
const Variable getMapEntry(const string &key) const
Get entry from map with given key.
Definition: MinitScript.h:1965
const int64_t * getByteArrayWritePointer() const
Get const byte array write pointer.
Definition: MinitScript.h:1767
unordered_set< int > garbageCollectionDataTypesIndices
Definition: MinitScript.h:3568
static bool viewIsStringLiteral(const string_view &candidate)
Returns if a given string is a string literal.
Definition: MinitScript.h:4179
static bool viewIsVariableAccess(const string_view &candidate)
Returns if a given string is a variable name.
Definition: MinitScript.h:4132
static MINITSCRIPT_STATIC_DLL_IMPEXT const string METHOD_SCRIPTCALLSTACKLETBYINDEX
Definition: MinitScript.h:2997
static MINITSCRIPT_STATIC_DLL_IMPEXT const string METHOD_SCRIPTCALLSTACKLET
Definition: MinitScript.h:2995
bool parseStatement(const string_view &executableStatement, string_view &methodName, vector< ParserArgument > &arguments, const Statement &statement, string &accessObjectMemberStatement)
Parse a statement.
bool callStacklet(const string &stacklet, span< Variable > &arguments, Variable &returnValue)
Call stacklet.
Definition: MinitScript.h:5256
const string getArgumentsInformation(const string &methodName)
Get arguments information.
Definition: MinitScript.h:4585
unordered_map< string, Method * > methods
Definition: MinitScript.h:3533
const SubStatement & getErrorSubStatement()
Definition: MinitScript.h:4337
int getStatementSubLineIdx(const string &statement, int idx)
Get statement sub line index.
Definition: MinitScript.h:4542
static const string_view viewGetPrivateKey(const string_view &candidate)
Returns private key.
void unsetVariable(const string &variableStatement, const SubStatement *subStatement=nullptr)
Unsets variable determined by given variable statement.
Definition: MinitScript.h:5025
bool parseScriptInternal(const string &scriptCode, int lineIdxOffset=0)
Parse script code into this MinitScript instance.
static string_view dequote(const string_view &str)
Dequote a string.
Definition: MinitScript.h:4205
static void initialize()
Initialize.
bool call(const string &function, span< Variable > &arguments, Variable &returnValue, bool pushScriptState)
Call function.
Definition: MinitScript.h:3898
DataType::ScriptContext * getDataTypeScriptContext(VariableType type)
Return data type script context.
Definition: MinitScript.h:4274
const vector< string > & getParseErrors()
Definition: MinitScript.h:4429
virtual const string getBaseClassHeader()
virtual const string getBaseClass()
void registerMethod(Method *method)
Register method.
void setContext(_Context *context)
Set context.
Definition: MinitScript.h:4293
void setLibrary(_Library *library)
Set library.
Definition: MinitScript.h:4308
unordered_map< uint8_t, Method * > operators
Definition: MinitScript.h:3537
bool call(int scriptIdx, span< Variable > &arguments, Variable &returnValue)
Call function.
Definition: MinitScript.h:5223
static constexpr int SETACCESSBOOL_FALSE
Definition: MinitScript.h:3050
void registerStateMachineState(StateMachineState *state)
Register state machine state.
static MINITSCRIPT_STATIC_DLL_IMPEXT vector< DataType * > dataTypes
Definition: MinitScript.h:3523
int getFunctionScriptIdx(const string &function)
Return function script index by function name.
Definition: MinitScript.h:5204
void setVariable(Variable *variablePtr, const string &variableStatement, const Variable &variable, const SubStatement *subStatement=nullptr, bool createReference=false)
Set variable by given variable pointer, variable statement and variable.
Definition: MinitScript.h:5130
void setScriptStateState(int state)
Set script state machine state.
Definition: MinitScript.h:3416
bool getObjectMemberAccess(const string_view &executableStatement, string_view &object, string_view &method, int &methodStartIdx, const Statement &statement)
Returns if statement has a object member access.
void popScriptState()
Pop script state.
Definition: MinitScript.h:3297
static const Variable initializeArray(const string_view &initializerString, MinitScript *minitScript, int scriptIdx, const Statement &statement)
Initialize array by initializer string.
void gotoStatementGoto(const Statement &statement)
Go to statement goto from given statement.
Definition: MinitScript.h:3247
virtual void startScript()
Start script.
bool validateStacklets(int scriptIdx)
Validate stacklets.
const string getStatementInformation(const Statement &statement, int subLineIdx=-1)
Return statement information.
Definition: MinitScript.h:4556
unordered_map< VariableType, DataType::ScriptContext * > garbageCollectionScriptContextsByDataType
Definition: MinitScript.h:3567
static constexpr int64_t TIME_NONE
Definition: MinitScript.h:3057
bool call(int scriptIdx, span< Variable > &arguments, Variable &returnValue, bool pushScriptState)
Call function.
void stopScriptExecution()
Stop script execution.
Definition: MinitScript.h:3399
void resetStackletScriptExecutationState(int scriptIdx, StateMachineStateId stateMachineState)
Reset stacklet script execution state.
Definition: MinitScript.h:3373
static bool getBooleanValue(const span< Variable > &arguments, int idx, bool &value, bool optional=false)
Get boolean value from given variable.
Definition: MinitScript.h:4674
static void setConstant(Variable &variable)
Set variable recursively to be a constant.
Definition: MinitScript.h:4255
Variable * getVariableIntern(const string &variableStatement, const string &callerMethod, string &variableName, Variable *&parentVariable, int64_t &arrayIdx, string &key, int &setAccessBool, const SubStatement *subStatement=nullptr, bool expectVariable=true, bool global=false)
Returns pointer of variable with given name or nullptr.
Definition: MinitScript.h:3810
static bool viewIsKeyPrivate(const string_view &candidate)
Returns if a given key candidate is marked as private by head '-'.
static bool viewIsLamdaFunction(const string_view &candidate, vector< string_view > &arguments, string_view &functionScriptCode, int &lineIdx)
Returns if a given string is a lambda function.
Definition: MinitScript.h:3982
void pushScriptState()
Push a new script state.
Definition: MinitScript.h:3290
static bool getFloatValue(const span< Variable > &arguments, int idx, float &value, bool optional=false)
Get float value from given variable.
Definition: MinitScript.h:4702
static bool isOperator(const string &candidate)
Is given candidate a operator string.
Definition: MinitScript.h:4635
static bool viewIsStacklet(const string_view &candidate, vector< string_view > &arguments, string_view &stackletScriptCode, int &lineIdx)
Returns if a given string is a stacklet.
Definition: MinitScript.h:4084
static constexpr int64_t GARBAGE_COLLECTION_INTERVAL
Definition: MinitScript.h:3497
bool validateCallable(const string &function)
Validate callabe.
const string doStatementPreProcessing(const string &processedStatement, const Statement &statement)
Do statement pre processing, 1) replace operators with corresponding methods.
bool hasFunction(const string &functionName)
Returns if function with given name does exist.
Definition: MinitScript.h:4517
static MINITSCRIPT_STATIC_DLL_IMPEXT ShutdownRAII shutdownRAII
Definition: MinitScript.h:3524
bool callStacklet(int scriptIdx, span< Variable > &arguments, Variable &returnValue)
Call stacklet.
Definition: MinitScript.h:5245
void tryGarbageCollection()
Try garbage collection.
Definition: MinitScript.h:3481
void parseScript(const string &pathName, const string &fileName, bool nativeOnly=false)
Parse script.
virtual void registerStateMachineStates()
Register state machine states.
virtual void initializeNative()
Initialize native mini script.
void complain(const string &methodName, const SubStatement &subStatement)
Complain about method usage.
static string getOperatorAsString(Operator operator_)
Get operator as string.
Definition: MinitScript.h:4599
static constexpr int STATEMENTIDX_FIRST
Definition: MinitScript.h:2991
virtual void registerVariables()
Register variables.
bool call(const string &function, span< Variable > &arguments, Variable &returnValue)
Call function.
Definition: MinitScript.h:5234
vector< pair< int, string > > deferredInlineScriptCodes
Definition: MinitScript.h:3129
void setNativeHash(const string &nativeHash)
Set native hash.
Definition: MinitScript.h:3230
bool hasVariable(const string &variableStatement, const SubStatement *subStatement=nullptr)
Returns if variable determined by given variable statement exists.
Definition: MinitScript.h:4813
void setNativeFunctions(const unordered_map< string, int > &nativeFunctions)
Set native functions.
Definition: MinitScript.h:3271
static const vector< DataType * > & getDataTypes()
Definition: MinitScript.h:4376
void createLamdaFunction(Variable &variable, const vector< string_view > &arguments, const string_view &functionScriptCode, int lineIdx, bool populateThis, const Statement &statement, const string &nameHint=string())
const Variable getMethodArgumentVariable(const string &variableStatement, const SubStatement *subStatement=nullptr)
Returns variable determined by given variable statement optimized for method argument usage.
Definition: MinitScript.h:4848
vector< GarbageCollectionDataType > garbageCollectionDataTypes
Definition: MinitScript.h:3566
virtual void registerMethods()
Register methods.
bool evaluateAccess(const string &variableStatement, const string &callerMethod, string::size_type &arrayAccessOperatorLeftIdx, string::size_type &arrayAccessOperatorRightIdx, int64_t &arrayIdx, string &key, const SubStatement *subStatement=nullptr)
Evaluate access.
virtual void emit(const string &condition)
Emit.
static bool getStringValue(const span< Variable > &arguments, int idx, string &value, bool optional=false)
Get string value from given variable.
Definition: MinitScript.h:4746
const Variable getVariable(Variable *variablePtr, const string &variableStatement, const SubStatement *subStatement=nullptr, bool createReference=false)
Returns variable determined by given variable statement and variable pointer.
Definition: MinitScript.h:4967
bool getNextStatement(const string &scriptCode, int &i, int &line, string &statement)
Get next statement from script code.
static MINITSCRIPT_STATIC_DLL_IMPEXT const string METHOD_SCRIPTCALLBYINDEX
Definition: MinitScript.h:2996
int getStackletScopeScriptIdx(int scriptIdx)
Return stacklet scope script index.
static constexpr int OPERATORIDX_NONE
Definition: MinitScript.h:3055
static const bool isOperatorChar(char c)
Returns if char is operator char.
Definition: MinitScript.h:3736
static void registerDataType(DataType *dataType)
Register data type.
bool getVariableAccessOperatorLeftRightIndices(const string &variableStatement, const string &callerMethod, string::size_type &accessOperatorLeftIdx, string::size_type &accessOperatorRightIdx, const SubStatement *subStatement=nullptr, int startIdx=0)
Get access operator left and right indices.
const string getSubStatementInformation(const SubStatement &subStatement)
Return sub statement information.
Definition: MinitScript.h:4576
static const string getArgumentIndicesAsString(const vector< int > &argumentIndices, const string &delimiter)
Returns string representation of given argument indices.
Definition: MinitScript.h:4318
static const Variable initializeMapSet(const string_view &initializerString, MinitScript *minitScript, int scriptIdx, const Statement &statement)
Initialize map/set by initializer string.
static MINITSCRIPT_STATIC_DLL_IMPEXT const string OPERATOR_CHARS
Definition: MinitScript.h:3522
void garbageCollection()
Issue garbage collection.
static void setConstantInternal(Variable &variable)
Set variable recursively to be a constant.
bool hasCondition(const string &condition)
Check if condition with given name exists.
Definition: MinitScript.h:5173
Method * getOperatorMethod(Operator operator_)
Get method by operator.
Definition: MinitScript.h:5308
void setNative(bool native)
Set native.
Definition: MinitScript.h:3222
void setNativeScripts(const vector< Script > &nativeScripts)
Set native scripts.
Definition: MinitScript.h:3263
static MINITSCRIPT_STATIC_DLL_IMPEXT const string METHOD_DISABLENAMEDCONDITION
Definition: MinitScript.h:2999
Variable * evaluateVariableAccessIntern(Variable *variablePtr, const string &variableStatement, const string &callerMethod, Variable *&parentVariable, int64_t &arrayIdx, string &key, int &setAccessBool, const SubStatement *subStatement=nullptr, bool expectVariable=true)
Returns pointer of variable with given name or nullptr.
void unsetVariable(Variable *variablePtr, const string &variableStatement, const SubStatement *subStatement=nullptr)
Unsets variable determined by given variable statement and variable pointer.
Definition: MinitScript.h:5000
static bool viewIsKey(const string_view &candidate)
Returns if a given string is a valid map key name.
const Variable getMethodArgumentVariable(Variable *variablePtr, const string &variableStatement, const SubStatement *subStatement=nullptr)
Returns variable determined by given variable statement and variable pointer optimized for method arg...
Definition: MinitScript.h:4891
void dumpScriptState(ScriptState &scriptState, const string &message=string())
Dump script state.
bool hasMethod(const string &methodName)
Returns if method with given name does exist.
Definition: MinitScript.h:4508
virtual const vector< string > getTranspilationUnits()
unordered_map< string, int > functions
Definition: MinitScript.h:3531
static const string escapeString(const string &str)
Escape string variable.
Definition: MinitScript.h:3147
const string getInformation()
Get MinitScript instance information.
const Variable getVariable(const string &variableStatement, const SubStatement *subStatement=nullptr, bool createReference=false)
Returns variable determined by given variable statement.
Definition: MinitScript.h:4923
static constexpr int ARGUMENTIDX_NONE
Definition: MinitScript.h:2992
static bool viewIsInitializer(const string_view &candidate)
Returns if a given string is a array/map/set initializer.
Definition: MinitScript.h:4214
Method * getMethod(const string &methodName)
Get method by method name.
Definition: MinitScript.h:5289
static MINITSCRIPT_STATIC_DLL_IMPEXT const string METHOD_SCRIPTCALL
Definition: MinitScript.h:2994
unique_ptr< MathMethods > minitScriptMath
Definition: MinitScript.h:3134
void gotoStatement(const Statement &statement)
Go to statement.
Definition: MinitScript.h:3238
unordered_map< int, StateMachineState * > stateMachineStates
Definition: MinitScript.h:3535
const string getArgumentsAsString(const vector< SyntaxTreeNode > &arguments)
Returns arguments as string.
Definition: MinitScript.h:3006
void createStacklet(Variable &variable, const string &scopeName, const vector< string_view > &arguments, const string_view &stackletScriptCode, int lineIdx, const Statement &statement)
const vector< Method * > getMethods()
void stopRunning()
Set running flag to false.
Definition: MinitScript.h:3392
const string getScriptInformation(int scriptIdx, bool includeStatements=true)
Get script information for a specific script index.
bool isVariableAccess(const string &candidate, const SubStatement *subStatement=nullptr)
Returns if a given string is a variable name.
Definition: MinitScript.h:4770
bool evaluateInternal(const string &statement, const string &executableStatement, Variable &returnValue, bool pushScriptState=true)
Evaluate given statement without executing preprocessor run.
void setVariable(const string &variableStatement, const Variable &variable, const SubStatement *subStatement=nullptr, bool createReference=false)
Set variable by given variable statement and variable.
Definition: MinitScript.h:5073
static bool getFunctionValue(const span< Variable > &arguments, int idx, string &function, int &scriptIdx, bool optional=false)
Get function value from given variable.
Definition: MinitScript.h:4717
void startErrorScript()
Start error script.
Definition: MinitScript.h:4499
static DataType * getDataTypeByClassName(const string &className)
Returns data type by class name or nullptr.
Definition: MinitScript.h:4385
bool validateContextFunctions(const string &function, vector< string > &functionStack)
Validate context functions.
void executeStateMachine()
Execute state machine.
const vector< Method * > getOperatorMethods()
static bool hasType(const span< Variable > &arguments, VariableType type)
Check if arguments contain argument with given type.
Definition: MinitScript.h:4648
static void unsetConstant(Variable &variable)
Set variable recursively to be a non constant.
Definition: MinitScript.h:4264
static const string decodeOperator(const span< MinitScript::Variable > &arguments, int operatorValueIdx, const string &defaultOperatorString)
Decode operator.
Definition: MinitScript.h:3192
static void unsetConstantInternal(Variable &variable)
Set variable recursively to be a non constant.
void complainOperator(const string &methodName, const string &operatorString, const SubStatement &subStatement)
Complain about operator usage.
void resetScriptExecutationState(int scriptIdx, StateMachineStateId stateMachineState)
Reset script execution state.
Definition: MinitScript.h:3335
void setVariableInternal(const string &variableStatement, Variable *parentVariable, Variable *variablePtr, int64_t arrayIdx, const string &key, const Variable &variable, const SubStatement *subStatement=nullptr, bool createReference=false)
Set variable internal.
static bool getStackletValue(const span< Variable > &arguments, int idx, string &stacklet, int &scriptIdx, bool optional=false)
Get stacklet value from given variable.
Definition: MinitScript.h:4732
bool setupFunctionAndStackletScriptIndices(int scriptIdx)
Setup function and stacket script indices.
static bool viewIsCall(const string_view &candidate)
Returns if a given string is a method/function call.
Definition: MinitScript.h:4226
static constexpr int SETACCESSBOOL_TRUE
Definition: MinitScript.h:3049
virtual int determineNamedScriptIdxToStart()
Determine named script index to start.
const vector< Script > & getScripts()
Definition: MinitScript.h:4471
const Variable initializeVariable(const Variable &variable)
Initialize variable.
static constexpr int STATEMENTIDX_NONE
Definition: MinitScript.h:2990
Variable executeStatement(const SyntaxTreeNode &syntaxTree, const Statement &statement)
Execute a statement.
bool createStatementSyntaxTree(int scriptIdx, const string_view &methodName, const vector< ParserArgument > &arguments, const Statement &statement, SyntaxTreeNode &syntaxTree, int subLineIdx=0)
Create statement syntax tree.
void setConstant(const string &variableStatement, const Variable &variable)
Set constant by given variable statement and variable.
Definition: MinitScript.h:5060
vector< unique_ptr< ScriptState > > scriptStateStack
Definition: MinitScript.h:3122
static bool hasTypeForOperatorArguments(const span< Variable > &arguments, VariableType type)
Checks if left and right operator arguments have given type.
Definition: MinitScript.h:4659
static bool getIntegerValue(const span< Variable > &arguments, int idx, int64_t &value, bool optional=false)
Get integer value from given variable.
Definition: MinitScript.h:4688
const string deescape(const string_view &str, const Statement &statement)
Deescape string.
Definition: MinitScript.h:3923
virtual int determineScriptIdxToStart()
Determine script index to start.
bool evaluate(const string &evaluateStatement, Variable &returnValue)
Evaluate statement.
Definition: MinitScript.h:5266
static MINITSCRIPT_STATIC_DLL_IMPEXT const string METHOD_ENABLENAMEDCONDITION
Definition: MinitScript.h:2998
static constexpr int SETACCESSBOOL_NONE
Definition: MinitScript.h:3048
void executeNextStatement()
Execute next statement.
MinitScript script script methods.
Definition: ScriptMethods.h:12
MinitScript transpiler.
Definition: Transpiler.h:28
static bool isSpace(uint32_t character)
Returns if character is a white space.
Definition: Character.h:50
static void appendToString(string &string, uint32_t character)
Appends a character / code point to given string.
Definition: Character.h:70
static bool isAlphaNumeric(uint32_t character)
Returns if character is alpha numeric.
Definition: Character.h:42
static void printLine()
Print newline to console.
Definition: Console.cpp:66
static bool viewIs(const string_view &str)
Check if given string is a float string.
Definition: Float.cpp:39
static float viewParse(const string_view &str)
Parse float.
Definition: Float.cpp:70
static float parse(const string &str)
Parse float.
Definition: Float.cpp:53
static bool is(const string &str)
Check if given string is a float string.
Definition: Float.cpp:26
Integer to hex string conversion utility class.
Definition: Hex.h:16
static uint64_t decodeInt(const string &encodedString)
Decodes a hex string representation to an 64 bit unsigned integer.
Definition: Hex.h:35
static bool viewIs(const string_view &str)
Check if given string is a integer string.
Definition: Integer.cpp:39
static int parse(const string &str)
Parse integer.
Definition: Integer.cpp:52
static int viewParse(const string_view &str)
Parse integer.
Definition: Integer.cpp:59
static bool is(const string &str)
Check if given string is a integer string.
Definition: Integer.cpp:26
static const string substring(const string &str, int64_t beginIndex)
Returns substring of given string from begin index.
Definition: StringTools.h:203
static const string_view viewSubstring(const string_view &str, int64_t beginIndex)
Returns substring of given string from begin index.
Definition: StringTools.h:213
static const string toLowerCase(const string &str)
Transform string to lower case.
Definition: StringTools.cpp:94
static const bool viewEndsWith(const string_view &str, const string_view &suffix)
Checks if string ends with suffix.
Definition: StringTools.h:61
static const string indent(const string &str, const string &with, int64_t count)
Indent a string.
Definition: StringTools.h:344
static const string replace(const string &str, const char what, const char by, int64_t beginIndex=0)
Replace char with another char.
Definition: StringTools.cpp:33
static const bool viewStartsWith(const string_view &str, const string_view &prefix)
Checks if string starts with prefix.
Definition: StringTools.h:39
static const vector< string > tokenize(const string &str, const string &delimiters, bool emptyTokens=false)
Tokenize.
Time utility class.
Definition: Time.h:20
static int64_t getCurrentMillis()
Retrieve current time in milliseconds.
Definition: Time.h:27
#define MINITSCRIPT_STATIC_DLL_IMPEXT
Definition: minitscript.h:18
#define _FORBID_CLASS_COPY(CLASS)
Definition: minitscript.h:9
std::exception Exception
Exception base class.
Definition: Exception.h:18
GarbageCollectionDataType(DataType *dataType, DataType::ScriptContext *context)
Constructor.
Definition: MinitScript.h:3553
ParserArgument(const string_view &argument, int subLineIdx)
Constructor.
Definition: MinitScript.h:3579
Block(Type type, bool match, const Statement *continueStatement, const Statement *breakStatement, const Variable &parameter)
Constructor.
Definition: MinitScript.h:3076
unordered_map< string, Variable * > variables
Definition: MinitScript.h:3109
unordered_map< int, int64_t > forTimeStarted
Definition: MinitScript.h:3110
Argument(const string &name, bool reference, bool privateScope)
Constructor.
Definition: MinitScript.h:2910
Script(Type type, int line, const string &condition, const string &executableCondition, Statement conditionStatement, SyntaxTreeNode conditionSyntaxTree, const string &name, bool emitCondition, const vector< Statement > &statements, const vector< SyntaxTreeNode > &syntaxTree, bool callable, const vector< Argument > &arguments)
Constructor.
Definition: MinitScript.h:2941
Statement(int line, int statementIdx, const string &statement, const string &executableStatement, int gotoStatementIdx)
Constructor.
Definition: MinitScript.h:138
SubStatement(const Statement &statement, int subLineIdx)
Sub statement.
Definition: MinitScript.h:175
SyntaxTreeNode(Type type, const Variable &value, uint64_t scriptIdx, const vector< SyntaxTreeNode > &arguments, int subLineIdx)
Constructor.
Definition: MinitScript.h:2849
void setScriptIdx(uint64_t scriptIdx)
Set function/stacklet script index.
Definition: MinitScript.h:2885
SyntaxTreeNode(Type type, const Variable &value, Method *method, const vector< SyntaxTreeNode > &arguments, int subLineIdx)
Constructor.
Definition: MinitScript.h:2828