Skip to content

Commit

Permalink
test: clang::mrdox::dom unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
alandefreitas committed Oct 18, 2023
1 parent 831a691 commit cc9e397
Show file tree
Hide file tree
Showing 20 changed files with 3,583 additions and 1,379 deletions.
29 changes: 21 additions & 8 deletions include/mrdox/Dom/Array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,15 @@ namespace dom {
class ArrayImpl;
class Value;

/** An array of values.
/** An array of values
Arrays are a collection of indexed values. They
are an extension of objects with a particular
relationship between integer-keyed properties
and some abstract length-property. Besides,
they include convenient methods to manipulate
these ordered sequences of values.
*/
class MRDOX_DECL
Array final
Expand All @@ -40,13 +48,13 @@ class MRDOX_DECL
This is a read-only reference to an element.
*/
using reference = value_type const&;
using reference = value_type;

/** A reference to an element.
This is a read-only reference to an element.
*/
using const_reference = value_type const&;
using const_reference = value_type;

/** A pointer to an element.
*/
Expand Down Expand Up @@ -182,10 +190,6 @@ class MRDOX_DECL
*/
void set(size_type i, Value v);

/** Return the i-th element, without bounds checking.
*/
value_type operator[](size_type i) const;

/** Return the i-th element.
@throw Exception `i >= size()`
Expand Down Expand Up @@ -217,7 +221,15 @@ class MRDOX_DECL
If the array is read-only, an exception
is thrown.
*/
void emplace_back(value_type value);
void push_back(value_type value);

/** Append an element to the end of the array.
If the array is read-only, an exception
is thrown.
*/
template< class... Args >
void emplace_back(Args&&... args);

/** Concatenate two arrays.
*/
Expand Down Expand Up @@ -356,6 +368,7 @@ class MRDOX_DECL
value_type get(size_type i) const override;
void set(size_type i, Value v) override;
void emplace_back(value_type value) override;
char const* type_key() const noexcept override;

private:
std::vector<value_type> elements_;
Expand Down
13 changes: 7 additions & 6 deletions include/mrdox/Dom/Array.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -175,11 +175,6 @@ inline void Array::set(std::size_t i, Value v)
impl_->set(i, std::move(v));
}

inline auto Array::operator[](std::size_t i) const -> value_type
{
return get(i);
}

inline auto Array::at(std::size_t i) const -> value_type
{
if(i < size())
Expand Down Expand Up @@ -207,11 +202,17 @@ inline auto Array::end() const -> iterator
return {*impl_, impl_->size()};
}

inline void Array::emplace_back(value_type value)
inline void Array::push_back(value_type value)
{
impl_->emplace_back(std::move(value));
}

template< class... Args >
void Array::emplace_back(Args&&... args)
{
impl_->emplace_back(value_type(std::forward<Args>(args)...));
}

