Skip to content

Commit cc9e397

Browse files
committed
test: clang::mrdox::dom unit tests
1 parent 831a691 commit cc9e397

20 files changed

+3583
-1379
lines changed

include/mrdox/Dom/Array.hpp

+21-8
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,15 @@ namespace dom {
2424
class ArrayImpl;
2525
class Value;
2626

27-
/** An array of values.
27+
/** An array of values
28+
29+
Arrays are a collection of indexed values. They
30+
are an extension of objects with a particular
31+
relationship between integer-keyed properties
32+
and some abstract length-property. Besides,
33+
they include convenient methods to manipulate
34+
these ordered sequences of values.
35+
2836
*/
2937
class MRDOX_DECL
3038
Array final
@@ -40,13 +48,13 @@ class MRDOX_DECL
4048
4149
This is a read-only reference to an element.
4250
*/
43-
using reference = value_type const&;
51+
using reference = value_type;
4452

4553
/** A reference to an element.
4654
4755
This is a read-only reference to an element.
4856
*/
49-
using const_reference = value_type const&;
57+
using const_reference = value_type;
5058

5159
/** A pointer to an element.
5260
*/
@@ -182,10 +190,6 @@ class MRDOX_DECL
182190
*/
183191
void set(size_type i, Value v);
184192

185-
/** Return the i-th element, without bounds checking.
186-
*/
187-
value_type operator[](size_type i) const;
188-
189193
/** Return the i-th element.
190194
191195
@throw Exception `i >= size()`
@@ -217,7 +221,15 @@ class MRDOX_DECL
217221
If the array is read-only, an exception
218222
is thrown.
219223
*/
220-
void emplace_back(value_type value);
224+
void push_back(value_type value);
225+
226+
/** Append an element to the end of the array.
227+
228+
If the array is read-only, an exception
229+
is thrown.
230+
*/
231+
template< class... Args >
232+
void emplace_back(Args&&... args);
221233

222234
/** Concatenate two arrays.
223235
*/
@@ -356,6 +368,7 @@ class MRDOX_DECL
356368
value_type get(size_type i) const override;
357369
void set(size_type i, Value v) override;
358370
void emplace_back(value_type value) override;
371+
char const* type_key() const noexcept override;
359372

360373
private:
361374
std::vector<value_type> elements_;

include/mrdox/Dom/Array.ipp

+7-6
Original file line numberDiff line numberDiff line change
@@ -175,11 +175,6 @@ inline void Array::set(std::size_t i, Value v)
175175
impl_->set(i, std::move(v));
176176
}
177177

178-
inline auto Array::operator[](std::size_t i) const -> value_type
179-
{
180-
return get(i);
181-
}
182-
183178
inline auto Array::at(std::size_t i) const -> value_type
184179
{
185180
if(i < size())
@@ -207,11 +202,17 @@ inline auto Array::end() const -> iterator
207202
return {*impl_, impl_->size()};
208203
}
209204

210-
inline void Array::emplace_back(value_type value)
205+
inline void Array::push_back(value_type value)
211206
{
212207
impl_->emplace_back(std::move(value));
213208
}
214209

