MinitScript  0.9.31 PRE-BETA
Transpiler.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <algorithm>
4 #include <array>
5 #include <string>
6 #include <unordered_map>
7 #include <unordered_set>
8 #include <vector>
9 
13 
14 using std::array;
15 using std::find;
16 using std::string;
17 using std::unordered_map;
18 using std::unordered_set;
19 using std::vector;
20 
23 
24 /**
25  * MinitScript transpiler
26  * @author Andreas Drewke
27  */
29 public:
30  /**
31  * Transpile MinitScript script instance
32  * @param minitScript MinitScript script instance
33  * @param transpilationFileName transpilation file name
34  * @param minitScriptExtensionFileNames MinitScript extension file names
35  */
36  static void transpile(MinitScript* minitScript, const string& transpilationFileName, const vector<string>& minitScriptExtensionFileNames);
37 
38  /**
39  * Untranspile
40  * @param scriptFileName script file name
41  * @param transpilationFileName transpilation file name
42  */
43  static void untranspile(const string& scriptFileName, const string& transpilationFileName);
44 
45  /**
46  * Create source code for whole script
47  * @param minitScript MinitScript instance
48  * @return source code
49  */
50  static const string createSourceCode(MinitScript* minitScript);
51 
52 private:
53  /**
54  * Get script type name
55  * @param type script type
56  * @return script type enum identifier
57  */
58  inline static const string getScriptTypeReadableName(MinitScript::Script::Type type) {
59  switch(type) {
60  case MinitScript::Script::TYPE_NONE: return "none";
61  case MinitScript::Script::TYPE_FUNCTION: return "function";
62  case MinitScript::Script::TYPE_STACKLET: return "stacklet";
63  case MinitScript::Script::TYPE_ON: return "on";
64  case MinitScript::Script::TYPE_ONENABLED: return "on-enabled";
65  };
66  //
67  return string();
68  }
69 
70  /**
71  * Get script type enum identifier
72  * @param type script type
73  * @return script type enum identifier
74  */
75  inline static const string getScriptTypeEnumIdentifier(MinitScript::Script::Type type) {
76  switch(type) {
77  case MinitScript::Script::TYPE_NONE: return "Script::TYPE_NONE";
78  case MinitScript::Script::TYPE_FUNCTION: return "Script::TYPE_FUNCTION";
79  case MinitScript::Script::TYPE_STACKLET: return "Script::TYPE_STACKLET";
80  case MinitScript::Script::TYPE_ON: return "Script::TYPE_ON";
81  case MinitScript::Script::TYPE_ONENABLED: return "Script::TYPE_ONENABLED";
82  };
83  //
84  return string();
85  }
86 
87  /**
88  * Create method name
89  * @param scriptIdx script index
90  * @return method name
91  */
92  inline static const string createMethodName(MinitScript* minitScript, int scriptIdx) {
93  if (scriptIdx < 0 || scriptIdx >= minitScript->getScripts().size()) return string();
94  const auto& script = minitScript->getScripts()[scriptIdx];
95  //
96  string methodType;
97  switch(script.type) {
99  case MinitScript::Script::TYPE_FUNCTION: methodType = "function"; break;
100  case MinitScript::Script::TYPE_STACKLET: methodType = "stacklet"; break;
101  case MinitScript::Script::TYPE_ON: methodType = "on"; break;
102  case MinitScript::Script::TYPE_ONENABLED: methodType = "on_enabled"; break;
103  };
104  //
105  return
106  methodType + "_" +
107  (script.name.empty() == false?script.name:(
108  StringTools::regexMatch(script.condition, "[a-zA-Z0-9_]+") == true?
109  script.condition:
110  to_string(scriptIdx)
111  )
112  );
113  }
114 
115  /**
116  * Create short method name
117  * @param scriptIdx script index
118  * @return short method name
119  */
120  inline static const string createShortMethodName(MinitScript* minitScript, int scriptIdx) {
121  if (scriptIdx < 0 || scriptIdx >= minitScript->getScripts().size()) return string();
122  const auto& script = minitScript->getScripts()[scriptIdx];
123  return
124  (script.name.empty() == false?script.name:(
125  StringTools::regexMatch(script.condition, "[a-zA-Z0-9_]+") == true?
126  script.condition:
127  to_string(scriptIdx)
128  )
129  );
130  }
131 
132  /**
133  * Escape string variable
134  * @param str string
135  * @return escaped string
136  */
137  inline static const string escapeString(const string& str) {
138  //
139  auto result = str;
140  const array<char, 11> escapeSequences = {'0', 'a', 'b', 'f', 'n', 'r', 't', 'v', 'U', '"'};
141  for (const auto c: escapeSequences) {
142  result = _StringTools::replace(result, string("\\") + c, string("\\\\") + c);
143  }
144  //
145  result = StringTools::replace(result, "\0", "\\0");
146  result = StringTools::replace(result, "\a", "\\a");
147  result = StringTools::replace(result, "\b", "\\b");
148  result = StringTools::replace(result, "\f", "\\f");
149  result = StringTools::replace(result, "\n", "\\n");
150  result = StringTools::replace(result, "\r", "\\r");
151  result = StringTools::replace(result, "\t", "\\t");
152  result = StringTools::replace(result, "\v", "\\v");
153  result = StringTools::replace(result, "\"", "\\\"");
154  //
155  string result2;
156  auto lc = '\0';
157  auto llc = '\0';
158  for (auto i = 0; i < result.size(); i++) {
159  //
160  auto c = result[i];
161  auto nc = i < result.size() - 1?result[i + 1]:'\0';
162  if (c == '\\' && lc != '\\' && nc != '\\' && find(escapeSequences.begin(), escapeSequences.end(), nc) == escapeSequences.end()) {
163  result2+= "\\\\";
164  } else {
165  result2+= c;
166  }
167  //
168  auto lc = c;
169  auto llc = lc;
170  }
171  //
172  return result2;
173  }
174 
175  /**
176  * Check if variable has access statement
177  * @param variableStatement variable statement
178  * @return variable has statement
179  */
180  inline static bool variableHasStatement(const string& variableStatement) {
181  auto doubleDotIdx = StringTools::indexOf(variableStatement, "::");
182  if (doubleDotIdx == string::npos) doubleDotIdx = 0;
183  auto dotIdx = StringTools::indexOf(variableStatement, ".", doubleDotIdx);
184  if (dotIdx != string::npos) return true;
185  auto squareBracketIdx = StringTools::indexOf(variableStatement, "[", doubleDotIdx);
186  if (squareBracketIdx != string::npos) return true;
187  return false;
188  }
189 
190  /**
191  * Create variable name
192  * @param variableStatement variable statement
193  * @return variable name
194  */
195  inline static const string createVariableName(const string& variableStatement) {
196  auto doubleDotIdx = StringTools::indexOf(variableStatement, "::");
197  if (doubleDotIdx == string::npos) doubleDotIdx = 0;
198  auto dotIdx = StringTools::indexOf(variableStatement, ".", doubleDotIdx);
199  if (dotIdx == string::npos) dotIdx = variableStatement.size();
200  auto squareBracketIdx = StringTools::indexOf(variableStatement, "[", doubleDotIdx);
201  if (squareBracketIdx == string::npos) squareBracketIdx = variableStatement.size();
202  auto cppVariableName = StringTools::substring(variableStatement, 0, dotIdx < squareBracketIdx?dotIdx:squareBracketIdx);
203  return cppVariableName;
204  }
205 
206  /**
207  * Create global variable name
208  * @param variableStatement variable statement
209  * @return global CPP variable name
210  */
211  inline static const string createGlobalVariableName(const string& variableStatement) {
212  auto doubleDotIdx = StringTools::indexOf(variableStatement, "::");
213  if (doubleDotIdx == string::npos) doubleDotIdx = 0;
214  auto dotIdx = StringTools::indexOf(variableStatement, ".", doubleDotIdx);
215  if (dotIdx == string::npos) dotIdx = variableStatement.size();
216  auto squareBracketIdx = StringTools::indexOf(variableStatement, "[", doubleDotIdx);
217  if (squareBracketIdx == string::npos) squareBracketIdx = variableStatement.size();
218  auto cppVariableName = "_" + StringTools::substring(variableStatement, 1, dotIdx < squareBracketIdx?dotIdx:squareBracketIdx);
219  cppVariableName = StringTools::replace(cppVariableName, "$", "_");
220  cppVariableName = StringTools::replace(cppVariableName, ":", "_");
221  cppVariableName = StringTools::replace(cppVariableName, ".", "_");
222  return cppVariableName;
223  }
224 
225  /**
226  * Create local variable name
227  * @param variableStatement variable statement
228  * @return local CPP variable name
229  */
230  inline static const string createLocalVariableName(const string& variableStatement) {
231  auto doubleDotIdx = StringTools::indexOf(variableStatement, "::");
232  if (doubleDotIdx == string::npos) doubleDotIdx = 0;
233  auto dotIdx = StringTools::indexOf(variableStatement, ".", doubleDotIdx);
234  if (dotIdx == string::npos) dotIdx = variableStatement.size();
235  auto squareBracketIdx = StringTools::indexOf(variableStatement, "[", doubleDotIdx);
236  if (squareBracketIdx == string::npos) squareBracketIdx = variableStatement.size();
237  auto cppVariableName = "_" + StringTools::substring(variableStatement, 1, dotIdx < squareBracketIdx?dotIdx:squareBracketIdx);
238  cppVariableName = StringTools::replace(cppVariableName, "$", "_");
239  cppVariableName = StringTools::replace(cppVariableName, ":", "_");
240  cppVariableName = StringTools::replace(cppVariableName, ".", "_");
241  return cppVariableName;
242  }
243 
244  /**
245  * Get all classes method names
246  * @param minitScript MinitScript instance
247  * @return all classes method names
248  */
249  static const unordered_set<string> getAllClassesMethodNames(MinitScript* minitScript);
250 
251  /**
252  * Get all classes method names sorted
253  * @param minitScript MinitScript instance
254  * @return all classes method names sorted
255  */
256  static const vector<string> getAllClassesMethodNamesSorted(MinitScript* minitScript);
257 
258  /**
259  * Get method names per classes
260  * @param minitScript MinitScript instance
261  * @return method names per classes
262  */
263  static const unordered_map<string, vector<string>> getClassesMethodNames(MinitScript* minitScript);
264 
265  /**
266  * Determine variables
267  * @param minitScript MinitScript script instance
268  * @param globalVariables global variables
269  * @param localVariables local variables per script index
270  */
271  static void determineVariables(MinitScript* minitScript, unordered_set<string>& globalVariables, vector<unordered_set<string>>& localVariables);
272 
273  /**
274  * Determine variables within syntax tree
275  * @param scriptIdx script index
276  * @param syntaxTreeNode syntax tree node
277  * @param globalVariables global variables
278  * @param localVariables local variables per script index
279  */
280  static void determineVariables(int scriptIdx, const MinitScript::SyntaxTreeNode& syntaxTreeNode, unordered_set<string>& globalVariables, vector<unordered_set<string>>& localVariables);
281 
282  /**
283  * Gather method code
284  * @param minitScriptExtensionsCode MinitScript extensions code
285  * @param className class name
286  * @param register line register line
287  * @param methodCodeMap method code map
288  */
289  static void gatherMethodCode(
290  const vector<string>& minitScriptExtensionsCode,
291  const string& className,
292  int registerLine,
293  unordered_map<string, vector<string>>& methodCodeMap
294  );
295 
296  /**
297  * Generate variable access
298  * @param minitScript MinitScript instance
299  * @param generatedCode generated code
300  * @param scriptConditionIdx script condition index
301  * @param scriptIdx script index
302  * @param variableName variable name
303  * @param accessName access name
304  * @param indent indent
305  * @param getMethodArgumentVariable get method argument variable
306  * @param getVariable issue get variable access
307  * @param getVariableReference issue get variable reference access
308  * @param setVariable set variable
309  * @param setVariableReference set variable reference
310  * @param setConstant set constant
311  * @param returnValue return value
312  * @param statementEnd statement end
313  * @param getArgumentIdx get argument index
314  * @param setArgumentIdx set argument index
315  */
316  static void generateVariableAccess(
317  MinitScript* minitScript,
318  string& generatedCode,
319  int scriptConditionIdx,
320  int scriptIdx,
321  const string& variableName,
322  const string& indent,
323  bool getMethodArgumentVariable,
324  bool getVariable,
325  bool getVariableReference,
326  bool setVariable,
327  bool setVariableReference,
328  bool setConstant,
329  const string& returnValueStatement = "returnValue = ",
330  const string& statementEnd = ";\n",
331  int getArgumentIdx = 0,
332  int setArgumentIdx = 1
333  );
334 
335  /**
336  * Generate array access methods
337  * @param minitScript MinitScript instance
338  * @param generatedDefinitions generated definitions
339  * @param minitScriptClassName MinitScript class name
340  * @param scriptConditionIdx script condition index
341  * @param scriptIdx script index
342  * @param methodName method name
343  * @param syntaxTree syntax tree
344  * @param statement statement
345  * @param methodCodeMap method code map
346  * @param allMethods all methods
347  * @param condition condition
348  * @param argumentIndices argument indices stack
349  * @param depth depth
350  */
351  static void generateArrayAccessMethods(
352  MinitScript* minitScript,
353  string& generatedDefinitions,
354  const string& minitScriptClassName,
355  int scriptConditionIdx,
356  int scriptIdx,
357  const string& methodName,
358  const MinitScript::SyntaxTreeNode& syntaxTree,
359  const MinitScript::Statement& statement,
360  const unordered_map<string, vector<string>>& methodCodeMap,
361  const unordered_set<string>& allMethods,
362  bool condition,
363  const vector<int>& argumentIndices = {},
364  int depth = 0
365  );
366 
367  /**
368  * Generate evaluate member access arrays
369  * @param minitScript MinitScript instance
370  * @param generatedDeclarations generated declarations
371  * @param generatedDefinitions generated definitions
372  */
374  MinitScript* minitScript,
375  vector<string>& generatedDeclarations,
376  vector<string>& generatedDefinitions
377  );
378 
379  /**
380  * Generate array/map/set variable
381  * @param minitScript MinitScript instance
382  * @param scriptConditionIdx script condition index
383  * @param scriptIdx script index
384  * @param variable variable
385  * @param methodCodeMap method code map
386  * @param allMethods all methods
387  * @param methodName method name
388  * @param condition condition
389  * @param minitScriptClassName MinitScript class name
390  * @param generatedDefinitions generated definitions
391  * @param depth depth
392  * @param initializerDepth initializer depth
393  * @param postStatement post statement
394  */
395  static void generateArrayMapSetVariable(
396  MinitScript* minitScript,
397  int scriptConditionIdx,
398  int scriptIdx,
399  const MinitScript::Variable& variable,
400  const unordered_map<string, vector<string>>& methodCodeMap,
401  const unordered_set<string>& allMethods,
402  const string& methodName,
403  bool condition,
404  const string& minitScriptClassName,
405  string& generatedDefinitions,
406  int depth = 0,
407  int initializerDepth = 0,
408  const string& postStatement = string()
409  );
410 
411  /**
412  * Generate array/map/set variable
413  * @param minitScript MinitScript instance
414  * @param generatedDefinitions generated definitions
415  * @param scriptConditionIdx script condition index
416  * @param scriptIdx script index
417  * @param minitScriptClassName MinitScript class name
418  * @param methodName method name
419  * @param syntaxTree syntax tree
420  * @param statement statement
421  * @param methodCodeMap method code map
422  * @param allMethods all methods
423  * @param condition condition
424  * @param argumentIndices argument indices
425  * @param depth depth
426  */
427  static void generateArrayMapSetInitializer(
428  MinitScript* minitScript,
429  string& generatedDefinitions,
430  int scriptConditionIdx,
431  int scriptIdx,
432  const string& minitScriptClassName,
433  const string& methodName,
434  const MinitScript::SyntaxTreeNode& syntaxTree,
435  const MinitScript::Statement& statement,
436  const unordered_map<string, vector<string>>& methodCodeMap,
437  const unordered_set<string>& allMethods,
438  bool condition,
439  const vector<int>& argumentIndices = {},
440  int depth = 0
441  );
442 
443  /**
444  * Transpile statement
445  * @param minitScript MinitScript instance
446  * @param generatedCode generated code
447  * @param syntaxTree syntax tree
448  * @param statement script statement
449  * @param scriptConditionIdx script condition index
450  * @param scriptIdx script index
451  * @param statementIdx statement index
452  * @param methodCodeMap method code map
453  * @param allMethods all methods
454  * @param scriptStateChanged script could have state changed
455  * @param scriptStopped script could have been stopped
456  * @param enabledNamedConditions enabled named conditions
457  * @param depth depth
458  * @param argumentIndices argument indices
459  * @param returnValue return value
460  * @param injectCode code to additionally inject
461  * @param additionalIndent additional indent
462  */
463  static bool transpileStatement(
464  MinitScript* minitScript,
465  string& generatedCode,
466  const MinitScript::SyntaxTreeNode& syntaxTree,
467  const MinitScript::Statement& statement,
468  int scriptConditionIdx,
469  int scriptIdx,
470  int& statementIdx,
471  const unordered_map<string, vector<string>>& methodCodeMap,
472  const unordered_set<string>& allMethods,
473  bool& scriptStateChanged,
474  bool& scriptStopped,
475  vector<string>& enabledNamedConditions,
476  int depth = 0,
477  const vector<int>& argumentIndices = {},
478  const string& returnValue = string(),
479  const string& injectCode = string(),
480  int additionalIndent = 0
481  );
482 
483  /**
484  * Transpile a script statement
485  * @param minitScript MinitScript instance
486  * @param className MinitScript class name
487  * @param generatedCode generated code
488  * @param scriptIdx script index
489  * @param methodCodeMap method code map
490  * @param allMethods all methods
491  * @return success
492  */
493  static bool transpile(
494  MinitScript* minitScript,
495  const string& className,
496  string& generatedCode,
497  int scriptIdx,
498  const unordered_map<string, vector<string>>& methodCodeMap,
499  const unordered_set<string>& allMethods
500  );
501 
502  /**
503  * Transpile a condition
504  * @param minitScript MinitScript instance
505  * @param generatedCode generated code
506  * @param scriptIdx script index
507  * @param methodCodeMap method code map
508  * @param allMethods all methods
509  * @param returnValue return value
510  * @param injectCode inject code
511  * @return success
512  */
513  static bool transpileCondition(
514  MinitScript* minitScript,
515  string& generatedCode,
516  int scriptIdx,
517  const unordered_map<string, vector<string>>& methodCodeMap,
518  const unordered_set<string>& allMethods,
519  const string& returnValue,
520  const string& injectCode,
521  int depth = 0
522  );
523 
524  /**
525  * Create source code for given syntax tree node
526  * @param syntaxTreeNode syntax tree node
527  */
528  static const string createSourceCode(const MinitScript::SyntaxTreeNode& syntaxTreeNode);
529 
530  /**
531  * Create source code for given syntax tree
532  * @param scriptType script type
533  * @param condition condition
534  * @param functionArguments function arguments
535  * @param name name of named conditions
536  * @param conditionSyntaxTree condition syntax tree
537  * @param syntaxTree syntax tree
538  */
539  static const string createSourceCode(
540  MinitScript::Script::Type scriptType,
541  const string& condition,
542  const vector<MinitScript::Script::Argument>& functionArguments,
543  const string& name,
544  const MinitScript::SyntaxTreeNode& conditionSyntaxTree,
545  const vector<MinitScript::SyntaxTreeNode>& syntaxTree
546  );
547 
548 };
const vector< Script > & getScripts()
Definition: MinitScript.h:4471
MinitScript transpiler.
Definition: Transpiler.h:28
static bool transpileStatement(MinitScript *minitScript, string &generatedCode, const MinitScript::SyntaxTreeNode &syntaxTree, const MinitScript::Statement &statement, int scriptConditionIdx, int scriptIdx, int &statementIdx, const unordered_map< string, vector< string >> &methodCodeMap, const unordered_set< string > &allMethods, bool &scriptStateChanged, bool &scriptStopped, vector< string > &enabledNamedConditions, int depth=0, const vector< int > &argumentIndices={}, const string &returnValue=string(), const string &injectCode=string(), int additionalIndent=0)
Transpile statement.
static void untranspile(const string &scriptFileName, const string &transpilationFileName)
Untranspile.
Definition: Transpiler.cpp:798
static const unordered_set< string > getAllClassesMethodNames(MinitScript *minitScript)
Get all classes method names.
Definition: Transpiler.cpp:912
static bool transpileCondition(MinitScript *minitScript, string &generatedCode, int scriptIdx, const unordered_map< string, vector< string >> &methodCodeMap, const unordered_set< string > &allMethods, const string &returnValue, const string &injectCode, int depth=0)
Transpile a condition.
static const string createSourceCode(MinitScript *minitScript)
Create source code for whole script.
static const string createMethodName(MinitScript *minitScript, int scriptIdx)
Create method name.
Definition: Transpiler.h:92
static void generateVariableAccess(MinitScript *minitScript, string &generatedCode, int scriptConditionIdx, int scriptIdx, const string &variableName, const string &indent, bool getMethodArgumentVariable, bool getVariable, bool getVariableReference, bool setVariable, bool setVariableReference, bool setConstant, const string &returnValueStatement="returnValue = ", const string &statementEnd=";\n", int getArgumentIdx=0, int setArgumentIdx=1)
Generate variable access.
static void generateEvaluateMemberAccessArrays(MinitScript *minitScript, vector< string > &generatedDeclarations, vector< string > &generatedDefinitions)
Generate evaluate member access arrays.
static const string createLocalVariableName(const string &variableStatement)
Create local variable name.
Definition: Transpiler.h:230
static const string getScriptTypeEnumIdentifier(MinitScript::Script::Type type)
Get script type enum identifier.
Definition: Transpiler.h:75
static void transpile(MinitScript *minitScript, const string &transpilationFileName, const vector< string > &minitScriptExtensionFileNames)
Transpile MinitScript script instance.
Definition: Transpiler.cpp:45
static const string createShortMethodName(MinitScript *minitScript, int scriptIdx)
Create short method name.
Definition: Transpiler.h:120
static const vector< string > getAllClassesMethodNamesSorted(MinitScript *minitScript)
Get all classes method names sorted.
Definition: Transpiler.cpp:934
static const string getScriptTypeReadableName(MinitScript::Script::Type type)
Get script type name.
Definition: Transpiler.h:58
static void gatherMethodCode(const vector< string > &minitScriptExtensionsCode, const string &className, int registerLine, unordered_map< string, vector< string >> &methodCodeMap)
Gather method code.
static const string escapeString(const string &str)
Escape string variable.
Definition: Transpiler.h:137
static bool variableHasStatement(const string &variableStatement)
Check if variable has access statement.
Definition: Transpiler.h:180
static void generateArrayAccessMethods(MinitScript *minitScript, string &generatedDefinitions, const string &minitScriptClassName, int scriptConditionIdx, int scriptIdx, const string &methodName, const MinitScript::SyntaxTreeNode &syntaxTree, const MinitScript::Statement &statement, const unordered_map< string, vector< string >> &methodCodeMap, const unordered_set< string > &allMethods, bool condition, const vector< int > &argumentIndices={}, int depth=0)
Generate array access methods.
static const string createVariableName(const string &variableStatement)
Create variable name.
Definition: Transpiler.h:195
static void generateArrayMapSetVariable(MinitScript *minitScript, int scriptConditionIdx, int scriptIdx, const MinitScript::Variable &variable, const unordered_map< string, vector< string >> &methodCodeMap, const unordered_set< string > &allMethods, const string &methodName, bool condition, const string &minitScriptClassName, string &generatedDefinitions, int depth=0, int initializerDepth=0, const string &postStatement=string())
Generate array/map/set variable.
static const unordered_map< string, vector< string > > getClassesMethodNames(MinitScript *minitScript)
Get method names per classes.
Definition: Transpiler.cpp:944
static void generateArrayMapSetInitializer(MinitScript *minitScript, string &generatedDefinitions, int scriptConditionIdx, int scriptIdx, const string &minitScriptClassName, const string &methodName, const MinitScript::SyntaxTreeNode &syntaxTree, const MinitScript::Statement &statement, const unordered_map< string, vector< string >> &methodCodeMap, const unordered_set< string > &allMethods, bool condition, const vector< int > &argumentIndices={}, int depth=0)
Generate array/map/set variable.
static const string createGlobalVariableName(const string &variableStatement)
Create global variable name.
Definition: Transpiler.h:211
static void determineVariables(MinitScript *minitScript, unordered_set< string > &globalVariables, vector< unordered_set< string >> &localVariables)
Determine variables.
Definition: Transpiler.cpp:967
static const string replace(const string &str, const char what, const char by, int64_t beginIndex=0)
Replace char with another char.
Definition: StringTools.cpp:33