From 2340bdb85101415d4e41648211189841c727e6f0 Mon Sep 17 00:00:00 2001 From: Arash Partow Date: Thu, 14 Nov 2024 00:00:00 +0000 Subject: [PATCH] Update ExprTk Signed-off-by: Arash Partow --- cmake/exprtk.txt.in | 2 +- cpp/perspective/src/cpp/scalar.cpp | 29 +++ cpp/perspective/src/cpp/table.cpp | 3 + .../include/perspective/computed_function.h | 36 +-- .../src/include/perspective/exprtk.h | 229 ++++++++++-------- .../src/include/perspective/scalar.h | 2 + .../test/js/expressions/functionality.spec.js | 3 +- 7 files changed, 185 insertions(+), 119 deletions(-) diff --git a/cmake/exprtk.txt.in b/cmake/exprtk.txt.in index 78f31a5484..d1a3942f5e 100644 --- a/cmake/exprtk.txt.in +++ b/cmake/exprtk.txt.in @@ -5,7 +5,7 @@ project(exprtk-download NONE) include(ExternalProject) ExternalProject_Add(exprtk GIT_REPOSITORY https://github.com/ArashPartow/exprtk.git - GIT_TAG 0.0.2 + GIT_TAG 0.0.3 SOURCE_DIR "${CMAKE_BINARY_DIR}/exprtk-src" BINARY_DIR "${CMAKE_BINARY_DIR}/exprtk-build" CONFIGURE_COMMAND "" diff --git a/cpp/perspective/src/cpp/scalar.cpp b/cpp/perspective/src/cpp/scalar.cpp index dd3f6c07f9..d2a6ebe361 100644 --- a/cpp/perspective/src/cpp/scalar.cpp +++ b/cpp/perspective/src/cpp/scalar.cpp @@ -409,6 +409,35 @@ t_tscalar::operator%=(const t_tscalar& rhs) { return *this; } +t_tscalar::operator std::size_t () const { + switch (get_dtype()) { + case perspective::t_dtype::DTYPE_INT64: + return static_cast(get()); + case perspective::t_dtype::DTYPE_INT32: + return static_cast(get()); + case perspective::t_dtype::DTYPE_INT16: + return static_cast(get()); + case perspective::t_dtype::DTYPE_INT8: + return static_cast(get()); + case perspective::t_dtype::DTYPE_UINT64: + return static_cast(get()); + case perspective::t_dtype::DTYPE_UINT32: + return static_cast(get()); + case perspective::t_dtype::DTYPE_UINT16: + return static_cast(get()); + case perspective::t_dtype::DTYPE_UINT8: + return static_cast(get()); + case perspective::t_dtype::DTYPE_FLOAT64: + return static_cast(get()); + case perspective::t_dtype::DTYPE_FLOAT32: + return static_cast(get()); + default: + return std::numeric_limits::max(); + } + + return std::numeric_limits::max(); +} + t_tscalar t_tscalar::add_typesafe(const t_tscalar& rhs) const { t_tscalar rval; diff --git a/cpp/perspective/src/cpp/table.cpp b/cpp/perspective/src/cpp/table.cpp index 7ffc032544..5c2045df07 100644 --- a/cpp/perspective/src/cpp/table.cpp +++ b/cpp/perspective/src/cpp/table.cpp @@ -483,6 +483,9 @@ rapidjson_type_to_dtype(const rapidjson::Value& value) { case rapidjson::kArrayType: PSP_COMPLAIN_AND_ABORT("Unknown JSON type"); return t_dtype::DTYPE_NONE; + default: + PSP_COMPLAIN_AND_ABORT("Unknown JSON type"); + return t_dtype::DTYPE_NONE; } } diff --git a/cpp/perspective/src/include/perspective/computed_function.h b/cpp/perspective/src/include/perspective/computed_function.h index 552234fa18..c92f14affa 100644 --- a/cpp/perspective/src/include/perspective/computed_function.h +++ b/cpp/perspective/src/include/perspective/computed_function.h @@ -42,23 +42,23 @@ namespace computed_function { // A regex function that caches its parsed regex objects. #define REGEX_FUNCTION_HEADER(NAME) \ - struct NAME : public exprtk::igeneric_function { \ + struct NAME final : public exprtk::igeneric_function { \ NAME(t_regex_mapping& regex_mapping); \ ~NAME(); \ - t_tscalar operator()(t_parameter_list parameters); \ + t_tscalar operator()(t_parameter_list parameters) override; \ t_regex_mapping& m_regex_mapping; \ }; // A regex function that returns a string stored in the expression vocab. #define REGEX_STRING_FUNCTION_HEADER(NAME) \ - struct NAME : public exprtk::igeneric_function { \ + struct NAME final : public exprtk::igeneric_function { \ NAME( \ t_expression_vocab& expression_vocab, \ t_regex_mapping& regex_mapping, \ bool is_type_validator \ ); \ ~NAME(); \ - t_tscalar operator()(t_parameter_list parameters); \ + t_tscalar operator()(t_parameter_list parameters) override; \ t_expression_vocab& m_expression_vocab; \ t_regex_mapping& m_regex_mapping; \ bool m_is_type_validator; \ @@ -74,10 +74,10 @@ namespace computed_function { // get_dtype, and because the gnode is guaranteed to be valid for all of // those invocations, we can store a reference to the vocab. #define STRING_FUNCTION_HEADER(NAME) \ - struct NAME : public exprtk::igeneric_function { \ + struct NAME final : public exprtk::igeneric_function { \ NAME(t_expression_vocab& expression_vocab, bool is_type_validator); \ ~NAME(); \ - t_tscalar operator()(t_parameter_list parameters); \ + t_tscalar operator()(t_parameter_list parameters) override; \ t_expression_vocab& m_expression_vocab; \ t_tscalar m_sentinel; \ bool m_is_type_validator; \ @@ -111,11 +111,11 @@ namespace computed_function { * Strings in the column not provided to `order()` will by default appear at * the end. */ - struct order : public exprtk::igeneric_function { + struct order final : public exprtk::igeneric_function { order(bool is_type_validator); ~order(); - t_tscalar operator()(t_parameter_list parameters); + t_tscalar operator()(t_parameter_list parameters) override; void clear_order_map(); tsl::hopscotch_map m_order_map; @@ -179,23 +179,23 @@ namespace computed_function { REGEX_STRING_FUNCTION_HEADER(replace_all) #define FUNCTION_HEADER(NAME) \ - struct NAME : public exprtk::igeneric_function { \ + struct NAME final : public exprtk::igeneric_function { \ NAME(); \ ~NAME(); \ - t_tscalar operator()(t_parameter_list parameters); \ + t_tscalar operator()(t_parameter_list parameters) override; \ }; // Length of the string FUNCTION_HEADER(length) - struct index : public exprtk::igeneric_function { + struct index final : public exprtk::igeneric_function { index( const t_pkey_mapping& pkey_map, std::shared_ptr source_table, t_uindex& row_idx ); ~index(); - t_tscalar operator()(t_parameter_list parameters); + t_tscalar operator()(t_parameter_list parameters) override; private: const t_pkey_mapping& m_pkey_map; @@ -203,13 +203,13 @@ namespace computed_function { t_uindex& m_row_idx; }; - struct col : public exprtk::igeneric_function { + struct col final : public exprtk::igeneric_function { col(t_expression_vocab& expression_vocab, bool is_type_validator, std::shared_ptr source_table, t_uindex& row_idx); ~col(); - t_tscalar operator()(t_parameter_list parameters); + t_tscalar operator()(t_parameter_list parameters) override; private: t_expression_vocab& m_expression_vocab; @@ -218,7 +218,7 @@ namespace computed_function { t_uindex& m_row_idx; }; - struct vlookup : public exprtk::igeneric_function { + struct vlookup final : public exprtk::igeneric_function { vlookup( t_expression_vocab& expression_vocab, bool is_type_validator, @@ -226,7 +226,7 @@ namespace computed_function { t_uindex& row_idx ); ~vlookup(); - t_tscalar operator()(t_parameter_list parameters); + t_tscalar operator()(t_parameter_list parameters) override; private: t_expression_vocab& m_expression_vocab; @@ -272,11 +272,11 @@ namespace computed_function { * * Any other inputs are invalid. */ - struct bucket : public exprtk::igeneric_function { + struct bucket final : public exprtk::igeneric_function { bucket(); ~bucket(); - t_tscalar operator()(t_parameter_list parameters); + t_tscalar operator()(t_parameter_list parameters) final; // faster unit lookups, since we are calling this lookup in a tight // loop. diff --git a/cpp/perspective/src/include/perspective/exprtk.h b/cpp/perspective/src/include/perspective/exprtk.h index 2889e4ab49..b2c82d592f 100644 --- a/cpp/perspective/src/include/perspective/exprtk.h +++ b/cpp/perspective/src/include/perspective/exprtk.h @@ -36,55 +36,60 @@ namespace details { inline T const_e_impl(t_tscalar_type_tag); template - inline int to_int32_impl(const T& v, t_tscalar_type_tag); + inline std::int32_t to_int32_impl(const T& v, t_tscalar_type_tag); template - inline long long int to_int64_impl(const T& v, t_tscalar_type_tag); + inline std::int64_t to_int64_impl(const T& v, t_tscalar_type_tag); + + template + inline std::uint64_t to_uint64_impl(const T& v, t_tscalar_type_tag); + #define define_unary_function_impl_header(FunctionName) \ template \ inline T FunctionName##_impl(const T v, t_tscalar_type_tag); - - define_unary_function_impl_header(abs - ) define_unary_function_impl_header(acos - ) define_unary_function_impl_header(acosh - ) define_unary_function_impl_header(asin - ) define_unary_function_impl_header(asinh - ) define_unary_function_impl_header(atan - ) define_unary_function_impl_header(atanh - ) define_unary_function_impl_header(ceil - ) define_unary_function_impl_header(cos - ) define_unary_function_impl_header(cosh - ) define_unary_function_impl_header(exp - ) define_unary_function_impl_header(expm1 - ) define_unary_function_impl_header(floor - ) define_unary_function_impl_header(log - ) define_unary_function_impl_header(log10 - ) define_unary_function_impl_header(log2 - ) define_unary_function_impl_header(log1p - ) define_unary_function_impl_header(neg - ) define_unary_function_impl_header(pos - ) define_unary_function_impl_header(round - ) define_unary_function_impl_header(sin - ) define_unary_function_impl_header(sinc - ) define_unary_function_impl_header(sinh - ) define_unary_function_impl_header(sqrt - ) define_unary_function_impl_header(tan - ) define_unary_function_impl_header(tanh - ) define_unary_function_impl_header(cot - ) define_unary_function_impl_header(sec - ) define_unary_function_impl_header(csc - ) define_unary_function_impl_header(r2d - ) define_unary_function_impl_header(d2r - ) define_unary_function_impl_header(d2g - ) define_unary_function_impl_header(g2d) - define_unary_function_impl_header(notl) - define_unary_function_impl_header(sgn) - define_unary_function_impl_header(erf) - define_unary_function_impl_header(erfc) - define_unary_function_impl_header(ncdf) - define_unary_function_impl_header(frac) - define_unary_function_impl_header(trunc) + // clang-format off + define_unary_function_impl_header(abs ) + define_unary_function_impl_header(acos ) + define_unary_function_impl_header(acosh) + define_unary_function_impl_header(asin ) + define_unary_function_impl_header(asinh) + define_unary_function_impl_header(atan ) + define_unary_function_impl_header(atanh) + define_unary_function_impl_header(ceil ) + define_unary_function_impl_header(cos ) + define_unary_function_impl_header(cosh ) + define_unary_function_impl_header(exp ) + define_unary_function_impl_header(expm1) + define_unary_function_impl_header(floor) + define_unary_function_impl_header(log ) + define_unary_function_impl_header(log10) + define_unary_function_impl_header(log2 ) + define_unary_function_impl_header(log1p) + define_unary_function_impl_header(neg ) + define_unary_function_impl_header(pos ) + define_unary_function_impl_header(round) + define_unary_function_impl_header(sin ) + define_unary_function_impl_header(sinc ) + define_unary_function_impl_header(sinh ) + define_unary_function_impl_header(sqrt ) + define_unary_function_impl_header(tan ) + define_unary_function_impl_header(tanh ) + define_unary_function_impl_header(cot ) + define_unary_function_impl_header(sec ) + define_unary_function_impl_header(csc ) + define_unary_function_impl_header(r2d ) + define_unary_function_impl_header(d2r ) + define_unary_function_impl_header(d2g ) + define_unary_function_impl_header(g2d ) + define_unary_function_impl_header(notl ) + define_unary_function_impl_header(sgn ) + define_unary_function_impl_header(erf ) + define_unary_function_impl_header(erfc ) + define_unary_function_impl_header(ncdf ) + define_unary_function_impl_header(frac ) + define_unary_function_impl_header(trunc) + // clang-format on #undef define_unary_function_impl_header @@ -93,28 +98,29 @@ namespace details { inline T FunctionName##_impl(const T v0, const T v1, t_tscalar_type_tag); // except reserved words: and, or, xor - define_binary_function_impl_header(min - ) define_binary_function_impl_header(max - ) define_binary_function_impl_header(equal - ) define_binary_function_impl_header(nequal - ) define_binary_function_impl_header(modulus - ) define_binary_function_impl_header(pow - ) define_binary_function_impl_header(logn - ) define_binary_function_impl_header(root - ) define_binary_function_impl_header(roundn - ) define_binary_function_impl_header(hypot) - define_binary_function_impl_header(atan2) - define_binary_function_impl_header(shr) - define_binary_function_impl_header(shl) - define_binary_function_impl_header(nand) - define_binary_function_impl_header(nor) - define_binary_function_impl_header(xnor) + // clang-format off + define_binary_function_impl_header(min ) + define_binary_function_impl_header(max ) + define_binary_function_impl_header(equal ) + define_binary_function_impl_header(nequal ) + define_binary_function_impl_header(modulus) + define_binary_function_impl_header(pow ) + define_binary_function_impl_header(logn ) + define_binary_function_impl_header(root ) + define_binary_function_impl_header(roundn ) + define_binary_function_impl_header(hypot ) + define_binary_function_impl_header(atan2 ) + define_binary_function_impl_header(shr ) + define_binary_function_impl_header(shl ) + define_binary_function_impl_header(nand ) + define_binary_function_impl_header(nor ) + define_binary_function_impl_header(xnor ) + // clang-format on #undef define_binary_function_impl_header - template - inline T - and_impl(const T v0, const T v1, t_tscalar_type_tag); + template + inline T and_impl(const T v0, const T v1, t_tscalar_type_tag); template inline T or_impl(const T v0, const T v1, t_tscalar_type_tag); @@ -128,7 +134,7 @@ namespace details { // #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || // !defined(_MSC_VER) // #define exprtk_define_erf(TT,impl) \ -// inline TT erf_impl(TT v) { return impl(v); } \ + // inline TT erf_impl(TT v) { return impl(v); } \ // exprtk_define_erf( float,::erff) // exprtk_define_erf( double,::erf ) @@ -139,7 +145,7 @@ namespace details { // #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || // !defined(_MSC_VER) // #define exprtk_define_erfc(TT,impl) \ -// inline TT erfc_impl(TT v) { return impl(v); } \ + // inline TT erfc_impl(TT v) { return impl(v); } \ // exprtk_define_erfc( float,::erfcf) // exprtk_define_erfc( double,::erfc ) @@ -260,73 +266,98 @@ namespace details { } template <> - inline int + inline std::int32_t to_int32_impl(const t_tscalar& v, t_tscalar_type_tag) { if (!v.is_valid()) { - return std::numeric_limits::quiet_NaN(); + return std::numeric_limits::quiet_NaN(); } switch (v.get_dtype()) { case perspective::t_dtype::DTYPE_INT64: - return static_cast(v.get()); + return static_cast(v.get()); case perspective::t_dtype::DTYPE_INT32: - return static_cast(v.get()); + return static_cast(v.get()); case perspective::t_dtype::DTYPE_INT16: - return static_cast(v.get()); + return static_cast(v.get()); case perspective::t_dtype::DTYPE_INT8: - return static_cast(v.get()); + return static_cast(v.get()); case perspective::t_dtype::DTYPE_UINT64: - return static_cast(v.get()); + return static_cast(v.get()); case perspective::t_dtype::DTYPE_UINT32: - return static_cast(v.get()); + return static_cast(v.get()); case perspective::t_dtype::DTYPE_UINT16: - return static_cast(v.get()); + return static_cast(v.get()); case perspective::t_dtype::DTYPE_UINT8: - return static_cast(v.get()); + return static_cast(v.get()); case perspective::t_dtype::DTYPE_FLOAT64: - return static_cast(v.get()); + return static_cast(v.get()); case perspective::t_dtype::DTYPE_FLOAT32: - return static_cast(v.get()); + return static_cast(v.get()); default: - return std::numeric_limits::quiet_NaN(); + return std::numeric_limits::quiet_NaN(); } } template <> - inline long long int + inline std::int64_t to_int64_impl(const t_tscalar& v, t_tscalar_type_tag) { if (!v.is_valid()) { - return std::numeric_limits::quiet_NaN(); + return std::numeric_limits::quiet_NaN(); } switch (v.get_dtype()) { case perspective::t_dtype::DTYPE_INT64: - return static_cast(v.get() - ); + return static_cast(v.get()); case perspective::t_dtype::DTYPE_INT32: - return static_cast(v.get() - ); + return static_cast(v.get()); case perspective::t_dtype::DTYPE_INT16: - return static_cast(v.get() - ); + return static_cast(v.get()); case perspective::t_dtype::DTYPE_INT8: - return static_cast(v.get()); + return static_cast(v.get()); case perspective::t_dtype::DTYPE_UINT64: - return static_cast(v.get() - ); + return static_cast(v.get()); case perspective::t_dtype::DTYPE_UINT32: - return static_cast(v.get() - ); + return static_cast(v.get()); case perspective::t_dtype::DTYPE_UINT16: - return static_cast(v.get() - ); + return static_cast(v.get()); case perspective::t_dtype::DTYPE_UINT8: - return static_cast(v.get() - ); + return static_cast(v.get()); + case perspective::t_dtype::DTYPE_FLOAT64: + return static_cast(v.get()); + case perspective::t_dtype::DTYPE_FLOAT32: + return static_cast(v.get()); + default: + return std::numeric_limits::quiet_NaN(); + } + } + + template <> + inline std::uint64_t + to_uint64_impl(const t_tscalar& v, t_tscalar_type_tag) { + if (!v.is_valid()) { + return std::numeric_limits::quiet_NaN(); + } + switch (v.get_dtype()) { + case perspective::t_dtype::DTYPE_INT64: + return static_cast(v.get()); + case perspective::t_dtype::DTYPE_INT32: + return static_cast(v.get()); + case perspective::t_dtype::DTYPE_INT16: + return static_cast(v.get()); + case perspective::t_dtype::DTYPE_INT8: + return static_cast(v.get()); + case perspective::t_dtype::DTYPE_UINT64: + return static_cast(v.get()); + case perspective::t_dtype::DTYPE_UINT32: + return static_cast(v.get()); + case perspective::t_dtype::DTYPE_UINT16: + return static_cast(v.get()); + case perspective::t_dtype::DTYPE_UINT8: + return static_cast(v.get()); case perspective::t_dtype::DTYPE_FLOAT64: - return static_cast(v.get()); + return static_cast(v.get()); case perspective::t_dtype::DTYPE_FLOAT32: - return static_cast(v.get()); + return static_cast(v.get()); default: - return std::numeric_limits::quiet_NaN(); + return std::numeric_limits::quiet_NaN(); } } @@ -702,7 +733,7 @@ namespace details { } // degrees to gradians - rval.set(v.to_double() * (20.0 / 9.0)); + rval.set(v.to_double() * (10.0 / 9.0)); return rval; } @@ -722,7 +753,7 @@ namespace details { } // gradians to degrees - rval.set(v.to_double() * (9.0 / 20.0)); + rval.set(v.to_double() * (9.0 / 10.0)); return rval; } template <> diff --git a/cpp/perspective/src/include/perspective/scalar.h b/cpp/perspective/src/include/perspective/scalar.h index 28149388b9..28c3ab98ac 100644 --- a/cpp/perspective/src/include/perspective/scalar.h +++ b/cpp/perspective/src/include/perspective/scalar.h @@ -146,6 +146,8 @@ struct PERSPECTIVE_EXPORT t_tscalar { t_tscalar& operator/=(const t_tscalar& rhs); t_tscalar& operator%=(const t_tscalar& rhs); + operator std::size_t () const; + t_tscalar add_typesafe(const t_tscalar& rhs) const; t_tscalar sub_typesafe(const t_tscalar& rhs) const; diff --git a/rust/perspective-js/test/js/expressions/functionality.spec.js b/rust/perspective-js/test/js/expressions/functionality.spec.js index b4fbe2e1fd..8f6e8c0dd2 100644 --- a/rust/perspective-js/test/js/expressions/functionality.spec.js +++ b/rust/perspective-js/test/js/expressions/functionality.spec.js @@ -512,7 +512,8 @@ import perspective from "../perspective_client"; expect(schema.errors["expr"]).toEqual({ column: 62, line: 0, - error_message: "Invalid expression encountered", + error_message: + "Invalid syntax 'x' possible missing operator or context", }); await table.delete();