210+
template< class... Args >
211+
void Array::emplace_back(Args&&... args)
212+
{
213+
impl_->emplace_back(value_type(std::forward<Args>(args)...));
214+
}
215+
215216
inline
216217
Array operator+(Array const& lhs, Array const& rhs)
217218
{

include/mrdox/Dom/Function.hpp

+15-4
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,21 @@ concept has_function_traits = requires {
9090
};
9191

9292
template<typename F>
93-
concept has_invoke_result_for_default_function_impl =
94-
// Return type is void or convertible to dom::Value
93+
concept has_invoke_result_convertible_to_dom_value =
9594
std::convertible_to<typename function_traits<F>::return_type, Value> ||
9695
std::same_as<typename function_traits<F>::return_type, void>;
9796

97+
template<typename F>
98+
concept has_invoke_expected_result_convertible_to_dom_value =
99+
detail::isExpected<typename function_traits<F>::return_type> &&
100+
(std::convertible_to<typename function_traits<F>::return_type::value_type, Value> ||
101+
std::same_as<typename function_traits<F>::return_type::value_type, void>);
102+
103+
template<typename F>
104+
concept has_invoke_result_for_default_function_impl =
105+
has_invoke_result_convertible_to_dom_value<F> ||
106+
has_invoke_expected_result_convertible_to_dom_value<F>;
107+
98108
template<typename F>
99109
concept has_function_args_for_default_function_impl =
100110
// All arguments are convertible to dom::Value
@@ -115,7 +125,8 @@ concept has_function_traits_for_default_function_impl =
115125

116126
template<class F>
117127
concept function_traits_convertible_to_value =
118-
has_function_traits<F> && has_function_traits_for_default_function_impl<F>;
128+
has_function_traits<F> &&
129+
has_function_traits_for_default_function_impl<F>;
119130

120131
//------------------------------------------------
121132
//
@@ -306,7 +317,7 @@ class DefaultFunctionImpl : public FunctionImpl
306317

307318
char const* type_key() const noexcept override
308319
{
309-
return "DefaultFunctionImpl";
320+
return "Function";
310321
}
311322

312323
Expected<Value>

include/mrdox/Dom/Function.ipp

+14-9
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,12 @@ Value
3333
Function::
3434
operator()(Args&&... args) const
3535
{
36-
return try_invoke(std::forward<Args>(args)...).value();
36+
auto exp = try_invoke(std::forward<Args>(args)...);
37+
if (exp)
38+
{
39+
return *exp;
40+
}
41+
throw Exception(std::move(exp.error()));
3742
}
3843

3944
template<class... Args>
@@ -161,27 +166,27 @@ call_impl(
161166
using R = decltype(
162167
f_(arg_type<std::decay_t<
163168
std::tuple_element_t<I, args_type> >
164-
>::get(args[I])...));
169+
>::get(args.get(I))...));
165170
if (args.size() < sizeof...(I))
166171
{
167172
Array clone;
168173
for (std::size_t i = 0; i < args.size(); ++i)
169-
clone.emplace_back(args[i]);
174+
clone.emplace_back(args.get(i));
170175
std::size_t const diff = sizeof...(I) - args.size();
171176
for (std::size_t i = 0; i < diff; ++i)
172177
clone.emplace_back(Value(Kind::Undefined));
173178
if constexpr (std::is_void_v<R>)
174179
{
175180
f_(arg_type<std::decay_t<
176181
std::tuple_element_t<I, args_type> >
177-
>::get(clone[I])...);
182+
>::get(clone.get(I))...);
178183
return Value(Kind::Undefined);
179184
}
180185
else if constexpr (std::same_as<R, Expected<void>>)
181186
{
182187
auto exp = f_(arg_type<std::decay_t<
183188
std::tuple_element_t<I, args_type> >
184-
>::get(clone[I])...);
189+
>::get(clone.get(I))...);
185190
if (!exp)
186191
{
187192
return Unexpected(exp.error());
@@ -192,21 +197,21 @@ call_impl(
192197
{
193198
return f_(arg_type<std::decay_t<
194199
std::tuple_element_t<I, args_type> >
195-
>::get(clone[I])...);
200+
>::get(clone.get(I))...);
196201
}
197202
}
198203
if constexpr (std::is_void_v<R>)
199204
{
200205
f_(arg_type<std::decay_t<
201206
std::tuple_element_t<I, args_type> >
202-
>::get(args[I])...);
207+
>::get(args.get(I))...);
203208
return Value(Kind::Undefined);
204209
}
205210
else if constexpr (std::same_as<R, Expected<void>>)
206211
{
207212
auto exp = f_(arg_type<std::decay_t<
208213
std::tuple_element_t<I, args_type> >
209-
>::get(args[I])...);
214+
>::get(args.get(I))...);
210215
if (!exp)
211216
{
212217
return Unexpected(exp.error());
@@ -217,7 +222,7 @@ call_impl(
217222
{
218223
return f_(arg_type<std::decay_t<
219224
std::tuple_element_t<I, args_type> >
220-
>::get(args[I])...);
225+
>::get(args.get(I))...);
221226
}
222227
}
223228

include/mrdox/Dom/Kind.hpp

+48
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,54 @@ namespace mrdox {
1919
namespace dom {
2020

2121
/** The type of data in a Value.
22+
23+
This is the type of data stored in a Value.
24+
These types are loosely modeled after the
25+
JavaScript types and data structures.
26+
27+
Primitive values are Undefined, Null, Boolean,
28+
Integer, and String.
29+
30+
Undefined and Null are inhabited by a single
31+
value each. The difference between Undefined
32+
and Null is that Undefined is the default
33+
value for a Value, while Null represents a
34+
value that is explicitly set. Undefined is
35+
used to represent things such as:
36+
37+
@li An uninitialized Value
38+
@li The Value returned from a function that failed to return a value
39+
@li The result of accessing a nonexistent object property
40+
@li The result of a `find` algorithm when no element is found
41+
42+
This distinction is semantically important as
43+
algorithms frequently need to distinguish between
44+
these two cases.
45+
46+
Booleans, Integers, and Strings are also primitive
47+
values. This means they are deeply copied when assigned or
48+
passed as a parameter.
49+
50+
Other value types, such as Array, Object, and Function
51+
are reference types, meaning that they are not copied
52+
when assigned or passed as a parameter. Instead, the
53+
reference is copied, and the original value is shared.
54+
55+
These reference types are modeled after JavaScript
56+
"Objects". All non-primitive types (Object types)
57+
are derived from Object in Javascript. This means
58+
types such as Array and Function represent a
59+
relevant selection of built-in types that would
60+
derive from Object in JavaScript.
61+
62+
Objects are a collection of properties, which are
63+
equivalent to key-value pairs. Property values
64+
can be any type, including other Objects, allowing
65+
for the creation of arbitrarily complex data
66+
structures.
67+
68+
@li https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures
69+
2270
*/
2371
enum class Kind
2472
{

0 commit comments

Comments
 (0)