inline
Array operator+(Array const& lhs, Array const& rhs)
{
Expand Down
19 changes: 15 additions & 4 deletions include/mrdox/Dom/Function.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,21 @@ concept has_function_traits = requires {
};

template<typename F>
concept has_invoke_result_for_default_function_impl =
// Return type is void or convertible to dom::Value
concept has_invoke_result_convertible_to_dom_value =
std::convertible_to<typename function_traits<F>::return_type, Value> ||
std::same_as<typename function_traits<F>::return_type, void>;

template<typename F>
concept has_invoke_expected_result_convertible_to_dom_value =
detail::isExpected<typename function_traits<F>::return_type> &&
(std::convertible_to<typename function_traits<F>::return_type::value_type, Value> ||
std::same_as<typename function_traits<F>::return_type::value_type, void>);

template<typename F>
concept has_invoke_result_for_default_function_impl =
has_invoke_result_convertible_to_dom_value<F> ||
has_invoke_expected_result_convertible_to_dom_value<F>;

template<typename F>
concept has_function_args_for_default_function_impl =
// All arguments are convertible to dom::Value
Expand All @@ -115,7 +125,8 @@ concept has_function_traits_for_default_function_impl =

template<class F>
concept function_traits_convertible_to_value =
has_function_traits<F> && has_function_traits_for_default_function_impl<F>;
has_function_traits<F> &&
has_function_traits_for_default_function_impl<F>;

//------------------------------------------------
//
Expand Down Expand Up @@ -306,7 +317,7 @@ class DefaultFunctionImpl : public FunctionImpl

char const* type_key() const noexcept override
{
return "DefaultFunctionImpl";
return "Function";
}

Expected<Value>
Expand Down
23 changes: 14 additions & 9 deletions include/mrdox/Dom/Function.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@ Value
Function::
operator()(Args&&... args) const
{
return try_invoke(std::forward<Args>(args)...).value();
auto exp = try_invoke(std::forward<Args>(args)...);
if (exp)
{
return *exp;
}
throw Exception(std::move(exp.error()));
}

template<class... Args>
Expand Down Expand Up @@ -161,27 +166,27 @@ call_impl(
using R = decltype(
f_(arg_type<std::decay_t<
std::tuple_element_t<I, args_type> >
>::get(args[I])...));
>::get(args.get(I))...));
if (args.size() < sizeof...(I))
{
Array clone;
for (std::size_t i = 0; i < args.size(); ++i)
clone.emplace_back(args[i]);
clone.emplace_back(args.get(i));
std::size_t const diff = sizeof...(I) - args.size();
for (std::size_t i = 0; i < diff; ++i)
clone.emplace_back(Value(Kind::Undefined));
if constexpr (std::is_void_v<R>)
{
f_(arg_type<std::decay_t<
std::tuple_element_t<I, args_type> >
>::get(clone[I])...);
>::get(clone.get(I))...);
return Value(Kind::Undefined);
}
else if constexpr (std::same_as<R, Expected<void>>)
{
auto exp = f_(arg_type<std::decay_t<
std::tuple_element_t<I, args_type> >
>::get(clone[I])...);
>::get(clone.get(I))...);
if (!exp)
{
return Unexpected(exp.error());
Expand All @@ -192,21 +197,21 @@ call_impl(
{
return f_(arg_type<std::decay_t<
std::tuple_element_t<I, args_type> >
>::get(clone[I])...);
>::get(clone.get(I))...);
}
}
if constexpr (std::is_void_v<R>)
{
f_(arg_type<std::decay_t<
std::tuple_element_t<I, args_type> >
>::get(args[I])...);
>::get(args.get(I))...);
return Value(Kind::Undefined);
}
else if constexpr (std::same_as<R, Expected<void>>)
{
auto exp = f_(arg_type<std::decay_t<
std::tuple_element_t<I, args_type> >
>::get(args[I])...);
>::get(args.get(I))...);
if (!exp)
{
return Unexpected(exp.error());
Expand All @@ -217,7 +222,7 @@ call_impl(
{
return f_(arg_type<std::decay_t<
std::tuple_element_t<I, args_type> >
>::get(args[I])...);
>::get(args.get(I))...);
}
}

Expand Down
48 changes: 48 additions & 0 deletions include/mrdox/Dom/Kind.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,54 @@ namespace mrdox {
namespace dom {

/** The type of data in a Value.
This is the type of data stored in a Value.
These types are loosely modeled after the
JavaScript types and data structures.
Primitive values are Undefined, Null, Boolean,
Integer, and String.
Undefined and Null are inhabited by a single
value each. The difference between Undefined
and Null is that Undefined is the default
value for a Value, while Null represents a
value that is explicitly set. Undefined is
used to represent things such as:
@li An uninitialized Value
@li The Value returned from a function that failed to return a value
@li The result of accessing a nonexistent object property
@li The result of a `find` algorithm when no element is found
This distinction is semantically important as
algorithms frequently need to distinguish between
these two cases.
Booleans, Integers, and Strings are also primitive
values. This means they are deeply copied when assigned or
passed as a parameter.
Other value types, such as Array, Object, and Function
are reference types, meaning that they are not copied
when assigned or passed as a parameter. Instead, the
reference is copied, and the original value is shared.
These reference types are modeled after JavaScript
"Objects". All non-primitive types (Object types)
are derived from Object in Javascript. This means
types such as Array and Function represent a
relevant selection of built-in types that would
derive from Object in JavaScript.
Objects are a collection of properties, which are
equivalent to key-value pairs. Property values
can be any type, including other Objects, allowing
for the creation of arbitrarily complex data
structures.
@li https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures
*/
enum class Kind
{
Expand Down
Loading

0 comments on commit cc9e397

Please sign in to comment.