| 789 | else if (!Qi::run.load()) break; |
| 790 | } |
| 791 | else if (!Qi::run.load()) break; |
| 792 | if (!execute(loopStmt.condition).toBool()) break; |
| 793 | executeStatementList(loopStmt.body, local); |
| 794 | } |
| 795 | } |
| 796 | else if (std::holds_alternative<FunctionDef>(stmt)) |
| 797 | { |
| 798 | const FunctionDef& funcDef = std::get<FunctionDef>(stmt); |
| 799 | std::unique_lock<std::mutex> lock(customFunctionsMutex); |
| 800 | customFunctions[funcDef.name] = std::make_unique<QiCustomFunc>(funcDef.parameters, funcDef.body); |
| 801 | } |
| 802 | else if (std::holds_alternative<ReturnStmt>(stmt)) |
| 803 | { |
| 804 | const ReturnStmt& returnStmt = std::get<ReturnStmt>(stmt); |
| 805 | throw ReturnException(returnStmt.expression.empty() ? QiVar() : execute(returnStmt.expression, local)); |
| 806 | } |
| 807 | } |
| 808 | } |
| 809 | |
| 810 | public: |
| 811 | QiScriptInterpreter() {} |
| 812 | QiScriptInterpreter(QiScriptInterpreter&& right) |
| 813 | { |
| 814 | std::unique_lock<std::mutex> lock(localVariablesMutex); |
| 815 | localVariables = std::move(right.localVariables); |
| 816 | workerPtr = right.workerPtr; |
| 817 | workerPtr = nullptr; |
| 818 | } |
| 819 | QiScriptInterpreter(const QiScriptInterpreter&) {}; |
| 820 | QiScriptInterpreter& operator=(QiScriptInterpreter&& right) |
| 821 | { |
| 822 | std::unique_lock<std::mutex> lock(localVariablesMutex); |
| 823 | localVariables = std::move(right.localVariables); |
| 824 | workerPtr = right.workerPtr; |
| 825 | workerPtr = nullptr; |
| 826 | return *this; |
| 827 | } |
| 828 | QiScriptInterpreter& operator=(const QiScriptInterpreter&) { return *this; }; |
| 829 | |
| 830 | auto execute(const std::string& code, QiVarMap* local = nullptr) -> QiVar |
| 831 | { |
| 832 | if (!initMutex) { ScriptException(ScriptException::error_interpreter_not_init, {}, {}); } |
| 833 | else if (initMutex == INVALID_HANDLE_VALUE) { ScriptException(ScriptException::error_interpreter_exited, {}, {}); } |
| 834 | std::vector<Token> tokens; |
| 835 | try { tokens = tokenize(code); } |
| 836 | catch (const ScriptException& e) { throw ScriptException(e.type(), code, e.token(), e.msg()); } |
| 837 | auto postfix = infixToPostfix(tokens); |
| 838 | try { return evaluatePostfix(postfix, local); } |
| 839 | catch (const ReturnException& e) { return e.returnValue; } |
| 840 | catch (const ScriptException& e) { throw ScriptException(e.type(), code, e.token(), e.msg()); } |
| 841 | } |
| 842 | void interpret(const std::string& code, QiVarMap* local = nullptr) |
| 843 | { |
| 844 | if (!initMutex) { ScriptException(ScriptException::error_interpreter_not_init, {}, {}); } |
| 845 | else if (initMutex == INVALID_HANDLE_VALUE) { ScriptException(ScriptException::error_interpreter_exited, {}, {}); } |
| 846 | std::string trimmedCode = trim(code); |
| 847 | size_t incPos = trimmedCode.find("++"); |
| 848 | size_t decPos = trimmedCode.find("--"); |