MinitScript  0.9.31 PRE-BETA
BaseMethods.cpp
Go to the documentation of this file.
1 #include <span>
2 #include <unordered_map>
3 #include <vector>
4 
12 
13 using std::span;
14 using std::unordered_map;
15 using std::vector;
16 
18 
20 
25 
26 void BaseMethods::registerConstants(MinitScript* minitScript) {
27  minitScript->setConstant("$___NULL", MinitScript::Variable());
28  minitScript->setConstant("$___ARRAY", MinitScript::Variable(vector<MinitScript::Variable*>()));
29  minitScript->setConstant("$___MAP", MinitScript::Variable(unordered_map<string, MinitScript::Variable*>()));
30 }
31 
32 void BaseMethods::registerMethods(MinitScript* minitScript) {
33  // script internal base methods
34  {
35  //
36  class MethodInternalScriptEvaluate: public MinitScript::Method {
37  private:
38  MinitScript* minitScript { nullptr };
39  public:
40  MethodInternalScriptEvaluate(MinitScript* minitScript):
42  {
43  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "statement", .optional = false, .reference = false, .nullable = false }
44  },
45  MinitScript::TYPE_PSEUDO_MIXED
46  ),
47  minitScript(minitScript) {}
48  const string getMethodName() override {
49  return "internal.script.evaluate";
50  }
51  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
52  if (arguments.size() != 1) {
53  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
54  } else
55  if (arguments.size() == 1) {
56  returnValue.setValue(arguments[0]);
57  }
58  }
59  bool isPrivate() const override {
60  return true;
61  }
62  };
63  minitScript->registerMethod(new MethodInternalScriptEvaluate(minitScript));
64  }
65  {
66  //
67  class MethodInternalEvaluateMemberAccess: public MinitScript::Method {
68  private:
69  MinitScript* minitScript { nullptr };
70  public:
71  MethodInternalEvaluateMemberAccess(MinitScript* minitScript):
73  {
74  { .type = MinitScript::TYPE_STRING, .name = "variable", .optional = false, .reference = false, .nullable = true },
75  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "this", .optional = false, .reference = false, .nullable = true },
76  { .type = MinitScript::TYPE_STRING, .name = "member", .optional = false, .reference = false, .nullable = false }
77  },
78  MinitScript::TYPE_PSEUDO_MIXED,
79  true
80  ),
81  minitScript(minitScript) {}
82  const string getMethodName() override {
83  return "internal.script.evaluateMemberAccess";
84  }
85  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
86  // Current layout:
87  // 0: variable name of object, 1: variable content of object
88  // 2: object method to call
89  // 3: variable name of argument 0; 4: variable content of argument 0
90  // 5: variable name of argument 1; 6: variable content of argument 1
91  // ..
92  //
93  string variable;
94  string member;
95  //
96  if (arguments.size() < 3 ||
97  minitScript->getStringValue(arguments, 2, member, false) == false) {
98  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
99  } else {
100  // complain?
101  auto complain = true;
102  // do we have a this variable name?
103  string thisVariableName;
104  {
105  if (arguments[0].getType() != MinitScript::TYPE_NULL && arguments[0].getStringValue(thisVariableName) == true) {
106  // yep, looks like that, we always use a reference here
107  #if defined(__MINITSCRIPT_TRANSPILATION__)
108  arguments[1] = MinitScript::Variable::createReferenceVariable(&EVALUATEMEMBERACCESS_ARGUMENT0);
109  #else
110  arguments[1] = minitScript->getVariable(thisVariableName, &subStatement, true);
111  #endif
112  }
113  }
114  // check if map, if so fetch function assignment of member property
115  auto functionScriptIdx = MinitScript::SCRIPTIDX_NONE;
116  if (arguments[1].getType() == MinitScript::TYPE_MAP) {
117  string function;
118  auto mapValue = arguments[1].getMapEntry(member);
119  if (mapValue.getType() == MinitScript::TYPE_FUNCTION_ASSIGNMENT && mapValue.getFunctionValue(function, functionScriptIdx) == true) {
120  // check if private and private scope
121  if (mapValue.isPrivate() == true && arguments[1].isPrivateScope() == false) {
122  complain = false;
123  functionScriptIdx = MinitScript::SCRIPTIDX_NONE;
124  _Console::printLine(minitScript->getSubStatementInformation(subStatement) + ": Private variable: " + thisVariableName + ": access not allowed from outside of object");
125  } else
126  // no function idx, so get it
127  if (functionScriptIdx == MinitScript::SCRIPTIDX_NONE) functionScriptIdx = minitScript->getFunctionScriptIdx(function);
128  }
129  }
130  //
131  const auto& className = arguments[1].getTypeAsString();
132  //
133  if (className.empty() == false || functionScriptIdx != MinitScript::SCRIPTIDX_NONE) {
134  //
135  MinitScript::Method* method { nullptr };
136  if (functionScriptIdx == MinitScript::SCRIPTIDX_NONE) {
137  #if defined(__MINITSCRIPT_TRANSPILATION__)
138  method = evaluateMemberAccessArrays[static_cast<int>(arguments[1].getType()) - static_cast<int>(MinitScript::TYPE_STRING)][EVALUATEMEMBERACCESS_MEMBER];
139  #else
140  method = minitScript->getMethod(className + "::" + member);
141  #endif
142  }
143  if (method != nullptr || functionScriptIdx != MinitScript::SCRIPTIDX_NONE) {
144  // create method call arguments
145  vector<MinitScript::Variable> callArguments(1 + (arguments.size() - 3) / 2);
146  // this
147  callArguments[0] = move(arguments[1]);
148  // additional method call arguments
149  {
150  auto callArgumentIdx = 1;
151  for (auto argumentIdx = 3; argumentIdx < arguments.size(); argumentIdx+=2) {
152  // do we have a this variable name?
153  string argumentVariableName;
154  if (arguments[argumentIdx].getType() != MinitScript::TYPE_NULL && arguments[argumentIdx].getStringValue(argumentVariableName) == true) {
155  #if defined(__MINITSCRIPT_TRANSPILATION__)
156  if (method != nullptr) {
157  arguments[argumentIdx + 1] =
158  callArgumentIdx >= method->getArgumentTypes().size() || method->getArgumentTypes()[callArgumentIdx].reference == false?
159  MinitScript::Variable::createNonReferenceVariable(&EVALUATEMEMBERACCESS_ARGUMENTS[callArgumentIdx - 1]):
160  EVALUATEMEMBERACCESS_ARGUMENTS[callArgumentIdx - 1];
161  } else
162  if (functionScriptIdx != MinitScript::SCRIPTIDX_NONE) {
163  arguments[argumentIdx + 1] =
164  callArgumentIdx >= minitScript->getScripts()[functionScriptIdx].arguments.size() || minitScript->getScripts()[functionScriptIdx].arguments[callArgumentIdx].reference == false?
165  MinitScript::Variable::createNonReferenceVariable(&EVALUATEMEMBERACCESS_ARGUMENTS[callArgumentIdx - 1]):
166  EVALUATEMEMBERACCESS_ARGUMENTS[callArgumentIdx - 1];
167  }
168  #else
169  // yep, looks like that
170  if (method != nullptr) {
171  arguments[argumentIdx + 1] = minitScript->getVariable(argumentVariableName, &subStatement, callArgumentIdx >= method->getArgumentTypes().size()?false:method->getArgumentTypes()[callArgumentIdx].reference);
172  } else
173  if (functionScriptIdx != MinitScript::SCRIPTIDX_NONE) {
174  arguments[argumentIdx + 1] = minitScript->getVariable(argumentVariableName, &subStatement, callArgumentIdx >= minitScript->getScripts()[functionScriptIdx].arguments.size()?false:minitScript->getScripts()[functionScriptIdx].arguments[callArgumentIdx].reference);
175  }
176  #endif
177  }
178  //
179  callArguments[callArgumentIdx] = move(arguments[argumentIdx + 1]);
180  callArgumentIdx++;
181  }
182  }
183  //
184  span callArgumentsSpan(callArguments);
185  //
186  if (method != nullptr) {
187  method->executeMethod(callArgumentsSpan, returnValue, subStatement);
188  } else
189  if (functionScriptIdx != MinitScript::SCRIPTIDX_NONE) {
190  minitScript->call(functionScriptIdx, callArgumentsSpan, returnValue);
191  }
192  // write back arguments from call arguments
193  // this
194  arguments[1] = move(callArgumentsSpan[0]);
195  // additional arguments
196  {
197  auto callArgumentIdx = 1;
198  for (auto argumentIdx = 3; argumentIdx < arguments.size(); argumentIdx+=2) {
199  arguments[argumentIdx] = move(callArgumentsSpan[callArgumentIdx]);
200  callArgumentIdx++;
201  }
202  }
203  } else {
204  if (complain == true) {
205  MINITSCRIPT_METHODUSAGE_COMPLAINM(getMethodName(), "Class/object member not found: " + member + "()");
206  }
207  }
208  } else {
209  if (complain == true) {
210  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
211  }
212  }
213  }
214  }
215  bool isVariadic() const override {
216  return true;
217  }
218  bool isPrivate() const override {
219  return true;
220  }
221  };
222  minitScript->registerMethod(new MethodInternalEvaluateMemberAccess(minitScript));
223  }
224  {
225  //
226  class MethodInternalScriptCallStacklet: public MinitScript::Method {
227  private:
228  MinitScript* minitScript { nullptr };
229  public:
230  MethodInternalScriptCallStacklet(MinitScript* minitScript):
232  {
233  { .type = MinitScript::TYPE_STACKLET_ASSIGNMENT, .name = "stacklet", .optional = false, .reference = false, .nullable = false }
234  },
235  MinitScript::TYPE_PSEUDO_MIXED
236  ),
237  minitScript(minitScript) {}
238  const string getMethodName() override {
239  return "internal.script.callStacklet";
240  }
241  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
242  string stacklet;
243  auto stackletScriptIdx = MinitScript::SCRIPTIDX_NONE;
244  if (arguments.size() == 1 &&
245  minitScript->getStackletValue(arguments, 0, stacklet, stackletScriptIdx) == true) {
246  if (stackletScriptIdx == MinitScript::SCRIPTIDX_NONE) {
247  stackletScriptIdx = minitScript->getFunctionScriptIdx(stacklet);
248  }
249  if (stackletScriptIdx == MinitScript::SCRIPTIDX_NONE || minitScript->getScripts()[stackletScriptIdx].type != MinitScript::Script::TYPE_STACKLET) {
250  MINITSCRIPT_METHODUSAGE_COMPLAINM(getMethodName(), "Stacklet not found: " + stacklet);
251  } else {
252  vector<MinitScript::Variable> callArguments(0);
253  span callArgumentsSpan(callArguments);
254  minitScript->callStacklet(stackletScriptIdx, callArgumentsSpan, returnValue);
255  }
256  } else {
257  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
258  }
259  }
260  bool isPrivate() const override {
261  return true;
262  }
263  };
264  minitScript->registerMethod(new MethodInternalScriptCallStacklet(minitScript));
265  }
266  // base methods
267  {
268  //
269  class MethodReturn: public MinitScript::Method {
270  private:
271  MinitScript* minitScript { nullptr };
272  public:
273  MethodReturn(MinitScript* minitScript):
275  {
276  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "value", .optional = true, .reference = false, .nullable = false }
277  },
278  MinitScript::TYPE_NULL
279  ),
280  minitScript(minitScript) {}
281  const string getMethodName() override {
282  return "return";
283  }
284  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
285  if (arguments.size() == 0 || arguments.size() == 1) {
286  if (minitScript->isFunctionRunning() == false) {
287  MINITSCRIPT_METHODUSAGE_COMPLAINM(getMethodName(), "No function is being executed, return($value) has no effect");
288  } else
289  if (arguments.size() == 1) minitScript->getScriptState().returnValue.setValue(arguments[0]);
290  minitScript->stopRunning();
291  } else {
292  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
293  }
294  }
295  };
296  minitScript->registerMethod(new MethodReturn(minitScript));
297  }
298  {
299  //
300  class MethodBreak: public MinitScript::Method {
301  private:
302  MinitScript* minitScript { nullptr };
303  public:
304  MethodBreak(MinitScript* minitScript):
306  {
307  { .type = MinitScript::TYPE_INTEGER, .name = "levels", .optional = true, .reference = false, .nullable = false }
308  }
309  ),
310  minitScript(minitScript) {}
311  const string getMethodName() override {
312  return "break";
313  }
314  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
315  int64_t levels = 1;
316  if ((arguments.size() == 0 || arguments.size() == 1) &&
317  MinitScript::getIntegerValue(arguments, 0, levels, true) == true) {
318  if (minitScript->getScriptState().blockStack.empty() == true) {
319  MINITSCRIPT_METHODUSAGE_COMPLAINM(getMethodName(), "break without forCondition/forTime");
320  } else {
321  int64_t level = 0;
322  auto& blockStack = minitScript->getScriptState().blockStack;
323  MinitScript::ScriptState::Block* endType = nullptr;
324  vector<int> blockStacksToRemove;
325  for (int i = blockStack.size() - 1; i >= 0; i--) {
326  if (blockStack[i].type == MinitScript::ScriptState::Block::TYPE_FOR) {
327  endType = &blockStack[i];
328  level++;
329  blockStacksToRemove.push_back(i);
330  if (level == levels) break;
331  } else
332  if (level < levels) {
333  blockStacksToRemove.push_back(i);
334  }
335  }
336  if (endType == nullptr) {
337  MINITSCRIPT_METHODUSAGE_COMPLAINM(getMethodName(), "break without forCondition, forTime");
338  } else
339  if (levels != level) {
340  MINITSCRIPT_METHODUSAGE_COMPLAINM(getMethodName(), "break(" + to_string(levels) + ") + without " + to_string(levels) + " levels of forCondition, forTime");
341  } else
342  if (endType->breakStatement != nullptr) {
343  auto breakStatement = endType->breakStatement;
344  for (auto i: blockStacksToRemove) blockStack.erase(blockStack.begin() + i);
345  minitScript->gotoStatement(*breakStatement);
346  } else {
347  MINITSCRIPT_METHODUSAGE_COMPLAINM(getMethodName(), "No break statement");
348  }
349  }
350  } else {
351  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
352  }
353  }
354  };
355  minitScript->registerMethod(new MethodBreak(minitScript));
356  }
357  {
358  //
359  class MethodContinue: public MinitScript::Method {
360  private:
361  MinitScript* minitScript { nullptr };
362  public:
363  MethodContinue(MinitScript* minitScript):
365  {
366  { .type = MinitScript::TYPE_INTEGER, .name = "levels", .optional = true, .reference = false, .nullable = false }
367  }
368  ),
369  minitScript(minitScript) {}
370  const string getMethodName() override {
371  return "continue";
372  }
373  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
374  int64_t levels = 1;
375  if ((arguments.size() == 0 || arguments.size() == 1) &&
376  MinitScript::getIntegerValue(arguments, 0, levels, true) == true) {
377  if (minitScript->getScriptState().blockStack.empty() == true) {
378  MINITSCRIPT_METHODUSAGE_COMPLAINM(getMethodName(), "continue without forCondition, forTime");
379  } else {
380  int64_t level = 0;
381  auto& blockStack = minitScript->getScriptState().blockStack;
382  MinitScript::ScriptState::Block* endType = nullptr;
383  vector<int> blockStacksToRemove;
384  for (int i = blockStack.size() - 1; i >= 0; i--) {
385  if (blockStack[i].type == MinitScript::ScriptState::Block::TYPE_FOR) {
386  endType = &blockStack[i];
387  level++;
388  if (level == levels) {
389  break;
390  } else {
391  blockStacksToRemove.push_back(i);
392  }
393  } else
394  if (level < levels) {
395  blockStacksToRemove.push_back(i);
396  }
397  }
398  if (endType == nullptr) {
399  MINITSCRIPT_METHODUSAGE_COMPLAINM(getMethodName(), "continue without forCondition, forTime");
400  } else
401  if (levels != level) {
402  MINITSCRIPT_METHODUSAGE_COMPLAINM(getMethodName(), "continue(" + to_string(levels) + ") + without " + to_string(levels) + " levels of forCondition, forTime");
403  } else
404  if (endType->continueStatement != nullptr) {
405  auto continueStatement = endType->continueStatement;
406  for (auto i: blockStacksToRemove) blockStack.erase(blockStack.begin() + i);
407  minitScript->gotoStatement(*continueStatement);
408  } else {
409  MINITSCRIPT_METHODUSAGE_COMPLAINM(getMethodName(), "No continue statement");
410  }
411  }
412  } else {
413  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
414  }
415  }
416  };
417  minitScript->registerMethod(new MethodContinue(minitScript));
418  }
419  {
420  //
421  class MethodEnd: public MinitScript::Method {
422  private:
423  MinitScript* minitScript { nullptr };
424  public:
425  MethodEnd(MinitScript* minitScript): MinitScript::Method(), minitScript(minitScript) {}
426  const string getMethodName() override {
427  return "end";
428  }
429  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
430  if (arguments.size() == 0) {
431  if (minitScript->getScriptState().blockStack.empty() == true) {
432  MINITSCRIPT_METHODUSAGE_COMPLAINM(getMethodName(), "end without if/elseif/else/switch/case/default/forCondition/forTime/end");
433  } else {
434  auto& blockStack = minitScript->getScriptState().blockStack;
435  auto& block = blockStack.back();
436  if (block.type == MinitScript::ScriptState::Block::TYPE_FUNCTION || block.type == MinitScript::ScriptState::Block::TYPE_STACKLET) {
437  minitScript->stopRunning();
438  } else
439  if (block.type == MinitScript::ScriptState::Block::TYPE_FOR && block.parameter.getType() == MinitScript::TYPE_INTEGER) {
440  vector<MinitScript::Variable> arguments {};
441  span argumentsSpan(arguments);
442  MinitScript::Variable returnValue;
443  int64_t iterationStackletScriptIdx;
444  if (block.parameter.getIntegerValue(iterationStackletScriptIdx) == true &&
445  iterationStackletScriptIdx != MinitScript::SCRIPTIDX_NONE) {
446  minitScript->callStacklet(iterationStackletScriptIdx, argumentsSpan, returnValue);
447  } else {
448  MINITSCRIPT_METHODUSAGE_COMPLAINM(getMethodName(), "end with for: iteration stacklet: invalid stacklet");
449  }
450  }
451  blockStack.erase(blockStack.begin() + blockStack.size() - 1);
452  if (minitScript->hasEmitted() == false &&
453  subStatement.statement->gotoStatementIdx != MinitScript::STATEMENTIDX_NONE) {
454  minitScript->gotoStatementGoto(*subStatement.statement);
455  }
456  }
457  } else {
458  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
459  }
460  }
461  };
462  minitScript->registerMethod(new MethodEnd(minitScript));
463  }
464  {
465  //
466  class MethodForTime: public MinitScript::Method {
467  private:
468  MinitScript* minitScript { nullptr };
469  public:
470  MethodForTime(MinitScript* minitScript):
472  {
473  { .type = MinitScript::TYPE_INTEGER, .name = "time", .optional = false, .reference = false, .nullable = false }
474  }
475  ),
476  minitScript(minitScript) {}
477  const string getMethodName() override {
478  return "forTime";
479  }
480  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
481  int64_t time;
482  if (arguments.size() == 1 &&
483  minitScript->getIntegerValue(arguments, 0, time) == true) {
484  auto& scriptState = minitScript->getScriptState();
485  auto now = _Time::getCurrentMillis();
486  auto timeWaitStarted = now;
487  auto forTimeStartedIt = scriptState.forTimeStarted.find(subStatement.statement->line);
488  if (forTimeStartedIt == scriptState.forTimeStarted.end()) {
489  minitScript->getScriptState().forTimeStarted[subStatement.statement->line] = timeWaitStarted;
490  } else {
491  timeWaitStarted = forTimeStartedIt->second;
492  }
493  //
494  if (_Time::getCurrentMillis() > timeWaitStarted + time) {
495  scriptState.forTimeStarted.erase(subStatement.statement->line);
496  minitScript->gotoStatementGoto(*subStatement.statement);
497  } else {
498  scriptState.blockStack.emplace_back(
499  MinitScript::ScriptState::Block::TYPE_FORTIME,
500  false,
501  &minitScript->getScripts()[scriptState.scriptIdx].statements[subStatement.statement->gotoStatementIdx - 1],
502  &minitScript->getScripts()[scriptState.scriptIdx].statements[subStatement.statement->gotoStatementIdx],
504  );
505  }
506  } else {
507  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
508  }
509  }
510  };
511  minitScript->registerMethod(new MethodForTime(minitScript));
512  }
513  {
514  //
515  class MethodForCondition: public MinitScript::Method {
516  private:
517  MinitScript* minitScript { nullptr };
518  public:
519  MethodForCondition(MinitScript* minitScript):
521  {
522  { .type = MinitScript::TYPE_BOOLEAN, .name = "condition", .optional = false, .reference = false, .nullable = false },
523  { .type = MinitScript::TYPE_STACKLET_ASSIGNMENT, .name = "iterationStacklet", .optional = true, .reference = false, .nullable = false }
524  }
525  ),
526  minitScript(minitScript) {}
527  const string getMethodName() override {
528  return "forCondition";
529  }
530  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
531  bool booleanValue;
532  string iterationStacklet;
533  auto iterationStackletScriptIdx = MinitScript::SCRIPTIDX_NONE;
534  if ((arguments.size() == 1 || arguments.size() == 2) &&
535  minitScript->getBooleanValue(arguments, 0, booleanValue) == true &&
536  minitScript->getStackletValue(arguments, 1, iterationStacklet, iterationStackletScriptIdx, true) == true) {
537  if (booleanValue == false) {
538  minitScript->gotoStatementGoto(*subStatement.statement);
539  } else {
540  if (iterationStacklet.empty() == false && iterationStackletScriptIdx == MinitScript::SCRIPTIDX_NONE) {
541  iterationStackletScriptIdx = minitScript->getFunctionScriptIdx(iterationStacklet);
542  }
543  // check if valid
544  if (iterationStacklet.empty() == false && iterationStackletScriptIdx == MinitScript::SCRIPTIDX_NONE) {
545  MINITSCRIPT_METHODUSAGE_COMPLAINM(getMethodName(), "Stacklet not found: " + iterationStacklet);
546  } else {
547  auto& scriptState = minitScript->getScriptState();
548  scriptState.blockStack.emplace_back(
549  MinitScript::ScriptState::Block::TYPE_FOR,
550  false,
551  &minitScript->getScripts()[scriptState.scriptIdx].statements[subStatement.statement->gotoStatementIdx - 1],
552  &minitScript->getScripts()[scriptState.scriptIdx].statements[subStatement.statement->gotoStatementIdx],
553  iterationStacklet.empty() == true?MinitScript::Variable():MinitScript::Variable(static_cast<int64_t>(iterationStackletScriptIdx))
554  );
555  }
556  }
557  } else {
558  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
559  }
560  }
561  };
562  minitScript->registerMethod(new MethodForCondition(minitScript));
563  }
564  {
565  //
566  class MethodIfCondition: public MinitScript::Method {
567  private:
568  MinitScript* minitScript { nullptr };
569  public:
570  MethodIfCondition(MinitScript* minitScript):
572  {
573  { .type = MinitScript::TYPE_BOOLEAN, .name = "condition", .optional = false, .reference = false, .nullable = false }
574  }
575  ),
576  minitScript(minitScript) {}
577  const string getMethodName() override {
578  return "if";
579  }
580  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
581  bool booleanValue;
582  if (arguments.size() == 1 &&
583  minitScript->getBooleanValue(arguments, 0, booleanValue) == true) {
584  minitScript->getScriptState().blockStack.emplace_back(MinitScript::ScriptState::Block::TYPE_IF, booleanValue, nullptr, nullptr, MinitScript::Variable());
585  if (booleanValue == false) {
586  minitScript->gotoStatementGoto(*subStatement.statement);
587  }
588  } else {
589  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
590  }
591  }
592  };
593  minitScript->registerMethod(new MethodIfCondition(minitScript));
594  }
595  {
596  //
597  class MethodElseIfCondition: public MinitScript::Method {
598  private:
599  MinitScript* minitScript { nullptr };
600  public:
601  MethodElseIfCondition(MinitScript* minitScript):
603  {
604  { .type = MinitScript::TYPE_BOOLEAN, .name = "condition", .optional = false, .reference = false, .nullable = false }
605  }
606  ),
607  minitScript(minitScript) {}
608  const string getMethodName() override {
609  return "elseif";
610  }
611  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
612  bool booleanValue;
613  if (arguments.size() == 1 &&
614  minitScript->getBooleanValue(arguments, 0, booleanValue) == true) {
615  auto& scriptState = minitScript->getScriptState();
616  if (minitScript->getScriptState().blockStack.empty() == true) {
617  MINITSCRIPT_METHODUSAGE_COMPLAINM(getMethodName(), "elseif without if");
618  } else {
619  auto& block = scriptState.blockStack.back();
620  if (block.type != MinitScript::ScriptState::Block::TYPE_IF) {
621  MINITSCRIPT_METHODUSAGE_COMPLAINM(getMethodName(), "elseif without if");
622  } else
623  if (block.match == true || booleanValue == false) {
624  minitScript->gotoStatementGoto(*subStatement.statement);
625  } else {
626  block.match = booleanValue;
627  }
628  }
629  } else {
630  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
631  }
632  }
633  };
634  minitScript->registerMethod(new MethodElseIfCondition(minitScript));
635  }
636  {
637  //
638  class MethodElse: public MinitScript::Method {
639  private:
640  MinitScript* minitScript { nullptr };
641  public:
642  MethodElse(MinitScript* minitScript): MinitScript::Method(), minitScript(minitScript) {}
643  const string getMethodName() override {
644  return "else";
645  }
646  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
647  if (arguments.size() == 0) {
648  auto& scriptState = minitScript->getScriptState();
649  auto& block = scriptState.blockStack.back();
650  if (block.type != MinitScript::ScriptState::Block::TYPE_IF) {
651  MINITSCRIPT_METHODUSAGE_COMPLAINM(getMethodName(), "else without if");
652  } else
653  if (block.match == true) {
654  minitScript->gotoStatementGoto(*subStatement.statement);
655  }
656  } else {
657  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
658  }
659  }
660  };
661  minitScript->registerMethod(new MethodElse(minitScript));
662  }
663  // switch
664  {
665  //
666  class MethodSwitch: public MinitScript::Method {
667  private:
668  MinitScript* minitScript { nullptr };
669  public:
670  MethodSwitch(MinitScript* minitScript):
672  {
673  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "value", .optional = false, .reference = false, .nullable = false }
674  }
675  ),
676  minitScript(minitScript) {}
677  const string getMethodName() override {
678  return "switch";
679  }
680  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
681  if (arguments.size() == 1) {
682  auto& scriptState = minitScript->getScriptState();
683  scriptState.blockStack.emplace_back(MinitScript::ScriptState::Block::TYPE_SWITCH, false, nullptr, nullptr, arguments[0]);
684  } else {
685  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
686  }
687  }
688  };
689  minitScript->registerMethod(new MethodSwitch(minitScript));
690  }
691  {
692  //
693  class MethodCase: public MinitScript::Method {
694  private:
695  MinitScript* minitScript { nullptr };
696  public:
697  MethodCase(MinitScript* minitScript):
699  {
700  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "value", .optional = false, .reference = false, .nullable = false }
701  }
702  ),
703  minitScript(minitScript) {}
704  const string getMethodName() override {
705  return "case";
706  }
707  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
708  if (arguments.size() == 1) {
709  auto& scriptState = minitScript->getScriptState();
710  if (minitScript->getScriptState().blockStack.empty() == true) {
711  MINITSCRIPT_METHODUSAGE_COMPLAINM(getMethodName(), "case without switch");
712  } else {
713  auto& block = scriptState.blockStack.back();
714  if (block.type != MinitScript::ScriptState::Block::TYPE_SWITCH) {
715  MINITSCRIPT_METHODUSAGE_COMPLAINM(getMethodName(), "case without switch");
716  } else {
717  auto match = arguments[0].getValueAsString() == block.parameter.getValueAsString();
718  if (block.match == true || match == false) {
719  minitScript->gotoStatementGoto(*subStatement.statement);
720  } else {
721  block.match = match;
722  scriptState.blockStack.emplace_back(MinitScript::ScriptState::Block::TYPE_CASE, false, nullptr, nullptr, MinitScript::Variable());
723  }
724  }
725  }
726  } else {
727  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
728  }
729  }
730  };
731  minitScript->registerMethod(new MethodCase(minitScript));
732  }
733  {
734  //
735  class MethodDefault: public MinitScript::Method {
736  private:
737  MinitScript* minitScript { nullptr };
738  public:
739  MethodDefault(MinitScript* minitScript): MinitScript::Method(), minitScript(minitScript) {}
740  const string getMethodName() override {
741  return "default";
742  }
743  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
744  if (arguments.size() == 0) {
745  auto& scriptState = minitScript->getScriptState();
746  if (minitScript->getScriptState().blockStack.empty() == true) {
747  MINITSCRIPT_METHODUSAGE_COMPLAINM(getMethodName(), "default without switch");
748  } else {
749  auto& block = scriptState.blockStack.back();
750  if (block.type != MinitScript::ScriptState::Block::TYPE_SWITCH) {
751  MINITSCRIPT_METHODUSAGE_COMPLAINM(getMethodName(), "default without switch");
752  } else
753  if (block.match == true) {
754  minitScript->gotoStatementGoto(*subStatement.statement);
755  }
756  }
757  } else {
758  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
759  }
760  }
761  };
762  minitScript->registerMethod(new MethodDefault(minitScript));
763  }
764  // equality
765  {
766  //
767  class MethodEquals: public MinitScript::Method {
768  private:
769  MinitScript* minitScript { nullptr };
770  public:
771  MethodEquals(MinitScript* minitScript):
773  {
774  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "a", .optional = false, .reference = false, .nullable = false },
775  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "b", .optional = false, .reference = false, .nullable = false },
776  { .type = MinitScript::TYPE_INTEGER, .name = "operator", .optional = true, .reference = false, .nullable = false }
777  },
778  MinitScript::TYPE_BOOLEAN
779  ),
780  minitScript(minitScript) {}
781  const string getMethodName() override {
782  return "equals";
783  }
784  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
785  if (arguments.size() == 2 || arguments.size() == 3) {
786  returnValue.setValue(true);
787  for (auto i = 1; i < 2; i++) {
788  if (arguments[0].getValueAsString() != arguments[i].getValueAsString()) {
789  returnValue.setValue(false);
790  break;
791  }
792  }
793  } else {
794  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
795  }
796  }
797  MinitScript::Operator getOperator() const override {
798  return MinitScript::OPERATOR_EQUALS;
799  }
800  };
801  minitScript->registerMethod(new MethodEquals(minitScript));
802  }
803  {
804  //
805  class MethodNotEqual: public MinitScript::Method {
806  private:
807  MinitScript* minitScript { nullptr };
808  public:
809  MethodNotEqual(MinitScript* minitScript):
811  {
812  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "a", .optional = false, .reference = false, .nullable = false },
813  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "b", .optional = false, .reference = false, .nullable = false },
814  { .type = MinitScript::TYPE_INTEGER, .name = "operator", .optional = true, .reference = false, .nullable = false }
815  },
816  MinitScript::TYPE_BOOLEAN
817  ),
818  minitScript(minitScript) {}
819  const string getMethodName() override {
820  return "notEqual";
821  }
822  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
823  if (arguments.size() == 2 || arguments.size() == 3) {
824  returnValue.setValue(true);
825  for (auto i = 1; i < 2; i++) {
826  if (arguments[0].getValueAsString() == arguments[i].getValueAsString()) {
827  returnValue.setValue(false);
828  break;
829  }
830  }
831  } else {
832  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
833  }
834  }
835  MinitScript::Operator getOperator() const override {
836  return MinitScript::OPERATOR_NOTEQUAL;
837  }
838  };
839  minitScript->registerMethod(new MethodNotEqual(minitScript));
840  }
841  // int methods
842  {
843  //
844  class MethodInt: public MinitScript::Method {
845  private:
846  MinitScript* minitScript { nullptr };
847  public:
848  MethodInt(MinitScript* minitScript):
850  {
851  { .type = MinitScript::TYPE_INTEGER, .name = "integer", .optional = false, .reference = false, .nullable = false }
852  },
853  MinitScript::TYPE_INTEGER
854  ),
855  minitScript(minitScript) {}
856  const string getMethodName() override {
857  return "integer";
858  }
859  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
860  int64_t integerValue;
861  if (arguments.size() == 1 &&
862  MinitScript::getIntegerValue(arguments, 0, integerValue) == true) {
863  returnValue.setValue(integerValue);
864  } else {
865  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
866  }
867  }
868  };
869  minitScript->registerMethod(new MethodInt(minitScript));
870  }
871  // float methods
872  // TODO: move me into FloatMethods
873  {
874  //
875  class MethodFloat: public MinitScript::Method {
876  private:
877  MinitScript* minitScript { nullptr };
878  public:
879  MethodFloat(MinitScript* minitScript):
881  {
882  { .type = MinitScript::TYPE_FLOAT, .name = "float", .optional = false, .reference = false, .nullable = false }
883  },
884  MinitScript::TYPE_FLOAT
885  ),
886  minitScript(minitScript) {}
887  const string getMethodName() override {
888  return "float";
889  }
890  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
891  float floatValue;
892  if (arguments.size() == 1 &&
893  MinitScript::getFloatValue(arguments, 0, floatValue) == true) {
894  returnValue.setValue(floatValue);
895  } else {
896  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
897  }
898  }
899  };
900  minitScript->registerMethod(new MethodFloat(minitScript));
901  }
902  {
903  //
904  class MethodFloatToIntValue: public MinitScript::Method {
905  private:
906  MinitScript* minitScript { nullptr };
907  public:
908  MethodFloatToIntValue(MinitScript* minitScript):
910  {
911  { .type = MinitScript::TYPE_FLOAT, .name = "float", .optional = false, .reference = false, .nullable = false }
912  },
913  MinitScript::TYPE_INTEGER
914  ),
915  minitScript(minitScript) {}
916  const string getMethodName() override {
917  return "float.toIntegerValue";
918  }
919  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
920  float floatValue;
921  if (arguments.size() == 1 &&
922  MinitScript::getFloatValue(arguments, 0, floatValue) == true) {
923  returnValue.setValue(static_cast<int64_t>(*((uint32_t*)&floatValue)));
924  } else {
925  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
926  }
927  }
928  };
929  minitScript->registerMethod(new MethodFloatToIntValue(minitScript));
930  }
931  {
932  //
933  class MethodFloatfromIntValue: public MinitScript::Method {
934  private:
935  MinitScript* minitScript { nullptr };
936  public:
937  MethodFloatfromIntValue(MinitScript* minitScript):
939  {
940  { .type = MinitScript::TYPE_INTEGER, .name = "integer", .optional = false, .reference = false, .nullable = false }
941  },
942  MinitScript::TYPE_FLOAT
943  ),
944  minitScript(minitScript) {}
945  const string getMethodName() override {
946  return "float.fromIntegerValue";
947  }
948  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
949  int64_t intValue;
950  if (arguments.size() == 1 &&
951  MinitScript::getIntegerValue(arguments, 0, intValue) == true) {
952  returnValue.setValue(*((float*)&intValue));
953  } else {
954  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
955  }
956  }
957  };
958  minitScript->registerMethod(new MethodFloatfromIntValue(minitScript));
959  }
960  //
961  {
962  //
963  class MethodGreater: public MinitScript::Method {
964  private:
965  MinitScript* minitScript { nullptr };
966  public:
967  MethodGreater(MinitScript* minitScript):
969  {
970  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "a", .optional = false, .reference = false, .nullable = false },
971  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "b", .optional = false, .reference = false, .nullable = false },
972  { .type = MinitScript::TYPE_INTEGER, .name = "operator", .optional = true, .reference = false, .nullable = false }
973  },
974  MinitScript::TYPE_BOOLEAN),
975  minitScript(minitScript) {}
976  const string getMethodName() override {
977  return "greater";
978  }
979  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
980  if (arguments.size() == 2 || arguments.size() == 3) {
981  if (MinitScript::hasTypeForOperatorArguments(arguments, MinitScript::TYPE_STRING) == true) {
982  string stringValueA;
983  string stringValueB;
984  if (MinitScript::getStringValue(arguments, 0, stringValueA, false) == true &&
985  MinitScript::getStringValue(arguments, 1, stringValueB, false) == true) {
986  returnValue.setValue(stringValueA > stringValueB);
987  } else {
988  MINITSCRIPT_METHODUSAGE_COMPLAINOM(getMethodName(), MinitScript::decodeOperator(arguments, 2, getMethodName()), "Can not compare '" + arguments[0].getValueAsString() + "' with '" + arguments[1].getValueAsString() + "'");
989  }
990  } else {
991  float floatValueA;
992  float floatValueB;
993  if (MinitScript::getFloatValue(arguments, 0, floatValueA, false) == true &&
994  MinitScript::getFloatValue(arguments, 1, floatValueB, false) == true) {
995  returnValue.setValue(floatValueA > floatValueB);
996  } else {
997  MINITSCRIPT_METHODUSAGE_COMPLAINOM(getMethodName(), MinitScript::decodeOperator(arguments, 2, getMethodName()), "Can not compare '" + arguments[0].getValueAsString() + "' with '" + arguments[1].getValueAsString() + "'");
998  }
999  }
1000  } else {
1001  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
1002  }
1003  }
1004  MinitScript::Operator getOperator() const override {
1005  return MinitScript::OPERATOR_GREATER;
1006  }
1007  };
1008  minitScript->registerMethod(new MethodGreater(minitScript));
1009  }
1010  {
1011  //
1012  class MethodGreaterEquals: public MinitScript::Method {
1013  private:
1014  MinitScript* minitScript { nullptr };
1015  public:
1016  MethodGreaterEquals(MinitScript* minitScript):
1018  {
1019  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "a", .optional = false, .reference = false, .nullable = false },
1020  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "b", .optional = false, .reference = false, .nullable = false },
1021  { .type = MinitScript::TYPE_INTEGER, .name = "operator", .optional = true, .reference = false, .nullable = false }
1022  },
1023  MinitScript::TYPE_BOOLEAN),
1024  minitScript(minitScript) {}
1025  const string getMethodName() override {
1026  return "greaterEquals";
1027  }
1028  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1029  if (arguments.size() == 2 || arguments.size() == 3) {
1030  if (MinitScript::hasTypeForOperatorArguments(arguments, MinitScript::TYPE_STRING) == true) {
1031  string stringValueA;
1032  string stringValueB;
1033  if (MinitScript::getStringValue(arguments, 0, stringValueA, false) == true &&
1034  MinitScript::getStringValue(arguments, 1, stringValueB, false) == true) {
1035  returnValue.setValue(stringValueA >= stringValueB);
1036  } else {
1037  MINITSCRIPT_METHODUSAGE_COMPLAINOM(getMethodName(), MinitScript::decodeOperator(arguments, 2, getMethodName()), "Can not compare '" + arguments[0].getValueAsString() + "' with '" + arguments[1].getValueAsString() + "'");
1038  }
1039  } else {
1040  float floatValueA;
1041  float floatValueB;
1042  if (MinitScript::getFloatValue(arguments, 0, floatValueA, false) == true &&
1043  MinitScript::getFloatValue(arguments, 1, floatValueB, false) == true) {
1044  returnValue.setValue(floatValueA >= floatValueB);
1045  } else {
1046  MINITSCRIPT_METHODUSAGE_COMPLAINOM(getMethodName(), MinitScript::decodeOperator(arguments, 2, getMethodName()), "Can not compare '" + arguments[0].getValueAsString() + "' with '" + arguments[1].getValueAsString() + "'");
1047  }
1048  }
1049  } else {
1050  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
1051  }
1052  }
1053  MinitScript::Operator getOperator() const override {
1054  return MinitScript::OPERATOR_GREATEREQUALS;
1055  }
1056  };
1057  minitScript->registerMethod(new MethodGreaterEquals(minitScript));
1058  }
1059  {
1060  //
1061  class MethodLesser: public MinitScript::Method {
1062  private:
1063  MinitScript* minitScript { nullptr };
1064  public:
1065  MethodLesser(MinitScript* minitScript):
1067  {
1068  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "a", .optional = false, .reference = false, .nullable = false },
1069  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "b", .optional = false, .reference = false, .nullable = false },
1070  { .type = MinitScript::TYPE_INTEGER, .name = "operator", .optional = true, .reference = false, .nullable = false }
1071  },
1072  MinitScript::TYPE_BOOLEAN),
1073  minitScript(minitScript) {}
1074  const string getMethodName() override {
1075  return "lesser";
1076  }
1077  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1078  if (arguments.size() == 2 || arguments.size() == 3) {
1079  if (MinitScript::hasTypeForOperatorArguments(arguments, MinitScript::TYPE_STRING) == true) {
1080  string stringValueA;
1081  string stringValueB;
1082  if (MinitScript::getStringValue(arguments, 0, stringValueA, false) == true &&
1083  MinitScript::getStringValue(arguments, 1, stringValueB, false) == true) {
1084  returnValue.setValue(stringValueA < stringValueB);
1085  } else {
1086  MINITSCRIPT_METHODUSAGE_COMPLAINOM(getMethodName(), MinitScript::decodeOperator(arguments, 2, getMethodName()), "Can not compare '" + arguments[0].getValueAsString() + "' with '" + arguments[1].getValueAsString() + "'");
1087  }
1088  } else {
1089  float floatValueA;
1090  float floatValueB;
1091  if (MinitScript::getFloatValue(arguments, 0, floatValueA, false) == true &&
1092  MinitScript::getFloatValue(arguments, 1, floatValueB, false) == true) {
1093  returnValue.setValue(floatValueA < floatValueB);
1094  } else {
1095  MINITSCRIPT_METHODUSAGE_COMPLAINOM(getMethodName(), MinitScript::decodeOperator(arguments, 2, getMethodName()), "Can not compare '" + arguments[0].getValueAsString() + "' with '" + arguments[1].getValueAsString() + "'");
1096  }
1097  }
1098  } else {
1099  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
1100  }
1101  }
1102  MinitScript::Operator getOperator() const override {
1103  return MinitScript::OPERATOR_LESSER;
1104  }
1105  };
1106  minitScript->registerMethod(new MethodLesser(minitScript));
1107  }
1108  {
1109  //
1110  class MethodLesserEquals: public MinitScript::Method {
1111  private:
1112  MinitScript* minitScript { nullptr };
1113  public:
1114  MethodLesserEquals(MinitScript* minitScript):
1116  {
1117  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "a", .optional = false, .reference = false, .nullable = false },
1118  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "b", .optional = false, .reference = false, .nullable = false },
1119  { .type = MinitScript::TYPE_INTEGER, .name = "operator", .optional = true, .reference = false, .nullable = false }
1120  },
1121  MinitScript::TYPE_BOOLEAN),
1122  minitScript(minitScript) {}
1123  const string getMethodName() override {
1124  return "lesserEquals";
1125  }
1126  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1127  if (arguments.size() == 2 || arguments.size() == 3) {
1128  if (MinitScript::hasTypeForOperatorArguments(arguments, MinitScript::TYPE_STRING) == true) {
1129  string stringValueA;
1130  string stringValueB;
1131  if (MinitScript::getStringValue(arguments, 0, stringValueA, false) == true &&
1132  MinitScript::getStringValue(arguments, 1, stringValueB, false) == true) {
1133  returnValue.setValue(stringValueA <= stringValueB);
1134  } else {
1135  MINITSCRIPT_METHODUSAGE_COMPLAINOM(getMethodName(), MinitScript::decodeOperator(arguments, 2, getMethodName()), "Can not compare '" + arguments[0].getValueAsString() + "' with '" + arguments[1].getValueAsString() + "'");
1136  }
1137  } else {
1138  float floatValueA;
1139  float floatValueB;
1140  if (MinitScript::getFloatValue(arguments, 0, floatValueA, false) == true &&
1141  MinitScript::getFloatValue(arguments, 1, floatValueB, false) == true) {
1142  returnValue.setValue(floatValueA <= floatValueB);
1143  } else {
1144  MINITSCRIPT_METHODUSAGE_COMPLAINOM(getMethodName(), MinitScript::decodeOperator(arguments, 2, getMethodName()), "Can not compare '" + arguments[0].getValueAsString() + "' with '" + arguments[1].getValueAsString() + "'");
1145  }
1146  }
1147  } else {
1148  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
1149  }
1150  }
1151  MinitScript::Operator getOperator() const override {
1152  return MinitScript::OPERATOR_LESSEREQUALS;
1153  }
1154  };
1155  minitScript->registerMethod(new MethodLesserEquals(minitScript));
1156  }
1157  // bool methods
1158  {
1159  //
1160  class MethodBool: public MinitScript::Method {
1161  private:
1162  MinitScript* minitScript { nullptr };
1163  public:
1164  MethodBool(MinitScript* minitScript):
1166  {
1167  { .type = MinitScript::TYPE_BOOLEAN, .name = "boolean", .optional = false, .reference = false, .nullable = false }
1168  },
1169  MinitScript::TYPE_BOOLEAN
1170  ),
1171  minitScript(minitScript) {}
1172  const string getMethodName() override {
1173  return "boolean";
1174  }
1175  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1176  bool booleanValue;
1177  if (arguments.size() == 1 &&
1178  MinitScript::getBooleanValue(arguments, 0, booleanValue) == true) {
1179  returnValue.setValue(booleanValue);
1180  } else {
1181  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
1182  }
1183  }
1184  };
1185  minitScript->registerMethod(new MethodBool(minitScript));
1186  }
1187  {
1188  //
1189  class MethodNot: public MinitScript::Method {
1190  private:
1191  MinitScript* minitScript { nullptr };
1192  public:
1193  MethodNot(MinitScript* minitScript):
1195  {
1196  { .type = MinitScript::TYPE_BOOLEAN, .name = "boolean", .optional = false, .reference = false, .nullable = false },
1197  { .type = MinitScript::TYPE_INTEGER, .name = "operator", .optional = true, .reference = false, .nullable = false }
1198  },
1199  MinitScript::TYPE_BOOLEAN), minitScript(minitScript) {}
1200  const string getMethodName() override {
1201  return "not";
1202  }
1203  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1204  bool booleanValue = false;
1205  if ((arguments.size() == 1 || arguments.size() == 2) &&
1206  MinitScript::getBooleanValue(arguments, 0, booleanValue) == true) {
1207  returnValue.setValue(!booleanValue);
1208  } else {
1209  MINITSCRIPT_METHODUSAGE_COMPLAINOM(getMethodName(), MinitScript::decodeOperator(arguments, 1, getMethodName()), "'" + arguments[0].getValueAsString() + "' is not a boolean value");
1210  }
1211  }
1212  MinitScript::Operator getOperator() const override {
1213  return MinitScript::OPERATOR_NOT;
1214  }
1215  };
1216  minitScript->registerMethod(new MethodNot(minitScript));
1217  }
1218  {
1219  //
1220  class MethodAnd: public MinitScript::Method {
1221  private:
1222  MinitScript* minitScript { nullptr };
1223  public:
1224  MethodAnd(MinitScript* minitScript):
1226  {
1227  { .type = MinitScript::TYPE_BOOLEAN, .name = "a", .optional = false, .reference = false, .nullable = false },
1228  { .type = MinitScript::TYPE_BOOLEAN, .name = "b", .optional = false, .reference = false, .nullable = false },
1229  { .type = MinitScript::TYPE_INTEGER, .name = "operator", .optional = true, .reference = false, .nullable = false }
1230  },
1231  MinitScript::TYPE_BOOLEAN
1232  ),
1233  minitScript(minitScript) {}
1234  const string getMethodName() override {
1235  return "and";
1236  }
1237  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1238  bool booleanValueA;
1239  bool booleanValueB;
1240  auto isBooleanValueA = MinitScript::getBooleanValue(arguments, 0, booleanValueA);
1241  auto isBooleanValueB = MinitScript::getBooleanValue(arguments, 1, booleanValueB);
1242  //
1243  if ((arguments.size() == 2 || arguments.size() == 3) &&
1244  isBooleanValueA == true &&
1245  isBooleanValueB == true) {
1246  returnValue.setValue(booleanValueA && booleanValueB);
1247  } else {
1248  MINITSCRIPT_METHODUSAGE_COMPLAINOM(getMethodName(), MinitScript::decodeOperator(arguments, 2, getMethodName()), string(isBooleanValueA == false?"Left argument '" + arguments[0].getValueAsString() + "' is not a boolean value":"") + string(isBooleanValueB == false?string(isBooleanValueA == false?" and right argument":"Right argument") + " '" + arguments[1].getValueAsString() + "' is not a boolean value":""));
1249  }
1250  }
1251  MinitScript::Operator getOperator() const override {
1252  return MinitScript::OPERATOR_AND;
1253  }
1254  };
1255  minitScript->registerMethod(new MethodAnd(minitScript));
1256  }
1257  {
1258  //
1259  class MethodOr: public MinitScript::Method {
1260  private:
1261  MinitScript* minitScript { nullptr };
1262  public:
1263  MethodOr(MinitScript* minitScript):
1265  {
1266  { .type = MinitScript::TYPE_BOOLEAN, .name = "a", .optional = false, .reference = false, .nullable = false },
1267  { .type = MinitScript::TYPE_BOOLEAN, .name = "b", .optional = false, .reference = false, .nullable = false },
1268  { .type = MinitScript::TYPE_INTEGER, .name = "operator", .optional = true, .reference = false, .nullable = false }
1269  },
1270  MinitScript::TYPE_BOOLEAN
1271  ),
1272  minitScript(minitScript) {}
1273  const string getMethodName() override {
1274  return "or";
1275  }
1276  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1277  bool booleanValueA;
1278  bool booleanValueB;
1279  auto isBooleanValueA = MinitScript::getBooleanValue(arguments, 0, booleanValueA);
1280  auto isBooleanValueB = MinitScript::getBooleanValue(arguments, 1, booleanValueB);
1281  //
1282  if ((arguments.size() == 2 || arguments.size() == 3) &&
1283  isBooleanValueA == true &&
1284  isBooleanValueB == true) {
1285  returnValue.setValue(booleanValueA || booleanValueB);
1286  } else {
1287  MINITSCRIPT_METHODUSAGE_COMPLAINOM(getMethodName(), MinitScript::decodeOperator(arguments, 2, getMethodName()), string(isBooleanValueA == false?"Left argument '" + arguments[0].getValueAsString() + "' is not a boolean value":"") + string(isBooleanValueB == false?string(isBooleanValueA == false?" and right argument":"Right argument") + " '" + arguments[1].getValueAsString() + "' is not a boolean value":""));
1288  }
1289  }
1290  MinitScript::Operator getOperator() const override {
1291  return MinitScript::OPERATOR_OR;
1292  }
1293  };
1294  minitScript->registerMethod(new MethodOr(minitScript));
1295  }
1296  // get type
1297  {
1298  //
1299  class MethodGetType: public MinitScript::Method {
1300  private:
1301  MinitScript* minitScript { nullptr };
1302  public:
1303  MethodGetType(MinitScript* minitScript):
1305  {
1306  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "variable", .optional = false, .reference = false, .nullable = false }
1307  },
1308  MinitScript::TYPE_STRING
1309  ),
1310  minitScript(minitScript) {}
1311  const string getMethodName() override {
1312  return "getType";
1313  }
1314  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1315  if (arguments.size() == 1) {
1316  returnValue.setValue(arguments[0].getTypeAsString());
1317  } else {
1318  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
1319  }
1320  }
1321  };
1322  minitScript->registerMethod(new MethodGetType(minitScript));
1323  }
1324  // is constant
1325  {
1326  //
1327  class MethodIsConstant: public MinitScript::Method {
1328  private:
1329  MinitScript* minitScript { nullptr };
1330  public:
1331  MethodIsConstant(MinitScript* minitScript):
1333  {
1334  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "variable", .optional = false, .reference = false, .nullable = false }
1335  },
1336  MinitScript::TYPE_BOOLEAN
1337  ),
1338  minitScript(minitScript) {}
1339  const string getMethodName() override {
1340  return "isConstant";
1341  }
1342  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1343  if (arguments.size() == 1) {
1344  returnValue.setValue(arguments[0].isConstant());
1345  } else {
1346  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
1347  }
1348  }
1349  };
1350  minitScript->registerMethod(new MethodIsConstant(minitScript));
1351  }
1352  // is reference
1353  {
1354  //
1355  class MethodIsReference: public MinitScript::Method {
1356  private:
1357  MinitScript* minitScript { nullptr };
1358  public:
1359  MethodIsReference(MinitScript* minitScript):
1361  {
1362  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "variable", .optional = false, .reference = false, .nullable = false }
1363  },
1364  MinitScript::TYPE_BOOLEAN
1365  ),
1366  minitScript(minitScript) {}
1367  const string getMethodName() override {
1368  return "isReference";
1369  }
1370  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1371  if (arguments.size() == 1) {
1372  returnValue.setValue(arguments[0].isReference());
1373  } else {
1374  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
1375  }
1376  }
1377  };
1378  minitScript->registerMethod(new MethodIsReference(minitScript));
1379  }
1380  // has variable
1381  {
1382  //
1383  class MethodHasVariable: public MinitScript::Method {
1384  private:
1385  MinitScript* minitScript { nullptr };
1386  public:
1387  MethodHasVariable(MinitScript* minitScript):
1389  {
1390  { .type = MinitScript::TYPE_STRING, .name = "variable", .optional = false, .reference = false, .nullable = false }
1391  },
1392  MinitScript::TYPE_BOOLEAN
1393  ),
1394  minitScript(minitScript) {}
1395  const string getMethodName() override {
1396  return "hasVariable";
1397  }
1398  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1399  string variable;
1400  if (arguments.size() == 1 &&
1401  MinitScript::getStringValue(arguments, 0, variable) == true) {
1402  returnValue.setValue(minitScript->hasVariable(variable, &subStatement));
1403  } else {
1404  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
1405  }
1406  }
1407  };
1408  minitScript->registerMethod(new MethodHasVariable(minitScript));
1409  }
1410  // get variable
1411  {
1412  //
1413  class MethodGetVariable: public MinitScript::Method {
1414  private:
1415  MinitScript* minitScript { nullptr };
1416  public:
1417  MethodGetVariable(MinitScript* minitScript):
1419  {
1420  { .type = MinitScript::TYPE_STRING, .name = "variable", .optional = false, .reference = false, .nullable = false }
1421  },
1422  MinitScript::TYPE_PSEUDO_MIXED
1423  ),
1424  minitScript(minitScript) {}
1425  const string getMethodName() override {
1426  return "getVariable";
1427  }
1428  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1429  string variable;
1430  if (arguments.size() == 1 &&
1431  MinitScript::getStringValue(arguments, 0, variable) == true) {
1432  returnValue = minitScript->getVariable(variable, &subStatement);
1433  } else {
1434  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
1435  }
1436  }
1437  };
1438  minitScript->registerMethod(new MethodGetVariable(minitScript));
1439  }
1440  // get variable for method arguments
1441  {
1442  //
1443  class MethodGetMethodArgumentVariable: public MinitScript::Method {
1444  private:
1445  MinitScript* minitScript { nullptr };
1446  public:
1447  MethodGetMethodArgumentVariable(MinitScript* minitScript):
1449  {
1450  { .type = MinitScript::TYPE_STRING, .name = "variable", .optional = false, .reference = false, .nullable = false }
1451  },
1452  MinitScript::TYPE_PSEUDO_MIXED
1453  ),
1454  minitScript(minitScript) {}
1455  const string getMethodName() override {
1456  return "getMethodArgumentVariable";
1457  }
1458  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1459  string variable;
1460  if (arguments.size() == 1 &&
1461  MinitScript::getStringValue(arguments, 0, variable) == true) {
1462  returnValue = minitScript->getMethodArgumentVariable(variable, &subStatement);
1463  } else {
1464  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
1465  }
1466  }
1467  bool isPrivate() const override {
1468  return true;
1469  }
1470  };
1471  minitScript->registerMethod(new MethodGetMethodArgumentVariable(minitScript));
1472  }
1473  // get variable reference
1474  {
1475  //
1476  class MethodGetVariableReference: public MinitScript::Method {
1477  private:
1478  MinitScript* minitScript { nullptr };
1479  public:
1480  MethodGetVariableReference(MinitScript* minitScript):
1482  {
1483  { .type = MinitScript::TYPE_STRING, .name = "variable", .optional = false, .reference = false, .nullable = false }
1484  },
1485  MinitScript::TYPE_PSEUDO_MIXED
1486  ),
1487  minitScript(minitScript) {}
1488  const string getMethodName() override {
1489  return "getVariableReference";
1490  }
1491  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1492  string variable;
1493  if (arguments.size() == 1 &&
1494  MinitScript::getStringValue(arguments, 0, variable) == true) {
1495  returnValue = minitScript->getVariable(variable, &subStatement, true);
1496  } else {
1497  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
1498  }
1499  }
1500  bool isPrivate() const override {
1501  return true;
1502  }
1503  };
1504  minitScript->registerMethod(new MethodGetVariableReference(minitScript));
1505  }
1506  // set variable
1507  {
1508  //
1509  class MethodSetVariable: public MinitScript::Method {
1510  private:
1511  MinitScript* minitScript { nullptr };
1512  public:
1513  MethodSetVariable(MinitScript* minitScript):
1515  {
1516  { .type = MinitScript::TYPE_STRING, .name = "variable", .optional = false, .reference = false, .nullable = false },
1517  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "value", .optional = false, .reference = false, .nullable = false },
1518  { .type = MinitScript::TYPE_INTEGER, .name = "operator", .optional = true, .reference = false, .nullable = false }
1519  },
1520  MinitScript::TYPE_PSEUDO_MIXED
1521  ),
1522  minitScript(minitScript) {
1523  //
1524  }
1525  const string getMethodName() override {
1526  return "setVariable";
1527  }
1528  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1529  string variable;
1530  if ((arguments.size() == 2 || arguments.size() == 3) &&
1531  MinitScript::getStringValue(arguments, 0, variable) == true) {
1532  minitScript->setVariable(variable, arguments[1].isConstant() == true?MinitScript::Variable::createNonConstVariable(&arguments[1]):arguments[1], &subStatement);
1533  returnValue.setValue(arguments[1]);
1534  } else {
1535  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
1536  }
1537  }
1538  MinitScript::Operator getOperator() const override {
1539  return MinitScript::OPERATOR_SET;
1540  }
1541  };
1542  minitScript->registerMethod(new MethodSetVariable(minitScript));
1543  }
1544  // set variable reference
1545  {
1546  //
1547  class MethodSetVariableReference: public MinitScript::Method {
1548  private:
1549  MinitScript* minitScript { nullptr };
1550  public:
1551  MethodSetVariableReference(MinitScript* minitScript):
1553  {
1554  { .type = MinitScript::TYPE_STRING, .name = "variable", .optional = false, .reference = false, .nullable = false },
1555  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "value", .optional = false, .reference = true, .nullable = false }
1556  },
1557  MinitScript::TYPE_PSEUDO_MIXED
1558  ),
1559  minitScript(minitScript) {
1560  //
1561  }
1562  const string getMethodName() override {
1563  return "setVariableReference";
1564  }
1565  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1566  string variable;
1567  if (arguments.size() == 2 &&
1568  MinitScript::getStringValue(arguments, 0, variable) == true) {
1569  minitScript->setVariable(variable, arguments[1], &subStatement, true);
1570  returnValue.setValue(arguments[1]);
1571  } else {
1572  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
1573  }
1574  }
1575  bool isPrivate() const override {
1576  return true;
1577  }
1578  };
1579  minitScript->registerMethod(new MethodSetVariableReference(minitScript));
1580  }
1581  // Unset variable reference
1582  {
1583  //
1584  class MethodUnsetVariableReference: public MinitScript::Method {
1585  private:
1586  MinitScript* minitScript { nullptr };
1587  public:
1588  MethodUnsetVariableReference(MinitScript* minitScript):
1590  {
1591  { .type = MinitScript::TYPE_STRING, .name = "variable", .optional = false, .reference = false, .nullable = false }
1592  }
1593  ),
1594  minitScript(minitScript) {}
1595  const string getMethodName() override {
1596  return "unsetVariableReference";
1597  }
1598  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1599  string variable;
1600  if (arguments.size() == 1 &&
1601  MinitScript::getStringValue(arguments, 0, variable) == true) {
1602  minitScript->unsetVariable(variable, &subStatement);
1603  } else {
1604  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
1605  }
1606  }
1607  bool isPrivate() const override {
1608  return true;
1609  }
1610  };
1611  minitScript->registerMethod(new MethodUnsetVariableReference(minitScript));
1612  }
1613  // set constant
1614  {
1615  //
1616  class MethodSetConstant: public MinitScript::Method {
1617  private:
1618  MinitScript* minitScript { nullptr };
1619  public:
1620  MethodSetConstant(MinitScript* minitScript):
1622  {
1623  { .type = MinitScript::TYPE_STRING, .name = "constant", .optional = false, .reference = false, .nullable = false },
1624  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "value", .optional = false, .reference = false, .nullable = false }
1625  },
1626  MinitScript::TYPE_PSEUDO_MIXED
1627  ),
1628  minitScript(minitScript) {
1629  //
1630  }
1631  const string getMethodName() override {
1632  return "setConstant";
1633  }
1634  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1635  string constant;
1636  if (arguments.size() == 2 &&
1637  MinitScript::getStringValue(arguments, 0, constant) == true) {
1638  MinitScript::setConstant(arguments[1]);
1639  minitScript->setVariable(constant, arguments[1], &subStatement);
1640  returnValue.setValue(arguments[1]);
1641  } else {
1642  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
1643  }
1644  }
1645  };
1646  minitScript->registerMethod(new MethodSetConstant(minitScript));
1647  }
1648  {
1649  //
1650  class MethodPostfixIncrement: public MinitScript::Method {
1651  private:
1652  MinitScript* minitScript { nullptr };
1653  public:
1654  MethodPostfixIncrement(MinitScript* minitScript):
1656  {
1657  { .type = MinitScript::TYPE_INTEGER, .name = "variable", .optional = false, .reference = true, .nullable = false },
1658  { .type = MinitScript::TYPE_INTEGER, .name = "operator", .optional = true, .reference = false, .nullable = false }
1659  },
1660  MinitScript::TYPE_INTEGER
1661  ),
1662  minitScript(minitScript) {}
1663  const string getMethodName() override {
1664  return "postfixIncrement";
1665  }
1666  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1667  int64_t value;
1668  if ((arguments.size() == 1 || arguments.size() == 2) &&
1669  MinitScript::getIntegerValue(arguments, 0, value) == true) {
1670  arguments[0].setValue(value + 1);
1671  returnValue.setValue(value);
1672  } else {
1673  MINITSCRIPT_METHODUSAGE_COMPLAINOM(getMethodName(), MinitScript::decodeOperator(arguments, 1, getMethodName()), "'" + arguments[0].getValueAsString() + "' is not a integer value");
1674  }
1675  }
1676  MinitScript::Operator getOperator() const override {
1677  return MinitScript::OPERATOR_POSTFIX_INCREMENT;
1678  }
1679  };
1680  minitScript->registerMethod(new MethodPostfixIncrement(minitScript));
1681  }
1682  {
1683  //
1684  class MethodPostfixDecrement: public MinitScript::Method {
1685  private:
1686  MinitScript* minitScript { nullptr };
1687  public:
1688  MethodPostfixDecrement(MinitScript* minitScript):
1690  {
1691  { .type = MinitScript::TYPE_INTEGER, .name = "variable", .optional = false, .reference = true, .nullable = false },
1692  { .type = MinitScript::TYPE_INTEGER, .name = "operator", .optional = true, .reference = false, .nullable = false }
1693  },
1694  MinitScript::TYPE_INTEGER
1695  ),
1696  minitScript(minitScript) {}
1697  const string getMethodName() override {
1698  return "postfixDecrement";
1699  }
1700  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1701  int64_t value;
1702  if ((arguments.size() == 1 || arguments.size() == 2) &&
1703  MinitScript::getIntegerValue(arguments, 0, value) == true) {
1704  arguments[0].setValue(value - 1);
1705  returnValue.setValue(value);
1706  } else {
1707  MINITSCRIPT_METHODUSAGE_COMPLAINOM(getMethodName(), MinitScript::decodeOperator(arguments, 1, getMethodName()), "'" + arguments[0].getValueAsString() + "' is not a integer value");
1708  }
1709  }
1710  MinitScript::Operator getOperator() const override {
1711  return MinitScript::OPERATOR_POSTFIX_DECREMENT;
1712  }
1713  };
1714  minitScript->registerMethod(new MethodPostfixDecrement(minitScript));
1715  }
1716  {
1717  //
1718  class MethodPrefixIncrement: public MinitScript::Method {
1719  private:
1720  MinitScript* minitScript { nullptr };
1721  public:
1722  MethodPrefixIncrement(MinitScript* minitScript):
1724  {
1725  { .type = MinitScript::TYPE_INTEGER, .name = "variable", .optional = false, .reference = true, .nullable = false },
1726  { .type = MinitScript::TYPE_INTEGER, .name = "operator", .optional = true, .reference = false, .nullable = false }
1727  },
1728  MinitScript::TYPE_INTEGER
1729  ),
1730  minitScript(minitScript) {}
1731  const string getMethodName() override {
1732  return "prefixIncrement";
1733  }
1734  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1735  int64_t value;
1736  if ((arguments.size() == 1 || arguments.size() == 2) &&
1737  MinitScript::getIntegerValue(arguments, 0, value) == true) {
1738  ++value;
1739  arguments[0].setValue(value);
1740  returnValue.setValue(value);
1741  } else {
1742  MINITSCRIPT_METHODUSAGE_COMPLAINOM(getMethodName(), MinitScript::decodeOperator(arguments, 1, getMethodName()), "'" + arguments[0].getValueAsString() + "' is not a integer value");
1743  }
1744  }
1745  MinitScript::Operator getOperator() const override {
1746  return MinitScript::OPERATOR_PREFIX_INCREMENT;
1747  }
1748  };
1749  minitScript->registerMethod(new MethodPrefixIncrement(minitScript));
1750  }
1751  {
1752  //
1753  class MethodPrefixDecrement: public MinitScript::Method {
1754  private:
1755  MinitScript* minitScript { nullptr };
1756  public:
1757  MethodPrefixDecrement(MinitScript* minitScript):
1759  {
1760  { .type = MinitScript::TYPE_INTEGER, .name = "variable", .optional = false, .reference = true, .nullable = false },
1761  { .type = MinitScript::TYPE_INTEGER, .name = "operator", .optional = true, .reference = false, .nullable = false }
1762  },
1763  MinitScript::TYPE_INTEGER
1764  ),
1765  minitScript(minitScript) {}
1766  const string getMethodName() override {
1767  return "prefixDecrement";
1768  }
1769  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1770  int64_t value;
1771  if ((arguments.size() == 1 || arguments.size() == 2) &&
1772  MinitScript::getIntegerValue(arguments, 0, value) == true) {
1773  --value;
1774  arguments[0].setValue(value);
1775  returnValue.setValue(value);
1776  } else {
1777  MINITSCRIPT_METHODUSAGE_COMPLAINOM(getMethodName(), MinitScript::decodeOperator(arguments, 1, getMethodName()), "'" + arguments[0].getValueAsString() + "' is not a integer value");
1778  }
1779  }
1780  MinitScript::Operator getOperator() const override {
1781  return MinitScript::OPERATOR_PREFIX_DECREMENT;
1782  }
1783  };
1784  minitScript->registerMethod(new MethodPrefixDecrement(minitScript));
1785  }
1786  //
1787  {
1788  //
1789  class MethodBitwiseNot: public MinitScript::Method {
1790  private:
1791  MinitScript* minitScript { nullptr };
1792  public:
1793  MethodBitwiseNot(MinitScript* minitScript):
1795  {
1796  { .type = MinitScript::TYPE_INTEGER, .name = "value", .optional = false, .reference = false, .nullable = false },
1797  { .type = MinitScript::TYPE_INTEGER, .name = "operator", .optional = true, .reference = false, .nullable = false }
1798  },
1799  MinitScript::TYPE_INTEGER),
1800  minitScript(minitScript) {}
1801  const string getMethodName() override {
1802  return "bitwiseNot";
1803  }
1804  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1805  int64_t value;
1806  if ((arguments.size() == 1 || arguments.size() == 2) &&
1807  MinitScript::getIntegerValue(arguments, 0, value) == true) {
1808  returnValue.setValue(~value);
1809  } else {
1810  MINITSCRIPT_METHODUSAGE_COMPLAINOM(getMethodName(), MinitScript::decodeOperator(arguments, 1, getMethodName()), "'" + arguments[0].getValueAsString() + "' is not a integer value");
1811  }
1812  }
1813  MinitScript::Operator getOperator() const override {
1814  return MinitScript::OPERATOR_BITWISENOT;
1815  }
1816  };
1817  minitScript->registerMethod(new MethodBitwiseNot(minitScript));
1818  }
1819  //
1820  {
1821  class MethodBitwiseAnd: public MinitScript::Method {
1822  private:
1823  MinitScript* minitScript { nullptr };
1824  public:
1825  MethodBitwiseAnd(MinitScript* minitScript):
1827  {
1828  { .type = MinitScript::TYPE_INTEGER, .name = "a", .optional = false, .reference = false, .nullable = false },
1829  { .type = MinitScript::TYPE_INTEGER, .name = "b", .optional = false, .reference = false, .nullable = false },
1830  { .type = MinitScript::TYPE_INTEGER, .name = "operator", .optional = true, .reference = false, .nullable = false }
1831  },
1832  MinitScript::TYPE_INTEGER),
1833  minitScript(minitScript) {}
1834  const string getMethodName() override {
1835  return "bitwiseAnd";
1836  }
1837  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1838  int64_t valueA;
1839  int64_t valueB;
1840  auto isValueAInteger = MinitScript::getIntegerValue(arguments, 0, valueA);
1841  auto isValueBInteger = MinitScript::getIntegerValue(arguments, 1, valueB);
1842  if ((arguments.size() == 2 || arguments.size() == 3) &&
1843  isValueAInteger == true &&
1844  isValueBInteger == true) {
1845  //
1846  returnValue.setValue(valueA & valueB);
1847  } else {
1848  MINITSCRIPT_METHODUSAGE_COMPLAINOM(getMethodName(), MinitScript::decodeOperator(arguments, 2, getMethodName()), string(isValueAInteger == false?"Left argument '" + arguments[0].getValueAsString() + "' is not a integer value":"") + string(isValueBInteger == false?string(isValueAInteger == false?" and right argument":"Right argument") + " '" + arguments[1].getValueAsString() + "' is not a integer value":""));
1849  }
1850  }
1851  MinitScript::Operator getOperator() const override {
1852  return MinitScript::OPERATOR_BITWISEAND;
1853  }
1854  };
1855  minitScript->registerMethod(new MethodBitwiseAnd(minitScript));
1856  }
1857  //
1858  {
1859  class MethodBitwiseOr: public MinitScript::Method {
1860  private:
1861  MinitScript* minitScript { nullptr };
1862  public:
1863  MethodBitwiseOr(MinitScript* minitScript):
1865  {
1866  { .type = MinitScript::TYPE_INTEGER, .name = "a", .optional = false, .reference = false, .nullable = false },
1867  { .type = MinitScript::TYPE_INTEGER, .name = "b", .optional = false, .reference = false, .nullable = false },
1868  { .type = MinitScript::TYPE_INTEGER, .name = "operator", .optional = true, .reference = false, .nullable = false }
1869  },
1870  MinitScript::TYPE_INTEGER),
1871  minitScript(minitScript) {}
1872  const string getMethodName() override {
1873  return "bitwiseOr";
1874  }
1875  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1876  int64_t valueA;
1877  int64_t valueB;
1878  auto isValueAInteger = MinitScript::getIntegerValue(arguments, 0, valueA);
1879  auto isValueBInteger = MinitScript::getIntegerValue(arguments, 1, valueB);
1880  if ((arguments.size() == 2 || arguments.size() == 3) &&
1881  isValueAInteger == true &&
1882  isValueBInteger == true) {
1883  //
1884  returnValue.setValue(valueA | valueB);
1885  } else {
1886  MINITSCRIPT_METHODUSAGE_COMPLAINOM(getMethodName(), MinitScript::decodeOperator(arguments, 2, getMethodName()), string(isValueAInteger == false?"Left argument '" + arguments[0].getValueAsString() + "' is not a integer value":"") + string(isValueBInteger == false?string(isValueAInteger == false?" and right argument":"Right argument") + " '" + arguments[1].getValueAsString() + "' is not a integer value":""));
1887  }
1888  }
1889  MinitScript::Operator getOperator() const override {
1890  return MinitScript::OPERATOR_BITWISEOR;
1891  }
1892  };
1893  minitScript->registerMethod(new MethodBitwiseOr(minitScript));
1894  }
1895  //
1896  {
1897  class MethodBitwiseXor: public MinitScript::Method {
1898  private:
1899  MinitScript* minitScript { nullptr };
1900  public:
1901  MethodBitwiseXor(MinitScript* minitScript):
1903  {
1904  { .type = MinitScript::TYPE_INTEGER, .name = "a", .optional = false, .reference = false, .nullable = false },
1905  { .type = MinitScript::TYPE_INTEGER, .name = "b", .optional = false, .reference = false, .nullable = false },
1906  { .type = MinitScript::TYPE_INTEGER, .name = "operator", .optional = true, .reference = false, .nullable = false }
1907  },
1908  MinitScript::TYPE_INTEGER),
1909  minitScript(minitScript) {}
1910  const string getMethodName() override {
1911  return "bitwiseXor";
1912  }
1913  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1914  int64_t valueA;
1915  int64_t valueB;
1916  auto isValueAInteger = MinitScript::getIntegerValue(arguments, 0, valueA);
1917  auto isValueBInteger = MinitScript::getIntegerValue(arguments, 1, valueB);
1918  if ((arguments.size() == 2 || arguments.size() == 3) &&
1919  isValueAInteger == true &&
1920  isValueBInteger == true) {
1921  //
1922  returnValue.setValue(valueA ^ valueB);
1923  } else {
1924  MINITSCRIPT_METHODUSAGE_COMPLAINOM(getMethodName(), MinitScript::decodeOperator(arguments, 2, getMethodName()), string(isValueAInteger == false?"Left argument '" + arguments[0].getValueAsString() + "' is not a integer value":"") + string(isValueBInteger == false?string(isValueAInteger == false?" and right argument":"Right argument") + " '" + arguments[1].getValueAsString() + "' is not a integer value":""));
1925  }
1926  }
1927  MinitScript::Operator getOperator() const override {
1928  return MinitScript::OPERATOR_BITWISEXOR;
1929  }
1930  };
1931  minitScript->registerMethod(new MethodBitwiseXor(minitScript));
1932  }
1933  // hex: move me into HexMethods
1934  {
1935  //
1936  class MethodHexEncode: public MinitScript::Method {
1937  private:
1938  MinitScript* minitScript { nullptr };
1939  public:
1940  MethodHexEncode(MinitScript* minitScript):
1942  {
1943  { .type = MinitScript::TYPE_INTEGER, .name = "value", .optional = false, .reference = false, .nullable = false }
1944  },
1945  MinitScript::TYPE_STRING
1946  ),
1947  minitScript(minitScript) {}
1948  const string getMethodName() override {
1949  return "hex.encode";
1950  }
1951  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1952  int64_t value;
1953  if (arguments.size() == 1 &&
1954  MinitScript::getIntegerValue(arguments, 0, value) == true) {
1955  returnValue.setValue(_Hex::encodeInt(value));
1956  } else {
1957  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
1958  }
1959  }
1960  };
1961  minitScript->registerMethod(new MethodHexEncode(minitScript));
1962  }
1963  {
1964  //
1965  class MethodHexDecode: public MinitScript::Method {
1966  private:
1967  MinitScript* minitScript { nullptr };
1968  public:
1969  MethodHexDecode(MinitScript* minitScript):
1971  {
1972  { .type = MinitScript::TYPE_STRING, .name = "value", .optional = false, .reference = false, .nullable = false }
1973  },
1974  MinitScript::TYPE_INTEGER
1975  ),
1976  minitScript(minitScript) {}
1977  const string getMethodName() override {
1978  return "hex.decode";
1979  }
1980  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
1981  string value;
1982  if (arguments.size() == 1 &&
1983  MinitScript::getStringValue(arguments, 0, value) == true) {
1984  returnValue.setValue(static_cast<int64_t>(_Hex::decodeInt(value)));
1985  } else {
1986  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
1987  }
1988  }
1989  };
1990  minitScript->registerMethod(new MethodHexDecode(minitScript));
1991  }
1992  {
1993  //
1994  class SwapMethod: public MinitScript::Method {
1995  private:
1996  MinitScript* minitScript { nullptr };
1997  public:
1998  SwapMethod(MinitScript* minitScript):
2000  {
2001  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "a", .optional = false, .reference = true, .nullable = false },
2002  { .type = MinitScript::TYPE_PSEUDO_MIXED, .name = "b", .optional = false, .reference = true, .nullable = false }
2003  }
2004  ),
2005  minitScript(minitScript) {}
2006  const string getMethodName() override {
2007  return "swap";
2008  }
2009  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
2010  if (arguments.size() == 2) {
2011  MinitScript::Variable::swap(arguments[0], arguments[1]);
2012  } else {
2013  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
2014  }
2015  }
2016  };
2017  minitScript->registerMethod(new SwapMethod(minitScript));
2018  }
2019  {
2020  //
2021  class ConcurrencyGetHardwareThreadCountMethod: public MinitScript::Method {
2022  private:
2023  MinitScript* minitScript { nullptr };
2024  public:
2025  ConcurrencyGetHardwareThreadCountMethod(MinitScript* minitScript):
2027  {},
2028  MinitScript::TYPE_INTEGER
2029  ),
2030  minitScript(minitScript) {}
2031  const string getMethodName() override {
2032  return "concurrency.getHardwareThreadCount";
2033  }
2034  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
2035  if (arguments.empty() == true) {
2036  returnValue.setValue(static_cast<int64_t>(_Thread::getHardwareThreadCount()));
2037  } else {
2038  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
2039  }
2040  }
2041  };
2042  minitScript->registerMethod(new ConcurrencyGetHardwareThreadCountMethod(minitScript));
2043  }
2044 }
#define MINITSCRIPT_METHODUSAGE_COMPLAINOM(methodName, operatorString, message)
Definition: MinitScript.h:62
#define MINITSCRIPT_METHODUSAGE_COMPLAINM(methodName, message)
Definition: MinitScript.h:60
#define MINITSCRIPT_METHODUSAGE_COMPLAIN(methodName)
Definition: MinitScript.h:59
MinitScript script base methods.
Definition: BaseMethods.h:13
void setValue(const Variable &variable)
Set value from given variable into variable.
Definition: MinitScript.h:1618
const Variable getMapEntry(const string &key) const
Get entry from map with given key.
Definition: MinitScript.h:1965
void registerMethod(Method *method)
Register method.
int getFunctionScriptIdx(const string &function)
Return function script index by function name.
Definition: MinitScript.h:5204
void gotoStatementGoto(const Statement &statement)
Go to statement goto from given statement.
Definition: MinitScript.h:3247
bool call(int scriptIdx, span< Variable > &arguments, Variable &returnValue, bool pushScriptState)
Call function.
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
bool callStacklet(int scriptIdx, span< Variable > &arguments, Variable &returnValue)
Call stacklet.
Definition: MinitScript.h:5245
bool hasVariable(const string &variableStatement, const SubStatement *subStatement=nullptr)
Returns if variable determined by given variable statement exists.
Definition: MinitScript.h:4813
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
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 string getSubStatementInformation(const SubStatement &subStatement)
Return sub statement information.
Definition: MinitScript.h:4576
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
const Variable getVariable(const string &variableStatement, const SubStatement *subStatement=nullptr, bool createReference=false)
Returns variable determined by given variable statement.
Definition: MinitScript.h:4923
Method * getMethod(const string &methodName)
Get method by method name.
Definition: MinitScript.h:5289
void gotoStatement(const Statement &statement)
Go to statement.
Definition: MinitScript.h:3238
void stopRunning()
Set running flag to false.
Definition: MinitScript.h:3392
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 getStackletValue(const span< Variable > &arguments, int idx, string &stacklet, int &scriptIdx, bool optional=false)
Get stacklet value from given variable.
Definition: MinitScript.h:4732
const vector< Script > & getScripts()
Definition: MinitScript.h:4471
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
Base class for threads.
Definition: Thread.h:20
static int getHardwareThreadCount()
Definition: Thread.h:40
static void printLine()
Print newline to console.
Definition: Console.cpp:66
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 const string encodeInt(const uint64_t decodedInt)
Encodes an 64 bit unsigned integer to a hex string representation.
Definition: Hex.h:24
Time utility class.
Definition: Time.h:20
static int64_t getCurrentMillis()
Retrieve current time in milliseconds.
Definition: Time.h:27
unordered_map< int, int64_t > forTimeStarted
Definition: MinitScript.h:3110