Skip to content
1,244 changes: 1,244 additions & 0 deletions include/cpp2reflect_api.h

Large diffs are not rendered by default.

264 changes: 264 additions & 0 deletions include/cpp2reflect_api.h2
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@

// Copyright (c) Herb Sutter
// SPDX-License-Identifier: CC-BY-NC-ND-4.0

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//===========================================================================
// Cpp2 reflection (meta and generation) public interface declaration file:
// This file contains only declarations (not definitions) usable by
// authors of metafunctions. See documentation for more details.
//

namespace cpp2::meta {

//-----------------------------------------------------------------------
//
// Metafunction registration support. Definitions are provided by the
// implementation (cppfront).
//

using mf_sign_type_in = void(cpp2::impl::in<type_declaration>);
using mf_sign_type_inout = void(type_declaration&);
using mf_sign_func_in = void(cpp2::impl::in<function_declaration>);
using mf_sign_func_inout = void(function_declaration&);

struct register_metafunction {
register_metafunction(const char* name, mf_sign_type_in* f);
register_metafunction(const char* name, mf_sign_type_inout* f);
register_metafunction(const char* name, mf_sign_func_in* f);
register_metafunction(const char* name, mf_sign_func_inout* f);
};

} // cpp2::meta

//-----------------------------------------------------------------------
//
// Metafunction objects. Expanded to complete definitions that use a
// interface, which is provided by the implementation (cppfront).
//

cpp2: namespace = {

// TODO(DyXel): put passing_style here, maybe?

meta: namespace = {

compiler_services: @_internal_foreign_interface_pseudovalue type =
{
// Common API
//
get_metafunction_name: (this) -> std::string_view;

get_argument : (inout this, index: int) -> std::string;
get_arguments: (inout this) -> std::vector<std::string>;

add_runtime_support_include: (inout this, s: std::string_view);

append_declaration_to_translation_unit: (inout this, source: std::string_view);

// Error diagnosis and handling, integrated with compiler output
// Unlike a contract violation, .require continues further processing
//
require : (this, b: bool, msg: std::string_view);
error : (this, msg: std::string_view);
// Enable custom contracts on this object, integrated with compiler output
// Unlike .require, a contract violation stops further processing
//
report_violation: (this, msg: std::string_view);
}

declaration: @_internal_foreign_interface_pseudovalue type =
{
this: compiler_services;

print: (this) -> std::string;

is_public : (this) -> bool;
is_protected : (this) -> bool;
is_private : (this) -> bool;
is_default_access: (this) -> bool;

default_to_public : (inout this);
default_to_protected: (inout this);
default_to_private : (inout this);

make_public : (inout this) -> bool;
make_protected: (inout this) -> bool;
make_private : (inout this) -> bool;

has_name: (this) -> bool;
has_name: (this, s: std::string_view) -> bool;

name : (this) -> std::string_view;
fully_qualified_name: (this) -> std::string;

has_initializer: (this) -> bool;

is_global : (this) -> bool;
is_function : (this) -> bool;
is_object : (this) -> bool;
is_base_object : (this) -> bool;
is_member_object : (this) -> bool;
is_type : (this) -> bool;
is_namespace : (this) -> bool;
is_alias : (this) -> bool;

is_type_alias : (this) -> bool;
is_namespace_alias : (this) -> bool;
is_object_alias : (this) -> bool;

is_function_expression: (this) -> bool;

as_function: (this) -> function_declaration;
as_object : (this) -> object_declaration;
as_type : (this) -> type_declaration;
as_alias : (this) -> alias_declaration;

get_parent: (this) -> declaration;

parent_is_function : (this) -> bool;
parent_is_object : (this) -> bool;
parent_is_type : (this) -> bool;
parent_is_namespace: (this) -> bool;
parent_is_alias : (this) -> bool;

parent_is_type_alias : (this) -> bool;
parent_is_namespace_alias: (this) -> bool;
parent_is_object_alias : (this) -> bool;

parent_is_polymorphic: (this) -> bool;

mark_for_removal_from_enclosing_type: (inout this);
}


function_declaration: @_internal_foreign_interface_pseudovalue type =
{
this: declaration;

index_of_parameter_named : (this, s: std::string_view) -> int;
has_parameter_named : (this, s: std::string_view) -> bool;
has_in_parameter_named : (this, s: std::string_view) -> bool;
has_copy_parameter_named : (this, s: std::string_view) -> bool;
has_inout_parameter_named : (this, s: std::string_view) -> bool;
has_out_parameter_named : (this, s: std::string_view) -> bool;
has_move_parameter_named : (this, s: std::string_view) -> bool;
has_forward_parameter_named: (this, s: std::string_view) -> bool;
first_parameter_name : (this) -> std::string;

// has_parameter_with_name_and_pass: (this, s: std::string_view, pass: passing_style) -> bool; // TODO

is_function_with_this : (this) -> bool;
is_virtual : (this) -> bool;
is_defaultable : (this) -> bool;
is_constructor : (this) -> bool;
is_default_constructor : (this) -> bool;
is_move : (this) -> bool;
is_swap : (this) -> bool;
is_constructor_with_that : (this) -> bool;
is_constructor_with_in_that : (this) -> bool;
is_constructor_with_move_that: (this) -> bool;
is_assignment : (this) -> bool;
is_assignment_with_that : (this) -> bool;
is_assignment_with_in_that : (this) -> bool;
is_assignment_with_move_that : (this) -> bool;
is_destructor : (this) -> bool;

is_copy_or_move : (this) -> bool;

has_declared_return_type: (this) -> bool;
has_deduced_return_type : (this) -> bool;
has_bool_return_type : (this) -> bool;
has_non_void_return_type: (this) -> bool;

unnamed_return_type: (this) -> std::string;

get_parameters: (this) -> std::vector<object_declaration>;

is_binary_comparison_function: (this) -> bool;

default_to_virtual: (inout this);

make_virtual: (inout this) -> bool;

add_initializer: (inout this, source: std::string_view);
}


object_declaration: @_internal_foreign_interface_pseudovalue type =
{
this: declaration;

is_const : (this) -> bool;
has_wildcard_type: (this) -> bool;

type: (this) -> std::string;

initializer: (this) -> std::string;
}

// Workaround due to https://github.com/hsutter/cppfront/issues/1109
_query_declared_value_set_functions_ret: @value type = {
public out_this_in_that: bool = false;
public out_this_move_that: bool = false;
public inout_this_in_that: bool = false;
public inout_this_move_that: bool = false;
}

type_declaration: @_internal_foreign_interface_pseudovalue type =
{
this: declaration;

is_polymorphic: (this) -> bool;
is_final : (this) -> bool;
make_final : (inout this) -> bool;

get_member_functions : (this) -> std::vector<function_declaration>;
get_member_functions_needing_initializer: (this) -> std::vector<function_declaration>;
get_member_objects : (this) -> std::vector<object_declaration>;
get_member_types : (this) -> std::vector<type_declaration>;
get_member_aliases : (this) -> std::vector<alias_declaration>;
get_members : (this) -> std::vector<declaration>;

query_declared_value_set_functions: (this) -> _query_declared_value_set_functions_ret;

add_member : (inout this, source: std::string_view);

remove_marked_members: (inout this);
remove_all_members : (inout this);

disable_member_function_generation: (inout this);
}


alias_declaration: @_internal_foreign_interface_pseudovalue type =
{
this: declaration;
}


reserve_names: (inout t: type_declaration, name: std::string_view, forward etc...) =
{ // etc is not declared ':string_view' for compatibility with GCC 10.x
for t.get_members()
do (m) {
n := t.get_metafunction_name();
m.require( !m.has_name( name ),
"in a '(n)$' type, the name '(name)$' "
"is reserved for use by the '(n)$' implementation"
);
}
if constexpr !CPP2_PACK_EMPTY(etc) {
t.reserve_names( etc... );
}
}

} // meta

} // cpp2
1 change: 1 addition & 0 deletions source/cpp2reflect_api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "../include/cpp2reflect_api.h"
124 changes: 124 additions & 0 deletions source/dll.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@

