MinitScript  0.9.31 PRE-BETA
ContextMethods.cpp
Go to the documentation of this file.
1 #include <span>
2 
3 #include <memory>
4 
9 
10 using std::span;
11 using std::unique_ptr;
12 
14 
16 
18 
19 void ContextMethods::registerConstants(MinitScript* minitScript) {
20 }
21 
22 void ContextMethods::registerMethods(MinitScript* minitScript) {
23  if (minitScript->getContext() == nullptr) return;
24  {
25  //
26  class MethodContextScriptHasCallable: public MinitScript::Method {
27  private:
28  MinitScript* minitScript { nullptr };
29  public:
30  MethodContextScriptHasCallable(MinitScript* minitScript):
32  {
33  { .type = MinitScript::TYPE_STRING, .name = "scriptId", .optional = false, .reference = false, .nullable = false },
34  { .type = MinitScript::TYPE_STRING, .name = "callable", .optional = false, .reference = false, .nullable = false }
35  },
36  MinitScript::TYPE_BOOLEAN
37  ),
38  minitScript(minitScript) {}
39  const string getMethodName() override {
40  return "context.script.hasCallable";
41  }
42  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
43  string scriptId;
44  string callable;
45  if (arguments.size() == 2 &&
46  MinitScript::getStringValue(arguments, 0, scriptId) == true &&
47  MinitScript::getStringValue(arguments, 1, callable) == true) {
48  auto script = minitScript->getContext()->getScript(scriptId);
49  if (script == nullptr) {
50  returnValue.setValue(false);
51  } else {
52  auto scriptIdx = script->getFunctionScriptIdx(callable);
53  if (scriptIdx == MinitScript::SCRIPTIDX_NONE || script->getScripts()[scriptIdx].callable == false) {
54  returnValue.setValue(false);
55  } else {
56  returnValue.setValue(true);
57  }
58  }
59  } else {
60  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
61  }
62  }
63  };
64  minitScript->registerMethod(new MethodContextScriptHasCallable(minitScript));
65  }
66  {
67  //
68  class MethodContextScriptCall: public MinitScript::Method {
69  private:
70  MinitScript* minitScript { nullptr };
71  public:
72  MethodContextScriptCall(MinitScript* minitScript):
73  Method(
74  {
75  { .type = MinitScript::TYPE_STRING, .name = "scriptId", .optional = false, .reference = false, .nullable = false },
76  { .type = MinitScript::TYPE_STRING, .name = "callable", .optional = false, .reference = false, .nullable = false }
77  },
78  MinitScript::TYPE_PSEUDO_MIXED
79  ),
80  minitScript(minitScript) {}
81  const string getMethodName() override {
82  return "context.script.call";
83  }
84  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
85  string scriptId;
86  string callable;
87  if (arguments.size() >= 2 &&
88  MinitScript::getStringValue(arguments, 0, scriptId) == true &&
89  MinitScript::getStringValue(arguments, 1, callable) == true) {
90  auto script = dynamic_cast<MinitScript*>(minitScript->getContext()->getScript(scriptId));
91  if (script == nullptr) {
92  MINITSCRIPT_METHODUSAGE_COMPLAINM(getMethodName(), "No script with given id: " + scriptId);
93  } else {
94  auto scriptIdx = script->getFunctionScriptIdx(callable);
95  if (scriptIdx == MinitScript::SCRIPTIDX_NONE || script->getScripts()[scriptIdx].callable == false) {
96  MINITSCRIPT_METHODUSAGE_COMPLAINM(getMethodName(), "Callable not found: " + callable);
97  } else {
98  minitScript->getContext()->push(script);
99  #if defined (__clang__)
100  // Clang currently does not support initializing span using begin and end iterators,
101  vector<MinitScript::Variable> callArguments(arguments.size() - 2);
102  for (auto i = 2; i < arguments.size(); i++) callArguments[i - 2] = move(arguments[i]);
103  // call
104  span callArgumentsSpan(callArguments);
105  script->call(scriptIdx, callArgumentsSpan, returnValue);
106  // move back arguments
107  for (auto i = 2; i < arguments.size(); i++) arguments[i] = move(callArguments[i - 2]);
108  #else
109  span callArgumentsSpan(arguments.begin() + 2, arguments.end());
110  script->call(scriptIdx, callArgumentsSpan, returnValue);
111  #endif
112  minitScript->getContext()->pop();
113  }
114  }
115  } else {
116  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
117  }
118  }
119  bool isVariadic() const override {
120  return true;
121  }
122  };
123  minitScript->registerMethod(new MethodContextScriptCall(minitScript));
124  }
125  {
126  //
127  class MethodContextScriptLoadScript: public MinitScript::Method {
128  private:
129  MinitScript* minitScript { nullptr };
130  public:
131  MethodContextScriptLoadScript(MinitScript* minitScript):
133  {
134  { .type = MinitScript::TYPE_STRING, .name = "scriptId", .optional = false, .reference = false, .nullable = false },
135  { .type = MinitScript::TYPE_STRING, .name = "pathName", .optional = false, .reference = false, .nullable = false },
136  { .type = MinitScript::TYPE_STRING, .name = "fileName", .optional = false, .reference = false, .nullable = false },
137  { .type = MinitScript::TYPE_BOOLEAN, .name = "verbose", .optional = true, .reference = false, .nullable = false },
138  },
139  MinitScript::TYPE_NULL
140  ),
141  minitScript(minitScript) {}
142  const string getMethodName() override {
143  return "context.script.loadScript";
144  }
145  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
146  string scriptId;
147  string pathName;
148  string fileName;
149  bool verbose = false;
150  if ((arguments.size() == 3 || arguments.size() == 4) &&
151  MinitScript::getStringValue(arguments, 0, scriptId) == true &&
152  MinitScript::getStringValue(arguments, 1, pathName) == true &&
153  MinitScript::getStringValue(arguments, 2, fileName) == true &&
154  MinitScript::getBooleanValue(arguments, 3, verbose, true) == true) {
155  unique_ptr<MinitScript> script;
156  // try to load from (native) library
157  if (minitScript->getLibrary() != nullptr) {
158  script = unique_ptr<MinitScript>(
159  minitScript->getLibrary()->loadScript(
160  pathName,
161  fileName
162  )
163  );
164  }
165  // no native script?
166  if (script == nullptr) {
167  // yarrrr, parse ordinary script
168  script = make_unique<MinitScript>();
169  script->setContext(minitScript->getContext());
170  script->parseScript(
171  pathName,
172  fileName
173  );
174  }
175  if (script != nullptr) {
176  // verbose
177  if (verbose == true) _Console::printLine(script->getInformation());
178  //
179  if (script->isValid() == false) {
180  _Console::printLine("Script not valid.");
181  } else {
182  minitScript->getContext()->addScript(scriptId, script.release());
183  }
184  }
185  } else {
186  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
187  }
188  }
189  };
190  minitScript->registerMethod(new MethodContextScriptLoadScript(minitScript));
191  }
192  {
193  //
194  class MethodContextScriptRemoveScript: public MinitScript::Method {
195  private:
196  MinitScript* minitScript { nullptr };
197  public:
198  MethodContextScriptRemoveScript(MinitScript* minitScript):
200  {
201  { .type = MinitScript::TYPE_STRING, .name = "scriptId", .optional = false, .reference = false, .nullable = false }
202  },
203  MinitScript::TYPE_NULL
204  ),
205  minitScript(minitScript) {}
206  const string getMethodName() override {
207  return "context.script.removeScript";
208  }
209  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
210  string scriptId;
211  if (arguments.size() == 1 &&
212  MinitScript::getStringValue(arguments, 0, scriptId) == true) {
213  minitScript->getContext()->removeScript(scriptId);
214  } else {
215  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
216  }
217  }
218  };
219  minitScript->registerMethod(new MethodContextScriptRemoveScript(minitScript));
220  }
221  {
222  //
223  class MethodContextScriptGetScriptIds: public MinitScript::Method {
224  private:
225  MinitScript* minitScript { nullptr };
226  public:
227  MethodContextScriptGetScriptIds(MinitScript* minitScript):
228  MinitScript::Method({}, MinitScript::TYPE_ARRAY),
229  minitScript(minitScript) {}
230  const string getMethodName() override {
231  return "context.script.getScriptIds";
232  }
233  void executeMethod(span<MinitScript::Variable>& arguments, MinitScript::Variable& returnValue, const MinitScript::SubStatement& subStatement) override {
234  if (arguments.size() == 0) {
235  auto scriptIds = minitScript->getContext()->getScriptIds();
236  returnValue.setType(MinitScript::TYPE_ARRAY);
237  for (const auto& scriptId: scriptIds) returnValue.pushArrayEntry(scriptId);
238  } else {
239  MINITSCRIPT_METHODUSAGE_COMPLAIN(getMethodName());
240  }
241  }
242  };
243  minitScript->registerMethod(new MethodContextScriptGetScriptIds(minitScript));
244  }
245 }
#define MINITSCRIPT_METHODUSAGE_COMPLAINM(methodName, message)
Definition: MinitScript.h:60
#define MINITSCRIPT_METHODUSAGE_COMPLAIN(methodName)
Definition: MinitScript.h:59
MinitScript script context methods.
void pop()
Remove from script call stack.
Definition: Context.h:103
const vector< string > getScriptIds()
Get script ids.
Definition: Context.h:84
void removeScript(const string &id)
Remove script.
Definition: Context.cpp:41
void addScript(const string &id, MinitScript *script)
Add script.
Definition: Context.cpp:30
MinitScript * getScript(const string &id)
Get script.
Definition: Context.h:75
void push(MinitScript *script)
Add to script call stack.
Definition: Context.h:96
virtual MinitScript * loadScript(const string &pathName, const string &fileName, const string &basePathName=string())
Load script from library.
Definition: Library.cpp:24
void pushArrayEntry(const Variable &value)
Push entry to array.
Definition: MinitScript.h:1892
void setType(VariableType newType)
Set type.
Definition: MinitScript.h:1253
void setValue(const Variable &variable)
Set value from given variable into variable.
Definition: MinitScript.h:1618
void registerMethod(Method *method)
Register method.
static void printLine()
Print newline to console.
Definition: Console.cpp:66