Skip to content

feat: user defined metafunctions #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions examples/user-defined-metafunction/build.cpp2
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import cpp2b.build;

build: (inout b: cpp2b::build) -> void = {
b.cppfront_reflect_inject("metafunction.h2");
}
Empty file.
21 changes: 21 additions & 0 deletions share/cpp2b.build.cppm.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ CPP2B_BUILD_API void (*cpp2b_detail_build_binary_name)(
cpp2b_detail_build_impl *, std::filesystem::path,
std::string_view) = nullptr;

CPP2B_BUILD_API void (*cpp2b_detail_build_cppfront_reflect_inject)(
cpp2b_detail_build_impl *, std::filesystem::path) = nullptr;

export namespace cpp2b {
class build {
cpp2b_detail_build_impl *impl;
Expand All @@ -34,6 +37,24 @@ public:
return (*cpp2b_detail_build_binary_name)(impl, binary_source_path,
new_binary_name);
}

/**
* Parses the .h2 header looking for functions with any of these signatures:
*
* (inout _: cpp2::meta::declaration) -> void
* (inout _: cpp2::meta::type_declaration) -> void
* (inout _: cpp2::meta::function_declaration) -> void
* (inout _: cpp2::meta::object_declaration) -> void
* (inout _: cpp2::meta::alias_declaration) -> void
*
* Every function with one of these signatures are injected into cppfront's
* reflect.h2 `apply_metafunctions`, making them available as user-defined
* metafunctions. Additionally the header_path is injected as an #include at
* the top of the reflect.h2 header.
*/
inline auto cppfront_reflect_inject(std::filesystem::path header_path) -> void {
return (*cpp2b_detail_build_cppfront_reflect_inject)(header_path);
}
};
} // namespace cpp2b

Expand Down
22 changes: 22 additions & 0 deletions src/main.cpp2
Original file line number Diff line number Diff line change
Expand Up @@ -635,10 +635,15 @@ build_binary: (info: cpp2b_source_binary_info) -> build_binary_result = {
return result;
}

cpp2b_reflect_header_info: @struct type = {
public header_paths: std::vector<fs::path>;
public metafunction_names: std::vector<std::string>;
}

cpp2b_detail_build_impl: @struct type = {
public build_cpp2_dir: fs::path;
public bins: *std::vector<cpp2b_source_binary_info>;
public reflect_inject: cpp2b_reflect_header_info;
}
cpp2b_detail_build_binary_name: (
copy impl: *cpp2b_detail_build_impl,
Expand All @@ -660,6 +665,21 @@ cpp2b_detail_build_binary_name: (
bin*.preferred_name = (build_cpp2_dir / new_binary_name).generic_string();
}


cpp2b_detail_build_cppfront_reflect_inject: (
copy impl: *cpp2b_detail_build_impl,
copy header_path: std::filesystem::path,
) = {
build_cpp2_dir: fs::path = impl*.build_cpp2_dir;
p := build_cpp2_dir / header_path;

if !fs::exists(header_path) {
return;
}

impl*.reflect_inject.header_paths.emplace_back(header_path);
}

cpp2b_detail_build: (copy _impl: *cpp2b_detail_build_impl) -> void = {
// empty. this is just so we can decltype the signature
}
Expand Down Expand Up @@ -922,8 +942,10 @@ do_build: (targets: std::vector<std::string>) -> (stuff: full_build_info, exit_c

build_dylib.assert_symbol("cpp2b_detail_build");
build_dylib.assert_symbol("cpp2b_detail_build_binary_name");
build_dylib.assert_symbol("cpp2b_detail_build_cppfront_reflect_inject");

build_dylib.get_variable<decltype(cpp2b_detail_build_binary_name&)>("cpp2b_detail_build_binary_name") = cpp2b_detail_build_binary_name&;
build_dylib.get_variable<decltype(cpp2b_detail_build_cppfront_reflect_inject&)>("cpp2b_detail_build_binary_name") = cpp2b_detail_build_cppfront_reflect_inject&;

b: cpp2b_detail_build_impl = (build_script.src.parent_path(), stuff.bins&);
build_dylib.get_function<decltype(cpp2b_detail_build)>("cpp2b_detail_build")(b&);
Expand Down
Loading