// Copyright (c) Herb Sutter
// SPDX-License-Identifier: CC-BY-NC-ND-4.0

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//===========================================================================
// Dynamic Library Loading
//===========================================================================

#ifndef CPP2_DLL_H
#define CPP2_DLL_H

#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <Windows.h>
#else
#include <dlfcn.h>
#endif // _WIN32

namespace cpp2 {

class dll
{
void* handle = {};
public:
dll(std::string const& path)
{
#ifdef _WIN32
handle = static_cast<void*>(LoadLibraryA(path.c_str()));
#else
handle = static_cast<void*>(dlopen(path.c_str(), RTLD_NOW|RTLD_LOCAL));
#endif // _WIN32
}

~dll() noexcept
{
if(handle != nullptr)
{
#ifdef _WIN32
FreeLibrary(static_cast<HMODULE>(handle));
#else
dlclose(handle);
#endif // _WIN32
}
}

// Uncopyable
dll(dll&) = delete;
dll(dll const&) = delete;
auto operator=(dll const&) -> dll& = delete;
// Movable
dll(dll&& from) noexcept
{
handle = from.handle;
from.handle = nullptr;
}
auto operator=(dll&& from) noexcept -> dll&
{
handle = from.handle;
from.handle = nullptr;
return *this;
}

auto is_open() noexcept -> bool { return handle != nullptr; }

static auto get_last_error() noexcept -> std::string {
#ifdef _WIN32
DWORD error_msg_id = GetLastError();
if(error_msg_id == 0)
return {}; // No error message has been recorded
LPSTR msg_buffer = nullptr;
auto size = FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr,
error_msg_id,
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
&msg_buffer,
0,
nullptr
);
std::string message(msg_buffer, static_cast<size_t>(size));
LocalFree(msg_buffer);
return message;
#else
return std::string{dlerror()};
#endif // _WIN32
}

template<typename T>
auto get_alias(std::string const& name) noexcept -> T*
{
#ifdef _WIN32
auto symbol = GetProcAddress(static_cast<HMODULE>(handle), name.c_str());
#else
auto symbol = dlsym(handle, name.c_str());
if(symbol == nullptr)
{
// Some platforms export with additional underscore, so try that.
auto const us_name = "_" + name;
symbol = dlsym(handle, us_name.c_str());
}
#endif // _WIN32
return function_cast_<T*>(symbol);
}
private:

template<typename T>
static auto function_cast_(auto ptr) noexcept -> T {
using generic_function_ptr = void (*)(void);
return reinterpret_cast<T>(reinterpret_cast<generic_function_ptr>(ptr));
}
};

}

#endif // CPP2_DLL_H
Loading