Skip to content

Commit b55c26d

Browse files
committed
Update make and define to take traits as the 1st template parameter
Signed-off-by: yamacir-kit <[email protected]>
1 parent 9c827f4 commit b55c26d

File tree

7 files changed

+153
-83
lines changed

7 files changed

+153
-83
lines changed

README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ Procedures for each standard are provided by the following R7RS-style libraries:
9191
cmake -B build -DCMAKE_BUILD_TYPE=Release
9292
cd build
9393
make package
94-
sudo apt install build/meevax_0.5.105_amd64.deb
94+
sudo apt install build/meevax_0.5.106_amd64.deb
9595
```
9696

9797
or
@@ -123,9 +123,9 @@ sudo rm -rf /usr/local/share/meevax
123123

124124
| Target Name | Description
125125
|-------------|-------------
126-
| `all` | Build shared-library `libmeevax.0.5.105.so` and executable `meevax`
126+
| `all` | Build shared-library `libmeevax.0.5.106.so` and executable `meevax`
127127
| `test` | Test executable `meevax`
128-
| `package` | Generate debian package `meevax_0.5.105_amd64.deb`
128+
| `package` | Generate debian package `meevax_0.5.106_amd64.deb`
129129
| `install` | Copy files into `/usr/local` directly
130130

131131
## Usage

VERSION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.5.105
1+
0.5.106

include/meevax/kernel/library.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ inline namespace kernel
4747
export_specs = cons(input_string_port(name).read(), export_specs);
4848
}
4949

50-
template <template <typename...> typename Template, typename... Ts>
50+
template <template <typename...> typename Traits, typename... Ts>
5151
auto define(Ts&&... xs) -> decltype(auto)
5252
{
53-
return define<Template<Ts...>>(std::forward<decltype(xs)>(xs)...);
53+
return define<typename Traits<Ts...>::type>(std::forward<decltype(xs)>(xs)...);
5454
}
5555

5656
auto evaluate(object const&) -> object;

include/meevax/kernel/pair.hpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,13 @@ inline namespace kernel
5353
return object::allocate<std::decay_t<T>, Allocator>(std::forward<decltype(x)>(x));
5454
}
5555

56-
template <template <typename...> typename Template,
56+
template <template <typename...> typename Traits,
5757
typename Allocator = collector::default_allocator<void>,
5858
typename... Ts,
59-
REQUIRES(std::is_constructible<Template<Ts...>, Ts...>)>
59+
REQUIRES(std::is_constructible<typename Traits<Ts...>::type, Ts...>)>
6060
auto make(Ts&&... xs) -> decltype(auto)
6161
{
62-
return make<Template<Ts...>, Allocator>(std::forward<decltype(xs)>(xs)...);
62+
return make<typename Traits<Ts...>::type, Allocator>(std::forward<decltype(xs)>(xs)...);
6363
}
6464

6565
struct pair : public std::pair<object, object>

include/meevax/kernel/procedure.hpp

+86-16
Original file line numberDiff line numberDiff line change
@@ -38,53 +38,123 @@ inline namespace kernel
3838

3939
auto operator <<(std::ostream &, callable const&) -> std::ostream &;
4040

41-
template <typename, typename Callee>
42-
struct procedure : public callable
41+
template <typename F>
42+
struct generic_procedure : public callable
4343
{
44-
Callee call;
44+
std::enable_if_t<std::is_invocable_v<F> or std::is_invocable_v<F, object &>, F> invocable;
4545

46-
explicit procedure(std::string const& name, Callee call)
46+
explicit generic_procedure(std::string const& name, F f)
4747
: callable { name }
48-
, call { call }
48+
, invocable { f }
4949
{}
5050

5151
auto operator ()(object & xs) const -> object override
5252
{
53-
if constexpr (std::is_invocable_v<Callee>)
53+
if constexpr (std::is_invocable_v<F>)
5454
{
55-
if constexpr (std::is_same_v<std::invoke_result_t<Callee>, void>)
55+
if constexpr (std::is_same_v<std::invoke_result_t<F>, void>)
5656
{
57-
call();
57+
std::invoke(invocable);
5858
return unspecified;
5959
}
60-
else if constexpr (std::is_same_v<std::invoke_result_t<Callee>, bool>)
60+
else if constexpr (std::is_same_v<std::invoke_result_t<F>, bool>)
6161
{
62-
return call() ? t : f;
62+
return std::invoke(invocable) ? t : f;
6363
}
6464
else
6565
{
66-
return call();
66+
return std::invoke(invocable);
6767
}
6868
}
6969
else
7070
{
71-
if constexpr (std::is_same_v<std::invoke_result_t<Callee, object &>, void>)
71+
if constexpr (std::is_same_v<std::invoke_result_t<F, object &>, void>)
7272
{
73-
call(xs);
73+
std::invoke(invocable, xs);
7474
return unspecified;
7575
}
76-
else if constexpr (std::is_same_v<std::invoke_result_t<Callee, object &>, bool>)
76+
else if constexpr (std::is_same_v<std::invoke_result_t<F, object &>, bool>)
7777
{
78-
return call(xs) ? t : f;
78+
return std::invoke(invocable, xs) ? t : f;
7979
}
8080
else
8181
{
82-
return call(xs);
82+
return std::invoke(invocable, xs);
8383
}
8484
}
8585
}
8686
};
8787

88+
/*
89+
There is no need to define specializations for this primary template to
90+
work. However, since the template parameter `F` is usually given a
91+
closure, there will be a unique template instantiation for each lambda
92+
expression. The problem in this case is that the binary size becomes huge.
93+
To deal with this, we take advantage of the fact that closures that do not
94+
capture anything can be converted to function pointers, and decay closures
95+
into function pointer types to reduce the number of template
96+
instantiations.
97+
*/
98+
template <typename, typename F, typename = void>
99+
struct procedure
100+
{
101+
using type = generic_procedure<F>;
102+
};
103+
104+
/*
105+
Thunk
106+
*/
107+
template <typename T, typename F>
108+
struct procedure<T, F, std::enable_if_t<std::is_convertible_v<F, auto (*)() -> object>>>
109+
{
110+
using type = generic_procedure<auto (*)() -> object>;
111+
};
112+
113+
/*
114+
Procedure
115+
*/
116+
template <typename T, typename F>
117+
struct procedure<T, F, std::enable_if_t<std::is_convertible_v<F, auto (*)(object const&) -> object>>>
118+
{
119+
using type = generic_procedure<auto (*)(object const&) -> object>;
120+
};
121+
122+
/*
123+
Linear update procedure
124+
*/
125+
template <typename T, typename F>
126+
struct procedure<T, F, std::enable_if_t<std::is_convertible_v<F, auto (*)(object &) -> object>>>
127+
{
128+
using type = generic_procedure<auto (*)(object &) -> object>;
129+
};
130+
131+
/*
132+
Predicate
133+
*/
134+
template <typename T, typename F>
135+
struct procedure<T, F, std::enable_if_t<std::is_convertible_v<F, auto (*)(object const&) -> bool>>>
136+
{
137+
using type = generic_procedure<auto (*)(object const&) -> bool>;
138+
};
139+
140+
/*
141+
Command
142+
*/
143+
template <typename T, typename F>
144+
struct procedure<T, F, std::enable_if_t<std::is_convertible_v<F, auto (*)(object const&) -> void>>>
145+
{
146+
using type = generic_procedure<auto (*)(object const&) -> void>;
147+
};
148+
149+
/*
150+
Mutation
151+
*/
152+
template <typename T, typename F>
153+
struct procedure<T, F, std::enable_if_t<std::is_convertible_v<F, auto (*)(object &) -> void>>>
154+
{
155+
using type = generic_procedure<auto (*)(object &) -> void>;
156+
};
157+
88158
using procedure_pointer = auto (*)(object &) -> object;
89159
} // namespace kernel
90160
} // namespace meevax

include/meevax/kernel/syntactic_environment.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1101,10 +1101,10 @@ inline namespace kernel
11011101
}
11021102
}
11031103

1104-
template <template <typename...> typename Template, typename... Ts>
1104+
template <template <typename...> typename Traits, typename... Ts>
11051105
inline auto define(Ts&&... xs) -> decltype(auto)
11061106
{
1107-
return define<Template<Ts...>>(std::forward<decltype(xs)>(xs)...);
1107+
return define<typename Traits<Ts...>::type>(std::forward<decltype(xs)>(xs)...);
11081108
}
11091109

11101110
inline auto identify(object const& variable,

0 commit comments

Comments
 (0)