Skip to content

Commit cc5a539

Browse files
committed
Functional basics
1 parent 3fca8aa commit cc5a539

17 files changed

+537
-162
lines changed

internals/testing/arithmetic_test.cpp

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
#include "lax_v1/arithmetic.hpp"
2-
#include "lax_v1/force.hpp"
32

43
#include "config.hpp"
54

65
#include <type_traits>
76

8-
static_assert(
9-
std::is_same_v<
10-
lax::force_t<lax::add_m<lax::value_t<short, 1>, lax::value_t<long, 2>>>,
11-
lax::value_t<long, 3>>);
7+
static_assert(std::is_same_v<lax::force_t<lax::adds_m<lax::value_t<short, 1>,
8+
lax::value_t<long, 2>>>,
9+
lax::value_t<long, 3>>);
1210

1311
static_assert(
1412
std::is_same_v<
@@ -17,7 +15,7 @@ static_assert(
1715

1816
static_assert(
1917
std::is_same_v<
20-
lax::force_t<lax::mul_m<lax::value_t<int, 1>, lax::value_t<short, 2>>>,
18+
lax::force_t<lax::muls_m<lax::value_t<int, 1>, lax::value_t<short, 2>>>,
2119
lax::value_t<int, 2>>);
2220

2321
static_assert(

internals/testing/comparison_test.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
#include "config.hpp"
44

5-
static_assert(
6-
lax::value_of_v<lax::gt_m<lax::value_t<int, 2>, lax::value_t<int, 1>>>);
5+
static_assert(lax::gt_m<lax::value_t<int, 2>, lax::value_t<int, 1>>::value);
76

8-
static_assert(
9-
!lax::value_of_v<lax::eq_m<lax::value_t<int, 2>, lax::value_t<int, 1>>>);
7+
static_assert(!lax::eq_m<lax::value_t<int, 2>, lax::value_t<int, 1>>::value);

internals/testing/functional_test.cpp

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#include "lax_v1/arithmetic.hpp"
2+
#include "lax_v1/comparison.hpp"
3+
#include "lax_v1/functional.hpp"
4+
#include "lax_v1/type_traits.hpp"
5+
6+
#include "config.hpp"
7+
8+
static_assert(lax::apply_m<lax::compose_m<lax::neg_m<>, lax::neg_m<>>,
9+
lax::value_t<int, 2>>::value == 2);
10+
11+
static_assert(lax::apply_m<lax::composes_m<lax::add_m<lax::value_t<int, 1>>,
12+
lax::neg_m<>,
13+
lax::add_m<lax::value_t<int, -1>>>,
14+
lax::value_t<int, 1>>::value == 1);
15+
16+
static_assert(lax::apply_m<lax::pipes_m<lax::add_m<lax::value_t<int, 1>>,
17+
lax::neg_m<>,
18+
lax::add_m<lax::value_t<int, -1>>>,
19+
lax::value_t<int, 1>>::value == -3);
20+
21+
static_assert(lax::thru_m<lax::value_t<int, 1>,
22+
lax::add_m<lax::value_t<int, 1>>,
23+
lax::neg_m<>,
24+
lax::add_m<lax::value_t<int, -1>>,
25+
lax::eq_m<lax::value_t<int, -3>>>::value == true);
26+
27+
struct V;
28+
29+
static_assert(lax::apply_m<lax::function_t<V, lax::add_m<V, lax::neg_m<V>>>,
30+
lax::value_t<int, 1>>::value == 0);
31+
32+
static_assert(lax::thru_m<lax::type_t<short * [1]>,
33+
lax::remove_all_extents_m<>,
34+
lax::remove_pointer_m<>,
35+
lax::alignment_of_m<>>::value == alignof(short));
36+
37+
static_assert(lax::thru_m<lax::value_t<int, 0>,
38+
lax::div_m<lax::value_t<int, 0>>,
39+
lax::constant_m<lax::value_t<int, 101>>>::value ==
40+
101);
41+
42+
template <class T>
43+
using adhoc_t = lax::as_type_trait_t<
44+
lax::pipe_m<lax::remove_all_extents_m<>, lax::remove_pointer_m<>>,
45+
T>;
46+
47+
static_assert(std::is_same_v<adhoc_t<int * [2][2]>, int>);
48+
49+
template <class T>
50+
inline constexpr auto adhoc_v = lax::as_value_trait_v<
51+
lax::pipe_m<lax::remove_all_extents_m<>, lax::alignment_of_m<>>,
52+
T>;
53+
54+
static_assert(adhoc_v<int * [2][2]> == alignof(int *));
55+
56+
struct F;
57+
58+
using factorial_m = lax::fix_m<lax::fn_t<
59+
lax::seq_t<F, V>,
60+
lax::if_m<
61+
lax::eq_m<lax::value_t<int, 0>, V>,
62+
lax::value_t<int, 1>,
63+
lax::mul_m<V, lax::apply_m<F, lax::sub_m<V, lax::value_t<int, 1>>>>>>>;
64+
65+
static_assert(lax::apply_m<factorial_m, lax::value_t<int, 5>>::value == 120);

internals/testing/logical_test.cpp

+7-9
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@
22

33
#include "config.hpp"
44

5-
static_assert(
6-
lax::value_of_v<
7-
lax::if_m<lax::and_m<>, lax::value_t<int, 1>, lax::value_t<int, 2>>> ==
8-
1);
5+
static_assert(lax::if_m<lax::ands_m<>,
6+
lax::value_t<int, 1>,
7+
lax::value_t<int, 2>>::value == 1);
98

10-
static_assert(
11-
lax::value_of_v<
12-
lax::if_m<lax::or_m<>, lax::value_t<int, 1>, lax::value_t<int, 2>>> ==
13-
2);
9+
static_assert(lax::if_m<lax::ors_m<>,
10+
lax::value_t<int, 1>,
11+
lax::value_t<int, 2>>::value == 2);
1412

15-
static_assert(lax::value_of_v<lax::not_m<lax::false_t>>);
13+
static_assert(lax::not_m<lax::false_t>::value);

internals/testing/type_traits_test.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
#include "config.hpp"
66

7-
static_assert(lax::value_of_v<lax::is_array_m<lax::type_t<int[2]>>>);
7+
static_assert(lax::is_array_m<lax::type_t<int[2]>>::value);
88

99
template <class Value>
1010
struct is_stored_plain_m
@@ -18,7 +18,7 @@ struct is_stored_plain_m
1818

1919
template <class Value>
2020
static inline constexpr bool is_stored_plain_v =
21-
lax::value_of_v<is_stored_plain_m<lax::type_t<Value>>>;
21+
is_stored_plain_m<lax::type_t<Value>>::value;
2222

2323
static_assert(!is_stored_plain_v<char>);
2424
static_assert(!is_stored_plain_v<char *>);

internals/testing/value_test.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#include "lax_v1/value.hpp"
1+
#include "lax_v1/core.hpp"
22

33
#include "config.hpp"
44

+24-27
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,29 @@
11
#pragma once
22

3-
#include "lax_v1/value.hpp"
3+
#include "lax_v1/core.hpp"
44

55
#include <type_traits>
66

7-
template <class Lhs, class Rhs>
8-
struct lax_v1::add_m
9-
: value_t<std::common_type_t<value_type_of_t<Lhs>, value_type_of_t<Rhs>>,
10-
value_of_v<Lhs> + value_of_v<Rhs>> {};
11-
12-
template <class Lhs, class Rhs>
13-
struct lax_v1::div_m
14-
: value_t<std::common_type_t<value_type_of_t<Lhs>, value_type_of_t<Rhs>>,
15-
value_of_v<Lhs> / value_of_v<Rhs>> {};
16-
17-
template <class Lhs, class Rhs>
18-
struct lax_v1::mod_m
19-
: value_t<std::common_type_t<value_type_of_t<Lhs>, value_type_of_t<Rhs>>,
20-
value_of_v<Lhs> % value_of_v<Rhs>> {};
21-
22-
template <class Lhs, class Rhs>
23-
struct lax_v1::mul_m
24-
: value_t<std::common_type_t<value_type_of_t<Lhs>, value_type_of_t<Rhs>>,
25-
value_of_v<Lhs> * value_of_v<Rhs>> {};
26-
27-
template <class Lhs, class Rhs>
28-
struct lax_v1::sub_m
29-
: value_t<std::common_type_t<value_type_of_t<Lhs>, value_type_of_t<Rhs>>,
30-
value_of_v<Lhs> - value_of_v<Rhs>> {};
31-
32-
template <class Expr> struct lax_v1::neg_m : auto_t<-value_of_v<Expr>> {};
7+
#define LAX(name, op) \
8+
namespace lax_v1 { \
9+
template <class Lhs, class Rhs> \
10+
using name##_t = value_t< \
11+
std::common_type_t<typename Lhs::value_type, typename Rhs::value_type>, \
12+
Lhs::value op Rhs::value>; \
13+
} \
14+
template <class... Exprs> \
15+
struct lax_v1::name##_m : primitive_t<name##_t, 2, Exprs...> {};
16+
17+
LAX(add, +)
18+
LAX(div, /)
19+
LAX(mod, %)
20+
LAX(mul, *)
21+
LAX(sub, -)
22+
#undef LAX
23+
24+
namespace lax_v1 {
25+
template <class Expr> using neg_t = auto_t<-Expr::value>;
26+
} // namespace lax_v1
27+
28+
template <class... Exprs>
29+
struct lax_v1::neg_m : primitive_t<neg_t, 1, Exprs...> {};
+14-14
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
#pragma once
22

3-
#include "lax_v1/value.hpp"
3+
#include "lax_v1/core.hpp"
44

5-
template <class Lhs, class Rhs>
6-
struct lax_v1::eq_m : auto_t<(value_of_v<Lhs> == value_of_v<Rhs>)> {};
5+
#define LAX(name, op) \
6+
namespace lax_v1 { \
7+
template <class Lhs, class Rhs> \
8+
using name##_t = auto_t<(Lhs::value op Rhs::value)>; \
9+
} \
10+
template <class... Exprs> \
11+
struct lax_v1::name##_m : primitive_t<name##_t, 2, Exprs...> {};
712

8-
template <class Lhs, class Rhs>
9-
struct lax_v1::gt_m : auto_t<(value_of_v<Lhs>> value_of_v<Rhs>)> {};
10-
11-
template <class Lhs, class Rhs>
12-
struct lax_v1::gte_m : auto_t<(value_of_v<Lhs> >= value_of_v<Rhs>)> {};
13-
14-
template <class Lhs, class Rhs>
15-
struct lax_v1::lt_m : auto_t<(value_of_v<Lhs> < value_of_v<Rhs>)> {};
16-
17-
template <class Lhs, class Rhs>
18-
struct lax_v1::lte_m : auto_t<(value_of_v<Lhs> <= value_of_v<Rhs>)> {};
13+
LAX(eq, ==)
14+
LAX(gt, >)
15+
LAX(gte, >=)
16+
LAX(lt, <)
17+
LAX(lte, <=)
18+
#undef LAX

provides/include/lax_v1/core.hpp

+151
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
#pragma once
2+
3+
#include "lax_v1/synopsis.hpp"
4+
5+
#include <type_traits>
6+
7+
//
8+
9+
template <class Type> struct lax_v1::type_t {
10+
using eval = type_t;
11+
using type = Type;
12+
};
13+
14+
//
15+
16+
template <class Type, Type value>
17+
struct lax_v1::value_t : std::integral_constant<Type, value> {
18+
using eval = value_t;
19+
};
20+
21+
//
22+
23+
template <class Else> struct lax_v1::if_m<Else> : force_t<Else> {};
24+
template <class Cond, class Then, class... Elses>
25+
struct lax_v1::if_m<Cond, Then, Elses...>
26+
: force_t<if_m<force_t<Cond>, Then, Elses...>> {};
27+
template <class Then, class... Elses>
28+
struct lax_v1::if_m<lax_v1::true_t, Then, Elses...> : force_t<Then> {};
29+
template <class Then, class... Elses>
30+
struct lax_v1::if_m<lax_v1::false_t, Then, Elses...> : force_t<if_m<Elses...>> {
31+
};
32+
33+
//
34+
35+
namespace lax_v1 {
36+
37+
class apply_private {
38+
template <class Function, class... Actuals> friend struct apply_m;
39+
template <class... Actuals> struct t { using eval = t; };
40+
template <class Prefix, class Suffix> struct concat;
41+
template <size_t n, class... Actuals> struct take_n;
42+
template <size_t n, class... Actuals> struct drop_n;
43+
template <class Function, class Actuals> struct apply_exact;
44+
template <class Function, class Actuals> struct apply_rest;
45+
template <class Function, class... Actuals> struct apply;
46+
};
47+
48+
} // namespace lax_v1
49+
50+
template <class Function, class... Actuals>
51+
struct lax_v1::apply_m
52+
: force_t<if_m<auto_t<(sizeof...(Actuals) < Function::arity)>,
53+
closure_t<Function, Actuals...>,
54+
apply_private::apply<Function, Actuals...>>> {};
55+
56+
//
57+
58+
template <class Function, class... BoundActuals> struct lax_v1::closure_t {
59+
using eval = closure_t;
60+
static constexpr size_t arity = Function::arity - sizeof...(BoundActuals);
61+
template <class... Actuals>
62+
struct m
63+
: force_t<typename Function::template m<BoundActuals..., Actuals...>> {};
64+
};
65+
66+
//
67+
68+
template <template <class... Formals> class Primitive, size_t arity_>
69+
struct lax_v1::from_primitive_t {
70+
using eval = from_primitive_t;
71+
static constexpr size_t arity = arity_;
72+
template <class... Actuals> struct m : force_t<Primitive<Actuals...>> {};
73+
};
74+
75+
//
76+
77+
template <template <class... Formals> class Trait, size_t arity_>
78+
struct lax_v1::from_type_trait_t {
79+
using eval = from_type_trait_t;
80+
static constexpr size_t arity = arity_;
81+
template <class... Actuals>
82+
struct m : type_t<type_of_t<Trait<type_of_t<Actuals>...>>> {};
83+
};
84+
85+
//
86+
87+
template <template <class... Formals> class Trait, size_t arity_, class Type>
88+
struct lax_v1::from_value_trait_t {
89+
using eval = from_value_trait_t;
90+
static constexpr size_t arity = arity_;
91+
template <class... Actuals>
92+
struct m : value_t<Type, Trait<type_of_t<Actuals>...>::value> {};
93+
};
94+
95+
//
96+
97+
template <class... Exprs> struct lax_v1::seq_t { using eval = seq_t; };
98+
99+
//
100+
101+
template <class... Prefix, class... Suffix>
102+
struct lax_v1::apply_private::concat<lax_v1::apply_private::t<Prefix...>,
103+
lax_v1::apply_private::t<Suffix...>>
104+
: t<Prefix..., Suffix...> {};
105+
106+
template <class... Actuals>
107+
struct lax_v1::apply_private::take_n<0, Actuals...> : t<> {};
108+
109+
template <size_t n, class Actual, class... Actuals>
110+
struct lax_v1::apply_private::take_n<n, Actual, Actuals...>
111+
: force_t<concat<t<Actual>, force_t<take_n<n - 1, Actuals...>>>> {};
112+
113+
template <class... Actuals>
114+
struct lax_v1::apply_private::drop_n<0, Actuals...> : t<Actuals...> {};
115+
116+
template <size_t n, class Actual, class... Actuals>
117+
struct lax_v1::apply_private::drop_n<n, Actual, Actuals...>
118+
: force_t<drop_n<n - 1, Actuals...>> {};
119+
120+
template <class Function, class... Actuals>
121+
struct lax_v1::apply_private::apply_exact<Function,
122+
lax_v1::apply_private::t<Actuals...>>
123+
: force_t<typename Function::template m<Actuals...>> {};
124+
125+
template <class Function, class Actual, class... Actuals>
126+
struct lax_v1::apply_private::
127+
apply_rest<Function, lax_v1::apply_private::t<Actual, Actuals...>>
128+
: force_t<apply_m<Function, Actual, Actuals...>> {};
129+
130+
template <class Function>
131+
struct lax_v1::apply_private::apply_rest<Function, lax_v1::apply_private::t<>>
132+
: force_t<Function> {};
133+
134+
template <class Function, class... Actuals>
135+
struct lax_v1::apply_private::apply
136+
: force_t<apply_rest<
137+
apply_exact<Function, force_t<take_n<Function::arity, Actuals...>>>,
138+
force_t<drop_n<Function::arity, Actuals...>>>> {};
139+
140+
//
141+
142+
template <class Empty, class Concat>
143+
struct lax_v1::monoid_m<Empty, Concat> : force_t<Empty> {};
144+
145+
template <class Empty, class Concat, class Expr>
146+
struct lax_v1::monoid_m<Empty, Concat, Expr> : force_t<Expr> {};
147+
148+
template <class Empty, class Concat, class Expr1, class Expr2, class... Exprs>
149+
struct lax_v1::monoid_m<Empty, Concat, Expr1, Expr2, Exprs...>
150+
: force_t<
151+
apply_m<Concat, Expr1, monoid_m<Empty, Concat, Expr2, Exprs...>>> {};

provides/include/lax_v1/force.hpp

-3
This file was deleted.

0 commit comments

Comments
 (0)