diff --git a/src/blaze/ast.h b/src/blaze/ast.h index e462640..633d1b5 100644 --- a/src/blaze/ast.h +++ b/src/blaze/ast.h @@ -11,16 +11,18 @@ #include // std::function #include #include -#include // std::shared_ptr +#include // std::make_shared, std::shared_ptr #include #include #include #include // typeid +#include // std::forward #include #include "ruc/format/formatter.h" #include "blaze/forward.h" +#include "blaze/to-from-hashmap.h" namespace blaze { @@ -77,14 +79,13 @@ protected: #define WITH_META(Type) \ virtual ValuePtr withMetaImpl(ValuePtr meta) const override \ { \ - return makePtr(*this, meta); \ + return std::make_shared(*this, meta); \ } -#define WITH_NO_META() \ - virtual ValuePtr withMetaImpl(ValuePtr meta) const override \ - { \ - (void)meta; \ - return nullptr; \ +#define WITH_NO_META() \ + virtual ValuePtr withMetaImpl(ValuePtr) const override \ + { \ + return nullptr; \ } // ----------------------------------------- @@ -195,6 +196,20 @@ public: HashMap(const HashMap& that, ValuePtr meta); virtual ~HashMap() = default; + static HashMapPtr create(const Elements& elements) + { + return std::make_shared(elements); + } + + // Customization Point + template + static HashMapPtr create(T value) + { + HashMapPtr hash_map; + to_hash_map(hash_map, std::forward(value)); + return hash_map; + } + static std::string getKeyString(ValuePtr key); bool exists(const std::string& key); @@ -222,6 +237,11 @@ public: String(char character); virtual ~String() = default; + static ValuePtr create(const std::string& data) + { + return std::make_shared(data); + } + const std::string& data() const { return m_data; } size_t size() const { return m_data.size(); } bool empty() const { return m_data.empty(); } @@ -287,6 +307,11 @@ public: Decimal(double decimal); virtual ~Decimal() = default; + static ValuePtr create(float value) + { + return std::make_shared(value); + } + double decimal() const { return m_decimal; } WITH_NO_META(); diff --git a/src/blaze/env/macro.h b/src/blaze/env/macro.h index e5dcbc4..e6a7542 100644 --- a/src/blaze/env/macro.h +++ b/src/blaze/env/macro.h @@ -6,15 +6,17 @@ #pragma once +#include // std::distance #include #include "blaze/env/environment.h" +#include "blaze/forward.h" #define ADD_FUNCTION(name, signature, documentation, lambda) \ - Environment::registerFunction( \ + blaze::Environment::registerFunction( \ { name, \ signature, \ documentation, \ - [](ValueVectorConstIt begin, ValueVectorConstIt end) -> blaze::ValuePtr lambda }); + [](blaze::ValueVectorConstIt begin, blaze::ValueVectorConstIt end) -> blaze::ValuePtr lambda }); #define SIZE() std::distance(begin, end) diff --git a/src/blaze/forward.h b/src/blaze/forward.h index cfc701e..d043d0c 100644 --- a/src/blaze/forward.h +++ b/src/blaze/forward.h @@ -15,7 +15,9 @@ namespace blaze { // Types class Value; +class HashMap; typedef std::shared_ptr ValuePtr; +typedef std::shared_ptr HashMapPtr; typedef std::vector ValueVector; typedef ValueVector::iterator ValueVectorIt; typedef ValueVector::reverse_iterator ValueVectorReverseIt; diff --git a/src/blaze/to-from-hashmap.h b/src/blaze/to-from-hashmap.h new file mode 100644 index 0000000..755fa24 --- /dev/null +++ b/src/blaze/to-from-hashmap.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2023 Riyyi + * + * SPDX-License-Identifier: MIT + */ + +#pragma once + +#include // std::forward + +#include "ruc/meta/odr.h" + +namespace blaze { + +namespace detail { + +// struct hashMapConstructor { +// template +// static void construct(HashMap& hash_map, bool boolean) +// { +// //.. +// } +// }; + +// template +// void toHashMap(HashMap& hash_map, const T& value) +// { +// hashMapConstructor::construct(hash_map, value); +// } + +struct toHashMapFunction { + template + auto operator()(HashMapPtr& hash_map, T&& value) const + { + return to_hash_map(hash_map, std::forward(value)); + } +}; + +} // namespace detail + +// Anonymous namespace prevents multiple definition of the reference +namespace { +// Function object +constexpr const auto& to_hash_map = ruc::detail::staticConst; // NOLINT(misc-definitions-in-headers,clang-diagnostic-unused-variable) +} // namespace + +} // namespace blaze + +// Customization Points +// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html + +// blaze::to_hash_map is a function object, the type of which is +// blaze::detail::toHashMapFunction. In the blaze::detail namespace are the to_hash_map +// free functions. The function call operator of toHashMapFunction makes an +// unqualified call to to_hash_map which, since it shares the detail namespace with +// the to_hash_map free functions, will consider those in addition to any overloads +// that are found by argument-dependent lookup. + +// Variable templates are linked externally, therefor every translation unit +// will see the same address for detail::staticConst. +// Since blaze::to_hash_map is a reference to the variable template, it too will have +// the same address in all translation units. diff --git a/src/blaze/util.h b/src/blaze/util.h index a63584a..7236f4c 100644 --- a/src/blaze/util.h +++ b/src/blaze/util.h @@ -34,10 +34,10 @@ // ----------------------------------------- -#define CHECK_ARG_COUNT_IS_IMPL(name, size, expected, result) \ - if (size != expected) { \ - Error::the().add(::format("wrong number of arguments: {}, {}", name, size)); \ - return result; \ +#define CHECK_ARG_COUNT_IS_IMPL(name, size, expected, result) \ + if (size != expected) { \ + blaze::Error::the().add(::format("wrong number of arguments: {}, {}", name, size)); \ + return result; \ } #define CHECK_ARG_COUNT_IS_3(name, size, expected) \ @@ -52,10 +52,10 @@ // ----------------------------------------- -#define CHECK_ARG_COUNT_AT_LEAST_IMPL(name, size, min, result) \ - if (size < min) { \ - Error::the().add(::format("wrong number of arguments: {}, {}", name, size)); \ - return result; \ +#define CHECK_ARG_COUNT_AT_LEAST_IMPL(name, size, min, result) \ + if (size < min) { \ + blaze::Error::the().add(::format("wrong number of arguments: {}, {}", name, size)); \ + return result; \ } #define CHECK_ARG_COUNT_AT_LEAST_3(name, size, min) \ @@ -70,10 +70,10 @@ // ----------------------------------------- -#define CHECK_ARG_COUNT_BETWEEN_IMPL(name, size, min, max, result) \ - if (size < min || size > max) { \ - Error::the().add(::format("wrong number of arguments: {}, {}", name, size)); \ - return result; \ +#define CHECK_ARG_COUNT_BETWEEN_IMPL(name, size, min, max, result) \ + if (size < min || size > max) { \ + blaze::Error::the().add(::format("wrong number of arguments: {}, {}", name, size)); \ + return result; \ } #define CHECK_ARG_COUNT_BETWEEN_4(name, size, min, max) \ @@ -88,10 +88,10 @@ // ----------------------------------------- -#define CHECK_ARG_COUNT_EVEN_IMPL(name, size, result) \ - if (size % 2 != 0) { \ - Error::the().add(::format("wrong number of arguments: {}, {}", name, size)); \ - return result; \ +#define CHECK_ARG_COUNT_EVEN_IMPL(name, size, result) \ + if (size % 2 != 0) { \ + blaze::Error::the().add(::format("wrong number of arguments: {}, {}", name, size)); \ + return result; \ } #define CHECK_ARG_COUNT_EVEN_2(name, size) \ @@ -106,10 +106,10 @@ // ----------------------------------------- -#define IS_VALUE_IMPL(type, value, result) \ - if (!is(value.get())) { \ - Error::the().add(::format("wrong argument type: {}, {}", #type, value)); \ - return result; \ +#define IS_VALUE_IMPL(type, value, result) \ + if (!is(value.get())) { \ + blaze::Error::the().add(::format("wrong argument type: {}, {}", #type, value)); \ + return result; \ } #define IS_VALUE_2(type, value) \