From a5aa002752817b46a4b59a25f06df08141568a70 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Thu, 23 Jun 2022 19:33:30 +0200 Subject: [PATCH] patterns: Moved most built-in functions to the pattern language repo --- lib/external/pattern_language | 2 +- .../source/content/pl_builtin_functions.cpp | 492 ------------------ 2 files changed, 1 insertion(+), 493 deletions(-) diff --git a/lib/external/pattern_language b/lib/external/pattern_language index 901efb43f..d399836b6 160000 --- a/lib/external/pattern_language +++ b/lib/external/pattern_language @@ -1 +1 @@ -Subproject commit 901efb43f206a9dfaa235ae1ec1366a88c1e71ce +Subproject commit d399836b693feaab3b323acd4374c1371164c0eb diff --git a/plugins/builtin/source/content/pl_builtin_functions.cpp b/plugins/builtin/source/content/pl_builtin_functions.cpp index 588dafddf..e7bdf270e 100644 --- a/plugins/builtin/source/content/pl_builtin_functions.cpp +++ b/plugins/builtin/source/content/pl_builtin_functions.cpp @@ -1,248 +1,18 @@ #include -#include #include -#include -#include #include #include #include #include -#include - -#include - namespace hex::plugin::builtin { - std::string format(const auto ¶ms) { - auto format = pl::Token::literalToString(params[0], true); - std::string message; - - fmt::dynamic_format_arg_store formatArgs; - - for (u32 i = 1; i < params.size(); i++) { - auto ¶m = params[i]; - - std::visit(overloaded { - [&](pl::Pattern *value) { - formatArgs.push_back(value->toString()); - }, - [&](auto &&value) { - formatArgs.push_back(value); - } }, - param); - } - - try { - return fmt::vformat(format, formatArgs); - } catch (fmt::format_error &error) { - pl::LogConsole::abortEvaluation(hex::format("format error: {}", error.what())); - } - } - void registerPatternLanguageFunctions() { using namespace pl; using FunctionParameterCount = pl::api::FunctionParameterCount; - pl::api::Namespace nsStd = { "builtin", "std" }; - { - /* print(format, args...) */ - ContentRegistry::PatternLanguage::addFunction(nsStd, "print", FunctionParameterCount::moreThan(0), [](Evaluator *ctx, auto params) -> std::optional { - ctx->getConsole().log(LogConsole::Level::Info, format(params)); - - return std::nullopt; - }); - - /* format(format, args...) */ - ContentRegistry::PatternLanguage::addFunction(nsStd, "format", FunctionParameterCount::moreThan(0), [](Evaluator *, auto params) -> std::optional { - return format(params); - }); - - /* env(name) */ - ContentRegistry::PatternLanguage::addFunction(nsStd, "env", FunctionParameterCount::exactly(1), [](Evaluator *ctx, auto params) -> std::optional { - auto name = Token::literalToString(params[0], false); - - auto env = ctx->getEnvVariable(name); - if (env) - return env; - else { - ctx->getConsole().log(LogConsole::Level::Warning, hex::format("environment variable '{}' does not exist", name)); - return ""; - } - }); - - /* pack_size(...) */ - ContentRegistry::PatternLanguage::addFunction(nsStd, "sizeof_pack", FunctionParameterCount::atLeast(0), [](Evaluator *, auto params) -> std::optional { - return u128(params.size()); - }); - - /* error(message) */ - ContentRegistry::PatternLanguage::addFunction(nsStd, "error", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - LogConsole::abortEvaluation(Token::literalToString(params[0], true)); - - return std::nullopt; - }); - - /* warning(message) */ - ContentRegistry::PatternLanguage::addFunction(nsStd, "warning", FunctionParameterCount::exactly(1), [](Evaluator *ctx, auto params) -> std::optional { - ctx->getConsole().log(LogConsole::Level::Warning, Token::literalToString(params[0], true)); - - return std::nullopt; - }); - } - - api::Namespace nsStdMem = { "builtin", "std", "mem" }; - { - - /* base_address() */ - ContentRegistry::PatternLanguage::addFunction(nsStdMem, "base_address", FunctionParameterCount::none(), [](Evaluator *ctx, auto params) -> std::optional { - hex::unused(params); - - return u128(ctx->getDataBaseAddress()); - }); - - /* size() */ - ContentRegistry::PatternLanguage::addFunction(nsStdMem, "size", FunctionParameterCount::none(), [](Evaluator *ctx, auto params) -> std::optional { - hex::unused(params); - - return u128(ctx->getDataSize()); - }); - - /* find_sequence_in_range(occurrence_index, start_offset, end_offset, bytes...) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMem, "find_sequence_in_range", FunctionParameterCount::moreThan(3), [](Evaluator *ctx, auto params) -> std::optional { - auto occurrenceIndex = Token::literalToUnsigned(params[0]); - auto offsetFrom = Token::literalToUnsigned(params[1]); - auto offsetTo = Token::literalToUnsigned(params[2]); - - std::vector sequence; - for (u32 i = 3; i < params.size(); i++) { - auto byte = Token::literalToUnsigned(params[i]); - - if (byte > 0xFF) - LogConsole::abortEvaluation(hex::format("byte #{} value out of range: {} > 0xFF", i, u64(byte))); - - sequence.push_back(u8(byte & 0xFF)); - } - - std::vector bytes(sequence.size(), 0x00); - u32 occurrences = 0; - const u64 bufferSize = ctx->getDataSize(); - const u64 endOffset = offsetTo <= offsetFrom ? bufferSize : std::min(bufferSize, u64(offsetTo)); - for (u64 offset = offsetFrom; offset < endOffset - sequence.size(); offset++) { - ctx->readData(offset, bytes.data(), bytes.size()); - - if (bytes == sequence) { - if (occurrences < occurrenceIndex) { - occurrences++; - continue; - } - - return u128(offset); - } - } - - return i128(-1); - }); - - /* read_unsigned(address, size) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMem, "read_unsigned", FunctionParameterCount::exactly(2), [](Evaluator *ctx, auto params) -> std::optional { - auto address = Token::literalToUnsigned(params[0]); - auto size = Token::literalToUnsigned(params[1]); - - if (size > 16) - LogConsole::abortEvaluation("read size out of range"); - - u128 result = 0; - ctx->readData(address, &result, size); - - return result; - }); - - /* read_signed(address, size) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMem, "read_signed", FunctionParameterCount::exactly(2), [](Evaluator *ctx, auto params) -> std::optional { - auto address = Token::literalToUnsigned(params[0]); - auto size = Token::literalToUnsigned(params[1]); - - if (size > 16) - LogConsole::abortEvaluation("read size out of range"); - - i128 value; - ctx->readData(address, &value, size); - return hex::signExtend(size * 8, value); - }); - - /* read_string(address, size) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMem, "read_string", FunctionParameterCount::exactly(2), [](Evaluator *ctx, auto params) -> std::optional { - auto address = Token::literalToUnsigned(params[0]); - auto size = Token::literalToUnsigned(params[1]); - - std::string result(size, '\x00'); - ctx->readData(address, result.data(), size); - - return result; - }); - } - - api::Namespace nsStdString = { "builtin", "std", "string" }; - { - /* length(string) */ - ContentRegistry::PatternLanguage::addFunction(nsStdString, "length", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - auto string = Token::literalToString(params[0], false); - - return u128(string.length()); - }); - - /* at(string, index) */ - ContentRegistry::PatternLanguage::addFunction(nsStdString, "at", FunctionParameterCount::exactly(2), [](Evaluator *, auto params) -> std::optional { - auto string = Token::literalToString(params[0], false); - auto index = Token::literalToSigned(params[1]); - -#if defined(OS_MACOS) - const auto signIndex = index >> (sizeof(index) * 8 - 1); - const auto absIndex = (index ^ signIndex) - signIndex; -#else - const auto absIndex = std::abs(index); -#endif - - if (absIndex > string.length()) - LogConsole::abortEvaluation("character index out of range"); - - if (index >= 0) - return char(string[index]); - else - return char(string[string.length() - -index]); - }); - - /* substr(string, pos, count) */ - ContentRegistry::PatternLanguage::addFunction(nsStdString, "substr", FunctionParameterCount::exactly(3), [](Evaluator *, auto params) -> std::optional { - auto string = Token::literalToString(params[0], false); - auto pos = Token::literalToUnsigned(params[1]); - auto size = Token::literalToUnsigned(params[2]); - - if (pos > string.length()) - LogConsole::abortEvaluation("character index out of range"); - - return string.substr(pos, size); - }); - - /* parse_int(string, base) */ - ContentRegistry::PatternLanguage::addFunction(nsStdString, "parse_int", FunctionParameterCount::exactly(2), [](Evaluator *, auto params) -> std::optional { - auto string = Token::literalToString(params[0], false); - auto base = Token::literalToUnsigned(params[1]); - - return i128(std::strtoll(string.c_str(), nullptr, base)); - }); - - /* parse_float(string) */ - ContentRegistry::PatternLanguage::addFunction(nsStdString, "parse_float", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - auto string = Token::literalToString(params[0], false); - - return double(std::strtod(string.c_str(), nullptr)); - }); - } - api::Namespace nsStdHttp = { "builtin", "std", "http" }; { /* get(url) */ @@ -253,267 +23,5 @@ namespace hex::plugin::builtin { return net.getString(url).get().body; }); } - - - api::Namespace nsStdFile = { "builtin", "std", "file" }; - { - static u32 fileCounter = 0; - static std::map openFiles; - - /* open(path, mode) */ - ContentRegistry::PatternLanguage::addDangerousFunction(nsStdFile, "open", FunctionParameterCount::exactly(2), [](Evaluator *, auto params) -> std::optional { - const auto path = Token::literalToString(params[0], false); - const auto modeEnum = Token::literalToUnsigned(params[1]); - - fs::File::Mode mode; - switch (modeEnum) { - case 1: - mode = fs::File::Mode::Read; - break; - case 2: - mode = fs::File::Mode::Write; - break; - case 3: - mode = fs::File::Mode::Create; - break; - default: - LogConsole::abortEvaluation("invalid file open mode"); - } - - fs::File file(path, mode); - - if (!file.isValid()) - LogConsole::abortEvaluation(hex::format("failed to open file {}", path)); - - fileCounter++; - openFiles.emplace(std::pair { fileCounter, std::move(file) }); - - return u128(fileCounter); - }); - - /* close(file) */ - ContentRegistry::PatternLanguage::addDangerousFunction(nsStdFile, "close", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - const auto file = Token::literalToUnsigned(params[0]); - - if (!openFiles.contains(file)) - LogConsole::abortEvaluation("failed to access invalid file"); - - openFiles.erase(file); - - return std::nullopt; - }); - - /* read(file, size) */ - ContentRegistry::PatternLanguage::addDangerousFunction(nsStdFile, "read", FunctionParameterCount::exactly(2), [](Evaluator *, auto params) -> std::optional { - const auto file = Token::literalToUnsigned(params[0]); - const auto size = Token::literalToUnsigned(params[1]); - - if (!openFiles.contains(file)) - LogConsole::abortEvaluation("failed to access invalid file"); - - return openFiles[file].readString(size); - }); - - /* write(file, data) */ - ContentRegistry::PatternLanguage::addDangerousFunction(nsStdFile, "write", FunctionParameterCount::exactly(2), [](Evaluator *, auto params) -> std::optional { - const auto file = Token::literalToUnsigned(params[0]); - const auto data = Token::literalToString(params[1], true); - - if (!openFiles.contains(file)) - LogConsole::abortEvaluation("failed to access invalid file"); - - openFiles[file].write(data); - - return std::nullopt; - }); - - /* seek(file, offset) */ - ContentRegistry::PatternLanguage::addDangerousFunction(nsStdFile, "seek", FunctionParameterCount::exactly(2), [](Evaluator *, auto params) -> std::optional { - const auto file = Token::literalToUnsigned(params[0]); - const auto offset = Token::literalToUnsigned(params[1]); - - if (!openFiles.contains(file)) - LogConsole::abortEvaluation("failed to access invalid file"); - - openFiles[file].seek(offset); - - return std::nullopt; - }); - - /* size(file) */ - ContentRegistry::PatternLanguage::addDangerousFunction(nsStdFile, "size", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - const auto file = Token::literalToUnsigned(params[0]); - - if (!openFiles.contains(file)) - LogConsole::abortEvaluation("failed to access invalid file"); - - return u128(openFiles[file].getSize()); - }); - - /* resize(file, size) */ - ContentRegistry::PatternLanguage::addDangerousFunction(nsStdFile, "resize", FunctionParameterCount::exactly(2), [](Evaluator *, auto params) -> std::optional { - const auto file = Token::literalToUnsigned(params[0]); - const auto size = Token::literalToUnsigned(params[1]); - - if (!openFiles.contains(file)) - LogConsole::abortEvaluation("failed to access invalid file"); - - openFiles[file].setSize(size); - - return std::nullopt; - }); - - /* flush(file) */ - ContentRegistry::PatternLanguage::addDangerousFunction(nsStdFile, "flush", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - const auto file = Token::literalToUnsigned(params[0]); - - if (!openFiles.contains(file)) - LogConsole::abortEvaluation("failed to access invalid file"); - - openFiles[file].flush(); - - return std::nullopt; - }); - - /* remove(file) */ - ContentRegistry::PatternLanguage::addDangerousFunction(nsStdFile, "remove", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - const auto file = Token::literalToUnsigned(params[0]); - - if (!openFiles.contains(file)) - LogConsole::abortEvaluation("failed to access invalid file"); - - openFiles[file].remove(); - - return std::nullopt; - }); - } - - - api::Namespace nsStdMath = { "builtin", "std", "math" }; - { - /* floor(value) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "floor", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - return std::floor(Token::literalToFloatingPoint(params[0])); - }); - - /* ceil(value) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "ceil", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - return std::ceil(Token::literalToFloatingPoint(params[0])); - }); - - /* round(value) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "round", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - return std::round(Token::literalToFloatingPoint(params[0])); - }); - - /* trunc(value) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "trunc", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - return std::trunc(Token::literalToFloatingPoint(params[0])); - }); - - - /* log10(value) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "log10", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - return std::log10(Token::literalToFloatingPoint(params[0])); - }); - - /* log2(value) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "log2", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - return std::log2(Token::literalToFloatingPoint(params[0])); - }); - - /* ln(value) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "ln", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - return std::log(Token::literalToFloatingPoint(params[0])); - }); - - - /* fmod(x, y) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "fmod", FunctionParameterCount::exactly(2), [](Evaluator *, auto params) -> std::optional { - return std::fmod(Token::literalToFloatingPoint(params[0]), Token::literalToFloatingPoint(params[1])); - }); - - /* pow(base, exp) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "pow", FunctionParameterCount::exactly(2), [](Evaluator *, auto params) -> std::optional { - return std::pow(Token::literalToFloatingPoint(params[0]), Token::literalToFloatingPoint(params[1])); - }); - - /* sqrt(value) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "sqrt", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - return std::sqrt(Token::literalToFloatingPoint(params[0])); - }); - - /* cbrt(value) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "cbrt", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - return std::cbrt(Token::literalToFloatingPoint(params[0])); - }); - - - /* sin(value) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "sin", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - return std::sin(Token::literalToFloatingPoint(params[0])); - }); - - /* cos(value) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "cos", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - return std::cos(Token::literalToFloatingPoint(params[0])); - }); - - /* tan(value) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "tan", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - return std::tan(Token::literalToFloatingPoint(params[0])); - }); - - /* asin(value) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "asin", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - return std::asin(Token::literalToFloatingPoint(params[0])); - }); - - /* acos(value) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "acos", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - return std::acos(Token::literalToFloatingPoint(params[0])); - }); - - /* atan(value) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "atan", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - return std::atan(Token::literalToFloatingPoint(params[0])); - }); - - /* atan2(y, x) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "atan", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - return std::atan2(Token::literalToFloatingPoint(params[0]), Token::literalToFloatingPoint(params[1])); - }); - - - /* sinh(value) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "sinh", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - return std::sinh(Token::literalToFloatingPoint(params[0])); - }); - - /* cosh(value) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "cosh", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - return std::cosh(Token::literalToFloatingPoint(params[0])); - }); - - /* tanh(value) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "tanh", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - return std::tanh(Token::literalToFloatingPoint(params[0])); - }); - - /* asinh(value) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "asinh", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - return std::asinh(Token::literalToFloatingPoint(params[0])); - }); - - /* acosh(value) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "acosh", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - return std::acosh(Token::literalToFloatingPoint(params[0])); - }); - - /* atanh(value) */ - ContentRegistry::PatternLanguage::addFunction(nsStdMath, "atanh", FunctionParameterCount::exactly(1), [](Evaluator *, auto params) -> std::optional { - return std::atanh(Token::literalToFloatingPoint(params[0])); - }); - } } }