From 39d25eddf3b8c4478e51ab16d880063adc311f5b Mon Sep 17 00:00:00 2001 From: Andreas Drewke Date: Wed, 17 Jan 2024 19:43:45 +0100 Subject: [PATCH] ext/MiniScript: updated MiniScript --- LICENSE | 4 +- Makefile | 1 + Makefile.nmake | 1 + README-MiniScript.md | 37 ++++-- ext/miniscript/LICENSE | 4 +- .../miniscript/ApplicationMethods.cpp | 68 +++++++++++ .../miniscript/miniscript/ConsoleMethods.cpp | 111 ++++++++++++++++++ .../src/miniscript/miniscript/Context.h | 16 +++ .../src/miniscript/miniscript/MiniScript.cpp | 18 ++- .../src/miniscript/miniscript/MiniScript.h | 46 +++++++- .../src/miniscript/miniscript/Transpiler.cpp | 2 +- .../src/miniscript/tools/miniscript-main.cpp | 5 +- .../src/miniscript/utilities/Console.cpp | 35 +++++- .../src/miniscript/utilities/Console.h | 23 +++- .../src/miniscript/utilities/ErrorConsole.cpp | 28 +++++ .../src/miniscript/utilities/ErrorConsole.h | 35 ++++++ .../src/miniscript/utilities/fwd-miniscript.h | 1 + .../tscript-methods.properties | 9 +- .../method-descriptions.properties | 12 +- .../miniscript/tests/application-test.tscript | 9 +- .../miniscript/tests/console-test.tscript | 30 +++++ .../miniscript/tests/network-test.tscript | 20 ++-- resources/miniscript/tests/pipe-test.tscript | 29 +++++ .../miniscript/tests/string-test.tscript | 29 +++++ .../miniscript/tests/switch-test.tscript | 54 +++++++++ 25 files changed, 587 insertions(+), 40 deletions(-) create mode 100644 ext/miniscript/src/miniscript/utilities/ErrorConsole.cpp create mode 100644 ext/miniscript/src/miniscript/utilities/ErrorConsole.h create mode 100644 resources/miniscript/tests/console-test.tscript create mode 100644 resources/miniscript/tests/pipe-test.tscript create mode 100644 resources/miniscript/tests/string-test.tscript create mode 100644 resources/miniscript/tests/switch-test.tscript diff --git a/LICENSE b/LICENSE index 2cc3d48e9..b66a166f5 100644 --- a/LICENSE +++ b/LICENSE @@ -1,9 +1,9 @@ MIT License -Developed 2012-2023 by Andreas Drewke, Dominik Hepp, Mathias Lenz, Kolja Gumpert, +Developed 2012-2024 by Andreas Drewke, Dominik Hepp, Mathias Lenz, Kolja Gumpert, drewke.net, mindty.com, github.com/mahula -Copyright 2012...2023 Andreas Drewke and others if not stated differently in +Copyright 2012...2024 Andreas Drewke and others if not stated differently in header file. Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/Makefile b/Makefile index ad9dc73e9..a109aa78c 100644 --- a/Makefile +++ b/Makefile @@ -862,6 +862,7 @@ EXT_MINISCRIPT_SRCS = \ ext/miniscript/src/miniscript/os/network/TCPSocket.cpp \ ext/miniscript/src/miniscript/utilities/Base64.cpp \ ext/miniscript/src/miniscript/utilities/Console.cpp \ + ext/miniscript/src/miniscript/utilities/ErrorConsole.cpp \ ext/miniscript/src/miniscript/utilities/ExceptionBase.cpp \ ext/miniscript/src/miniscript/utilities/Float.cpp \ ext/miniscript/src/miniscript/utilities/Hex.cpp \ diff --git a/Makefile.nmake b/Makefile.nmake index cbae3a12c..639ac0681 100644 --- a/Makefile.nmake +++ b/Makefile.nmake @@ -730,6 +730,7 @@ EXT_MINISCRIPT_SRCS = \ ext/miniscript/src/miniscript/os/network/TCPSocket.cpp \ ext/miniscript/src/miniscript/utilities/Base64.cpp \ ext/miniscript/src/miniscript/utilities/Console.cpp \ + ext/miniscript/src/miniscript/utilities/ErrorConsole.cpp \ ext/miniscript/src/miniscript/utilities/ExceptionBase.cpp \ ext/miniscript/src/miniscript/utilities/Float.cpp \ ext/miniscript/src/miniscript/utilities/Hex.cpp \ diff --git a/README-MiniScript.md b/README-MiniScript.md index 34a6b517a..a3a423c35 100644 --- a/README-MiniScript.md +++ b/README-MiniScript.md @@ -1364,12 +1364,27 @@ end | console.dump($value: Mixed): Null | | Print to console | | console.log(...): Null | -| Print to console | +| Print to console without trainling new line | | console.print(...): Null | | Print to console with a trailing new line | | console.println(...): Null | +| Read all input into string value | +| console.readAll(): String | +| Read all input into array of strings | +| console.readAllAsArray(): Array | +| Read a line from input | +| console.readln(): String | + +## 7.4. Error console/stream methods + +|                                                                                           Table of methods                                                                                           | +|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Print to error console/stream without trainling new line | +| console.error.print(...): Null | +| Print to error console/stream with a trailing new line | +| console.error.println(...): Null | -## 7.4. Cryptography Base64 methods +## 7.5. Cryptography Base64 methods |                                                                                           Table of methods                                                                                           | |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| @@ -1378,14 +1393,14 @@ end | Encode a string using Base64 | | cryptography.base64.encode($value: String): String | -## 7.5. Cryptography SHA256 methods +## 7.6. Cryptography SHA256 methods |                                                                                           Table of methods                                                                                           | |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Hash a string using SHA256 | | cryptography.sha256.encode($value: String): String | -## 7.6. File System methods +## 7.7. File System methods |                                                                                           Table of methods                                                                                           | |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| @@ -1436,7 +1451,7 @@ end | Renames a file/folder | | filesystem.rename($fileNameFrom: String, $fileNameTo: String): Boolean | -## 7.7. Float methods +## 7.8. Float methods |                                                                                           Table of methods                                                                                           | |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| @@ -1447,7 +1462,7 @@ end | Convert float to integer bit representation of float | | float.toIntValue($float: Float): Integer | -## 7.8. JSON methods +## 7.9. JSON methods |                                                                                           Table of methods                                                                                           | |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| @@ -1456,7 +1471,7 @@ end | Serialize JSON | | json.serialize($value: Mixed): String | -## 7.9. Math methods +## 7.10. Math methods |                                                                                           Table of methods                                                                                           | |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| @@ -1515,7 +1530,7 @@ end | Compute tan | | math.tan($x: Float): Float | -## 7.10. HTTP/HTTPS client methods +## 7.11. HTTP/HTTPS client methods |                                                                                           Table of methods                                                                                           | |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| @@ -1530,7 +1545,7 @@ end | Execute a HTTP/HTTPS PUT request | | network.httpclient.put($url: String, $data: Mixed[, $queryParameters: ?Map[, $headers: ?Map]]): ?Map| -## 7.11. Script methods +## 7.12. Script methods |                                                                                           Table of methods                                                                                           | |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| @@ -1557,7 +1572,7 @@ end | Wait for condition to happen | | script.waitForCondition(): Null | -## 7.12. Time methods +## 7.13. Time methods |                                                                                           Table of methods                                                                                           | |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| @@ -1566,7 +1581,7 @@ end | Get current time in milliseconds | | time.getCurrentMillis(): Integer | -## 7.13. XML methods +## 7.14. XML methods |                                                                                           Table of methods                                                                                           | |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| diff --git a/ext/miniscript/LICENSE b/ext/miniscript/LICENSE index 945b8cf45..7b388fa95 100644 --- a/ext/miniscript/LICENSE +++ b/ext/miniscript/LICENSE @@ -1,9 +1,9 @@ MIT License -Developed 2021-2023 by Andreas Drewke, Dominik Hepp, Kolja Gumpert, +Developed 2021-2024 by Andreas Drewke, Dominik Hepp, Kolja Gumpert, drewke.net, mindty.com -Copyright 2023 Andreas Drewke. +Copyright 2024 Andreas Drewke. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/ext/miniscript/src/miniscript/miniscript/ApplicationMethods.cpp b/ext/miniscript/src/miniscript/miniscript/ApplicationMethods.cpp index 506e0cb7a..412c4c4c4 100644 --- a/ext/miniscript/src/miniscript/miniscript/ApplicationMethods.cpp +++ b/ext/miniscript/src/miniscript/miniscript/ApplicationMethods.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -21,6 +22,43 @@ using _Console = miniscript::utilities::Console; using _StringTools = miniscript::utilities::StringTools; void ApplicationMethods::registerConstants(MiniScript* miniScript) { + miniScript->setConstant("$APPLICATION::EXITCODE_SUCCESS", static_cast(EXIT_SUCCESS)); + miniScript->setConstant("$APPLICATION::EXITCODE_FAILURE", static_cast(EXIT_FAILURE)); + // + #if defined(__FreeBSD__) + miniScript->setConstant("$APPLICATION::OS", string("FreeBSD")); + #elif defined(__HAIKU__) + miniScript->setConstant("$APPLICATION::OS", string("Haiku")); + #elif defined(__linux__) + miniScript->setConstant("$APPLICATION::OS", string("Linux")); + #elif defined(__APPLE__) + miniScript->setConstant("$APPLICATION::OS", string("MacOSX")); + #elif defined(__NetBSD__) + miniScript->setConstant("$APPLICATION::OS", string("NetBSD")); + #elif defined(__OpenBSD__) + miniScript->setConstant("$APPLICATION::OS", string("OpenBSD")); + #elif defined(_MSC_VER) + miniScript->setConstant("$APPLICATION::OS", string("Windows-MSC")); + #elif defined(_WIN32) + miniScript->setConstant("$APPLICATION::OS", string("Windows-MINGW")); + #else + miniScript->setConstant("$APPLICATION::OS", string("Unknown")); + #endif + #if defined(__amd64__) || defined(_M_X64) + miniScript->setConstant("$APPLICATION::CPU", string("X64")); + #elif defined(__ia64__) || defined(_M_IA64) + miniScript->setConstant("$APPLICATION::CPU", string("IA64")); + #elif defined(__aarch64__) + miniScript->setConstant("$APPLICATION::CPU", string("ARM64")); + #elif defined(__arm__) || defined(_M_ARM) + miniScript->setConstant("$APPLICATION::CPU", string("ARM")); + #elif defined(__powerpc64__) + miniScript->setConstant("$APPLICATION::CPU", string("PPC64")); + #elif defined(__powerpc__) + miniScript->setConstant("$APPLICATION::CPU", string("PPC")); + #else + miniScript->setConstant("$APPLICATION::CPU", string("Unknown")); + #endif } const string ApplicationMethods::execute(const string& command) { @@ -95,5 +133,35 @@ void ApplicationMethods::registerMethods(MiniScript* miniScript) { }; miniScript->registerMethod(new MethodApplicationGetArguments(miniScript)); } + { + // + class MethodApplicationExit: public MiniScript::Method { + private: + MiniScript* miniScript { nullptr }; + public: + MethodApplicationExit(MiniScript* miniScript): + MiniScript::Method( + { + { .type = MiniScript::TYPE_INTEGER, .name = "exitCode", .optional = true, .reference = false, .nullable = false }, + } + ), + miniScript(miniScript) {} + const string getMethodName() override { + return "application.exit"; + } + void executeMethod(span& arguments, MiniScript::Variable& returnValue, const MiniScript::Statement& statement) override { + int64_t exitCode = 0ll; + if (MiniScript::getIntegerValue(arguments, 0, exitCode, true) == true) { + miniScript->getContext()->setExitCode(static_cast(exitCode)); + miniScript->stopScriptExecution(); + miniScript->stopRunning(); + } else { + _Console::println(getMethodName() + "(): " + miniScript->getStatementInformation(statement) + ": argument mismatch: expected arguments: " + miniScript->getArgumentInformation(getMethodName())); + miniScript->startErrorScript(); + } + } + }; + miniScript->registerMethod(new MethodApplicationExit(miniScript)); + } } } diff --git a/ext/miniscript/src/miniscript/miniscript/ConsoleMethods.cpp b/ext/miniscript/src/miniscript/miniscript/ConsoleMethods.cpp index dd100fb61..d89a6ee2d 100644 --- a/ext/miniscript/src/miniscript/miniscript/ConsoleMethods.cpp +++ b/ext/miniscript/src/miniscript/miniscript/ConsoleMethods.cpp @@ -1,10 +1,14 @@ +#include #include #include #include #include #include +#include +using std::cin; +using std::getline; using std::span; using miniscript::miniscript::ConsoleMethods; @@ -12,6 +16,7 @@ using miniscript::miniscript::ConsoleMethods; using miniscript::miniscript::MiniScript; using _Console = miniscript::utilities::Console; +using _ErrorConsole = miniscript::utilities::ErrorConsole; void ConsoleMethods::registerConstants(MiniScript* miniScript) { } @@ -110,4 +115,110 @@ void ConsoleMethods::registerMethods(MiniScript* miniScript) { }; miniScript->registerMethod(new MethodConsolePrintln(miniScript)); } + { + // + class MethodConsoleReadln: public MiniScript::Method { + private: + MiniScript* miniScript { nullptr }; + public: + MethodConsoleReadln(MiniScript* miniScript): + MiniScript::Method({}, MiniScript::TYPE_STRING), + miniScript(miniScript) { + // + } + const string getMethodName() override { + return "console.readln"; + } + void executeMethod(span& arguments, MiniScript::Variable& returnValue, const MiniScript::Statement& statement) override { + returnValue.setValue(_Console::readln()); + } + }; + miniScript->registerMethod(new MethodConsoleReadln(miniScript)); + } + { + // + class MethodConsoleReadAll: public MiniScript::Method { + private: + MiniScript* miniScript { nullptr }; + public: + MethodConsoleReadAll(MiniScript* miniScript): + MiniScript::Method({}, MiniScript::TYPE_STRING), + miniScript(miniScript) { + // + } + const string getMethodName() override { + return "console.readAll"; + } + void executeMethod(span& arguments, MiniScript::Variable& returnValue, const MiniScript::Statement& statement) override { + returnValue.setValue(_Console::readAll()); + } + }; + miniScript->registerMethod(new MethodConsoleReadAll(miniScript)); + } + { + // + class MethodConsoleReadAllAsArray: public MiniScript::Method { + private: + MiniScript* miniScript { nullptr }; + public: + MethodConsoleReadAllAsArray(MiniScript* miniScript): + MiniScript::Method({}, MiniScript::TYPE_ARRAY), + miniScript(miniScript) { + // + } + const string getMethodName() override { + return "console.readAllAsArray"; + } + void executeMethod(span& arguments, MiniScript::Variable& returnValue, const MiniScript::Statement& statement) override { + returnValue.setType(MiniScript::TYPE_ARRAY); + const auto input = _Console::readAllAsArray(); + for (const auto& line: input) returnValue.pushArrayEntry(MiniScript::Variable(line)); + } + }; + miniScript->registerMethod(new MethodConsoleReadAllAsArray(miniScript)); + } + { + // + class MethodConsoleErrorPrint: public MiniScript::Method { + private: + MiniScript* miniScript { nullptr }; + public: + MethodConsoleErrorPrint(MiniScript* miniScript): MiniScript::Method(), miniScript(miniScript) {} + const string getMethodName() override { + return "console.error.print"; + } + void executeMethod(span& arguments, MiniScript::Variable& returnValue, const MiniScript::Statement& statement) override { + for (const auto& argument: arguments) { + _ErrorConsole::print(argument.getValueAsString()); + } + } + bool isVariadic() const override { + return true; + } + }; + miniScript->registerMethod(new MethodConsoleErrorPrint(miniScript)); + } + { + // + class MethodConsoleErrorPrintln: public MiniScript::Method { + private: + MiniScript* miniScript { nullptr }; + public: + MethodConsoleErrorPrintln(MiniScript* miniScript): MiniScript::Method(), miniScript(miniScript) {} + const string getMethodName() override { + return "console.error.println"; + } + void executeMethod(span& arguments, MiniScript::Variable& returnValue, const MiniScript::Statement& statement) override { + for (const auto& argument: arguments) { + _ErrorConsole::print(argument.getValueAsString()); + } + _ErrorConsole::println(); + } + bool isVariadic() const override { + return true; + } + }; + miniScript->registerMethod(new MethodConsoleErrorPrintln(miniScript)); + } } + diff --git a/ext/miniscript/src/miniscript/miniscript/Context.h b/ext/miniscript/src/miniscript/miniscript/Context.h index edcb3e755..1264752ba 100644 --- a/ext/miniscript/src/miniscript/miniscript/Context.h +++ b/ext/miniscript/src/miniscript/miniscript/Context.h @@ -23,6 +23,7 @@ class miniscript::miniscript::Context unordered_map scriptsById; vector scriptCallStack; vector argumentValues; + int exitCode { 0 }; public: // forbid class copy @@ -103,4 +104,19 @@ class miniscript::miniscript::Context scriptCallStack.erase(scriptCallStack.begin() + scriptCallStack.size() - 1); } + /** + * Set exit code + * @param exitCode exit code + */ + inline void setExitCode(int exitCode) { + this->exitCode = exitCode; + } + + /** + * @return exit code + */ + inline int getExitCode() { + return exitCode; + } + }; diff --git a/ext/miniscript/src/miniscript/miniscript/MiniScript.cpp b/ext/miniscript/src/miniscript/miniscript/MiniScript.cpp index fd94610cd..2559ad5d3 100644 --- a/ext/miniscript/src/miniscript/miniscript/MiniScript.cpp +++ b/ext/miniscript/src/miniscript/miniscript/MiniScript.cpp @@ -1,5 +1,9 @@ #include +#if defined(_MSC_VER) + #include +#endif + #include #include #include @@ -125,6 +129,10 @@ const string MiniScript::Variable::TYPENAME_SET = "Set"; const vector MiniScript::Method::CONTEXTFUNCTIONS_ALL = {}; void MiniScript::initialize() { + // + #if defined(_MSC_VER) + SetConsoleOutputCP(65001); + #endif // registerDataType(new HTTPDownloadClientClass()); // @@ -785,7 +793,7 @@ bool MiniScript::createStatementSyntaxTree(const string_view& methodName, const if (viewIsVariableAccess(argument) == true) { // Variable value; - value.setValue(deescape(argument)); + value.setValue(deescape(argument, statement)); // look up getVariable method string methodName = argumentIdx >= argumentReferences.size() || argumentReferences[argumentIdx] == false?"getVariable":"getVariableReference"; @@ -805,7 +813,7 @@ bool MiniScript::createStatementSyntaxTree(const string_view& methodName, const syntaxTree.arguments.emplace_back( SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_METHOD, - MiniScript::Variable(deescape(methodName)), + MiniScript::Variable(deescape(methodName, statement)), method, initializer_list { @@ -853,7 +861,7 @@ bool MiniScript::createStatementSyntaxTree(const string_view& methodName, const _StringTools::viewEndsWith(argument, "'") == true)) { // Variable value; - value.setValue(deescape(_StringTools::viewSubstring(argument, 1, argument.size() - 1))); + value.setValue(deescape(_StringTools::viewSubstring(argument, 1, argument.size() - 1), statement)); // syntaxTree.arguments.emplace_back( SyntaxTreeNode::SCRIPTSYNTAXTREENODE_LITERAL, @@ -880,7 +888,7 @@ bool MiniScript::createStatementSyntaxTree(const string_view& methodName, const // try first user functions if (functionIdx != SCRIPTIDX_NONE) { syntaxTree.type = SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_FUNCTION; - syntaxTree.value.setValue(deescape(methodName)); + syntaxTree.value.setValue(deescape(methodName, statement)); syntaxTree.setFunctionScriptIdx(functionIdx); // return true; @@ -888,7 +896,7 @@ bool MiniScript::createStatementSyntaxTree(const string_view& methodName, const // try methods next if (method != nullptr) { syntaxTree.type = SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_METHOD; - syntaxTree.value.setValue(deescape(methodName)); + syntaxTree.value.setValue(deescape(methodName, statement)); syntaxTree.setMethod(method); // return true; diff --git a/ext/miniscript/src/miniscript/miniscript/MiniScript.h b/ext/miniscript/src/miniscript/miniscript/MiniScript.h index 211ceeb8e..21c7f4376 100644 --- a/ext/miniscript/src/miniscript/miniscript/MiniScript.h +++ b/ext/miniscript/src/miniscript/miniscript/MiniScript.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,7 @@ using _Character = miniscript::utilities::Character; using _Console = miniscript::utilities::Console; using _Exception = miniscript::utilities::Exception; using _Float = miniscript::utilities::Float; +using _Hex = miniscript::utilities::Hex; using _Integer = miniscript::utilities::Integer; using _StringTools = miniscript::utilities::StringTools; using _Time = miniscript::utilities::Time; @@ -58,6 +60,7 @@ using _Library = miniscript::miniscript::Library; * @author Andreas Drewke */ class miniscript::miniscript::MiniScript { + friend class ApplicationMethods; friend class BaseMethods; friend class JSONMethods; friend class ScriptMethods; @@ -1967,7 +1970,7 @@ class miniscript::miniscript::MiniScript { if (viewIsVariableAccess(value) == true) { setFunctionCallStatement("getVariable(\"" + string(value) + "\")", miniScript, statement); } else { - setValue(deescape(value)); + setValue(miniScript->deescape(value, statement)); } } @@ -3147,15 +3150,52 @@ class miniscript::miniscript::MiniScript { /** * Deescape string * @param str string + * @param statement statement * @return deescaped string */ - inline static const string deescape(const string_view& str) { + inline const string deescape(const string_view& str, const Statement& statement) { string deescapedStr; auto lc = '\0'; for (auto i = 0; i < str.size(); i++) { auto c = str[i]; if (c != '\\' || lc == '\\') { - deescapedStr+= c; + // escape sequences + // see: https://en.cppreference.com/w/cpp/language/escape + // \0 null character + if (lc == '\\' && c == '0') deescapedStr+= '\0'; else + // \a audible bell + if (lc == '\\' && c == 'a') deescapedStr+= '\a'; else + // \b backspace + if (lc == '\\' && c == 'b') deescapedStr+= '\b'; else + // \f form feed - new page + if (lc == '\\' && c == 'f') deescapedStr+= '\f'; else + // \n line feed - new line + if (lc == '\\' && c == 'n') deescapedStr+= '\n'; else + // \r carriage return + if (lc == '\\' && c == 'r') deescapedStr+= '\r'; else + // \t horizontal tab + if (lc == '\\' && c == 't') deescapedStr+= '\t'; else + // \v vertical tab + if (lc == '\\' && c == 'v') deescapedStr+= '\v'; else + // unicode \Unnnnnnnn + if (lc == '\\' && c == 'U') { + string unicodeHexadecimalSequence; + auto j = 0; + auto valid = true; + for (i++; i < str.size() && j < 8; i++ && j++) { + c = str[i]; + unicodeHexadecimalSequence+= c; + if (((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) == false) break; + } + i--; + if (valid == false || j != 8) { + _Console::println(getStatementInformation(statement) + ": Invalid hexadecimal unicode character sequence: " + unicodeHexadecimalSequence); + } else { + _Character::appendToString(deescapedStr, _Hex::decodeInt(unicodeHexadecimalSequence)); + } + } else + deescapedStr+= c; + // lc = '\0'; continue; } diff --git a/ext/miniscript/src/miniscript/miniscript/Transpiler.cpp b/ext/miniscript/src/miniscript/miniscript/Transpiler.cpp index 1108c6058..28bf1a009 100644 --- a/ext/miniscript/src/miniscript/miniscript/Transpiler.cpp +++ b/ext/miniscript/src/miniscript/miniscript/Transpiler.cpp @@ -1359,7 +1359,7 @@ void Transpiler::generateArrayAccessMethods( if (arrayAccessStatementAsScriptVariable.getFloatValue(floatValue) == true) { generatedDefinitions+= lamdaIndent + "// Miniscript transpilation for a " + (condition == true?"condition":"statement") + " array access statement, statement index " + to_string(statement.statementIdx) + ", argument indices " + MiniScript::getArgumentIndicesAsString(nextArgumentIndices, ", ") + ", array access statement index " + to_string(arrayAccessStatementIdx) + "\n"; generatedDefinitions+= lamdaIndent + "auto array_access_statement_" + to_string(statement.statementIdx) + "_" + MiniScript::getArgumentIndicesAsString(nextArgumentIndices, "_") + "_" + to_string(arrayAccessStatementIdx) + " = [&](const Statement& statement) -> Variable {" + "\n"; - generatedDefinitions+= lamdaIndent + " return Variable(static_cast(" + to_string(static_cast(floatValue)) + "ll));" + "\n"; + "\n"; + generatedDefinitions+= lamdaIndent + " return Variable(static_cast(" + to_string(static_cast(floatValue)) + "ll));" + "\n"; generatedDefinitions+= lamdaIndent + "};" + "\n"; } // literals diff --git a/ext/miniscript/src/miniscript/tools/miniscript-main.cpp b/ext/miniscript/src/miniscript/tools/miniscript-main.cpp index 7c579a5c6..d978c4d04 100644 --- a/ext/miniscript/src/miniscript/tools/miniscript-main.cpp +++ b/ext/miniscript/src/miniscript/tools/miniscript-main.cpp @@ -164,6 +164,7 @@ int main(int argc, char** argv) // if (script->isValid() == false) { Console::println(pathToScript + ": Script not valid. Exiting!"); + return EXIT_SUCCESS; } else { // TODO: we need a MiniScript startup routine Network::initialize(); @@ -181,6 +182,8 @@ int main(int argc, char** argv) } context->pop(); } + } else { + return EXIT_FAILURE; } } else if (version == false) { @@ -202,5 +205,5 @@ int main(int argc, char** argv) } // - return script == nullptr || script->isValid() == false?EXIT_FAILURE:EXIT_SUCCESS; + return context->getExitCode(); } diff --git a/ext/miniscript/src/miniscript/utilities/Console.cpp b/ext/miniscript/src/miniscript/utilities/Console.cpp index 00b392a2a..c1af21b31 100644 --- a/ext/miniscript/src/miniscript/utilities/Console.cpp +++ b/ext/miniscript/src/miniscript/utilities/Console.cpp @@ -1,11 +1,19 @@ #include #include +#include +#include #include #include #include -using namespace std; +using std::cin; +using std::cout; +using std::endl; +using std::getline; +using std::string; +using std::string_view; +using std::vector; using miniscript::utilities::Console; @@ -26,3 +34,28 @@ void Console::println() cout << endl; cout.flush(); } + +const string Console::readln() +{ + string line; + getline(cin, line); + return line; +} + +const string Console::readAll() { + string line; + string result; + while (cin.eof() == false && getline(cin, line)) { + result+= line + "\n"; + } + return line; +} + +const vector Console::readAllAsArray() { + vector result; + string line; + while (cin.eof() == false && getline(cin, line)) { + result.push_back(line); + } + return result; +} diff --git a/ext/miniscript/src/miniscript/utilities/Console.h b/ext/miniscript/src/miniscript/utilities/Console.h index 605eb653c..555a3ccf6 100644 --- a/ext/miniscript/src/miniscript/utilities/Console.h +++ b/ext/miniscript/src/miniscript/utilities/Console.h @@ -1,11 +1,15 @@ #pragma once +#include #include +#include #include #include +using std::string; using std::string_view; +using std::vector; /** * Console class @@ -22,14 +26,29 @@ class miniscript::utilities::Console static void println(const string_view& str); /** - * Print given string + * Print given string without trainling newline to console * @param str string */ static void print(const string_view& str); /** - * Print new line to console + * Print newline to console */ static void println(); + /** + * Read line from console + */ + static const string readln(); + + /** + * Read all input from console into string + */ + static const string readAll(); + + /** + * Read all input from console into string vector + */ + static const vector readAllAsArray(); + }; diff --git a/ext/miniscript/src/miniscript/utilities/ErrorConsole.cpp b/ext/miniscript/src/miniscript/utilities/ErrorConsole.cpp new file mode 100644 index 000000000..1f28a25a5 --- /dev/null +++ b/ext/miniscript/src/miniscript/utilities/ErrorConsole.cpp @@ -0,0 +1,28 @@ +#include +#include + +#include +#include + +using std::cerr; +using std::endl; + +using miniscript::utilities::ErrorConsole; + +void ErrorConsole::println(const string_view& str) +{ + cerr << str << endl; + cerr.flush(); +} + +void ErrorConsole::print(const string_view& str) +{ + cerr << str; + cerr.flush(); +} + +void ErrorConsole::println() +{ + cerr << endl; + cerr.flush(); +} diff --git a/ext/miniscript/src/miniscript/utilities/ErrorConsole.h b/ext/miniscript/src/miniscript/utilities/ErrorConsole.h new file mode 100644 index 000000000..2c3c8404a --- /dev/null +++ b/ext/miniscript/src/miniscript/utilities/ErrorConsole.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +#include +#include + +using std::string_view; + +/** + * Console class + * @author Andreas Drewke + * @versio $Id$ + */ +class miniscript::utilities::ErrorConsole +{ +public: + /** + * Print given string and trailing newline to error console + * @param str string + */ + static void println(const string_view& str); + + /** + * Print given string to error console without trainling new line + * @param str string + */ + static void print(const string_view& str); + + /** + * Print newline to error console + */ + static void println(); + +}; diff --git a/ext/miniscript/src/miniscript/utilities/fwd-miniscript.h b/ext/miniscript/src/miniscript/utilities/fwd-miniscript.h index 8037c217b..01a604ad0 100644 --- a/ext/miniscript/src/miniscript/utilities/fwd-miniscript.h +++ b/ext/miniscript/src/miniscript/utilities/fwd-miniscript.h @@ -6,6 +6,7 @@ namespace utilities { class Base64; class Character; class Console; + class ErrorConsole; class ExceptionBase; class Float; class Hex; diff --git a/resources/engine/code-completion/tscript-methods.properties b/resources/engine/code-completion/tscript-methods.properties index fa64b79c6..5d97e362f 100644 --- a/resources/engine/code-completion/tscript-methods.properties +++ b/resources/engine/code-completion/tscript-methods.properties @@ -92,6 +92,7 @@ miniscript.basemethod.group.cryptography.base64=Cryptography Base64 methods miniscript.basemethod.group.cryptography.sha256=Cryptography SHA256 methods miniscript.basemethod.group.context.script=Script container and interoperability methods miniscript.basemethod.group.console=Console methods +miniscript.basemethod.group.console.error=Error console/stream methods miniscript.basemethod.group.filesystem=File System methods miniscript.basemethod.group.float=Float methods miniscript.basemethod.group.json=JSON methods @@ -133,6 +134,7 @@ miniscript.basemethod.add=Add miniscript.basemethod.and=Logical and miniscript.basemethod.application.getArguments=Get application command line arguments miniscript.basemethod.application.execute=Execute Application +miniscript.basemethod.application.exit=Exit application with optional exit code miniscript.basemethod.Array=Create array miniscript.basemethod.Array::get=Get array entry miniscript.basemethod.Array::set=Set array entry @@ -184,9 +186,14 @@ miniscript.basemethod.cryptography.base64.encode=Encode a string using Base64 miniscript.basemethod.cryptography.base64.decode=Decode a Base64 encoded string miniscript.basemethod.cryptography.sha256.encode=Hash a string using SHA256 miniscript.basemethod.console.dump=Pretty print variable to console +miniscript.basemethod.console.error.print=Print to error console/stream without trainling new line +miniscript.basemethod.console.error.println=Print to error console/stream with a trailing new line miniscript.basemethod.console.log=Print to console -miniscript.basemethod.console.print=Print to console +miniscript.basemethod.console.print=Print to console without trainling new line miniscript.basemethod.console.println=Print to console with a trailing new line +miniscript.basemethod.console.readAll=Read all input into string value +miniscript.basemethod.console.readAllAsArray=Read all input into array of strings +miniscript.basemethod.console.readln=Read a line from input miniscript.basemethod.context.script.hasCallable=Returns if a script has a specific callable function miniscript.basemethod.context.script.getScriptIds=Returns all script ids of its context miniscript.basemethod.context.script.call=Call a script callable function diff --git a/resources/miniscript/documentation/method-descriptions.properties b/resources/miniscript/documentation/method-descriptions.properties index 5dabdf0d6..18a5036ea 100644 --- a/resources/miniscript/documentation/method-descriptions.properties +++ b/resources/miniscript/documentation/method-descriptions.properties @@ -13,6 +13,7 @@ miniscript.basemethod.group.cryptography.base64=Cryptography Base64 methods miniscript.basemethod.group.cryptography.sha256=Cryptography SHA256 methods miniscript.basemethod.group.context.script=Script container and interoperability methods miniscript.basemethod.group.console=Console methods +miniscript.basemethod.group.console.error=Error console/stream methods miniscript.basemethod.group.filesystem=File System methods miniscript.basemethod.group.float=Float methods miniscript.basemethod.group.json=JSON methods @@ -54,6 +55,7 @@ miniscript.basemethod.add=Add miniscript.basemethod.and=Logical and miniscript.basemethod.application.getArguments=Get application command line arguments miniscript.basemethod.application.execute=Execute Application +miniscript.basemethod.application.exit=Exit application with optional exit code miniscript.basemethod.Array=Create array miniscript.basemethod.Array::get=Get array entry miniscript.basemethod.Array::set=Set array entry @@ -73,6 +75,7 @@ miniscript.basemethod.bitwiseOr=Bitwise or miniscript.basemethod.bitwiseXor=Bitwise xor miniscript.basemethod.bool=Create bool miniscript.basemethod.break=Break out of current forCondition or forTime loop +miniscript.basemethod.case=Begins a case block within a switch block, which will be executed if the case value has matched miniscript.basemethod.continue=Continue to next iteration of forCondition or forTime loop miniscript.basemethod.ByteArray=Create byte array miniscript.basemethod.ByteArray::clear=Clear byte array @@ -104,14 +107,20 @@ miniscript.basemethod.cryptography.base64.encode=Encode a string using Base64 miniscript.basemethod.cryptography.base64.decode=Decode a Base64 encoded string miniscript.basemethod.cryptography.sha256.encode=Hash a string using SHA256 miniscript.basemethod.console.dump=Pretty print variable to console +miniscript.basemethod.console.error.print=Print to error console/stream without trainling new line +miniscript.basemethod.console.error.println=Print to error console/stream with a trailing new line miniscript.basemethod.console.log=Print to console -miniscript.basemethod.console.print=Print to console +miniscript.basemethod.console.print=Print to console without trainling new line miniscript.basemethod.console.println=Print to console with a trailing new line +miniscript.basemethod.console.readAll=Read all input into string value +miniscript.basemethod.console.readAllAsArray=Read all input into array of strings +miniscript.basemethod.console.readln=Read a line from input miniscript.basemethod.context.script.hasCallable=Returns if a script has a specific callable function miniscript.basemethod.context.script.getScriptIds=Returns all script ids of its context miniscript.basemethod.context.script.call=Call a script callable function miniscript.basemethod.context.script.loadScript=Load a script into context miniscript.basemethod.context.script.removeScript=Remove a script from context +miniscript.basemethod.default=Begins a default block within a switch block, which will be executed if no case value has matched miniscript.basemethod.div=Divide miniscript.basemethod.else=Else miniscript.basemethod.elseif=Else if @@ -215,6 +224,7 @@ miniscript.basemethod.script.evaluate=Evaluate a script statement miniscript.basemethod.script.stop=Stop script miniscript.basemethod.script.wait=Wait for given milliseconds miniscript.basemethod.script.waitForCondition=Wait for condition to happen +miniscript.basemethod.switch=Begins switch block to match a given value to case values or a default miniscript.basemethod.Set=Create set miniscript.basemethod.Set::has=Has key in set miniscript.basemethod.Set::getKeys=Get set keys diff --git a/resources/miniscript/tests/application-test.tscript b/resources/miniscript/tests/application-test.tscript index 0981f1e8b..7800a7f62 100644 --- a/resources/miniscript/tests/application-test.tscript +++ b/resources/miniscript/tests/application-test.tscript @@ -13,9 +13,12 @@ on: nothing console.log("---------------------------") console.log() console.log("application.getArguments(): " + application.getArguments()) - console.log("application.execute('ls'): " + application.execute('ls')) - # - script.stop() + if ($APPLICATION::OS == "Windows-MSC") + console.log("application.execute('dir'): " + application.execute('dir')) + else + console.log("application.execute('ls'): " + application.execute('ls')) + end + application.exit(2) end # an error has occurred diff --git a/resources/miniscript/tests/console-test.tscript b/resources/miniscript/tests/console-test.tscript new file mode 100644 index 000000000..dc8417db0 --- /dev/null +++ b/resources/miniscript/tests/console-test.tscript @@ -0,0 +1,30 @@ +# initialize +on: initialize + console.log("--------------------------") + console.log("console-test: Initialize") + console.log("--------------------------") + console.log() +end + +# if no condition is met, nothing will be executed, lol :D +on: nothing + console.log("-----------------------") + console.log("console-test: Nothing") + console.log("-----------------------") + console.log() + console.print("Whats your name: ") + $name = console.readln() + console.println("You have the mighty name: " + $name) + console.error.print("Now printing your name to error console: ") + console.error.println($name) + script.stop() +end + +# an error has occurred +on: error + console.log("---------------------") + console.log("console-test: Error") + console.log("---------------------") + console.log("An error occurred") + script.stop() +end diff --git a/resources/miniscript/tests/network-test.tscript b/resources/miniscript/tests/network-test.tscript index 5e2318377..fc593fb0e 100644 --- a/resources/miniscript/tests/network-test.tscript +++ b/resources/miniscript/tests/network-test.tscript @@ -36,16 +36,22 @@ on: nothing end # $httpDownloadClient = HTTPDownloadClient() - $httpDownloadClient->setURL("https://mindty.com") - $httpDownloadClient->setFile("mindty.com.html") + $httpDownloadClient->setURL("https://download.freebsd.org/releases/ISO-IMAGES/14.0/FreeBSD-14.0-RELEASE-amd64-bootonly.iso") + $httpDownloadClient->setFile("FreeBSD-14.0-RELEASE-amd64-bootonly.iso") + $httpDownloadClient->setHeaders({a: 1}) console.log("HTTP download client: " + $httpDownloadClient) - $httpDownloadClient->execute() + $httpDownloadClient->start() + console.print("[") forCondition($httpDownloadClient->isFinished() == false) - console.log($httpDownloadClient->getProgress()) + console.print("-") script.wait(1000) end - if (filesystem.removeFile(".", "mindty.com.html") == false) - console.log("Could not remove file mindty.com.html.") + console.println("]") + $httpDownloadClient->join() + console.log("HTTP Download status code: " + $httpDownloadClient->getStatusCode()) + console.log("HTTP Download response headers: " + $httpDownloadClient->getResponseHeaders()) + if (filesystem.removeFile(".", "FreeBSD-14.0-RELEASE-amd64-bootonly.iso") == false) + console.log("Could not remove file FreeBSD-14.0-RELEASE-amd64-bootonly.iso.") end # script.stop() @@ -58,4 +64,4 @@ on: error console.log("---------------------") console.log("An error occurred") script.stop() -end \ No newline at end of file +end diff --git a/resources/miniscript/tests/pipe-test.tscript b/resources/miniscript/tests/pipe-test.tscript new file mode 100644 index 000000000..032972141 --- /dev/null +++ b/resources/miniscript/tests/pipe-test.tscript @@ -0,0 +1,29 @@ +# initialize +on: initialize + console.log("-----------------------") + console.log("pipe-test: Initialize") + console.log("-----------------------") + console.log() +end + +# if no condition is met, nothing will be executed, lol :D +on: nothing + console.log("--------------------") + console.log("pipe-test: Nothing") + console.log("--------------------") + console.log() + console.println("Reading from pipe or console input stream: ") + $input = console.readAllAsArray() + console.println("Input was: ") + console.println($input) + script.stop() +end + +# an error has occurred +on: error + console.log("-------------------") + console.log("pipe-test: Error") + console.log("-------------------") + console.log("An error occurred") + script.stop() +end \ No newline at end of file diff --git a/resources/miniscript/tests/string-test.tscript b/resources/miniscript/tests/string-test.tscript new file mode 100644 index 000000000..8a10f5505 --- /dev/null +++ b/resources/miniscript/tests/string-test.tscript @@ -0,0 +1,29 @@ +# initialize +on: initialize + console.log("-------------------------") + console.log("string-test: Initialize") + console.log("-------------------------") + console.log() +end + +# if no condition is met, nothing will be executed, lol :D +on: nothing + console.log("----------------------") + console.log("string-test: Nothing") + console.log("----------------------") + console.log() + console.println("Hi, lets produce\na newline, and\nanother one: \"yarrrrr\"") + console.println("Some Umlauts love: äöü >>> ÄÖÜ") + console.println("Some more Umlauts love: \U000000fc") + console.println("Beep\a") + script.stop() +end + +# an error has occurred +on: error + console.log("--------------------") + console.log("string-test: Error") + console.log("--------------------") + console.log("An error occurred") + script.stop() +end diff --git a/resources/miniscript/tests/switch-test.tscript b/resources/miniscript/tests/switch-test.tscript new file mode 100644 index 000000000..3c50b320c --- /dev/null +++ b/resources/miniscript/tests/switch-test.tscript @@ -0,0 +1,54 @@ +# initialize +on: initialize + console.log("-------------------------") + console.log("switch-test: Initialize") + console.log("-------------------------") + console.log() +end + +# if no condition is met, nothing will be executed, lol :D +on: nothing + console.log("----------------------") + console.log("switch-test: Nothing") + console.log("----------------------") + console.log() + # + $i = 1 + $j = b + switch($i) + case(0) + console.log("$i = 0") + end + case(1) + console.log("$i = 1") + switch($j) + case("a") + console.log("$j = a") + end + case("b") + console.log("$j = b") + end + case("c") + console.log("$j = c") + end + end + end + case(2) + console.log("$i = 2") + end + default + console.log("default: $i = " + $i) + end + end + # + script.stop() +end + +# an error has occurred +on: error + console.log("--------------------") + console.log("switch-test: Error") + console.log("--------------------") + console.log("An error occurred") + script.stop() +end \ No newline at end of file