6 #include <unordered_map>
7 #include <unordered_set>
27 using std::string_view;
30 using std::unordered_map;
31 using std::unordered_set;
45 void Transpiler::transpile(
MinitScript* minitScript,
const string& transpilationFileName,
const vector<string>& minitScriptExtensionFileNames) {
48 Console::printLine(scriptFileName +
": Processing script");
50 auto replace = [](
const vector<string> input,
const string& startTag,
const string& endTag,
const string& replacement, vector<string>& output) ->
bool {
52 auto replaceSuccess =
false;
53 for (
auto i = 0; i < input.size(); i++) {
54 const auto& line = input[i];
55 auto trimmedLine = StringTools::trim(line);
56 if (StringTools::startsWith(trimmedLine,
"//") ==
true) {
57 if (reject ==
false) output.push_back(line);
60 if (trimmedLine == startTag) {
62 output.push_back(line);
64 if (trimmedLine == endTag) {
66 replaceSuccess =
true;
67 output.push_back(replacement);
68 output.push_back(line);
70 if (reject ==
false) output.push_back(line);
74 return replaceSuccess;
78 unordered_map<string, vector<string>> methodCodeMap;
79 auto allMethods = getAllClassesMethodNames(minitScript);
82 vector<string> transpilationUnitIncludes;
83 vector<string> transpilationUnitUsings;
86 vector<string> transpilationUnits;
87 for (
const auto& transpilationUnit: minitScript->
getTranspilationUnits()) transpilationUnits.push_back(transpilationUnit);
88 for (
const auto& transpilationUnit: minitScriptExtensionFileNames) transpilationUnits.push_back(transpilationUnit);
89 for (
const auto& transpilationUnit: transpilationUnits) {
90 vector<string> transpilationUnitCode;
91 FileSystem::getContentAsStringArray(FileSystem::getPathName(transpilationUnit), FileSystem::getFileName(transpilationUnit), transpilationUnitCode);
92 for (
auto i = 0; i < transpilationUnitCode.size(); i++) {
93 const auto& line = transpilationUnitCode[i];
94 auto trimmedLine = StringTools::trim(line);
95 if (StringTools::startsWith(trimmedLine,
"#include ") ==
true) {
96 transpilationUnitIncludes.push_back(trimmedLine);
98 if (StringTools::startsWith(trimmedLine,
"using ") ==
true) {
99 transpilationUnitUsings.push_back(trimmedLine);
101 if (StringTools::startsWith(trimmedLine,
"registerMethod") ==
true ||
102 StringTools::startsWith(trimmedLine,
"minitScript->registerMethod") ==
true) {
103 auto bracketCount = 0;
105 if (StringTools::firstIndexOf(StringTools::substring(trimmedLine, 14),
"new") == string::npos) {
106 Console::printLine(transpilationUnit +
": registerMethod @ " + to_string(i) +
": '" + trimmedLine +
"': unable to determine class name");
108 auto classNameStartIdx = trimmedLine.find(
"registerMethod") + 14 + 5;
109 for (
auto j = classNameStartIdx; j < trimmedLine.size(); j++) {
110 auto c = trimmedLine[j];
112 if (c ==
' ')
continue;
115 gatherMethodCode(transpilationUnitCode, className, i, methodCodeMap);
121 sort(transpilationUnitIncludes.begin(), transpilationUnitIncludes.end());
122 transpilationUnitIncludes.erase(unique(transpilationUnitIncludes.begin(), transpilationUnitIncludes.end()), transpilationUnitIncludes.end());
125 sort(transpilationUnitUsings.begin(), transpilationUnitUsings.end());
126 transpilationUnitUsings.erase(unique(transpilationUnitUsings.begin(), transpilationUnitUsings.end()), transpilationUnitUsings.end());
132 const auto& scripts = minitScript->
getScripts();
135 unordered_set<string> globalVariables;
136 vector<unordered_set<string>> localVariables(scripts.size());
137 determineVariables(minitScript, globalVariables, localVariables);
140 string declarationIndent =
"\t";
141 string definitionIndent =
"\t";
142 string generatedExecuteCode;
145 for (
const auto& script: scripts) {
146 auto methodName = createMethodName(minitScript, scriptIdx);
147 generatedExecuteCode+= declarationIndent +
"\t\t" +
"if (getScriptState().scriptIdx == " + to_string(scriptIdx) +
") " + methodName +
"(scriptState.statementIdx); else\n";
151 if (generatedExecuteCode.empty() ==
false) generatedExecuteCode+= declarationIndent +
"\t\t\t" +
";\n";
154 auto initializeScriptIdx = -1;
155 auto nothingScriptIdx = -1;
158 for (
const auto& script: scripts) {
160 if (StringTools::regexMatch(script.condition,
"[a-zA-Z0-9_]+") ==
true) {
161 if (script.condition ==
"nothing") nothingScriptIdx = scriptIdx;
162 if (script.condition ==
"initialize") initializeScriptIdx = scriptIdx;
170 vector<string> memberAccessEvaluationDeclarations;
171 vector<string> memberAccessEvaluationDefinitions;
172 generateEvaluateMemberAccessArrays(minitScript, memberAccessEvaluationDeclarations, memberAccessEvaluationDefinitions);
175 string minitScriptClassName = FileSystem::getFileName(transpilationFileName);
176 string generatedDeclarations =
"\n";
177 generatedDeclarations+= declarationIndent +
"/**" +
"\n";
178 generatedDeclarations+= declarationIndent +
" * Public destructor" +
"\n";
179 generatedDeclarations+= declarationIndent +
" */" +
"\n";
180 generatedDeclarations+= declarationIndent +
"inline ~" + minitScriptClassName +
"() {" +
"\n";
181 generatedDeclarations+= declarationIndent +
"\t" +
"if (native == true) {" +
"\n";
182 for (
const auto& variable: globalVariables) {
183 generatedDeclarations+= declarationIndent +
"\t\t" + createGlobalVariableName(variable) +
".unset();" +
"\n";
187 for (
const auto& script: scripts) {
188 if (script.type == MinitScript::Script::TYPE_ON ||
189 script.type == MinitScript::Script::TYPE_ONENABLED ||
190 script.type == MinitScript::Script::TYPE_STACKLET) {
194 auto methodName = createMethodName(minitScript, scriptIdx);
195 auto shortMethodName = createShortMethodName(minitScript, scriptIdx);
196 generatedDeclarations+= declarationIndent +
"\t\t" +
"if (" + shortMethodName +
"_Stack.empty() == false) _Console::printLine(\"~" + minitScriptClassName +
"(): Warning: " + methodName +
": stack not empty, size = \" + to_string(" + shortMethodName +
"_Stack.size()));" +
"\n";
200 generatedDeclarations+= declarationIndent +
"\t" +
"}" +
"\n";
202 generatedDeclarations+= declarationIndent +
"}" +
"\n";
203 generatedDeclarations+=
"\n";
204 generatedDeclarations+= declarationIndent +
"// overridden methods" +
"\n";
205 generatedDeclarations+= declarationIndent +
"void registerMethods() override;" +
"\n";
206 generatedDeclarations+= declarationIndent +
"inline void registerVariables() override {" +
"\n";
207 if (globalVariables.empty() ==
false) {
208 generatedDeclarations+= declarationIndent +
"\t" +
"if (native == true) {" +
"\n";
209 for (
const auto& variable: globalVariables) {
210 generatedDeclarations+= declarationIndent +
"\t\t" + createGlobalVariableName(variable) +
".unset();" +
"\n";
212 generatedDeclarations+= declarationIndent +
"\t" +
"}" +
"\n";
213 generatedDeclarations+= declarationIndent +
"\t" +
"//" +
"\n";
215 generatedDeclarations+= declarationIndent +
"\t" + minitScript->
getBaseClass() +
"::registerVariables();" +
"\n";
216 generatedDeclarations+= declarationIndent +
"\t" +
"if (native == true) {" +
"\n";
217 generatedDeclarations+= declarationIndent +
"\t\t" +
"// global script variables" +
"\n";
218 for (
const auto& variable: globalVariables) {
219 generatedDeclarations+= declarationIndent +
"\t\t" +
"if (hasVariable(\"" + variable +
"\") == false) setVariable(\"" + variable +
"\", Variable())" +
";" +
"\n";
220 generatedDeclarations+= declarationIndent +
"\t\t" + createGlobalVariableName(variable) +
" = getVariable(\"" + variable +
"\", nullptr, true);" +
"\n";
222 generatedDeclarations+= declarationIndent +
"\t" +
"}" +
"\n";
223 generatedDeclarations+= declarationIndent +
"}" +
"\n";
224 generatedDeclarations+= declarationIndent +
"void emit(const string& condition) override;" +
"\n";
225 generatedDeclarations+= declarationIndent +
"inline void startScript() override {" +
"\n";
226 generatedDeclarations+= declarationIndent +
"\t" +
"if (native == false) {" +
"\n";
227 generatedDeclarations+= declarationIndent +
"\t" +
"\t" + minitScript->
getBaseClass() +
"::startScript();" +
"\n";
228 generatedDeclarations+= declarationIndent +
"\t" +
"\t" +
"return;" +
"\n";
229 generatedDeclarations+= declarationIndent +
"\t" +
"}" +
"\n";
230 generatedDeclarations+= declarationIndent +
"\t" +
"getScriptState().running = true;" +
"\n";
231 generatedDeclarations+= declarationIndent +
"\t" +
"registerVariables();" +
"\n";
232 generatedDeclarations+= declarationIndent +
"\t" +
"resetScriptExecutationState(" + to_string(initializeScriptIdx) +
", STATEMACHINESTATE_NEXT_STATEMENT);" +
"\n";
233 generatedDeclarations+= declarationIndent +
"}" +
"\n";
234 generatedDeclarations+= declarationIndent +
"inline void execute() override {" +
"\n";
235 generatedDeclarations+= declarationIndent +
"\t" +
"if (native == false) {" +
"\n";
236 generatedDeclarations+= declarationIndent +
"\t" +
"\t" + minitScript->
getBaseClass() +
"::execute();" +
"\n";
237 generatedDeclarations+= declarationIndent +
"\t" +
"\t" +
"return;" +
"\n";
238 generatedDeclarations+= declarationIndent +
"\t" +
"}" +
"\n";
239 generatedDeclarations+= declarationIndent +
"\t" +
"auto& scriptState = getScriptState();" +
"\n";
240 generatedDeclarations+= declarationIndent +
"\t" +
"if (scriptState.running == false) return;" +
"\n";
241 generatedDeclarations+= declarationIndent +
"\t" +
"// execute while having statements to be processed" +
"\n";
242 generatedDeclarations+= declarationIndent +
"\t" +
"if (scriptState.state == STATEMACHINESTATE_NEXT_STATEMENT) {" +
"\n";
243 generatedDeclarations+= declarationIndent +
"\t" +
"\t" +
"// take goto statement index into account" +
"\n";
244 generatedDeclarations+= declarationIndent +
"\t" +
"\t" +
"if (scriptState.gotoStatementIdx != STATEMENTIDX_NONE) {" +
"\n";
245 generatedDeclarations+= declarationIndent +
"\t" +
"\t" +
"\t" +
"scriptState.statementIdx = scriptState.gotoStatementIdx;" +
"\n";
246 generatedDeclarations+= declarationIndent +
"\t" +
"\t" +
"\t" +
"scriptState.gotoStatementIdx = STATEMENTIDX_NONE;" +
"\n";
247 generatedDeclarations+= declarationIndent +
"\t" +
"\t" +
"}" +
"\n";
248 generatedDeclarations+= declarationIndent +
"\t" +
"\t" +
"//" +
"\n";
249 generatedDeclarations+= generatedExecuteCode;
250 generatedDeclarations+= declarationIndent +
"\t" +
"}" +
"\n";
251 generatedDeclarations+= declarationIndent +
"\t" +
"if (getScriptState().running == false) return;" +
"\n";
252 generatedDeclarations+= declarationIndent +
"\t" +
"if (isFunctionRunning() == false && deferredEmit.empty() == false) {" +
"\n";
253 generatedDeclarations+= declarationIndent +
"\t\t" +
"auto condition = deferredEmit;" +
"\n";
254 generatedDeclarations+= declarationIndent +
"\t\t" +
"deferredEmit.clear();" +
"\n";
255 generatedDeclarations+= declarationIndent +
"\t\t" +
"emit(condition);" +
"\n";
256 generatedDeclarations+= declarationIndent +
"\t" +
"}" +
"\n";
257 generatedDeclarations+= declarationIndent +
"\t" +
"if (getScriptState().running == false) return;" +
"\n";
258 generatedDeclarations+= declarationIndent +
"\t" +
"executeStateMachine();" +
"\n";
259 generatedDeclarations+= declarationIndent +
"\t" +
"// try garbage collection" +
"\n";
260 generatedDeclarations+= declarationIndent +
"\t" +
"tryGarbageCollection();" +
"\n";
261 generatedDeclarations+= declarationIndent +
"}" +
"\n";
262 generatedDeclarations+=
"\n";
263 generatedDeclarations+= string() +
"protected:" +
"\n";
266 for (
const auto& memberAccessEvaluationDeclaration: memberAccessEvaluationDeclarations) {
267 generatedDeclarations+= declarationIndent + memberAccessEvaluationDeclaration +
"\n";
269 generatedDeclarations+=
"\n";
272 generatedDeclarations+= declarationIndent +
"// overridden methods" +
"\n";
273 generatedDeclarations+= declarationIndent +
"void initializeNative() override;" +
"\n";
274 generatedDeclarations+= declarationIndent +
"int determineScriptIdxToStart() override;" +
"\n";
275 generatedDeclarations+= declarationIndent +
"int determineNamedScriptIdxToStart() override;" +
"\n";
276 generatedDeclarations+=
"\n";
278 string registerMethodsDefinitions;
279 registerMethodsDefinitions+=
"void " + minitScriptClassName +
"::registerMethods() {" +
"\n";
280 registerMethodsDefinitions+= definitionIndent + minitScript->
getBaseClass() +
"::registerMethods();" +
"\n";
281 registerMethodsDefinitions+= definitionIndent +
"if (native == false) return;" +
"\n";
283 for (
const auto& memberAccessEvaluationDefintion: memberAccessEvaluationDefinitions) {
284 registerMethodsDefinitions+= definitionIndent + memberAccessEvaluationDefintion +
"\n";
286 registerMethodsDefinitions+= string() +
"}" +
"\n";
289 string emitDefinition;
290 emitDefinition+=
"void " + minitScriptClassName +
"::emit(const string& condition) {" +
"\n";
291 emitDefinition+= definitionIndent +
"if (native == false) {" +
"\n";
292 emitDefinition+= definitionIndent +
"\t" + minitScript->
getBaseClass() +
"::emit(condition);" +
"\n";
293 emitDefinition+= definitionIndent +
"\t" +
"return;" +
"\n";
294 emitDefinition+= definitionIndent +
"}" +
"\n";
295 emitDefinition+= definitionIndent +
"if (isFunctionRunning() == true) {" +
"\n";
296 emitDefinition+= definitionIndent +
"\t" +
"deferredEmit = condition;" +
"\n";
297 emitDefinition+= definitionIndent +
"\t" +
"return;" +
"\n";
298 emitDefinition+= definitionIndent +
"}" +
"\n";
299 emitDefinition+= definitionIndent +
"emitted = true;" +
"\n";
302 string generatedDefinitions =
"\n";
303 string initializeNativeDefinition;
304 initializeNativeDefinition+=
"void " + minitScriptClassName +
"::initializeNative() {" +
"\n";
305 initializeNativeDefinition+= definitionIndent +
"setNative(true);" +
"\n";
306 initializeNativeDefinition+= definitionIndent +
"setNativeHash(\"" + minitScript->
getNativeHash() +
"\");" +
"\n";
307 initializeNativeDefinition+= definitionIndent +
"setNativeScripts(" +
"\n";
308 initializeNativeDefinition+= definitionIndent +
"\t" +
"{" +
"\n";
311 for (
const auto& script: scripts) {
312 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"Script(" +
"\n";
313 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" + getScriptTypeEnumIdentifier(script.type) +
"," +
"\n";
314 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" + to_string(script.line) +
"," +
"\n";
315 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"\"" + escapeString(script.condition) +
"\"," +
"\n";
316 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"\"" + escapeString(script.executableCondition) +
"\"," +
"\n";
317 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"Statement(" +
"\n";
318 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"\t" + to_string(script.conditionStatement.line) +
"," +
"\n";
319 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"\t" + to_string(script.conditionStatement.statementIdx) +
"," +
"\n";
320 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"\t" +
"\"" + escapeString(script.conditionStatement.statement) +
"\"," +
"\n";
321 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"\t" +
"\"" + escapeString(script.conditionStatement.executableStatement) +
"\"," +
"\n";
322 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"\t" + to_string(script.conditionStatement.gotoStatementIdx) +
"\n";
323 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
")," +
"\n";
324 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"{}," +
"\n";
325 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"\"" + script.name +
"\"," +
"\n";
326 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" + (script.emitCondition ==
true?
"true":
"false") +
"," +
"\n";
327 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"{" +
"\n";
328 auto statementIdx = MinitScript::STATEMENTIDX_FIRST;
329 for (
const auto& statement: script.statements) {
330 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"\t" +
"Statement(" +
"\n";
331 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"\t" +
"\t" + to_string(statement.line) +
"," +
"\n";
332 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"\t" +
"\t" + to_string(statement.statementIdx) +
"," +
"\n";
333 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"\t" +
"\t" +
"\"" + escapeString(statement.statement) +
"\"," +
"\n";
334 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"\t" +
"\t" +
"\"" + escapeString(statement.executableStatement) +
"\"," +
"\n";
335 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"\t" +
"\t" + to_string(statement.gotoStatementIdx) +
"\n";
336 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"\t" +
")" + (statementIdx < script.statements.size() - 1?
",":
"") +
"\n";
339 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"}," +
"\n";
340 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"{},\n";
341 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" + (script.callable ==
true?
"true":
"false") +
",\n";
342 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"{\n";
343 auto argumentIdx = 0;
344 for (
const auto& argument: script.arguments) {
345 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"\t" +
"Script::Argument(" +
"\n";
346 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"\t" +
"\t" +
"\"" + argument.name +
"\"," +
"\n";
347 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"\t" +
"\t" + (argument.reference ==
true?
"true":
"false") +
",\n";
348 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"\t" +
"\t" + (argument.privateScope ==
true?
"true":
"false") +
"\n";
349 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"\t" ")" + (argumentIdx != script.arguments.size() - 1?
",":
"") +
"\n";
352 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"}\n";
353 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
")" + (scriptIdx < scripts.size() - 1?
",":
"") +
"\n";
357 initializeNativeDefinition+= definitionIndent +
"\t" +
"}" +
"\n";
358 initializeNativeDefinition+= definitionIndent +
");" +
"\n";
359 initializeNativeDefinition+= definitionIndent +
"setNativeFunctions(" +
"\n";
360 initializeNativeDefinition+= definitionIndent +
"\t" +
"{" +
"\n";
361 auto functionItIdx = 0;
362 for (
const auto& [functionName, functionScriptIdx]: minitScript->
functions) {
363 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"{" +
"\n";
364 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" +
"\"" + functionName +
"\"," +
"\n";
365 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"\t" + to_string(functionScriptIdx) +
"\n";
366 initializeNativeDefinition+= definitionIndent +
"\t" +
"\t" +
"}" + (functionItIdx != minitScript->
functions.size() - 1?
",":
"") +
"\n";
369 initializeNativeDefinition+= definitionIndent +
"\t" +
"}" +
"\n";
370 initializeNativeDefinition+= definitionIndent +
");" +
"\n";
371 initializeNativeDefinition+= string() +
"}" +
"\n";
374 string generatedDetermineScriptIdxToStartDefinition =
"\n";
375 generatedDetermineScriptIdxToStartDefinition+=
"int " + minitScriptClassName +
"::determineScriptIdxToStart() {" +
"\n";
376 generatedDetermineScriptIdxToStartDefinition+= definitionIndent +
"#define MINITSCRIPT_METHOD_POPSTACK()" +
"\n";
377 generatedDetermineScriptIdxToStartDefinition+= definitionIndent +
"if (native == false) return MinitScript::determineScriptIdxToStart();" +
"\n";
378 generatedDetermineScriptIdxToStartDefinition+= definitionIndent +
"// MinitScript setup" +
"\n";
379 generatedDetermineScriptIdxToStartDefinition+= definitionIndent +
"auto minitScript = this;" +
"\n";
380 generatedDetermineScriptIdxToStartDefinition+= definitionIndent +
"//" +
"\n";
381 string generatedDetermineNamedScriptIdxToStartDefinition =
"\n";
382 generatedDetermineNamedScriptIdxToStartDefinition+=
"int " + minitScriptClassName +
"::determineNamedScriptIdxToStart() {" +
"\n";
383 generatedDetermineNamedScriptIdxToStartDefinition+= definitionIndent +
"#define MINITSCRIPT_METHOD_POPSTACK()" +
"\n";
384 generatedDetermineNamedScriptIdxToStartDefinition+= definitionIndent +
"if (native == false) return MinitScript::determineNamedScriptIdxToStart();" +
"\n";
385 generatedDetermineNamedScriptIdxToStartDefinition+= definitionIndent +
"auto minitScript = this;" +
"\n";
386 generatedDetermineNamedScriptIdxToStartDefinition+= definitionIndent +
"for (const auto& enabledNamedCondition: enabledNamedConditions) {" +
"\n";
389 for (
const auto& script: scripts) {
391 auto methodName = createMethodName(minitScript, scriptIdx);
392 auto shortMethodName = createShortMethodName(minitScript, scriptIdx);
396 (script.name.empty() ==
false?script.name:(
397 StringTools::regexMatch(script.condition,
"[a-zA-Z0-9_]+") ==
true?
404 if (script.type == MinitScript::Script::TYPE_ON && StringTools::regexMatch(script.condition,
"[a-zA-Z0-9_]+") ==
true) {
405 string emitDefinitionIndent =
"\t";
406 emitDefinition+= emitDefinitionIndent +
"if (condition == \"" + emitName +
"\") {" +
"\n";
407 emitDefinition+= emitDefinitionIndent +
"\t" +
"resetScriptExecutationState(" + to_string(scriptIdx) +
", STATEMACHINESTATE_NEXT_STATEMENT);" +
"\n";
408 emitDefinition+= emitDefinitionIndent +
"} else" +
"\n";
412 generatedDeclarations+= declarationIndent +
"/**" +
"\n";
413 generatedDeclarations+= declarationIndent +
" * MinitScript transpilation of: " + getScriptTypeReadableName(script.type) +
": " + script.condition + (script.name.empty() ==
false?
" (" + script.name +
")":
"") +
"\n";
414 generatedDeclarations+= declarationIndent +
" * @param minitScriptGotoStatementIdx MinitScript goto statement index" +
"\n";
415 generatedDeclarations+= declarationIndent +
" */" +
"\n";
416 generatedDeclarations+= declarationIndent +
"void " + methodName +
"(int minitScriptGotoStatementIdx);" +
"\n";
417 generatedDeclarations+=
"\n";
420 generatedDefinitions+=
"void " + minitScriptClassName +
"::" + methodName +
"(int minitScriptGotoStatementIdx) {" +
"\n";
421 string generatedSubCode;
424 if (localVariables[scriptIdx].empty() ==
false) {
425 generatedDefinitions+= definitionIndent +
"// local script variables" +
"\n";
426 generatedDefinitions+= definitionIndent +
"#define MINITSCRIPT_METHOD_POPSTACK() " + shortMethodName +
"_Stack.pop();" +
"\n";
427 generatedDefinitions+= definitionIndent +
"// STATEMENTIDX_FIRST means complete method call" +
"\n";
428 generatedDefinitions+= definitionIndent +
"if (minitScriptGotoStatementIdx == STATEMENTIDX_FIRST) {" +
"\n";
429 generatedDefinitions+= definitionIndent +
"\t" +
"auto& _lv = " + shortMethodName +
"_Stack.emplace();" +
"\n";
430 for (
const auto& variable: localVariables[scriptIdx]) {
431 generatedDefinitions+= definitionIndent +
"\t" +
"if (hasVariable(\"" + variable +
"\") == false) setVariable(\"" + variable +
"\", Variable())" +
"; _lv." + createLocalVariableName(variable) +
" = getVariable(\"" + variable +
"\", nullptr, true);" +
"\n";
433 generatedDefinitions+= definitionIndent +
"}" +
"\n";
434 generatedDefinitions+= definitionIndent +
"//" +
"\n";
435 generatedDefinitions+= definitionIndent +
"auto& _lv = " + shortMethodName +
"_Stack.top();" +
"\n";
438 if (script.type == MinitScript::Script::TYPE_STACKLET) {
440 if (scopeScriptIdx != MinitScript::SCRIPTIDX_NONE) {
442 generatedDefinitions+= definitionIndent +
"// local script variables" +
"\n";
443 generatedDefinitions+= definitionIndent +
"auto& _lv = " + scopeShortMethodName +
"_Stack.top();" +
"\n";
447 if (script.type == MinitScript::Script::TYPE_ON ||
448 script.type == MinitScript::Script::TYPE_ONENABLED) {
449 generatedDefinitions+= definitionIndent +
"// reset emitted" +
"\n";
450 generatedDefinitions+= definitionIndent +
"emitted = false;" +
"\n";
453 generatedDefinitions+= definitionIndent +
"// local script variables" +
"\n";
454 generatedDefinitions+= definitionIndent +
"#define MINITSCRIPT_METHOD_POPSTACK()" +
"\n";
458 string arrayAccessMethodsDefinitions;
459 string arrayMapSetInitializerDefinitions;
462 for (
auto statementIdx = 0; statementIdx < script.statements.size(); statementIdx++) {
463 string statementArrayMapSetInitializerDefinitions;
465 generateArrayMapSetInitializer(
467 statementArrayMapSetInitializerDefinitions,
468 MinitScript::SCRIPTIDX_NONE,
469 script.type == MinitScript::Script::TYPE_FUNCTION || script.type == MinitScript::Script::TYPE_STACKLET?
471 MinitScript::SCRIPTIDX_NONE,
472 minitScriptClassName,
474 script.syntaxTree[statementIdx],
475 script.statements[statementIdx],
482 if (statementArrayMapSetInitializerDefinitions.empty() ==
false) statementArrayMapSetInitializerDefinitions+=
"\n";
483 arrayMapSetInitializerDefinitions+= statementArrayMapSetInitializerDefinitions;
485 generateArrayAccessMethods(
487 arrayAccessMethodsDefinitions,
488 minitScriptClassName,
489 MinitScript::SCRIPTIDX_NONE,
490 script.type == MinitScript::Script::TYPE_FUNCTION || script.type == MinitScript::Script::TYPE_STACKLET?
492 MinitScript::SCRIPTIDX_NONE,
494 script.syntaxTree[statementIdx],
495 script.statements[statementIdx],
505 generatedDefinitions+= arrayMapSetInitializerDefinitions;
506 generatedDefinitions+= arrayAccessMethodsDefinitions;
509 transpile(minitScript, minitScriptClassName, generatedSubCode, scriptIdx, methodCodeMap, allMethods);
510 generatedDefinitions+= generatedSubCode;
513 if (localVariables[scriptIdx].empty() ==
false) {
514 generatedDefinitions+= definitionIndent +
"//" +
"\n";
515 generatedDefinitions+= definitionIndent +
"MINITSCRIPT_METHOD_POPSTACK();" +
"\n";
517 generatedDefinitions+= definitionIndent +
"#undef MINITSCRIPT_METHOD_POPSTACK" +
"\n";
520 generatedDefinitions+= string() +
"}" +
"\n\n";
523 if (script.emitCondition ==
false) {
524 if (script.type == MinitScript::Script::TYPE_ONENABLED) {
525 generatedDetermineNamedScriptIdxToStartDefinition+= definitionIndent;
526 generatedDetermineNamedScriptIdxToStartDefinition+= definitionIndent +
"\t" +
"// next statements belong to tested enabled named condition with name \"" + script.name +
"\"" +
"\n";
527 generatedDetermineNamedScriptIdxToStartDefinition+= definitionIndent +
"\t" +
"if (enabledNamedCondition == \"" + script.name +
"\") {" +
"\n";
529 generatedDetermineScriptIdxToStartDefinition+= definitionIndent +
"{" +
"\n";
532 string arrayMapSetInitializerDefinitions;
533 string arrayAccessMethodsDefinitions;
535 generateArrayMapSetInitializer(
537 arrayMapSetInitializerDefinitions,
538 MinitScript::SCRIPTIDX_NONE,
539 MinitScript::SCRIPTIDX_NONE,
540 minitScriptClassName,
542 script.conditionSyntaxTree,
543 script.conditionStatement,
548 script.type == MinitScript::Script::TYPE_ONENABLED?3:2
550 if (arrayMapSetInitializerDefinitions.empty() ==
false) arrayMapSetInitializerDefinitions+=
"\n";
552 generateArrayAccessMethods(
554 arrayAccessMethodsDefinitions,
555 minitScriptClassName,
556 MinitScript::SCRIPTIDX_NONE,
557 MinitScript::SCRIPTIDX_NONE,
559 script.conditionSyntaxTree,
560 script.conditionStatement,
565 script.type == MinitScript::Script::TYPE_ONENABLED?3:2
568 if (script.type == MinitScript::Script::TYPE_ON) {
569 generatedDetermineScriptIdxToStartDefinition+= arrayMapSetInitializerDefinitions;
570 generatedDetermineScriptIdxToStartDefinition+= arrayAccessMethodsDefinitions;
572 generatedDetermineNamedScriptIdxToStartDefinition+= arrayMapSetInitializerDefinitions;
573 generatedDetermineNamedScriptIdxToStartDefinition+= arrayAccessMethodsDefinitions;
578 script.type == MinitScript::Script::TYPE_ON?generatedDetermineScriptIdxToStartDefinition:generatedDetermineNamedScriptIdxToStartDefinition,
583 "bool returnValueBool; returnValue.getBooleanValue(returnValueBool); if (returnValueBool == true) return " + to_string(scriptIdx) +
";",
584 script.type == MinitScript::Script::TYPE_ONENABLED?1:0
587 if (script.type == MinitScript::Script::TYPE_ONENABLED) {
588 generatedDetermineNamedScriptIdxToStartDefinition+= definitionIndent +
"\t" +
"}" +
"\n";
590 generatedDetermineScriptIdxToStartDefinition+= definitionIndent +
"}" +
"\n";
600 generatedDetermineScriptIdxToStartDefinition+=
"\n";
601 generatedDetermineScriptIdxToStartDefinition+= definitionIndent +
"//" +
"\n";
602 generatedDetermineScriptIdxToStartDefinition+= definitionIndent +
"return " + to_string(nothingScriptIdx) +
";" +
"\n";
603 generatedDetermineScriptIdxToStartDefinition+= definitionIndent +
"#undef MINITSCRIPT_METHOD_POPSTACK" +
"\n";
604 generatedDetermineScriptIdxToStartDefinition+= string() +
"}" +
"\n";
606 generatedDetermineNamedScriptIdxToStartDefinition+= definitionIndent +
"}" +
"\n";
607 generatedDetermineNamedScriptIdxToStartDefinition+=
"\n";
608 generatedDetermineNamedScriptIdxToStartDefinition+= definitionIndent +
"//" +
"\n";
609 generatedDetermineNamedScriptIdxToStartDefinition+= definitionIndent +
"return SCRIPTIDX_NONE;" +
"\n";
610 generatedDetermineNamedScriptIdxToStartDefinition+= definitionIndent +
"#undef MINITSCRIPT_METHOD_POPSTACK" +
"\n";
611 generatedDetermineNamedScriptIdxToStartDefinition+= string() +
"}" +
"\n";
615 string emitDefinitionIndent =
"\t";
616 emitDefinition+= emitDefinitionIndent +
"{" +
"\n";
617 emitDefinition+= emitDefinitionIndent +
"\t" +
"_Console::printLine(\"" + minitScriptClassName +
"::emit(): no condition with name: '\" + condition + \"'\");" +
"\n";
618 emitDefinition+= emitDefinitionIndent +
"}" +
"\n";
619 emitDefinition+= string() +
"}" +
"\n";
623 if (globalVariables.empty() ==
false) {
624 generatedDeclarations+= declarationIndent +
"// global script variables" +
"\n";
625 for (
const auto& variable: globalVariables) {
626 generatedDeclarations+= declarationIndent +
"Variable " + createGlobalVariableName(variable) +
";" +
"\n";
628 generatedDeclarations+=
"\n";
634 for (
const auto& script: scripts) {
636 if (script.type == MinitScript::Script::TYPE_ON ||
637 script.type == MinitScript::Script::TYPE_ONENABLED ||
638 script.type == MinitScript::Script::TYPE_STACKLET) {
643 auto shortMethodName = createShortMethodName(minitScript, scriptIdx);
645 generatedDeclarations+= declarationIndent +
"// local script variables of: " + getScriptTypeReadableName(script.type) +
": " + script.condition + (script.name.empty() ==
false?
" (" + script.name +
")":
"") +
"\n";
646 generatedDeclarations+= declarationIndent +
"struct LV_" + shortMethodName +
" {" +
"\n";
647 for (
const auto& variable: localVariables[scriptIdx]) {
648 generatedDeclarations+= declarationIndent +
"\t" +
"Variable " + createLocalVariableName(variable) +
";" +
"\n";
650 generatedDeclarations+= declarationIndent +
"\t" +
"// destructor, we unset the variable references here" +
"\n";
651 generatedDeclarations+= declarationIndent +
"\t" +
"~LV_" + shortMethodName +
"() {" +
"\n";
652 for (
const auto& variable: localVariables[scriptIdx]) {
653 generatedDeclarations+= declarationIndent +
"\t" +
"\t" + createLocalVariableName(variable) +
".unset();" +
"\n";
655 generatedDeclarations+= declarationIndent +
"\t" +
"}" +
"\n";
656 generatedDeclarations+= declarationIndent +
"};" +
"\n";
657 generatedDeclarations+= declarationIndent +
"stack<LV_" + shortMethodName +
"> " + shortMethodName +
"_Stack;" +
"\n\n";
664 generatedDefinitions =
665 string(
"\n#define __MINITSCRIPT_TRANSPILATION__\n\n") +
666 initializeNativeDefinition +
667 registerMethodsDefinitions +
668 generatedDetermineScriptIdxToStartDefinition +
669 generatedDetermineNamedScriptIdxToStartDefinition +
"\n" +
671 generatedDefinitions;
676 auto injectedGeneratedCode =
true;
678 vector<string> minitScriptCPP;
679 vector<string> generatedMinitScriptCPP;
680 auto transpilationCPPFileName = FileSystem::getPathName(transpilationFileName) +
"/" + FileSystem::getFileName(transpilationFileName) +
".cpp";
681 if (FileSystem::exists(transpilationCPPFileName) ==
false) {
682 auto minitScriptCPPString = FileSystem::getContentAsString(
MINITSCRIPT_DATA +
"/resources/minitscript/templates/transpilation",
"Transpilation.cpp");
683 minitScriptCPPString = StringTools::replace(minitScriptCPPString,
"{$script}", scriptFileName);
684 minitScriptCPPString = StringTools::replace(minitScriptCPPString,
"{$class-name}", minitScriptClassName);
685 minitScriptCPPString = StringTools::replace(minitScriptCPPString,
"{$base-class}", minitScript->
getBaseClass());
686 minitScriptCPPString = StringTools::replace(minitScriptCPPString,
"{$base-class-header}", minitScript->
getBaseClassHeader());
687 minitScriptCPP = StringTools::tokenize(minitScriptCPPString,
"\n",
true);
689 FileSystem::getContentAsStringArray(FileSystem::getPathName(transpilationCPPFileName), FileSystem::getFileName(transpilationCPPFileName), minitScriptCPP);
692 if (injectedGeneratedCode ==
true) {
695 for (
const auto& include: transpilationUnitIncludes) includes+= include +
"\n";
697 injectedGeneratedCode = replace(
699 "/*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_INCLUDES_START__*/",
700 "/*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_INCLUDES_END__*/",
702 generatedMinitScriptCPP
704 if (injectedGeneratedCode ==
false) {
705 Console::printLine(scriptFileName +
": Could not inject generated C++ code, are you missing the /*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_INCLUDES_START__*/ and /*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_INCLUDES_END__*/ tags in file " + transpilationFileName +
"?");
707 minitScriptCPP = generatedMinitScriptCPP;
708 generatedMinitScriptCPP.clear();
712 if (injectedGeneratedCode ==
true) {
715 for (
const auto& _using: transpilationUnitUsings) usings+= _using +
"\n";
717 injectedGeneratedCode = replace(
719 "/*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_USINGS_START__*/",
720 "/*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_USINGS_END__*/",
722 generatedMinitScriptCPP
724 if (injectedGeneratedCode ==
false) {
725 Console::printLine(scriptFileName +
": Could not inject generated C++ code, are you missing the /*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_USINGS_START__*/ and /*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_USINGS_END__*/ tags in file " + transpilationFileName +
"?");
727 minitScriptCPP = generatedMinitScriptCPP;
728 generatedMinitScriptCPP.clear();
732 if (injectedGeneratedCode ==
true) {
733 injectedGeneratedCode = replace(
735 "/*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_DEFINITIONS_START__*/",
736 "/*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_DEFINITIONS_END__*/",
737 generatedDefinitions,
738 generatedMinitScriptCPP
740 if (injectedGeneratedCode ==
false) {
741 Console::printLine(scriptFileName +
": Could not inject generated C++ code, are you missing the /*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_DEFINITIONS_START__*/ and /*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_DEFINITIONS_END__*/ tags in file " + transpilationFileName +
"?");
743 minitScriptCPP.clear();
747 if (injectedGeneratedCode ==
true) {
748 FileSystem::setContentFromStringArray(
749 FileSystem::getPathName(transpilationCPPFileName),
750 FileSystem::getFileName(transpilationCPPFileName),
751 generatedMinitScriptCPP
754 Console::printLine(scriptFileName +
": Injected generated C++ code in file " + transpilationCPPFileName +
". Dont forget to rebuild your sources.");
761 vector<string> minitScriptClassHeader;
762 vector<string> generatedMinitScriptClassHeader;
763 auto transpilationHeaderFileName = FileSystem::getPathName(transpilationFileName) +
"/" + FileSystem::getFileName(transpilationFileName) +
".h";
764 if (FileSystem::exists(transpilationHeaderFileName) ==
false) {
765 auto minitScriptHeaderString = FileSystem::getContentAsString(
MINITSCRIPT_DATA +
"/resources/minitscript/templates/transpilation",
"Transpilation.h");
766 minitScriptHeaderString = StringTools::replace(minitScriptHeaderString,
"{$script}", scriptFileName);
767 minitScriptHeaderString = StringTools::replace(minitScriptHeaderString,
"{$class-name}", minitScriptClassName);
768 minitScriptHeaderString = StringTools::replace(minitScriptHeaderString,
"{$base-class}", minitScript->
getBaseClass());
769 minitScriptHeaderString = StringTools::replace(minitScriptHeaderString,
"{$base-class-header}", minitScript->
getBaseClassHeader());
770 minitScriptClassHeader = StringTools::tokenize(minitScriptHeaderString,
"\n",
true);
772 FileSystem::getContentAsStringArray(FileSystem::getPathName(transpilationHeaderFileName), FileSystem::getFileName(transpilationHeaderFileName), minitScriptClassHeader);
775 auto injectedGeneratedCode = replace(
776 minitScriptClassHeader,
777 "/*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_DECLARATIONS_START__*/",
778 "/*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_DECLARATIONS_END__*/",
779 generatedDeclarations,
780 generatedMinitScriptClassHeader
783 if (injectedGeneratedCode ==
false) {
784 Console::printLine(scriptFileName +
": Could not inject generated C++ code, are you missing the /*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_DECLARATIONS_START__*/ and /*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_DECLARATIONS_END__*/ tags in file " + transpilationFileName +
"?");
787 FileSystem::setContentFromStringArray(
788 FileSystem::getPathName(transpilationHeaderFileName),
789 FileSystem::getFileName(transpilationHeaderFileName),
790 generatedMinitScriptClassHeader
793 Console::printLine(scriptFileName +
": Injected generated C++ code in header file " + transpilationHeaderFileName +
". Dont forget to rebuild your sources.");
798 void Transpiler::untranspile(
const string& scriptFileName,
const string& transpilationFileName) {
799 Console::printLine(scriptFileName +
": Processing script");
801 auto replace = [](
const vector<string> input,
const string& startTag,
const string& endTag,
const string& replacement, vector<string>& output) ->
bool {
803 auto replaceSuccess =
false;
804 for (
auto i = 0; i < input.size(); i++) {
805 const auto& line = input[i];
806 auto trimmedLine = StringTools::trim(line);
807 if (StringTools::startsWith(trimmedLine,
"//") ==
true) {
808 if (reject ==
false) output.push_back(line);
811 if (trimmedLine == startTag) {
813 output.push_back(line);
815 if (trimmedLine == endTag) {
817 replaceSuccess =
true;
818 output.push_back(replacement);
819 output.push_back(line);
821 if (reject ==
false) output.push_back(line);
825 return replaceSuccess;
829 vector<string> minitScriptClass;
830 vector<string> minitScriptClassNew;
831 auto transpilationCPPFileName = FileSystem::getPathName(transpilationFileName) +
"/" + FileSystem::getFileName(transpilationFileName) +
".cpp";
832 FileSystem::getContentAsStringArray(FileSystem::getPathName(transpilationCPPFileName), FileSystem::getFileName(transpilationCPPFileName), minitScriptClass);
834 auto injectedGeneratedCode =
false;
836 injectedGeneratedCode = replace(
838 "/*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_INCLUDES_START__*/",
839 "/*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_INCLUDES_END__*/",
843 minitScriptClass = minitScriptClassNew;
844 minitScriptClassNew.clear();
846 if (injectedGeneratedCode ==
true) {
847 injectedGeneratedCode = replace(
849 "/*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_USINGS_START__*/",
850 "/*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_USINGS_END__*/",
854 minitScriptClass = minitScriptClassNew;
855 minitScriptClassNew.clear();
857 if (injectedGeneratedCode ==
true) {
858 injectedGeneratedCode = replace(
860 "/*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_DEFINITIONS_START__*/",
861 "/*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_DEFINITIONS_END__*/",
867 if (injectedGeneratedCode ==
false) {
868 Console::printLine(scriptFileName +
": Could not remove generated C++ code, are you missing the /*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_DEFINITIONS_START__*/ and /*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_DEFINITIONS_END__*/ markers in file " + transpilationFileName +
"?");
871 FileSystem::setContentFromStringArray(
872 FileSystem::getPathName(transpilationCPPFileName),
873 FileSystem::getFileName(transpilationCPPFileName),
877 Console::printLine(scriptFileName +
": Removed generated C++ code in file " + transpilationCPPFileName +
". Dont forget to rebuild your sources.");
883 vector<string> minitScriptClassHeader;
884 vector<string> minitScriptClassHeaderNew;
885 auto transpilationHeaderFileName = FileSystem::getPathName(transpilationFileName) +
"/" + FileSystem::getFileName(transpilationFileName) +
".h";
886 FileSystem::getContentAsStringArray(FileSystem::getPathName(transpilationHeaderFileName), FileSystem::getFileName(transpilationHeaderFileName), minitScriptClassHeader);
888 auto injectedGeneratedCode =
false;
889 injectedGeneratedCode = replace(
890 minitScriptClassHeader,
891 "/*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_DECLARATIONS_START__*/",
892 "/*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_DECLARATIONS_END__*/",
894 minitScriptClassHeaderNew
897 if (injectedGeneratedCode ==
false) {
898 Console::printLine(scriptFileName +
": Could not remove generated C++ code, are you missing the /*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_DECLARATIONS_START__*/ and /*__MINITSCRIPT_TRANSPILEDMINITSCRIPTCODE_DECLARATIONS_END__*/ markers in file " + transpilationFileName +
"?");
901 FileSystem::setContentFromStringArray(
902 FileSystem::getPathName(transpilationHeaderFileName),
903 FileSystem::getFileName(transpilationHeaderFileName),
904 minitScriptClassHeaderNew
907 Console::printLine(scriptFileName +
": Removed generated C++ code in header file " + transpilationHeaderFileName +
". Dont forget to rebuild your sources.");
912 const unordered_set<string> Transpiler::getAllClassesMethodNames(
MinitScript* minitScript) {
913 unordered_set<string> allMethods;
914 for (
auto scriptMethod: minitScript->
getMethods()) {
916 if (scriptMethod->getMethodName().rfind(
"::") != string::npos) className = StringTools::substring(scriptMethod->getMethodName(), 0, scriptMethod->getMethodName().rfind(
"::"));
917 if (className.empty() ==
true)
continue;
919 StringTools::substring(
920 scriptMethod->getMethodName(),
921 className.size() + 2,
922 scriptMethod->getMethodName().size());
924 if (scriptMethod->getArgumentTypes().empty() ==
true ||
925 scriptMethod->getArgumentTypes()[0].name != StringTools::toLowerCase(className))
continue;
927 if (className != MinitScript::Variable::getTypeAsString(scriptMethod->getArgumentTypes()[0].type))
continue;
928 allMethods.insert(method);
934 const vector<string> Transpiler::getAllClassesMethodNamesSorted(
MinitScript* minitScript) {
935 auto allMethods = getAllClassesMethodNames(minitScript);
937 vector<string> result;
938 for (
auto method: allMethods) result.push_back(method);
939 sort(result.begin(), result.end());
944 const unordered_map<string, vector<string>> Transpiler::getClassesMethodNames(
MinitScript* minitScript) {
945 unordered_map<string, vector<string>> methodByClasses;
946 for (
auto scriptMethod: minitScript->
getMethods()) {
948 if (scriptMethod->getMethodName().rfind(
"::") != string::npos) className = StringTools::substring(scriptMethod->getMethodName(), 0, scriptMethod->getMethodName().rfind(
"::"));
949 if (className.empty() ==
true)
continue;
951 StringTools::substring(
952 scriptMethod->getMethodName(),
953 className.size() + 2,
954 scriptMethod->getMethodName().size());
956 if (scriptMethod->getArgumentTypes().empty() ==
true ||
957 scriptMethod->getArgumentTypes()[0].name != StringTools::toLowerCase(className))
continue;
959 if (className != MinitScript::Variable::getTypeAsString(scriptMethod->getArgumentTypes()[0].type))
continue;
961 methodByClasses[className].push_back(method);
964 return methodByClasses;
967 void Transpiler::determineVariables(
MinitScript* minitScript, unordered_set<string>& globalVariables, vector<unordered_set<string>>& localVariables) {
973 const auto& scripts = minitScript->
getScripts();
977 for (
const auto& script: scripts) {
979 determineVariables(MinitScript::SCRIPTIDX_NONE, script.conditionSyntaxTree, globalVariables, localVariables);
981 for (
auto statementIdx = 0; statementIdx < script.statements.size(); statementIdx++) {
983 script.type == MinitScript::Script::TYPE_FUNCTION || script.type == MinitScript::Script::TYPE_STACKLET?
985 MinitScript::SCRIPTIDX_NONE,
986 script.syntaxTree[statementIdx],
996 for (
auto scriptIdx = 0; scriptIdx < localVariables.size(); scriptIdx++) {
997 const auto& script = scripts[scriptIdx];
998 if (script.type != MinitScript::Script::TYPE_STACKLET)
continue;
1001 for (
const auto& variable: localVariables[scriptIdx]) {
1002 if (stackletScopeScriptIdx == MinitScript::SCRIPTIDX_NONE) {
1003 globalVariables.insert(variable);
1005 localVariables[stackletScopeScriptIdx].insert(variable);
1008 localVariables[scriptIdx].clear();
1012 void Transpiler::determineVariables(
int scriptIdx,
const MinitScript::SyntaxTreeNode& syntaxTreeNode, unordered_set<string>& globalVariables, vector<unordered_set<string>>& localVariables) {
1013 auto addVariable = [&](
const string& variableStatement) ->
void {
1015 if (scriptIdx == MinitScript::SCRIPTIDX_NONE ||
1016 StringTools::startsWith(variableStatement,
"$$.") ==
true ||
1017 StringTools::startsWith(variableStatement,
"$GLOBAL.") ==
true) {
1019 if (StringTools::startsWith(variableStatement,
"$$.") ==
true) {
1020 const auto variableName = createVariableName(
"$" + StringTools::substring(variableStatement, string_view(
"$$.").size()));
1021 globalVariables.insert(variableName);
1023 if (StringTools::startsWith(variableStatement,
"$GLOBAL.") ==
true) {
1024 const auto variableName = createVariableName(
"$" + StringTools::substring(variableStatement, string_view(
"$GLOBAL.").size()));
1025 globalVariables.insert(variableName);
1027 const auto variableName = createVariableName(variableStatement);
1028 globalVariables.insert(variableName);
1031 const auto variableName = createVariableName(variableStatement);
1032 localVariables[scriptIdx].insert(variableName);
1036 switch (syntaxTreeNode.
type) {
1037 case MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_LITERAL:
1041 case MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_FUNCTION:
1043 for (
const auto& argument: syntaxTreeNode.
arguments) determineVariables(scriptIdx, argument, globalVariables, localVariables);
1047 case MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_METHOD:
1056 syntaxTreeNode.
arguments.empty() ==
false &&
1057 syntaxTreeNode.
arguments[0].type == MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_LITERAL) {
1059 addVariable(syntaxTreeNode.
arguments[0].value.getValueAsString());
1062 if (syntaxTreeNode.
arguments[0].value.getType() == MinitScript::TYPE_STRING) {
1063 addVariable(syntaxTreeNode.
arguments[0].value.getValueAsString());
1065 for (
auto i = 3; i < syntaxTreeNode.
arguments.size(); i+= 2) {
1066 if (syntaxTreeNode.
arguments[i].value.getType() == MinitScript::TYPE_STRING) {
1067 addVariable(syntaxTreeNode.
arguments[i].value.getValueAsString());
1072 for (
const auto& argument: syntaxTreeNode.
arguments) determineVariables(scriptIdx, argument, globalVariables, localVariables);
1081 void Transpiler::gatherMethodCode(
1082 const vector<string>& minitScriptExtensionsCode,
1083 const string& className,
1085 unordered_map<
string, vector<string>>& methodCodeMap
1088 auto classDefinitionLine = -1;
1090 for (
auto i = registerLine; i >= 0; i--) {
1091 const auto& line = minitScriptExtensionsCode[i];
1092 auto trimmedLine = StringTools::trim(line);
1093 if (StringTools::regexMatch(trimmedLine,
"class[\\ \\t]+" + className +
"[\\ \\t]*:.*") ==
true) {
1094 classDefinitionLine = i;
1099 if (classDefinitionLine == -1) {
1100 Console::printLine(
"Transpiler::gatherMethodCode(): did not found '" + className +
"' definition");
1104 auto curlyBracketCount = 0;
1105 auto finished =
false;
1106 auto haveExecuteMethodDeclaration =
false;
1107 auto executeMethodCurlyBracketStart = -1;
1108 auto haveGetMethodNameDeclaration =
false;
1109 auto getMethodNameCurlyBracketStart = -1;
1110 vector<string> executeMethodCode;
1111 string getMethodNameCode;
1112 for (
auto i = classDefinitionLine; finished ==
false && i < minitScriptExtensionsCode.size(); i++) {
1113 const auto& line = minitScriptExtensionsCode[i];
1114 auto trimmedLine = StringTools::trim(line);
1116 if (StringTools::regexMatch(trimmedLine,
"const[\\ \\t]+string[\\ \\t]+getMethodName()[\\ \\t]*\\(.*") ==
true) {
1117 haveGetMethodNameDeclaration =
true;
1120 if (StringTools::regexMatch(trimmedLine,
"void[\\ \\t]+executeMethod[\\ \\t]*\\(.*") ==
true) {
1121 haveExecuteMethodDeclaration =
true;
1124 for (
auto j = 0; j < trimmedLine.size(); j++) {
1125 auto c = trimmedLine[j];
1127 curlyBracketCount++;
1130 if (haveExecuteMethodDeclaration ==
true) {
1131 executeMethodCurlyBracketStart = curlyBracketCount;
1134 if (haveGetMethodNameDeclaration ==
true) {
1135 getMethodNameCurlyBracketStart = curlyBracketCount;
1140 if (getMethodNameCurlyBracketStart != -1 && curlyBracketCount == getMethodNameCurlyBracketStart) {
1142 getMethodNameCurlyBracketStart = -1;
1145 if (executeMethodCurlyBracketStart != -1 && curlyBracketCount == executeMethodCurlyBracketStart) {
1147 executeMethodCurlyBracketStart = -1;
1150 curlyBracketCount--;
1152 if (curlyBracketCount <= 0) {
1159 if (haveGetMethodNameDeclaration ==
false && getMethodNameCurlyBracketStart != -1 && curlyBracketCount >= getMethodNameCurlyBracketStart) {
1160 getMethodNameCode+= trimmedLine;
1163 if (haveExecuteMethodDeclaration ==
false && executeMethodCurlyBracketStart != -1 && curlyBracketCount >= executeMethodCurlyBracketStart) {
1164 executeMethodCode.push_back(line);
1167 if (haveGetMethodNameDeclaration ==
true) {
1169 haveGetMethodNameDeclaration =
false;
1172 if (haveExecuteMethodDeclaration ==
true) {
1174 haveExecuteMethodDeclaration =
false;
1181 auto haveMethodName =
false;
1182 for (
auto i = 0; i < getMethodNameCode.size(); i++) {
1183 auto c = getMethodNameCode[i];
1185 if (haveMethodName ==
false) haveMethodName =
true;
else
1188 if (haveMethodName ==
true) {
1195 int minIndent = Integer::MAX_VALUE;
1196 for (
const auto& codeLine: executeMethodCode) {
1198 for (
auto i = 0; i < codeLine.size(); i++) {
1199 auto c = codeLine[i];
1206 minIndent = Math::min(minIndent, indent);
1210 for (
auto& codeLine: executeMethodCode) {
1211 codeLine = StringTools::substring(codeLine, minIndent);
1215 auto methodCodeMapIt = methodCodeMap.find(methodName);
1216 if (methodCodeMapIt != methodCodeMap.end()) {
1217 Console::printLine(
"Transpiler::gatherMethodCode(): Not registering method with methodName: '" + methodName +
"': method already registered");
1222 Console::printLine(
"Transpiler::gatherMethodCode(): registering method with methodName: '" + methodName +
"'");
1225 methodCodeMap[methodName] = executeMethodCode;
1228 void Transpiler::generateVariableAccess(
1230 string& generatedCode,
1231 int scriptConditionIdx,
1233 const string& variableName,
1234 const string& indent,
1235 bool getMethodArgumentVariable,
1237 bool getVariableReference,
1239 bool setVariableReference,
1241 const string& returnValueStatement,
1242 const string& statementEnd,
1247 auto haveFunction =
false;
1248 auto haveScript = (scriptConditionIdx != MinitScript::SCRIPTIDX_NONE || scriptIdx != MinitScript::SCRIPTIDX_NONE);
1249 if (haveScript ==
true) {
1250 const auto& script = minitScript->
getScripts()[scriptConditionIdx != MinitScript::SCRIPTIDX_NONE?scriptConditionIdx:scriptIdx];
1252 script.type == MinitScript::Script::TYPE_FUNCTION ||
1253 (script.type == MinitScript::Script::TYPE_STACKLET && minitScript->
getStackletScopeScriptIdx(scriptIdx) != MinitScript::SCRIPTIDX_NONE);
1256 auto dollarDollarVariable = StringTools::startsWith(variableName,
"$$.");
1257 auto dollarGlobalVariable = StringTools::startsWith(variableName,
"$GLOBAL.");
1258 if (haveFunction ==
true ||
1259 dollarDollarVariable ==
true ||
1260 dollarGlobalVariable ==
true) {
1262 if (dollarDollarVariable ==
true || dollarGlobalVariable ==
true) {
1263 auto globalVariableIdx = 0;
1264 string globalVariable;
1265 if (dollarDollarVariable ==
true) {
1266 globalVariable =
"$" + StringTools::substring(variableName, string_view(
"$$.").size());
1267 globalVariableIdx = 3;
1269 if (dollarGlobalVariable ==
true) {
1270 globalVariable =
"$" + StringTools::substring(variableName, string_view(
"$GLOBAL.").size());
1271 globalVariableIdx = 8;
1273 auto haveVariableStatement = variableHasStatement(globalVariable);
1274 if (getMethodArgumentVariable ==
true) {
1275 if (haveVariableStatement ==
true) {
1276 generatedCode+= indent + returnValueStatement +
"getMethodArgumentVariable(&" + createGlobalVariableName(globalVariable) +
", \"$\" + StringTools::substring(arguments[" + to_string(getArgumentIdx) +
"].getValueAsString(), " + to_string(globalVariableIdx) +
"), &subStatement)" + statementEnd;
1278 generatedCode+= indent + returnValueStatement +
"Variable::createMethodArgumentVariable(&" + createGlobalVariableName(globalVariable) +
")" + statementEnd;
1281 if (getVariable ==
true) {
1282 if (haveVariableStatement ==
true) {
1283 generatedCode+= indent + returnValueStatement +
"getVariable(&" + createGlobalVariableName(globalVariable) +
", \"$\" + StringTools::substring(arguments[" + to_string(getArgumentIdx) +
"].getValueAsString(), " + to_string(globalVariableIdx) +
"), &subStatement, false)" + statementEnd;
1285 generatedCode+= indent + returnValueStatement +
"Variable::createNonReferenceVariable(&" + createGlobalVariableName(globalVariable) +
")" + statementEnd;
1288 if (getVariableReference ==
true) {
1289 if (haveVariableStatement ==
true) {
1290 generatedCode+= indent + returnValueStatement +
"getVariable(&" + createGlobalVariableName(globalVariable) +
", \"$\" + StringTools::substring(arguments[" + to_string(getArgumentIdx) +
"].getValueAsString(), " + to_string(globalVariableIdx) +
"), &subStatement, true)" + statementEnd;
1292 generatedCode+= indent + returnValueStatement +
"Variable::createReferenceVariable(&" + createGlobalVariableName(globalVariable) +
")" + statementEnd;
1295 if (setVariable ==
true || setConstant ==
true) {
1296 if (haveVariableStatement ==
true) {
1297 if (setConstant ==
true) {
1298 generatedCode+= indent +
"setConstant(&" + createGlobalVariableName(globalVariable) +
", \"$\" + StringTools::substring(arguments[" + to_string(getArgumentIdx) +
"].getValueAsString(), " + to_string(globalVariableIdx) +
"), arguments[" + to_string(setArgumentIdx) +
"], &subStatement); returnValue = arguments[" + to_string(setArgumentIdx) +
"]" + statementEnd;
1300 generatedCode+= indent +
"setVariable(&" + createGlobalVariableName(globalVariable) +
", \"$\" + StringTools::substring(arguments[" + to_string(getArgumentIdx) +
"].getValueAsString(), " + to_string(globalVariableIdx) +
"), arguments[" + to_string(setArgumentIdx) +
"].isConstant() == true?MinitScript::Variable::createNonConstVariable(&arguments[" + to_string(setArgumentIdx) +
"]):arguments[" + to_string(setArgumentIdx) +
"], &subStatement); returnValue = arguments[" + to_string(setArgumentIdx) +
"]" + statementEnd;
1303 generatedCode+= indent +
"if (" + createGlobalVariableName(globalVariable) +
".isConstant() == true) _Console::printLine(getStatementInformation(statement) + \": Constant: " + globalVariable +
": assignment of constant is not allowed\"); else ";
1304 if (setConstant ==
true) {
1305 generatedCode+=
"{ ";
1306 generatedCode+= createGlobalVariableName(globalVariable) +
".setValue(arguments[" + to_string(setArgumentIdx) +
"]); ";
1307 generatedCode+=
"setConstant(" + createGlobalVariableName(globalVariable) +
"); ";
1308 generatedCode+=
"} ";
1310 generatedCode+= createGlobalVariableName(globalVariable) +
".setValue(arguments[" + to_string(setArgumentIdx) +
"].isConstant() == true?MinitScript::Variable::createNonConstVariable(&arguments[" + to_string(setArgumentIdx) +
"]):arguments[" + to_string(setArgumentIdx) +
"]); ";
1312 generatedCode+= returnValueStatement +
"arguments[" + to_string(setArgumentIdx) +
"]" + statementEnd;
1315 if (setVariableReference ==
true) {
1316 if (haveVariableStatement ==
true) {
1317 generatedCode+= indent +
"setVariable(&" + createGlobalVariableName(globalVariable) +
", \"$\" + StringTools::substring(arguments[" + to_string(getArgumentIdx) +
"].getValueAsString(), " + to_string(globalVariableIdx) +
"), arguments[" + to_string(setArgumentIdx) +
"], &subStatement, true); returnValue = arguments[" + to_string(setArgumentIdx) +
"]" + statementEnd;
1319 generatedCode+= indent +
"if (" + createGlobalVariableName(globalVariable) +
".isConstant() == true) _Console::printLine(getStatementInformation(statement) + \": Constant: " + globalVariable +
": assignment of constant is not allowed\"); else ";
1320 generatedCode+= createGlobalVariableName(globalVariable) +
".setReference(&arguments[" + to_string(setArgumentIdx) +
"]); " + returnValueStatement +
"arguments[" + to_string(setArgumentIdx) +
"]" + statementEnd;
1324 const auto& localVariable = variableName;
1325 auto haveVariableStatement = variableHasStatement(localVariable);
1326 if (getMethodArgumentVariable ==
true) {
1327 if (haveVariableStatement ==
true) {
1328 generatedCode+= indent + returnValueStatement +
"getMethodArgumentVariable(&_lv." + createLocalVariableName(localVariable) +
", arguments[" + to_string(getArgumentIdx) +
"].getValueAsString(), &subStatement)" + statementEnd;
1330 generatedCode+= indent + returnValueStatement +
"Variable::createMethodArgumentVariable(&_lv." + createLocalVariableName(localVariable) +
")" + statementEnd;
1333 if (getVariable ==
true) {
1334 if (haveVariableStatement ==
true) {
1335 generatedCode+= indent + returnValueStatement +
"getVariable(&_lv." + createLocalVariableName(localVariable) +
", arguments[" + to_string(getArgumentIdx) +
"].getValueAsString(), &subStatement, false)" + statementEnd;
1337 generatedCode+= indent + returnValueStatement +
"Variable::createNonReferenceVariable(&_lv." + createLocalVariableName(localVariable) +
")" + statementEnd;
1340 if (getVariableReference ==
true) {
1341 if (haveVariableStatement ==
true) {
1342 generatedCode+= indent + returnValueStatement +
"getVariable(&_lv." + createLocalVariableName(localVariable) +
", arguments[" + to_string(getArgumentIdx) +
"].getValueAsString(), &subStatement, true)" + statementEnd;
1344 generatedCode+= indent + returnValueStatement +
"Variable::createReferenceVariable(&_lv." + createLocalVariableName(localVariable) +
")" + statementEnd;
1347 if (setVariable ==
true || setConstant ==
true) {
1348 if (haveVariableStatement ==
true) {
1349 if (setConstant ==
true) {
1350 generatedCode+= indent +
"setConstant(&_lv." + createLocalVariableName(localVariable) +
", arguments[" + to_string(getArgumentIdx) +
"].getValueAsString(), arguments[" + to_string(setArgumentIdx) +
"], &subStatement); returnValue = arguments[" + to_string(setArgumentIdx) +
"]" + statementEnd;
1352 generatedCode+= indent +
"setVariable(&_lv." + createLocalVariableName(localVariable) +
", arguments[" + to_string(getArgumentIdx) +
"].getValueAsString(), arguments[" + to_string(setArgumentIdx) +
"].isConstant() == true?MinitScript::Variable::createNonConstVariable(&arguments[" + to_string(setArgumentIdx) +
"]):arguments[" + to_string(setArgumentIdx) +
"], &subStatement); returnValue = arguments[" + to_string(setArgumentIdx) +
"]" + statementEnd;
1355 generatedCode+= indent +
"if (_lv." + createLocalVariableName(localVariable) +
".isConstant() == true) _Console::printLine(getStatementInformation(statement) + \": Constant: " + localVariable +
": assignment of constant is not allowed\"); else ";
1356 if (setConstant ==
true) {
1357 generatedCode+=
"{ ";
1358 generatedCode+=
"_lv." + createLocalVariableName(localVariable) +
".setValue(arguments[" + to_string(setArgumentIdx) +
"]); ";
1359 generatedCode+=
"setConstant(_lv." + createLocalVariableName(localVariable) +
"); ";
1360 generatedCode+=
"} ";
1362 generatedCode+=
"_lv." + createLocalVariableName(localVariable) +
".setValue(arguments[" + to_string(setArgumentIdx) +
"].isConstant() == true?MinitScript::Variable::createNonConstVariable(&arguments[" + to_string(setArgumentIdx) +
"]):arguments[" + to_string(setArgumentIdx) +
"]); ";
1364 generatedCode+= returnValueStatement +
"arguments[" + to_string(setArgumentIdx) +
"]" + statementEnd;
1367 if (setVariableReference ==
true) {
1368 if (haveVariableStatement ==
true) {
1369 generatedCode+= indent +
"setVariable(&_lv." + createLocalVariableName(localVariable) +
", arguments[" + to_string(getArgumentIdx) +
"].getValueAsString(), arguments[" + to_string(setArgumentIdx) +
"], &subStatement, true); returnValue = arguments[" + to_string(setArgumentIdx) +
"]" + statementEnd;
1371 generatedCode+= indent +
"if (_lv." + createLocalVariableName(localVariable) +
".isConstant() == true) _Console::printLine(getStatementInformation(statement) + \": Constant: " + localVariable +
": assignment of constant is not allowed\"); else ";
1372 generatedCode+=
"_lv." + createLocalVariableName(localVariable) +
".setReference(&arguments[" + to_string(setArgumentIdx) +
"]); " + returnValueStatement +
"arguments[" + to_string(setArgumentIdx) +
"]" + statementEnd;
1378 const auto& globalVariable = variableName;
1379 auto haveVariableStatement = variableHasStatement(globalVariable);
1380 if (getMethodArgumentVariable ==
true) {
1381 if (haveVariableStatement ==
true) {
1382 generatedCode+= indent + returnValueStatement +
"getMethodArgumentVariable(&" + createGlobalVariableName(globalVariable) +
", arguments[" + to_string(getArgumentIdx) +
"].getValueAsString(), &subStatement)" + statementEnd;
1384 generatedCode+= indent + returnValueStatement +
"Variable::createMethodArgumentVariable(&" + createGlobalVariableName(globalVariable) +
")" + statementEnd;
1387 if (getVariable ==
true) {
1388 if (haveVariableStatement ==
true) {
1389 generatedCode+= indent + returnValueStatement +
"getVariable(&" + createGlobalVariableName(globalVariable) +
", arguments[" + to_string(getArgumentIdx) +
"].getValueAsString(), &subStatement, false)" + statementEnd;
1391 generatedCode+= indent + returnValueStatement +
"Variable::createNonReferenceVariable(&" + createGlobalVariableName(globalVariable) +
")" + statementEnd;
1394 if (getVariableReference ==
true) {
1395 if (haveVariableStatement ==
true) {
1396 generatedCode+= indent + returnValueStatement +
"getVariable(&" + createGlobalVariableName(globalVariable) +
", arguments[" + to_string(getArgumentIdx) +
"].getValueAsString(), &subStatement, true)" + statementEnd;
1398 generatedCode+= indent + returnValueStatement +
"Variable::createReferenceVariable(&" + createGlobalVariableName(globalVariable) +
")" + statementEnd;
1401 if (setVariable ==
true || setConstant ==
true) {
1402 if (haveVariableStatement ==
true) {
1403 if (setConstant ==
true) {
1404 generatedCode+= indent +
"setConstant(&" + createGlobalVariableName(globalVariable) +
", arguments[" + to_string(getArgumentIdx) +
"].getValueAsString(), arguments[" + to_string(setArgumentIdx) +
"], &subStatement); " + returnValueStatement +
"arguments[" + to_string(getArgumentIdx) +
"]" + statementEnd;
1406 generatedCode+= indent +
"setVariable(&" + createGlobalVariableName(globalVariable) +
", arguments[" + to_string(getArgumentIdx) +
"].getValueAsString(), arguments[" + to_string(setArgumentIdx) +
"].isConstant() == true?MinitScript::Variable::createNonConstVariable(&arguments[" + to_string(setArgumentIdx) +
"]):arguments[" + to_string(setArgumentIdx) +
"], &subStatement); " + returnValueStatement +
"arguments[" + to_string(getArgumentIdx) +
"]" + statementEnd;
1409 generatedCode+= indent +
"if (" + createGlobalVariableName(globalVariable) +
".isConstant() == true) _Console::printLine(getStatementInformation(statement) + \": Constant: " + globalVariable +
": assignment of constant is not allowed\"); else ";
1410 if (setConstant ==
true) {
1411 generatedCode+=
"{ ";
1412 generatedCode+= createGlobalVariableName(globalVariable) +
".setValue(arguments[" + to_string(setArgumentIdx) +
"]); ";
1413 generatedCode+=
"setConstant(" + createGlobalVariableName(globalVariable) +
"); ";
1414 generatedCode+=
"} ";
1416 generatedCode+= createGlobalVariableName(globalVariable) +
".setValue(arguments[" + to_string(setArgumentIdx) +
"].isConstant() == true?MinitScript::Variable::createNonConstVariable(&arguments[" + to_string(setArgumentIdx) +
"]):arguments[" + to_string(setArgumentIdx) +
"]); ";
1418 generatedCode+= returnValueStatement +
"arguments[" + to_string(setArgumentIdx) +
"]" + statementEnd;
1421 if (setVariableReference ==
true) {
1422 if (haveVariableStatement ==
true) {
1423 generatedCode+= indent +
"setVariable(&" + createGlobalVariableName(globalVariable) +
", arguments[" + to_string(getArgumentIdx) +
"].getValueAsString(), arguments[" + to_string(setArgumentIdx) +
"], &subStatement, true); " + returnValueStatement +
"arguments[" + to_string(getArgumentIdx) +
"]" + statementEnd;
1425 generatedCode+= indent +
"if (" + createGlobalVariableName(globalVariable) +
".isConstant() == true) _Console::printLine(getStatementInformation(statement) + \": Constant: " + globalVariable +
": assignment of constant is not allowed\"); else ";
1426 generatedCode+= createGlobalVariableName(globalVariable) +
".setReference(&arguments[" + to_string(setArgumentIdx) +
"]); " + returnValueStatement +
"arguments[" + to_string(setArgumentIdx) +
"]" + statementEnd;
1432 void Transpiler::generateArrayAccessMethods(
1434 string& generatedDefinitions,
1435 const string& minitScriptClassName,
1436 int scriptConditionIdx,
1438 const string& methodName,
1441 const unordered_map<
string, vector<string>>& methodCodeMap,
1442 const unordered_set<string>& allMethods,
1444 const vector<int>& argumentIndices,
1448 switch (syntaxTree.
type) {
1449 case MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_LITERAL:
1453 case MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_METHOD:
1462 auto lamdaIndent = StringTools::indent(
string(),
"\t", depth);
1464 for (
auto argumentIdx = 0; argumentIdx < syntaxTree.
arguments.size(); argumentIdx++) {
1465 auto argumentString = escapeString(syntaxTree.
arguments[argumentIdx].value.getValueAsString());
1467 auto nextArgumentIndices = argumentIndices;
1468 nextArgumentIndices.push_back(argumentIdx);
1470 if (StringTools::startsWith(argumentString,
"[") ==
true ||
1471 StringTools::startsWith(argumentString,
"{") ==
true)
continue;
1473 auto arrayAccessStatementIdx = 0;
1474 auto arrayAccessStatementLeftIdx = -1;
1475 auto arrayAccessStatementRightIdx = -1;
1477 auto bracketCount = 0;
1478 for (
auto i = 0; i < argumentString.size(); i++) {
1479 auto c = argumentString[i];
1481 if (quote !=
'\0') {
1488 if (c ==
'"' || c ==
'\'') {
1492 if (bracketCount == 0) arrayAccessStatementLeftIdx = i;
1497 if (bracketCount == 0) {
1498 arrayAccessStatementRightIdx = i;
1500 auto arrayAccessStatementString = StringTools::substring(argumentString, arrayAccessStatementLeftIdx + 1, arrayAccessStatementRightIdx);
1502 if (arrayAccessStatementString.empty() ==
true) {
1504 arrayAccessStatementIdx++;
1511 arrayAccessStatementAsScriptVariable.
setImplicitTypedValue(arrayAccessStatementString, minitScript, scriptIdx, statement);
1512 switch (arrayAccessStatementAsScriptVariable.
getType()) {
1513 case MinitScript::TYPE_BOOLEAN:
1516 if (arrayAccessStatementAsScriptVariable.
getBooleanValue(booleanValue) ==
true) {
1517 generatedDefinitions+= lamdaIndent +
"// MinitScript transpilation for a " + (condition ==
true?
"condition":
"statement") +
" array access statement, statement index " + to_string(statement.
statementIdx) +
", argument indices " + MinitScript::getArgumentIndicesAsString(nextArgumentIndices,
", ") +
", array access statement index " + to_string(arrayAccessStatementIdx) +
"\n";
1518 generatedDefinitions+= lamdaIndent +
"auto array_access_statement_" + to_string(statement.
statementIdx) +
"_" + MinitScript::getArgumentIndicesAsString(nextArgumentIndices,
"_") +
"_" + to_string(arrayAccessStatementIdx) +
" = [&](const SubStatement& subStatement) -> Variable {" +
"\n";
1519 generatedDefinitions+= lamdaIndent +
" return Variable(" + (booleanValue ==
true?
"true":
"false") +
");" +
"\n";
1520 generatedDefinitions+= lamdaIndent +
"};" +
"\n";
1523 arrayAccessStatementIdx++;
1527 case MinitScript::TYPE_INTEGER:
1529 int64_t integerValue;
1530 if (arrayAccessStatementAsScriptVariable.
getIntegerValue(integerValue) ==
true) {
1531 generatedDefinitions+= lamdaIndent +
"// MinitScript transpilation for a " + (condition ==
true?
"condition":
"statement") +
" array access statement, statement index " + to_string(statement.
statementIdx) +
", argument indices " + MinitScript::getArgumentIndicesAsString(nextArgumentIndices,
", ") +
", array access statement index " + to_string(arrayAccessStatementIdx) +
"\n";
1532 generatedDefinitions+= lamdaIndent +
"auto array_access_statement_" + to_string(statement.
statementIdx) +
"_" + MinitScript::getArgumentIndicesAsString(nextArgumentIndices,
"_") +
"_" + to_string(arrayAccessStatementIdx) +
" = [&](const SubStatement& subStatement) -> Variable {" +
"\n";
1533 generatedDefinitions+= lamdaIndent +
" return Variable(static_cast<int64_t>(" + to_string(integerValue) +
"ll));" +
"\n";
1534 generatedDefinitions+= lamdaIndent +
"};" +
"\n";
1537 arrayAccessStatementIdx++;
1541 case MinitScript::TYPE_FLOAT:
1544 if (arrayAccessStatementAsScriptVariable.
getFloatValue(floatValue) ==
true) {
1545 generatedDefinitions+= lamdaIndent +
"// MinitScript transpilation for a " + (condition ==
true?
"condition":
"statement") +
" array access statement, statement index " + to_string(statement.
statementIdx) +
", argument indices " + MinitScript::getArgumentIndicesAsString(nextArgumentIndices,
", ") +
", array access statement index " + to_string(arrayAccessStatementIdx) +
"\n";
1546 generatedDefinitions+= lamdaIndent +
"auto array_access_statement_" + to_string(statement.
statementIdx) +
"_" + MinitScript::getArgumentIndicesAsString(nextArgumentIndices,
"_") +
"_" + to_string(arrayAccessStatementIdx) +
" = [&](const SubStatement& subStatement) -> Variable {" +
"\n";
1547 generatedDefinitions+= lamdaIndent +
" return Variable(static_cast<int64_t>(" + to_string(
static_cast<int64_t
>(floatValue)) +
"ll));" +
"\n";
1548 generatedDefinitions+= lamdaIndent +
"};" +
"\n";
1551 arrayAccessStatementIdx++;
1559 if (StringTools::startsWith(arrayAccessStatementString,
"$") ==
true) arrayAccessStatementString =
"getVariable(\"" + arrayAccessStatementString +
"\")";
1561 string_view arrayAccessMethodName;
1562 vector<MinitScript::ParserArgument> arrayAccessArguments;
1563 string accessObjectMemberStatement;
1568 arrayAccessStatementString,
1569 arrayAccessStatementString,
1570 MinitScript::STATEMENTIDX_NONE
1573 if (minitScript->
parseStatement(string_view(arrayAccessStatementString), arrayAccessMethodName, arrayAccessArguments, arrayAccessStatement, accessObjectMemberStatement) ==
false) {
1578 if (minitScript->
createStatementSyntaxTree(scriptIdx, arrayAccessMethodName, arrayAccessArguments, arrayAccessStatement, arrayAccessSyntaxTree) ==
false) {
1583 string transpiledCode;
1584 auto statementIdx = MinitScript::STATEMENTIDX_FIRST;
1585 auto scriptStateChanged =
false;
1586 auto scriptStopped =
false;
1587 vector<string >enabledNamedConditions;
1591 arrayAccessSyntaxTree,
1592 arrayAccessStatement,
1600 enabledNamedConditions,
1604 "return returnValue;",
1607 generatedDefinitions+= lamdaIndent +
"// MinitScript transpilation for array access statement, statement index " + to_string(statement.
statementIdx) +
", argument indices " + MinitScript::getArgumentIndicesAsString(nextArgumentIndices,
", ") +
", array access statement index " + to_string(arrayAccessStatementIdx) +
"\n";
1608 generatedDefinitions+= lamdaIndent +
"auto array_access_statement_" + to_string(statement.
statementIdx) +
"_" + MinitScript::getArgumentIndicesAsString(nextArgumentIndices,
"_") +
"_" + to_string(arrayAccessStatementIdx) +
" = [&](const SubStatement& subStatement) -> Variable {" +
"\n";
1609 generatedDefinitions+= lamdaIndent +
"\t" +
"// MinitScript setup" +
"\n";
1610 generatedDefinitions+= lamdaIndent +
"\t" +
"auto minitScript = this;" +
"\n";
1611 generatedDefinitions+= transpiledCode;
1612 generatedDefinitions+= lamdaIndent +
"};" +
"\n";
1614 arrayAccessStatementIdx++;
1621 auto argumentIdx = 0;
1622 for (
const auto& argument: syntaxTree.
arguments) {
1624 auto nextArgumentIndices = argumentIndices;
1625 nextArgumentIndices.push_back(argumentIdx);
1627 generateArrayAccessMethods(
1629 generatedDefinitions,
1630 minitScriptClassName,
1639 nextArgumentIndices,
1647 case MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_FUNCTION:
1649 auto argumentIdx = 1;
1650 for (
const auto& argument: syntaxTree.
arguments) {
1652 auto nextArgumentIndices = argumentIndices;
1653 nextArgumentIndices.push_back(argumentIdx);
1655 generateArrayAccessMethods(
1657 generatedDefinitions,
1658 minitScriptClassName,
1667 nextArgumentIndices,
1681 void Transpiler::generateEvaluateMemberAccessArrays(
1683 vector<string>& generatedDeclarations,
1684 vector<string>& generatedDefinitions
1687 auto scriptMethods = minitScript->
getMethods();
1688 auto allMethods = getAllClassesMethodNamesSorted(minitScript);
1689 auto methodsByClasses = getClassesMethodNames(minitScript);
1690 generatedDeclarations.push_back(
"// evaluate member access constants");
1691 generatedDeclarations.push_back(
"static constexpr int EVALUATEMEMBERACCESSARRAYIDX_NONE { -1 };");
1693 for (
const auto& method: allMethods) {
1694 generatedDeclarations.push_back(
"static constexpr int EVALUATEMEMBERACCESSARRAYIDX_" + StringTools::toUpperCase(method) +
" { " + to_string(methodIdx) +
" };");
1697 generatedDeclarations.push_back(
"");
1698 generatedDeclarations.push_back(
"// evaluate member access arrays");
1699 generatedDeclarations.push_back(
1700 "array<array<Method*, " +
1701 to_string(methodIdx) +
1703 to_string((
static_cast<int>(MinitScript::TYPE_PSEUDO_DATATYPES + MinitScript::getDataTypes().size()) -
static_cast<int>(MinitScript::TYPE_STRING))) +
1704 "> evaluateMemberAccessArrays {};"
1706 generatedDefinitions.push_back(
"evaluateMemberAccessArrays = {};");
1707 for (
auto typeIdx =
static_cast<int>(MinitScript::TYPE_STRING); typeIdx < static_cast<int>(MinitScript::TYPE_PSEUDO_DATATYPES + MinitScript::getDataTypes().size()); typeIdx++) {
1709 const auto& methods = methodsByClasses[className];
1711 for (
const auto& method: allMethods) {
1713 if (std::find(methods.begin(), methods.end(), method) == methods.end()) {
1718 generatedDefinitions.push_back(
"evaluateMemberAccessArrays[" + to_string(typeIdx -
static_cast<int>(MinitScript::TYPE_STRING)) +
"][" +
"EVALUATEMEMBERACCESSARRAYIDX_" + StringTools::toUpperCase(method) +
"] = getMethod(\"" + className +
"::" + method +
"\");");
1724 void Transpiler::generateArrayMapSetVariable(
1726 int scriptConditionIdx,
1729 const unordered_map<
string, vector<string>>& methodCodeMap,
1730 const unordered_set<string>& allMethods,
1731 const string& methodName,
1733 const string& minitScriptClassName,
1734 string& generatedDefinitions,
1736 int initializerDepth,
1737 const string& postStatement
1740 string headerIndent =
"\t";
1741 auto indent = StringTools::indent(
string(),
"\t", initializerDepth + depth);
1743 case MinitScript::TYPE_NULL:
1745 generatedDefinitions+= indent +
"{" +
"\n";
1746 generatedDefinitions+= indent +
"\t" +
"Variable variableD" + to_string(initializerDepth) +
";" +
"\n";
1747 generatedDefinitions+= indent +
"\t" + postStatement +
"\n";
1748 generatedDefinitions+= indent +
"}" +
"\n";
1751 case MinitScript::TYPE_BOOLEAN:
1755 generatedDefinitions+= indent +
"{" +
"\n";
1756 generatedDefinitions+= indent +
"\t" +
"Variable variableD" + to_string(initializerDepth) +
"(" + (value ==
true?
"true":
"false") +
");" +
"\n";
1757 generatedDefinitions+= indent +
"\t" + postStatement +
"\n";
1758 generatedDefinitions+= indent +
"}" +
"\n";
1761 case MinitScript::TYPE_INTEGER:
1765 generatedDefinitions+= indent +
"{" +
"\n";
1766 generatedDefinitions+= indent +
"\t" +
"Variable variableD" + to_string(initializerDepth) +
"(static_cast<int64_t>(" + to_string(value) +
"ll));" +
"\n";
1767 generatedDefinitions+= indent +
"\t" + postStatement +
"\n";
1768 generatedDefinitions+= indent +
"}" +
"\n";
1771 case MinitScript::TYPE_FLOAT:
1775 generatedDefinitions+= indent +
"{" +
"\n";
1776 generatedDefinitions+= indent +
"\t" +
"Variable variableD" + to_string(initializerDepth) +
"(" + to_string(value) +
"f);" +
"\n";
1777 generatedDefinitions+= indent +
"\t" + postStatement +
"\n";
1778 generatedDefinitions+= indent +
"}" +
"\n";
1781 case MinitScript::TYPE_FUNCTION_CALL:
1785 string transpiledCode;
1786 auto statementIdx = MinitScript::STATEMENTIDX_FIRST;
1787 auto scriptStateChanged =
false;
1788 auto scriptStopped =
false;
1789 vector<string>enabledNamedConditions;
1802 enabledNamedConditions,
1806 "const auto& variableD" + to_string(initializerDepth) +
" = returnValue; " + postStatement +
"\n", 1
1808 generatedDefinitions+= transpiledCode;
1811 case MinitScript::TYPE_FUNCTION_ASSIGNMENT:
1814 auto functionScriptIdx = MinitScript::SCRIPTIDX_NONE;
1816 function = escapeString(
function);
1818 generatedDefinitions+= indent +
"{" +
"\n";
1819 generatedDefinitions+= indent +
"\t" +
"Variable variableD" + to_string(initializerDepth) +
";" +
"\n";
1820 generatedDefinitions+= indent +
"\t" +
"variableD" + to_string(initializerDepth) +
".setFunctionAssignment(\"" +
function +
"\", " + to_string(functionScriptIdx) +
");" +
"\n";
1821 generatedDefinitions+= indent +
"\t" + postStatement +
"\n";
1822 generatedDefinitions+= indent +
"}" +
"\n";
1825 case MinitScript::TYPE_STACKLET_ASSIGNMENT:
1828 auto stackletScriptIdx = MinitScript::SCRIPTIDX_NONE;
1830 stacket = escapeString(stacket);
1832 generatedDefinitions+= indent +
"{" +
"\n";
1833 generatedDefinitions+= indent +
"\t" +
"Variable variableD" + to_string(initializerDepth) +
";" +
"\n";
1834 generatedDefinitions+= indent +
"\t" +
"variableD" + to_string(initializerDepth) +
".setStackletAssignment(\"" + stacket +
"\", " + to_string(stackletScriptIdx) +
");" +
"\n";
1835 generatedDefinitions+= indent +
"\t" + postStatement +
"\n";
1836 generatedDefinitions+= indent +
"}" +
"\n";
1839 case MinitScript::TYPE_STRING:
1843 value = escapeString(value);
1845 generatedDefinitions+= indent +
"{" +
"\n";
1846 generatedDefinitions+= indent +
"\t" +
"Variable variableD" + to_string(initializerDepth) +
"(string(\"" + value +
"\"));" +
"\n";
1847 generatedDefinitions+= indent +
"\t" + postStatement +
"\n";
1848 generatedDefinitions+= indent +
"}" +
"\n";
1851 case MinitScript::TYPE_ARRAY:
1853 if (initializerDepth == 0) {
1854 generatedDefinitions+= string() +
"{" +
"\n";
1855 generatedDefinitions+= indent +
"\t" +
"// MinitScript setup" +
"\n";
1856 generatedDefinitions+= indent +
"\t" +
"auto minitScript = this;" +
"\n";
1857 generatedDefinitions+= indent +
"\t" +
"//" +
"\n";
1859 generatedDefinitions+= indent +
"{" +
"\n";
1861 generatedDefinitions+= indent +
"\t" +
"Variable variableD" + to_string(initializerDepth) +
";" +
"\n";
1862 generatedDefinitions+= indent +
"\t" +
"variableD" + to_string(initializerDepth) +
".setType(TYPE_ARRAY);" +
"\n";
1864 for (
const auto arrayEntry: *arrayValue) {
1865 generateArrayMapSetVariable(
1874 minitScriptClassName,
1875 generatedDefinitions,
1877 initializerDepth + 1,
1878 "variableD" + to_string(initializerDepth) +
".pushArrayEntry(variableD" + to_string(initializerDepth + 1) +
");"
1881 generatedDefinitions+= indent +
"\t" + postStatement +
"\n";
1882 generatedDefinitions+= indent +
"}";
1883 generatedDefinitions+= initializerDepth == 0?
";":
"\n";
1886 case MinitScript::TYPE_MAP:
1888 if (initializerDepth == 0) {
1889 generatedDefinitions+= string() +
"{" +
"\n";
1890 generatedDefinitions+= indent +
"\t" +
"// MinitScript setup" +
"\n";
1891 generatedDefinitions+= indent +
"\t" +
"auto minitScript = this;" +
"\n";
1892 generatedDefinitions+= indent +
"\t" +
"//" +
"\n";
1894 generatedDefinitions+= indent +
"{" +
"\n";
1896 generatedDefinitions+= indent +
"\t" +
"Variable variableD" + to_string(initializerDepth) +
";" +
"\n";
1897 generatedDefinitions+= indent +
"\t" +
"variableD" + to_string(initializerDepth) +
".setType(TYPE_MAP);" +
"\n";
1899 for (
const auto& [mapEntryName, mapEntryValue]: *mapValue) {
1900 auto mapEntryNameEscaped = escapeString(mapEntryName);
1901 generateArrayMapSetVariable(
1910 minitScriptClassName,
1911 generatedDefinitions,
1913 initializerDepth + 1,
1914 "variableD" + to_string(initializerDepth) +
".setMapEntry(\"" + mapEntryNameEscaped +
"\", variableD" + to_string(initializerDepth + 1) +
", " + (mapEntryValue->isPrivate() ==
true?
"true":
"false") +
");"
1917 generatedDefinitions+= indent +
"\t" + postStatement +
"\n";
1918 generatedDefinitions+= indent +
"}";
1919 generatedDefinitions+= initializerDepth == 0?
";":
"\n";
1922 case MinitScript::TYPE_SET:
1924 if (initializerDepth == 0) {
1925 generatedDefinitions+= string() +
"{" +
"\n";
1926 generatedDefinitions+= indent +
"\t" +
"// MinitScript setup" +
"\n";
1927 generatedDefinitions+= indent +
"\t" +
"auto minitScript = this;" +
"\n";
1928 generatedDefinitions+= indent +
"\t" +
"//" +
"\n";
1930 generatedDefinitions+= indent +
"{" +
"\n";
1932 generatedDefinitions+= indent +
"\t" +
"Variable variableD" + to_string(initializerDepth) +
";" +
"\n";
1933 generatedDefinitions+= indent +
"\t" +
"variableD" + to_string(initializerDepth) +
".setType(TYPE_SET);" +
"\n";
1935 for (
const auto& key: *setValue) {
1936 generatedDefinitions+= indent +
"\t" +
"variableD" + to_string(initializerDepth) +
".insertSetKey(\"" + key +
"\");" +
"\n";
1938 generatedDefinitions+= indent +
"\t" + postStatement +
"\n";
1939 generatedDefinitions+= indent +
"}";
1940 generatedDefinitions+= initializerDepth == 0?
";":
"\n";
1947 void Transpiler::generateArrayMapSetInitializer(
1949 string& generatedDefinitions,
1950 int scriptConditionIdx,
1952 const string& minitScriptClassName,
1953 const string& methodName,
1956 const unordered_map<
string, vector<string>>& methodCodeMap,
1957 const unordered_set<string>& allMethods,
1959 const vector<int>& argumentIndices,
1963 auto indent = StringTools::indent(
string(),
"\t", depth);
1965 switch (syntaxTree.
type) {
1966 case MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_LITERAL:
1969 case MinitScript::TYPE_ARRAY:
1970 case MinitScript::TYPE_MAP:
1971 case MinitScript::TYPE_SET:
1974 string generatedInitializerDefinitions;
1976 generateArrayMapSetVariable(
1985 minitScriptClassName,
1986 generatedInitializerDefinitions,
1989 "return variableD0;"
1992 generatedDefinitions+= indent +
"// MinitScript transpilation for array/map/set initializer, statement index " + to_string(statement.
statementIdx) +
", argument indices " + MinitScript::getArgumentIndicesAsString(argumentIndices,
", ") +
"\n";
1993 generatedDefinitions+= indent +
"auto initializer_" + to_string(statement.
statementIdx) +
"_" + MinitScript::getArgumentIndicesAsString(argumentIndices,
"_") +
" = [&](const SubStatement& subStatement) -> Variable ";
1994 generatedDefinitions+= generatedInitializerDefinitions;
2003 case MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_METHOD:
2005 auto argumentIdx = 0;
2006 for (
const auto& argument: syntaxTree.
arguments) {
2008 auto nextArgumentIndices = argumentIndices;
2009 nextArgumentIndices.push_back(argumentIdx);
2011 generateArrayMapSetInitializer(
2013 generatedDefinitions,
2016 minitScriptClassName,
2023 nextArgumentIndices,
2031 case MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_FUNCTION:
2033 auto argumentIdx = 1;
2034 for (
const auto& argument: syntaxTree.
arguments) {
2036 auto nextArgumentIndices = argumentIndices;
2037 nextArgumentIndices.push_back(argumentIdx);
2039 generateArrayMapSetInitializer(
2041 generatedDefinitions,
2044 minitScriptClassName,
2051 nextArgumentIndices,
2065 bool Transpiler::transpileStatement(
2067 string& generatedCode,
2070 int scriptConditionIdx,
2073 const unordered_map<
string, vector<string>>& methodCodeMap,
2074 const unordered_set<string>& allMethods,
2075 bool& scriptStateChanged,
2076 bool& scriptStopped,
2077 vector<string>& enabledNamedConditions,
2079 const vector<int>& argumentIndices,
2080 const string& returnValue,
2081 const string& injectCode,
2082 int additionalIndent) {
2085 auto currentStatementIdx = statementIdx;
2088 string minIndentString =
"\t";
2089 string depthIndentString;
2090 for (
auto i = 0; i < depth + additionalIndent; i++) depthIndentString+=
"\t";
2093 struct ArrayAccessStatement {
2094 ArrayAccessStatement(
2099 string statementMethod
2101 argumentIdx(argumentIdx),
2102 statementIdx(statementIdx),
2105 statementMethod(statementMethod)
2111 string statementMethod;
2115 vector<ArrayAccessStatement> arrayAccessStatements;
2118 switch (syntaxTree.
type) {
2119 case MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_FUNCTION:
2120 case MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_STACKLET:
2123 auto functionStackletScriptIdx = syntaxTree.
getScriptIdx();
2124 if (functionStackletScriptIdx != MinitScript::SCRIPTIDX_NONE) {
2127 callSyntaxTreeNode.
type = MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_METHOD;
2128 callSyntaxTreeNode.
value =
2129 syntaxTree.
type == MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_FUNCTION?
2130 MinitScript::METHOD_SCRIPTCALLBYINDEX:
2131 MinitScript::METHOD_SCRIPTCALLSTACKLETBYINDEX;
2134 callArgumentSyntaxTreeNode.
type = MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_LITERAL;
2137 callSyntaxTreeNode.
arguments.push_back(callArgumentSyntaxTreeNode);
2139 if (syntaxTree.
type == MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_FUNCTION) {
2141 for (
const auto& argument: syntaxTree.
arguments) {
2142 callSyntaxTreeNode.
arguments.push_back(argument);
2147 if (method ==
nullptr) {
2148 Console::printLine(
"Transpiler::transpileStatement(): method code not found: '" + callSyntaxTreeNode.
value.
getValueAsString() +
"'");
2152 return transpileStatement(
2164 enabledNamedConditions,
2172 Console::printLine(
"Transpiler::transpileStatement(): Function/stacklet not found: '" + syntaxTree.
value.
getValueAsString() +
"'");
2178 case MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_METHOD:
2180 if ((scriptConditionIdx != MinitScript::SCRIPTIDX_NONE ||
2181 scriptIdx != MinitScript::SCRIPTIDX_NONE) &&
2189 for (
auto argumentIdx = 0; argumentIdx < syntaxTree.
arguments.size(); argumentIdx++) {
2191 auto nextArgumentIndices = argumentIndices;
2192 nextArgumentIndices.push_back(argumentIdx);
2194 auto argumentString = escapeString(syntaxTree.
arguments[argumentIdx].value.getValueAsString());
2195 auto arrayAccessStatementIdx = 0;
2196 auto arrayAccessStatementLeftIdx = -1;
2197 auto arrayAccessStatementRightIdx = -1;
2199 auto bracketCount = 0;
2201 for (
auto i = 0; i < argumentString.size(); i++) {
2202 auto c = argumentString[i];
2204 if ((c ==
'"' || c ==
'\'') && lc !=
'\\') {
2205 if (quote ==
'\0') {
2213 if (bracketCount == 0) arrayAccessStatementLeftIdx = i;
2218 if (bracketCount == 0) {
2219 arrayAccessStatementRightIdx = i;
2221 auto arrayAccessStatementString = StringTools::substring(argumentString, arrayAccessStatementLeftIdx + 1, arrayAccessStatementRightIdx);
2223 if (arrayAccessStatementString.empty() ==
true) {
2225 arrayAccessStatementIdx++;
2230 const auto& script = minitScript->
getScripts()[scriptConditionIdx != MinitScript::SCRIPTIDX_NONE?scriptConditionIdx:scriptIdx];
2232 auto arrayAccessStatementMethod = string() +
"array_access_statement_" + to_string(statement.
statementIdx) +
"_" + MinitScript::getArgumentIndicesAsString(nextArgumentIndices,
"_") +
"_" + to_string(arrayAccessStatementIdx);
2234 generatedCode+= minIndentString + depthIndentString +
"// we will use " + arrayAccessStatementMethod +
"() to determine array access index"+
"\n";
2236 arrayAccessStatements.emplace_back(
2238 arrayAccessStatementIdx,
2239 arrayAccessStatementLeftIdx,
2240 arrayAccessStatementRightIdx,
2241 arrayAccessStatementMethod
2244 arrayAccessStatementIdx++;
2255 Console::printLine(
"Transpiler::transpileStatement(): " + minitScript->
getStatementInformation(statement) +
": Function or method call expected, but got literal or 'none' syntaxTree");
2264 auto methodCodeMapIt = methodCodeMap.find(method);
2265 if (methodCodeMapIt == methodCodeMap.end()) {
2266 Console::printLine(
"Transpiler::transpileStatement(): method code not found: '" + method +
"'");
2269 const auto& methodCode = methodCodeMapIt->second;
2272 auto scriptMethod = minitScript->
getMethod(
string(method));
2273 if (scriptMethod ==
nullptr) {
2274 Console::printLine(
"Transpiler::transpileStatement(): method not found: '" + method +
"'");
2279 generatedCode+= minIndentString + depthIndentString;
2280 generatedCode+=
"// " + (depth > 0?
"depth = " + to_string(depth):
"") + (argumentIndices.empty() ==
false?
" / argument index = " + to_string(argumentIndices.back()):
"");
2281 generatedCode+= depth > 0 || argumentIndices.empty() ==
false?
": ":
"";
2283 generatedCode+=
"\n";
2286 generatedCode+= minIndentString + depthIndentString +
"{" +
"\n";
2289 auto parentArgumentIdx = argumentIndices.size() >= 2?argumentIndices[argumentIndices.size() - 2]:MinitScript::ARGUMENTIDX_NONE;
2290 auto argumentIdx = argumentIndices.empty() ==
false?argumentIndices.back():MinitScript::ARGUMENTIDX_NONE;
2294 generatedCode+= minIndentString + depthIndentString +
"\t" +
"// statement setup" +
"\n";
2295 if (scriptConditionIdx != MinitScript::SCRIPTIDX_NONE) {
2296 generatedCode+= minIndentString + depthIndentString +
"\t" +
"const auto& statement = scripts[" + to_string(scriptConditionIdx) +
"].conditionStatement;" +
"\n";
2297 generatedCode+= minIndentString + depthIndentString +
"\t" +
"const SubStatement subStatement(statement, " + to_string(syntaxTree.
subLineIdx) +
");" +
"\n";
2299 if (scriptIdx != MinitScript::SCRIPTIDX_NONE) {
2300 generatedCode+= minIndentString + depthIndentString +
"\t" +
"const auto& statement = scripts[" + to_string(scriptIdx) +
"].statements[" + to_string(statement.
statementIdx) +
"];" +
"\n";
2301 generatedCode+= minIndentString + depthIndentString +
"\t" +
"const SubStatement subStatement(statement, " + to_string(syntaxTree.
subLineIdx) +
");" +
"\n";
2303 generatedCode+= minIndentString + depthIndentString +
"\t" +
"getScriptState().statementIdx = subStatement.statement->statementIdx;" +
"\n";
2304 generatedCode+= minIndentString + depthIndentString +
"\t" +
"//" +
"\n";
2306 generatedCode+= minIndentString + depthIndentString +
"\t" +
"// sub statement setup" +
"\n";
2307 if (scriptConditionIdx != MinitScript::SCRIPTIDX_NONE) {
2308 generatedCode+= minIndentString + depthIndentString +
"\t" +
"const SubStatement subStatement(statement, " + to_string(syntaxTree.
subLineIdx) +
");" +
"\n";
2310 if (scriptIdx != MinitScript::SCRIPTIDX_NONE) {
2311 generatedCode+= minIndentString + depthIndentString +
"\t" +
"const SubStatement subStatement(statement, " + to_string(syntaxTree.
subLineIdx) +
");" +
"\n";
2316 string indent =
"\t";
2318 vector<string> argumentsCode;
2320 argumentsCode.push_back(
"auto& returnValue = argumentsD" + to_string(depth - 1) + (parentArgumentIdx != MinitScript::ARGUMENTIDX_NONE?
"AIDX" + to_string(parentArgumentIdx):
"") +
"[" + to_string(argumentIdx) +
"];");
2322 argumentsCode.push_back(
"Variable returnValue;");
2324 argumentsCode.push_back(
"array<Variable, " + to_string(syntaxTree.
arguments.size()) +
"> arguments {");
2327 if (syntaxTree.
arguments.empty() ==
false) {
2328 generatedCode+= minIndentString + depthIndentString +
"\t" +
"// required method code arguments" +
"\n";
2329 auto argumentIdx = 0;
2330 for (
const auto& argument: syntaxTree.
arguments) {
2332 auto nextArgumentIndices = argumentIndices;
2333 nextArgumentIndices.push_back(argumentIdx);
2335 auto lastArgument = argumentIdx == syntaxTree.
arguments.size() - 1;
2336 switch (argument.type) {
2337 case MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_LITERAL:
2339 switch (argument.value.getType()) {
2340 case MinitScript::TYPE_NULL:
2341 argumentsCode.push_back(indent +
"Variable()" + (lastArgument ==
false?
",":
""));
2343 case MinitScript::TYPE_BOOLEAN:
2346 argument.value.getBooleanValue(value);
2347 argumentsCode.push_back(indent +
"Variable(" + (value ==
true?
"true":
"false") +
")" + (lastArgument ==
false?
",":
""));
2350 case MinitScript::TYPE_INTEGER:
2353 argument.value.getIntegerValue(value);
2354 argumentsCode.push_back(indent + +
"Variable(static_cast<int64_t>(" + to_string(value) +
"ll))" + (lastArgument ==
false?
",":
""));
2357 case MinitScript::TYPE_FLOAT:
2360 argument.value.getFloatValue(value);
2361 argumentsCode.push_back(indent + +
"Variable(" + to_string(value) +
"f)" + (lastArgument ==
false?
",":
""));
2364 case MinitScript::TYPE_STRING:
2365 case MinitScript::TYPE_FUNCTION_ASSIGNMENT:
2366 case MinitScript::TYPE_STACKLET_ASSIGNMENT:
2369 auto scriptIdx = MinitScript::SCRIPTIDX_NONE;
2371 if (argument.value.getType() == MinitScript::TYPE_FUNCTION_ASSIGNMENT) {
2372 argument.value.getFunctionValue(value, scriptIdx);
2374 if (argument.value.getType() == MinitScript::TYPE_STACKLET_ASSIGNMENT) {
2375 argument.value.getStackletValue(value, scriptIdx);
2377 argument.value.getStringValue(value);
2379 value = escapeString(value);
2381 auto arrayAccessStatementOffset = 0;
2382 for (
auto& arrayAccessStatement: arrayAccessStatements) {
2383 if (arrayAccessStatement.argumentIdx != argumentIdx)
continue;
2384 string arrayAccessStatementMethodCall =
"\" + " + arrayAccessStatement.statementMethod +
"(subStatement).getValueAsString() + \"";
2386 StringTools::substring(value, 0, arrayAccessStatement.leftIdx + 1 + arrayAccessStatementOffset) +
2387 arrayAccessStatementMethodCall +
2388 StringTools::substring(value, arrayAccessStatement.rightIdx + arrayAccessStatementOffset, value.size());
2389 arrayAccessStatementOffset-= (arrayAccessStatement.rightIdx - (arrayAccessStatement.leftIdx + 1)) - arrayAccessStatementMethodCall.size();
2392 argumentsCode.push_back(indent +
"Variable(static_cast<VariableType>(" + to_string(argument.value.getType()) +
"), string(\"" + value +
"\"), " + to_string(scriptIdx) +
")" + (lastArgument ==
false?
",":
""));
2396 case MinitScript::TYPE_ARRAY:
2397 case MinitScript::TYPE_MAP:
2398 case MinitScript::TYPE_SET:
2400 const auto& script = minitScript->
getScripts()[scriptConditionIdx != MinitScript::SCRIPTIDX_NONE?scriptConditionIdx:scriptIdx];
2401 auto methodName = createMethodName(minitScript, scriptIdx);
2403 argumentsCode.push_back(indent + initializerMethod +
"(subStatement)" + (lastArgument ==
false?
",":
""));
2408 Console::printLine(
"Transpiler::transpileStatement(): " + minitScript->
getStatementInformation(statement) +
": '" + argument.value.getAsString() +
"': Unknown argument type: " + argument.value.getTypeAsString());
2414 case MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_FUNCTION:
2415 case MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_STACKLET:
2417 argumentsCode.push_back(indent +
"Variable()" + (lastArgument ==
false?
",":
"") +
" // arguments[" + to_string(argumentIdx) +
"] --> returnValue of " + escapeString(argument.value.getValueAsString()) +
"(" + minitScript->
getArgumentsAsString(argument.arguments) +
")");
2420 case MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_METHOD:
2422 argumentsCode.push_back(indent +
"Variable()" + (lastArgument ==
false?
",":
"") +
" // arguments[" + to_string(argumentIdx) +
"] --> returnValue of " + escapeString(argument.value.getValueAsString()) +
"(" + minitScript->
getArgumentsAsString(argument.arguments) +
")");
2433 argumentsCode.push_back(
"};");
2436 argumentsCode.push_back(
"array<Variable, " + to_string(syntaxTree.
arguments.size()) +
">& argumentsD" + to_string(depth) + (argumentIdx != MinitScript::ARGUMENTIDX_NONE?
"AIDX" + to_string(argumentIdx):
"") +
" = arguments;");
2439 for (
const auto& codeLine: argumentsCode) {
2440 generatedCode+= minIndentString + depthIndentString +
"\t" + codeLine +
"\n";
2445 if (method == MinitScript::METHOD_ENABLENAMEDCONDITION && syntaxTree.
arguments.empty() ==
false) {
2447 Console::printLine(
"Transpiler::transpileStatement(): " + minitScript->
getStatementInformation(statement) +
": " + MinitScript::METHOD_ENABLENAMEDCONDITION +
"(): Expected string argument @ 0");
2449 string name = syntaxTree.
arguments[0].value.getValueAsString();
2450 enabledNamedConditions.erase(
2452 enabledNamedConditions.begin(),
2453 enabledNamedConditions.end(),
2456 enabledNamedConditions.end()
2458 enabledNamedConditions.push_back(name);
2461 if (method == MinitScript::METHOD_DISABLENAMEDCONDITION && syntaxTree.
arguments.empty() ==
false) {
2463 Console::printLine(
"Transpiler::transpileStatement(): " + minitScript->
getStatementInformation(statement) +
": " + MinitScript::METHOD_DISABLENAMEDCONDITION +
"(): Expected string argument @ 0");
2465 string name = syntaxTree.
arguments[0].value.getValueAsString();
2466 enabledNamedConditions.erase(
2468 enabledNamedConditions.begin(),
2469 enabledNamedConditions.end(),
2472 enabledNamedConditions.end()
2479 auto argumentIdx = 0;
2480 for (
const auto& argument: syntaxTree.
arguments) {
2481 switch (argument.type) {
2482 case MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_FUNCTION:
2483 case MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_STACKLET:
2484 case MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_METHOD:
2487 auto nextArgumentIndices = argumentIndices;
2488 nextArgumentIndices.push_back(argumentIdx);
2491 if (transpileStatement(
2503 enabledNamedConditions,
2505 nextArgumentIndices,
2524 if (scriptMethod !=
nullptr && scriptMethod->getMethodName() ==
"internal.script.evaluateMemberAccess") {
2526 auto callArgumentIdx = 0;
2528 if (syntaxTree.
arguments[0].value.getType() != MinitScript::TYPE_NULL) {
2529 generateVariableAccess(
2534 syntaxTree.
arguments[0].value.getValueAsString(),
2535 minIndentString + depthIndentString +
"\t",
2542 "auto EVALUATEMEMBERACCESS_ARGUMENT" + to_string(callArgumentIdx) +
" = "
2545 generatedCode+= minIndentString + depthIndentString +
"\t" +
"auto EVALUATEMEMBERACCESS_ARGUMENT" + to_string(callArgumentIdx) +
" = Variable();" +
"\n";
2550 vector<string> argumentVariables;
2551 for (
auto argumentIdx = 3; argumentIdx < syntaxTree.
arguments.size(); argumentIdx+=2) {
2553 argumentVariables.push_back(
string());
2555 if (syntaxTree.
arguments[argumentIdx].value.getType() != MinitScript::TYPE_NULL) {
2557 generateVariableAccess(
2559 argumentVariables[argumentVariables.size() - 1],
2562 syntaxTree.
arguments[argumentIdx].value.getValueAsString(),
2563 minIndentString + depthIndentString +
"\t\t",
2577 argumentVariables[argumentVariables.size() - 1] = minIndentString + depthIndentString +
"\t\t" +
"Variable()," +
"\n";
2582 generatedCode+= minIndentString + depthIndentString +
"\t" +
"array<Variable, " + to_string(argumentVariables.size()) +
"> EVALUATEMEMBERACCESS_ARGUMENTS" +
" {" +
"\n";
2583 for (
const auto& argumentVariable: argumentVariables) generatedCode+= argumentVariable;
2584 generatedCode+= minIndentString + depthIndentString +
"\t" +
"};" +
"\n";
2586 if (allMethods.contains(syntaxTree.
arguments[2].value.getValueAsString()) ==
true) {
2588 generatedCode+= minIndentString + depthIndentString +
"\t" +
"const auto EVALUATEMEMBERACCESS_MEMBER = EVALUATEMEMBERACCESSARRAYIDX_" + StringTools::toUpperCase(syntaxTree.
arguments[2].value.getValueAsString()) +
";\n";
2590 generatedCode+= minIndentString + depthIndentString +
"\t" +
"const auto EVALUATEMEMBERACCESS_MEMBER = EVALUATEMEMBERACCESSARRAYIDX_NONE;" +
"\n";
2596 if (syntaxTree.
type == MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_METHOD &&
2605 syntaxTree.
arguments.empty() ==
false &&
2606 syntaxTree.
arguments[0].type == MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_LITERAL) {
2608 generateVariableAccess(
2613 syntaxTree.
arguments[0].value.getValueAsString(),
2614 minIndentString + depthIndentString +
"\t",
2623 const auto& script = minitScript->
getScripts()[scriptConditionIdx != MinitScript::SCRIPTIDX_NONE?scriptConditionIdx:scriptIdx];
2625 generatedCode+= minIndentString + depthIndentString +
"\t" +
"// method code: " + string(method) +
"\n";
2626 for (
auto codeLine: methodCode) {
2627 codeLine = StringTools::replace(codeLine,
"getMethodName()",
"string(\"" +
string(method) +
"\")");
2629 if (StringTools::regexMatch(codeLine,
"[\\ \\t]*return[\\ \\t]*;.*") ==
true) {
2630 Console::printLine(
"Transpiler::transpileStatement(): method '" +
string(method) +
"': return statement not supported!");
2633 if (StringTools::regexMatch(codeLine,
"[\\ \\t]*minitScript[\\ \\t]*->gotoStatementGoto[\\ \\t]*\\([\\ \\t]*\\*subStatement\\.statement[\\ \\t]*\\)[\\ \\t]*;[\\ \\t]*") ==
true) {
2637 for (
auto i = 0; i < codeLine.size(); i++) {
2638 auto c = codeLine[i];
2645 string indentString;
2646 for (
auto i = 0; i < indent; i++) indentString+=
"\t";
2648 generatedCode+= minIndentString + indentString + depthIndentString +
"\t" +
"goto minitscript_statement_" + to_string(statement.
gotoStatementIdx) +
";\n";
2651 generatedCode+= minIndentString + depthIndentString +
"\t" + codeLine +
" return;" +
"\n";
2654 if (StringTools::regexMatch(codeLine,
"[\\ \\t]*minitScript[\\ \\t]*->gotoStatement[\\ \\t]*\\(.*\\)[\\ \\t]*;[\\ \\t]*") ==
true) {
2658 generatedCode+= minIndentString + depthIndentString +
"\t" + codeLine +
" return;" +
"\n";
2660 if (StringTools::regexMatch(codeLine,
"[\\ \\t]*MINITSCRIPT_METHODUSAGE_COMPLAIN[\\ \\t]*\\([\\ \\t]*(.*)\\)[\\ \\t]*;[\\ \\t]*") ==
true ||
2661 StringTools::regexMatch(codeLine,
"[\\ \\t]*MINITSCRIPT_METHODUSAGE_COMPLAINM[\\ \\t]*\\([\\ \\t]*(.*)[\\ \\t]*,[\\ \\t]*(.*)[\\ \\t]*\\)[\\ \\t]*;[\\ \\t]*") ==
true ||
2662 StringTools::regexMatch(codeLine,
"[\\ \\t]*minitScript[\\ \\t]*->emit[\\ \\t]*\\([\\ \\t]*[a-zA-Z0-9]*[\\ \\t]*\\)[\\ \\t]*;[\\ \\t]*") ==
true) {
2665 for (
auto i = 0; i < codeLine.size(); i++) {
2666 auto c = codeLine[i];
2673 string indentString;
2674 for (
auto i = 0; i < indent; i++) indentString+=
"\t";
2675 codeLine = StringTools::trim(codeLine);
2677 generatedCode+= minIndentString + depthIndentString + indentString +
"\t{ " + codeLine + (script.type == MinitScript::Script::TYPE_ON || script.type == MinitScript::Script::TYPE_ONENABLED?
" MINITSCRIPT_METHOD_POPSTACK(); return" + (returnValue.empty() ==
false?
" " + returnValue:
"") +
";":
"") +
" }\n";
2679 if (StringTools::regexMatch(codeLine,
".*[\\ \\t]*minitScript[\\ \\t]*->[\\ \\t]*setScriptStateState[\\ \\t]*\\([\\ \\t]*.+[\\ \\t]*\\);.*") ==
true) {
2680 scriptStateChanged =
true;
2682 if (StringTools::regexMatch(codeLine,
".*[\\ \\t]*minitScript[\\ \\t]*->[\\ \\t]*stopScriptExecutation[\\ \\t]*\\([\\ \\t]*\\);.*") ==
true) {
2683 scriptStopped =
true;
2685 if (StringTools::regexMatch(codeLine,
".*[\\ \\t]*minitScript[\\ \\t]*->[\\ \\t]*stopRunning[\\ \\t]*\\([\\ \\t]*\\);.*") ==
true) {
2686 scriptStopped =
true;
2688 generatedCode+= minIndentString + depthIndentString +
"\t" + codeLine +
"\n";
2694 if (injectCode.empty() ==
false) {
2695 generatedCode+= minIndentString + depthIndentString +
"\t" + injectCode +
"\n";
2699 generatedCode+= minIndentString + depthIndentString +
"}" +
"\n";
2705 bool Transpiler::transpile(
MinitScript* minitScript,
const string& className,
string& generatedCode,
int scriptIdx,
const unordered_map<
string, vector<string>>& methodCodeMap,
const unordered_set<string>& allMethods) {
2706 if (scriptIdx < 0 || scriptIdx >= minitScript->
getScripts().size()) {
2707 Console::printLine(
"Transpiler::transpile(): invalid script index");
2712 const auto& script = minitScript->
getScripts()[scriptIdx];
2715 Console::printLine(
"Transpiler::transpile(): transpiling code for " + getScriptTypeReadableName(script.type) +
" = '" + script.condition +
"', with name '" + script.name +
"'");
2718 string methodIndent =
"\t";
2719 string generatedCodeHeader;
2722 generatedCodeHeader+= methodIndent +
"// script setup" +
"\n";
2723 generatedCodeHeader+= methodIndent +
"auto minitScript = this;" +
"\n";
2724 generatedCodeHeader+= methodIndent +
"getScriptState().scriptIdx = " + to_string(scriptIdx) +
";" +
"\n";
2727 auto methodName = createMethodName(minitScript, scriptIdx);
2730 unordered_set<int> gotoStatementIdxSet;
2731 for (
const auto& statement: script.statements) {
2732 if (statement.gotoStatementIdx != MinitScript::STATEMENTIDX_NONE) {
2733 gotoStatementIdxSet.insert(statement.statementIdx);
2734 gotoStatementIdxSet.insert(statement.gotoStatementIdx);
2739 auto statementIdx = MinitScript::STATEMENTIDX_FIRST;
2740 vector<string> enabledNamedConditions;
2741 auto scriptStateChanged =
false;
2742 for (
auto scriptStatementIdx = MinitScript::STATEMENTIDX_FIRST; scriptStatementIdx < script.statements.size(); scriptStatementIdx++) {
2743 const auto& statement = script.statements[scriptStatementIdx];
2744 const auto& syntaxTree = script.syntaxTree[scriptStatementIdx];
2746 if (scriptStateChanged ==
true || gotoStatementIdxSet.find(statement.statementIdx) != gotoStatementIdxSet.end()) {
2747 generatedCodeHeader+= methodIndent +
"if (minitScriptGotoStatementIdx == " + to_string(statement.statementIdx) +
") goto minitscript_statement_" + to_string(statement.statementIdx) +
"; else" +
"\n";
2751 if (enabledNamedConditions.empty() ==
false) {
2752 generatedCode+=
"\n";
2753 generatedCode+= methodIndent +
"// enabled named conditions" +
"\n";
2754 generatedCode+= methodIndent +
"{" +
"\n";
2755 generatedCode+= methodIndent +
"\t" +
"auto scriptIdxToStart = determineNamedScriptIdxToStart();" +
"\n";
2756 generatedCode+= methodIndent +
"\t" +
"if (scriptIdxToStart != SCRIPTIDX_NONE && scriptIdxToStart != getScriptState().scriptIdx) {" +
"\n";
2757 generatedCode+= methodIndent +
"\t\t" +
"resetScriptExecutationState(scriptIdxToStart, STATEMACHINESTATE_NEXT_STATEMENT);" +
"\n";
2758 generatedCode+= methodIndent +
"\t\t" +
"timeEnabledConditionsCheckLast = _Time::getCurrentMillis();" +
"\n";
2759 generatedCode+= methodIndent +
"\t\t" +
"return;" +
"\n";
2760 generatedCode+= methodIndent +
"\t" +
"}" +
"\n";
2761 generatedCode+= methodIndent +
"}" +
"\n";
2765 generatedCode+= methodIndent +
"// statement: " + to_string(statement.statementIdx) +
"\n";
2766 if (scriptStateChanged ==
true || gotoStatementIdxSet.find(statement.statementIdx) != gotoStatementIdxSet.end()) {
2767 generatedCode+= methodIndent +
"minitscript_statement_" + to_string(statement.statementIdx) +
":" +
"\n";
2769 scriptStateChanged =
false;
2770 auto scriptStopped =
false;
2776 MinitScript::SCRIPTIDX_NONE,
2783 enabledNamedConditions
2785 if (scriptStopped ==
true) {
2786 generatedCode+= methodIndent +
"if (getScriptState().running == false) {" +
"\n";
2787 generatedCode+= methodIndent +
"\t" +
"MINITSCRIPT_METHOD_POPSTACK();" +
"\n";
2788 generatedCode+= methodIndent +
"\t" +
"return;" +
"\n";
2789 generatedCode+= methodIndent +
"}" +
"\n";
2791 if (scriptStateChanged ==
true) {
2792 generatedCode+= methodIndent +
"if (getScriptState().state != STATEMACHINESTATE_NEXT_STATEMENT) {" +
"\n";
2793 generatedCode+= methodIndent +
"\t" +
"getScriptState().statementIdx++;" +
"\n";
2794 generatedCode+= methodIndent +
"\t" +
"return;" +
"\n";
2795 generatedCode+= methodIndent +
"}" +
"\n";
2798 generatedCode+= methodIndent +
"getScriptState().scriptIdx = SCRIPTIDX_NONE;" +
"\n";
2799 generatedCode+= methodIndent +
"getScriptState().statementIdx = STATEMENTIDX_NONE;" +
"\n";
2800 generatedCode+= methodIndent +
"setScriptStateState(STATEMACHINESTATE_WAIT_FOR_CONDITION);" +
"\n";
2803 generatedCodeHeader+= methodIndent +
"if (minitScriptGotoStatementIdx != STATEMENTIDX_NONE && minitScriptGotoStatementIdx != STATEMENTIDX_FIRST) _Console::printLine(\"" + className +
"::" + methodName +
"(): Can not go to statement \" + to_string(minitScriptGotoStatementIdx));" +
"\n";
2805 generatedCode = generatedCodeHeader + generatedCode;
2809 bool Transpiler::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) {
2810 if (scriptIdx < 0 || scriptIdx >= minitScript->
getScripts().size()) {
2811 Console::printLine(
"Transpiler::transpileScriptCondition(): invalid script index");
2816 const auto& script = minitScript->
getScripts()[scriptIdx];
2819 Console::printLine(
"Transpiler::transpileScriptCondition(): transpiling code condition for condition = '" + script.condition +
"', with name '" + script.name +
"'");
2822 auto statementIdx = MinitScript::STATEMENTIDX_FIRST;
2823 auto scriptStateChanged =
false;
2824 auto scriptStopped =
false;
2825 vector<string >enabledNamedConditions;
2829 script.conditionSyntaxTree,
2830 script.conditionStatement,
2832 MinitScript::SCRIPTIDX_NONE,
2838 enabledNamedConditions,
2847 generatedCode+=
"\t\n";
2856 switch (syntaxTreeNode.
type) {
2857 case MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_LITERAL:
2860 case MinitScript::TYPE_NULL:
2862 result+= (result.empty() ==
false?
", ":
"") +
string(
"<VOID>");
2865 case MinitScript::TYPE_BOOLEAN:
2866 case MinitScript::TYPE_INTEGER:
2867 case MinitScript::TYPE_FLOAT:
2872 case MinitScript::TYPE_STRING:
2874 result+= (result.empty() ==
false?
", ":
"") +
string(
"\"") + syntaxTreeNode.
value.
getValueAsString() + string(
"\"");
2879 result+= (result.empty() ==
false?
", ":
"") +
string(
"<COMPLEX DATATYPE>");
2885 case MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_METHOD:
2886 case MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_FUNCTION:
2887 case MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_STACKLET:
2891 if (endElse ==
false) result+= string(
"(");
2892 auto argumentIdx = 0;
2893 for (
const auto& argument: syntaxTreeNode.
arguments) {
2894 if (argumentIdx > 0) result+=
", ";
2895 result+= createSourceCode(argument);
2898 if (endElse ==
false) result+= string(
")");
2907 const string Transpiler::createSourceCode(
MinitScript::Script::Type scriptType,
const string& condition,
const vector<MinitScript::Script::Argument>& functionArguments,
const string& name,
const MinitScript::SyntaxTreeNode& conditionSyntaxTree,
const vector<MinitScript::SyntaxTreeNode>& syntaxTree) {
2911 switch(scriptType) {
2912 case MinitScript::Script::TYPE_FUNCTION: {
2913 result+=
"function: ";
2914 if (condition.empty() ==
false) {
2917 auto argumentIdx = 0;
2919 for (
const auto& argument: functionArguments) {
2920 if (argumentIdx > 0) result+=
", ";
2921 if (argument.reference ==
true) result+=
"&";
2922 if (argument.privateScope ==
true) result+=
"&";
2923 result+= argument.name;
2929 case MinitScript::Script::TYPE_ON:
2932 if (condition.empty() ==
false) {
2937 case MinitScript::Script::TYPE_ONENABLED:
2939 result+=
"on-enabled: ";
2940 if (condition.empty() ==
false) {
2947 if (conditionSyntaxTree.
type != MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_NONE)
2948 result+= createSourceCode(conditionSyntaxTree);
2949 if (name.empty() ==
false) {
2950 result+=
" := " + name +
"\n";
2956 for (
const auto& syntaxTreeNode: syntaxTree) {
2957 if (syntaxTreeNode.type == MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_METHOD) {
2958 if (syntaxTreeNode.value.getValueAsString() ==
"if") indent+= 0;
else
2959 if (syntaxTreeNode.value.getValueAsString() ==
"elseif") indent-= 1;
else
2960 if (syntaxTreeNode.value.getValueAsString() ==
"else") indent-= 1;
else
2961 if (syntaxTreeNode.value.getValueAsString() ==
"end") indent-= 1;
else
2962 if (syntaxTreeNode.value.getValueAsString() ==
"forTime") indent-= 0;
else
2963 if (syntaxTreeNode.value.getValueAsString() ==
"forCondition") indent-= 0;
else
2964 if (syntaxTreeNode.value.getValueAsString() ==
"switch") indent-= 0;
else
2965 if (syntaxTreeNode.value.getValueAsString() ==
"case") indent-= 1;
else
2966 if (syntaxTreeNode.value.getValueAsString() ==
"default") indent-= 1;
2968 for (
auto i = 0; i < indent; i++) result+=
"\t";
2969 result+= createSourceCode(syntaxTreeNode) +
"\n";
2970 if (syntaxTreeNode.type == MinitScript::SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_METHOD) {
2971 if (syntaxTreeNode.value.getValueAsString() ==
"if") indent+= 1;
else
2972 if (syntaxTreeNode.value.getValueAsString() ==
"elseif") indent+= 1;
else
2973 if (syntaxTreeNode.value.getValueAsString() ==
"else") indent+= 1;
else
2974 if (syntaxTreeNode.value.getValueAsString() ==
"end") indent+= 0;
else
2975 if (syntaxTreeNode.value.getValueAsString() ==
"forTime") indent+= 1;
else
2976 if (syntaxTreeNode.value.getValueAsString() ==
"forCondition") indent+= 1;
else
2977 if (syntaxTreeNode.value.getValueAsString() ==
"switch") indent+= 0;
else
2978 if (syntaxTreeNode.value.getValueAsString() ==
"case") indent+= 1;
else
2979 if (syntaxTreeNode.value.getValueAsString() ==
"default") indent+= 1;
2988 for (
const auto& script: minitScript->
getScripts()) {
2989 result+= createSourceCode(script.type, script.emitCondition ==
true?script.condition:
string(), script.arguments, script.name, script.conditionSyntaxTree, script.syntaxTree);
const Statement & getStatement() const
const SyntaxTreeNode * getSyntaxTree() const
bool getIntegerValue(int64_t &value, bool optional=false) const
Get integer value from given variable.
bool getStackletValue(string &stacklet, int &scriptIdx, bool optional=false) const
Get stacklet values from given variable.
VariableType getType() const
bool getStringValue(string &value, bool optional=false) const
Get string value from given variable.
const unordered_map< string, Variable * > * getMapPointer() const
const unordered_set< string > * getSetPointer() const
const vector< Variable * > * getArrayPointer() const
bool getFloatValue(float &value, bool optional=false) const
Get float value from given variable.
bool getBooleanValue(bool &value, bool optional=false) const
Get boolean value from given variable.
Initializer * getInitializer() const
Return initializer.
const string getValueAsString(bool formatted=false, bool jsonCompatible=false, int depth=0) const
Print string representation of variable.
void setImplicitTypedValue(const string &value, MinitScript *minitScript, int scriptIdx, const Statement &statement)
Set implicit typed value given by value string.
bool getFunctionValue(string &function, int &scriptIdx, bool optional=false) const
Get function values from given variable.
const string & getScriptPathName()
bool parseStatement(const string_view &executableStatement, string_view &methodName, vector< ParserArgument > &arguments, const Statement &statement, string &accessObjectMemberStatement)
Parse a statement.
virtual const string getBaseClassHeader()
virtual const string getBaseClass()
const string getStatementInformation(const Statement &statement, int subLineIdx=-1)
Return statement information.
const string & getNativeHash()
int getStackletScopeScriptIdx(int scriptIdx)
Return stacklet scope script index.
static const string getArgumentIndicesAsString(const vector< int > &argumentIndices, const string &delimiter)
Returns string representation of given argument indices.
const string & getScriptFileName()
virtual const vector< string > getTranspilationUnits()
unordered_map< string, int > functions
const string getInformation()
Get MinitScript instance information.
Method * getMethod(const string &methodName)
Get method by method name.
const string getArgumentsAsString(const vector< SyntaxTreeNode > &arguments)
Returns arguments as string.
const vector< Method * > getMethods()
const vector< Script > & getScripts()
bool createStatementSyntaxTree(int scriptIdx, const string_view &methodName, const vector< ParserArgument > &arguments, const Statement &statement, SyntaxTreeNode &syntaxTree, int subLineIdx=0)
Create statement syntax tree.
std::exception Exception
Exception base class.
vector< SyntaxTreeNode > arguments
void setMethod(Method *method)
Set method.
int64_t getScriptIdx() const