Commit 23be3256 authored by Tom Niget's avatar Tom Niget

Migrate class and method emission to new referencemodel

parent 316e4d8b
...@@ -20,7 +20,7 @@ public: ...@@ -20,7 +20,7 @@ public:
return sync_wrapper(std::forward<Args>(args)...); return sync_wrapper(std::forward<Args>(args)...);
} }
}; };
/*
struct method {}; struct method {};
template <typename Func, typename Self> template <typename Func, typename Self>
...@@ -52,5 +52,8 @@ auto dot_bind(Obj, Attr attr) { ...@@ -52,5 +52,8 @@ auto dot_bind(Obj, Attr attr) {
#define dotp(OBJ, NAME) [](auto && obj) -> auto { return dot_bind(obj, obj->NAME); }(OBJ) #define dotp(OBJ, NAME) [](auto && obj) -> auto { return dot_bind(obj, obj->NAME); }(OBJ)
#define dots(OBJ, NAME) [](auto && obj) -> auto { return std::remove_reference<decltype(obj)>::type::py_type::NAME; }(OBJ) #define dots(OBJ, NAME) [](auto && obj) -> auto { return std::remove_reference<decltype(obj)>::type::py_type::NAME; }(OBJ)
*/
#include "referencemodel.hpp"
#endif // TYPON_BASEDEF_HPP #endif // TYPON_BASEDEF_HPP
...@@ -25,17 +25,17 @@ ...@@ -25,17 +25,17 @@
#define _Args(...) __VA_ARGS__ #define _Args(...) __VA_ARGS__
#define COMMA() , #define COMMA() ,
#define METHOD(ret, name, args, ...) \ #define METHOD(ret, name, args, ...) \
static constexpr struct name##_s : method { \ static constexpr struct name##_s : referencemodel::method { \
template <typename Self> ret operator() args const __VA_ARGS__ \ template <typename Self> ret operator() args const __VA_ARGS__ \
} name{}; } name{};
#define METHOD_GEN(gen, ret, name, args, ...) \ #define METHOD_GEN(gen, ret, name, args, ...) \
static constexpr struct name##_s : method { \ static constexpr struct name##_s : referencemodel::method { \
template <typename Self, _Args gen> ret operator() args const __VA_ARGS__ \ template <typename Self, _Args gen> ret operator() args const __VA_ARGS__ \
} name{}; } name{};
#define FUNCTION(ret, name, args, ...) \ #define FUNCTION(ret, name, args, ...) \
struct { \ struct : referencemodel::staticmethod { \
ret operator() args const __VA_ARGS__ \ ret operator() args const __VA_ARGS__ \
} static constexpr name{}; } static constexpr name{};
......
#ifndef REFERENCEMODEL_H
#define REFERENCEMODEL_H
#include <array>
#include <atomic>
#include <cassert>
#include <concepts>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <string_view>
#include <type_traits>
#include <utility>
namespace referencemodel {
/* Object model forward declarations */
struct object;
template <typename T, typename O>
struct instance;
template <typename T>
struct classtype;
template <typename M>
struct moduletype;
struct function;
struct method;
struct classmethod;
struct staticmethod;
template <typename S, typename F>
struct boundmethod;
/* Reference model forward declarations */
template <typename T>
struct Pack;
template <typename T>
struct Rc;
template <typename T>
struct Arc;
template <typename T>
struct Box;
template <typename T>
struct Ref;
/* Meta-programming utilities */
namespace meta {
/* Meta-programming utilities: always_false */
template <typename T>
struct always_false_s {
constexpr static bool value {false};
};
template <typename T>
inline constexpr bool always_false = always_false_s<T>::value;
/* Meta-programming utilities: unwrap_one */
template <typename T>
struct unwrap_one_s {
using type = T;
};
template <typename T>
struct unwrap_one_s<Pack<T>> {
using type = T;
};
template <typename T>
struct unwrap_one_s<Rc<T>> {
using type = T;
};
template <typename T>
struct unwrap_one_s<Arc<T>> {
using type = T;
};
template <typename T>
struct unwrap_one_s<Box<T>> {
using type = T;
};
template <typename T>
struct unwrap_one_s<Ref<T>> {
using type = T;
};
template <typename T>
using unwrap_one = typename unwrap_one_s<std::remove_cvref_t<T>>::type;
/* Meta-programming utilities: unwrap_all */
template <typename T>
struct unwrap_all_s {
using type = unwrap_one<T>;
};
template <typename T>
struct unwrap_all_s<Ref<Pack<T>>> {
using type = T;
};
template <typename T>
struct unwrap_all_s<Ref<Arc<T>>> {
using type = T;
};
template <typename T>
struct unwrap_all_s<Box<Pack<T>>> {
using type = T;
};
template <typename T>
using unwrap_all = typename unwrap_all_s<std::remove_cvref_t<T>>::type;
/* Meta-programming utilities: unwrap_pack */
template <typename T>
struct unwrap_pack_s {
using type = unwrap_all<T>;
};
template <typename T>
struct unwrap_pack_s<Pack<T>> {
using type = Pack<T>;
};
template <typename T>
struct unwrap_pack_s<Ref<Pack<T>>> {
using type = Pack<T>;
};
template <typename T>
struct unwrap_pack_s<Ref<Arc<T>>> {
using type = Pack<T>;
};
template <typename T>
struct unwrap_pack_s<Box<Pack<T>>> {
using type = Pack<T>;
};
template <typename T>
using unwrap_pack = typename unwrap_pack_s<std::remove_cvref_t<T>>::type;
/* Meta-programming utilities for object model */
template <typename T>
concept instance = std::derived_from<
unwrap_all<T>,
referencemodel::instance<typename unwrap_all<T>::type, unwrap_all<T>>
>;
template <typename T>
concept classtype = !instance<T> && std::derived_from<
unwrap_all<T>,
referencemodel::classtype<
typename unwrap_all<T>::type
>
>;
template <typename F>
concept function = std::derived_from<F, referencemodel::function>;
template <typename F>
concept method = std::derived_from<F, referencemodel::method>;
template <typename F>
concept classmethod = std::derived_from<F, referencemodel::classmethod>;
template <typename F>
concept staticmethod = std::derived_from<F, referencemodel::staticmethod>;
template <typename T>
struct boundmethod_s {
static constexpr bool value = false;
};
template <typename S, typename F>
struct boundmethod_s<referencemodel::boundmethod<S, F>> {
static constexpr bool value = true;
};
template <typename T>
concept boundmethod = boundmethod_s<std::remove_cvref_t<T>>::value;
template <typename T>
concept value = !instance<T> && !boundmethod<T>;
/* Meta-programming utilities: wrapped and unwrapped */
template <typename T>
concept unwrapped = std::is_same_v<T, unwrap_one<T>>;
template <typename T>
concept wrapped = !unwrapped<T>;
/* Meta-programming utilities: wrapped_by */
template <typename T, template <typename> typename M>
struct wrapped_by_s {
static constexpr bool value {false};
};
template <typename T, template <typename> typename M>
struct wrapped_by_s<M<T>, M> {
static constexpr bool value {true};
};
template <typename T, template <typename> typename M>
concept wrapped_by = wrapped_by_s<std::remove_cvref<T>, M>::value;
/* Meta-programming utilities: pack */
template <typename T>
struct pack_s {
using type = Pack<unwrap_all<T>>;
};
template <value T>
struct pack_s<T> {
using type = T;
};
template <typename T>
using pack = typename pack_s<T>::type;
/* Meta-programming utilities: rc */
template <typename T>
struct rc_s {
using type = Rc<unwrap_all<T>>;
};
template <value T>
struct rc_s<T> {
using type = T;
};
template <typename T>
using rc = typename rc_s<T>::type;
/* Meta-programming utilities: arc */
template <typename T>
struct arc_s {
using type = Arc<unwrap_all<T>>;
};
template <value T>
struct arc_s<T> {
using type = T;
};
template <typename T>
using arc = typename arc_s<T>::type;
/* Meta-programming utilities: box */
template <typename T>
struct box_s {
using type = Box<unwrap_pack<T>>;
};
template <value T>
struct box_s<T> {
using type = T;
};
template <typename T>
using box = typename box_s<T>::type;
/* Meta-programming utilities: ref */
template <typename T>
struct ref_s {
using type = Ref<unwrap_all<T>>;
};
template <value T>
struct ref_s<T> {
using type = T;
};
template <typename T>
using ref = typename ref_s<T>::type;
/* Meta-programming utilities: borrow */
template <typename T>
struct borrow_s {
using type = ref<T>;
};
template <typename T>
struct borrow_s<Rc<T>> {
using type = Ref<Pack<T>>;
};
template <typename T>
struct borrow_s<Ref<Pack<T>>> {
using type = Ref<Pack<T>>;
};
template <typename T>
struct borrow_s<Arc<T>> {
using type = Ref<Arc<T>>;
};
template <typename T>
struct borrow_s<Ref<Arc<T>>> {
using type = Ref<Arc<T>>;
};
template <typename T>
using borrow = typename borrow_s<std::remove_cvref_t<T>>::type;
/* Meta-programming utilities: forward */
template <typename T>
struct forward_s {
using type = borrow<T>;
};
template <typename T>
struct forward_s<Box<T> &&> {
using type = Box<T>;
};
template <typename T>
using forward = typename forward_s<T>::type;
/* Meta-programming utilities: recover */
template <typename T>
struct recover_s {
using type = T;
};
template <value T>
struct recover_s<T> {
using type = T;
};
template <typename T>
struct recover_s<Ref<Pack<T>>> {
using type = Rc<T>;
};
template <typename T>
struct recover_s<Ref<Arc<T>>> {
using type = Arc<T>;
};
template <typename T>
using recover = typename recover_s<std::remove_cvref_t<T>>::type;
/* Meta-programming utilities: own */
template <typename T>
struct own_s {
using type = recover<T>;
};
template <unwrapped T>
struct own_s<Ref<T>> {
static_assert(always_false<T>, "Ref<T> cannot be owned");
};
template <typename T>
using own = typename own_s<std::remove_cvref_t<T>>::type;
/* Meta-programming utilities: common_forward */
template <typename...>
struct common_forward_s {};
template <typename... T>
using common_forward = typename common_forward_s<T...>::type;
template <typename T>
struct common_forward_s<T> {
using type = forward<T>;
};
template <typename T, typename U>
struct common_forward_s<T, U> {
using type = std::common_type_t<forward<T>, forward<U>>;
};
template <typename T>
struct common_forward_s<T, T> {
using type = forward<T>;
};
template <instance T, instance U>
requires std::is_same_v<forward<T>, forward<U>>
struct common_forward_s<T, U> {
using type = forward<T>;
};
template <instance T, instance U>
requires std::is_same_v<unwrap_all<T>, unwrap_all<U>>
&& (!std::is_same_v<forward<T>, forward<U>>)
struct common_forward_s<T, U> {
static_assert(!std::is_same_v<T, Box<unwrap_all<T>> &&>);
static_assert(!std::is_same_v<U, Box<unwrap_all<U>> &&>);
using type = ref<T>;
};
template <typename T, typename U, typename... V>
struct common_forward_s<T, U, V...> {
using type = common_forward<common_forward<T, U>, V...>;
};
} // namespace meta
/* Conversion functions */
template <typename T>
auto pack(T && t) {
return meta::pack<T>(std::forward<T>(t));
}
template <typename T>
auto rc(T && t) {
return meta::rc<T>(std::forward<T>(t));
}
template <typename T>
auto arc(T && t) {
return meta::arc<T>(std::forward<T>(t));
}
template <typename T>
auto box(T && t) {
return meta::box<T>(std::forward<T>(t));
}
template <typename T>
auto ref(T && t) {
return meta::ref<T>(std::forward<T>(t));
}
template <typename T>
auto borrow(T && t) {
return meta::borrow<T>(std::forward<T>(t));
}
template <typename T>
auto forward(T && t) {
return meta::forward<T &&>(std::forward<T>(t));
}
template <typename T>
auto recover(T && t) {
return meta::recover<T>(std::forward<T>(t));
}
template <typename T>
auto own(T && t) {
return meta::own<T>(std::forward<T>(t));
}
/* Utilities: NonNull */
template <typename T>
struct NonNull {
NonNull() = default;
NonNull(T * some) : ptr(some) {
assert(ptr);
};
NonNull & operator = (const T * some) {
ptr = some;
assert(ptr);
return *this;
}
NonNull(std::nullptr_t) : ptr(nullptr) {}
NonNull & operator = (std::nullptr_t) {
ptr = nullptr;
return *this;
}
T * operator -> () const { return ptr; }
operator T * () const { return ptr; }
operator bool () const { return ptr; }
private:
T * ptr;
};
/* Reference model */
template <typename T>
struct Pack {
static_assert(std::is_same_v<T, meta::unwrap_all<T>>);
static_assert(std::atomic_ref<std::uint32_t>::is_always_lock_free);
Pack() = default;
Pack(T && t) : rc(1), value(std::move(t)) {}
Pack(Pack &&) = default;
const T * operator -> () const { return std::addressof(value); }
T * operator -> () { return std::addressof(value); }
auto read_count() const { return rc; }
auto atomic_read_count() const {
return std::atomic_ref(rc).load(std::memory_order_relaxed);
}
friend struct Rc<T>;
friend struct Arc<T>;
friend struct Box<Pack>;
friend struct Ref<T>;
friend struct Ref<Pack>;
friend struct Ref<Arc<T>>;
private:
std::uint32_t rc = 1;
T value;
};
template <typename T>
struct Rc {
static_assert(std::is_same_v<T, meta::unwrap_all<T>>);
Rc() : ptr(nullptr) {}
Rc(std::nullptr_t) : ptr(nullptr) {}
Rc(T && t) : ptr(new Pack<T>(std::move(t))) {}
Rc(Pack<T> && pack) : ptr(new Pack<T>(std::move(pack))) {}
Rc(Pack<T> & pack) : ptr(&pack) {
ptr->rc++;
}
Rc(Rc && rc) : ptr(std::exchange(rc.ptr, nullptr)) {}
Rc(const Rc & rc) : ptr(rc.ptr) {
ptr->rc++;
}
Rc(const Ref<Pack<T>> & ref) : ptr(ref.ptr) {
assert(ptr->read_count());
ptr->rc++;
}
Rc(Box<Pack<T>> & box) : ptr(std::exchange(box.ptr, nullptr)) {
assert(!ptr->rc++);
}
Rc(Box<Pack<T>> && box) : ptr(std::exchange(box.ptr, nullptr)) {
assert(!ptr->rc++);
}
Rc & operator = (Rc rc) {
std::swap(ptr, rc.ptr);
return *this;
}
~Rc() {
if (ptr) { // null only if (swapped with a) moved from or uninitialised Rc
if (!--(ptr->rc)) {
delete ptr;
}
}
}
T* operator -> () const { return std::addressof(ptr->value); }
auto read_count() const { return ptr->read_count(); }
friend struct Box<Pack<T>>;
friend struct Ref<T>;
friend struct Ref<Pack<T>>;
private:
NonNull<Pack<T>> ptr;
};
template <typename T>
struct Arc {
static_assert(std::is_same_v<T, meta::unwrap_all<T>>);
Arc() : ptr(nullptr) {}
Arc(std::nullptr_t) : ptr(nullptr) {}
Arc(T && t) : ptr(new Pack<T>(std::move(t))) {}
Arc(Arc && arc) : ptr(std::exchange(arc.ptr, nullptr)) {}
Arc(const Arc & arc) : ptr(arc.ptr) {
std::atomic_ref(ptr->rc).fetch_add(1, std::memory_order_relaxed);
}
Arc(const Ref<Arc<T>> & ref) : ptr(ref.ptr) {
assert(ptr->atomic_read_count());
std::atomic_ref(ptr->rc).fetch_add(1, std::memory_order_relaxed);
}
Arc(Box<Pack<T>> & box) : ptr(std::exchange(box.ptr, nullptr)) {
assert(!std::atomic_ref(ptr->rc).fetch_add(1, std::memory_order_relaxed));
}
Arc(Box<Pack<T>> && box) : ptr(std::exchange(box.ptr, nullptr)) {
assert(!std::atomic_ref(ptr->rc).fetch_add(1, std::memory_order_relaxed));
}
Arc & operator = (Arc arc) {
std::swap(ptr, arc.ptr);
return *this;
}
~Arc() {
if (ptr) { // null only if (swapped with a) moved from or uninitialised Arc
if (std::atomic_ref(ptr->rc).fetch_sub(1, std::memory_order_release) == 1)
{
std::atomic_thread_fence(std::memory_order_acquire);
delete ptr;
}
}
}
T* operator -> () const { return std::addressof(ptr->value); }
auto read_count() const { return ptr->atomic_read_count(); }
friend struct Box<Pack<T>>;
friend struct Ref<T>;
friend struct Ref<Arc<T>>;
private:
NonNull<Pack<T>> ptr;
};
template <typename T>
struct Box {
static_assert(std::is_same_v<T, meta::unwrap_all<T>>);
Box() : ptr(nullptr) {}
Box(std::nullptr_t) : ptr(nullptr) {}
Box(T && t) : ptr(new T(std::move(t))) {}
Box(Box & box) : ptr(std::exchange(box.ptr, nullptr)) {}
Box(Box && box) : ptr(std::exchange(box.ptr, nullptr)) {}
Box & operator = (Box box) {
std::swap(ptr, box.ptr);
return *this;
}
~Box() {
if (ptr) { // null only if (swapped with a) moved from or uninitialised Box
delete ptr;
}
}
T* operator ->() const { return ptr; }
friend struct Ref<T>;
private:
NonNull<T> ptr;
};
template <typename T>
struct Box<Pack<T>> {
Box() : ptr(nullptr) {}
Box(std::nullptr_t) : ptr(nullptr) {}
Box(T && t) : ptr(new Pack<T>(std::move(t))) {
assert(!--(ptr->rc));
}
Box(Pack<T> && pack) : ptr(new Pack<T>(std::move(pack))) {
assert(!--(ptr->rc));
}
Box(Rc<T> && rc) : ptr(rc.ptr) {
assert(!--(ptr->rc));
}
Box(Arc<T> && rc) : ptr(rc.ptr) {
assert(
std::atomic_ref(ptr->rc).fetch_sub(1, std::memory_order_relaxed) == 1);
}
Box(Box & box) : ptr(std::exchange(box.ptr, nullptr)) {}
Box(Box && box) : ptr(std::exchange(box.ptr, nullptr)) {}
Box & operator = (Box box) {
std::swap(ptr, box.ptr);
return *this;
}
~Box() {
if (ptr) { // null only if (swapped with a) moved from or uninitialised Box
delete ptr;
}
}
T* operator ->() const { return ptr; }
friend struct Rc<T>;
friend struct Arc<T>;
friend struct Ref<T>;
private:
NonNull<Pack<T>> ptr;
};
template <typename T>
struct Ref {
static_assert(std::is_same_v<T, meta::unwrap_all<T>>);
Ref() = default;
Ref(T & t) : ptr(std::addressof(t)) {
}
Ref(const Ref &) = default;
Ref(Ref &&) = default;
Ref & operator = (Ref ref) {
ptr = ref.ptr;
return *this;
}
Ref(Pack<T> & pack) : ptr(std::addressof(pack.value)) {}
Ref(const Rc<T> & rc) : ptr(std::addressof(rc.ptr->value)) {}
Ref(const Arc<T> & arc) : ptr(std::addressof(arc.ptr->value)) {}
Ref(const Ref<Pack<T>> & ref) : ptr(std::addressof(ref.ptr->value)) {}
Ref(const Ref<Arc<T>> & ref) : ptr(std::addressof(ref.ptr->value)) {}
Ref(const Box<T> & box) : ptr(box.ptr) {}
Ref(const Box<Pack<T>> & box) : ptr(box.ptr) {}
T * operator ->() const {
return ptr; }
private:
NonNull<T> ptr;
};
template <typename T>
struct Ref<Pack<T>> {
Ref() = default;
Ref(Pack<T> & pack) : ptr(std::addressof(pack)) {}
Ref(const Ref &) = default;
Ref(Ref &&) = default;
Ref & operator = (Ref ref) {
ptr = ref.ptr;
return *this;
}
Ref(const Rc<T> & rc) : ptr(rc.ptr) {}
T * operator ->() const { return std::addressof(ptr->value); }
friend struct Rc<T>;
friend struct Ref<T>;
private:
NonNull<Pack<T>> ptr;
};
template <typename T>
struct Ref<Arc<T>> {
Ref() = default;
Ref(const Ref &) = default;
Ref(Ref &&) = default;
Ref & operator = (Ref ref) {
ptr = ref.ptr;
return *this;
}
Ref(const Arc<T> & arc) : ptr(arc.ptr) {}
T * operator ->() const { return std::addressof(ptr->value); }
friend struct Arc<T>;
friend struct Ref<T>;
private:
NonNull<Pack<T>> ptr;
};
template <typename T>
Ref(Rc<T> &) -> Ref<T>;
template <typename T>
Ref(Rc<T> &&) -> Ref<T>;
template <typename T>
Ref(Arc<T> &) -> Ref<T>;
template <typename T>
Ref(Arc<T> &&) -> Ref<T>;
template <typename T>
Ref(Box<T> &) -> Ref<meta::unwrap_all<T>>;
template <typename T>
Ref(Box<T> &&) -> Ref<meta::unwrap_all<T>>;
template <meta::wrapped T>
Ref(Ref<T> &) -> Ref<meta::unwrap_all<T>>;
template <meta::wrapped T>
Ref(Ref<T> &&) -> Ref<meta::unwrap_all<T>>;
/* Equality */
template <typename T, typename U>
requires meta::wrapped<T> || meta::wrapped<U>
bool operator == (const T & t, const U & u) {
return t.operator -> () == u.operator -> ();
}
namespace meta {
/* Compile-time string concatenation */
// taken from https://stackoverflow.com/a/62823211
template <std::string_view const&... Strs>
struct join_s {
// Join all strings into a single std::array of chars
static constexpr auto impl() noexcept
{
constexpr std::size_t len = (Strs.size() + ... + 0);
std::array<char, len + 1> arr{};
auto append = [i = 0, &arr](auto const& s) mutable {
for (auto c : s) arr[i++] = c;
};
(append(Strs), ...);
arr[len] = 0;
return arr;
}
// Give the joined string static storage
static constexpr auto arr = impl();
// View as a std::string_view
static constexpr std::string_view value {arr.data(), arr.size() - 1};
};
template <std::string_view const&... Strs>
static constexpr auto join = join_s<Strs...>::value;
} // namespace meta
/* Object model */
struct object {
template <typename T, typename O>
friend struct instance;
template <typename T>
friend struct classtype;
template <typename B, typename T>
friend struct classbodytype;
template <typename M>
friend struct moduletype;
private:
static constexpr std::string_view object_of_ = "object of ";
static constexpr std::string_view class_ = "class ";
static constexpr std::string_view module_ = "module ";
};
template <typename T, typename O>
struct instance : T::template body<> {
using type = T;
using body = T::template body<>;
static constexpr std::string_view repr = meta::join<object::object_of_, body::repr>;
const O * operator -> () const { return static_cast<const O *>(this); }
O * operator -> () { return static_cast<O *>(this); }
};
template <typename T>
struct classtype {
using type = T;
auto * operator -> () const { return &(T::_body); }
auto * operator -> () { return &(T::_body); }
};
template <typename B, typename T>
struct classbodytype : B {
using base = B;
static constexpr std::string_view repr = meta::join<object::class_, T::name>;
auto * operator -> () const { return static_cast<const T *>(this); }
auto * operator -> () { return static_cast<T *>(this); }
};
template <typename M>
struct moduletype : object {
using type = M;
static constexpr std::string_view repr = meta::join<object::module_, M::name>;
const M * operator -> () const { return static_cast<const M *>(this); }
M * operator -> () { return static_cast<M *>(this); }
};
struct function {};
struct method : function {};
struct classmethod : function {};
struct staticmethod : function {};
template <meta::instance T, meta::method G>
auto bind(T &&, const G &);
template <meta::classtype T, meta::classmethod G>
auto bind(T &&, const G &);
template <meta::instance T, meta::classmethod G>
auto bind(T &&, const G &);
template <typename S, typename F>
struct boundmethod : object {
using Self = S;
using Func = F;
boundmethod() = default;
boundmethod(boundmethod &) = default;
boundmethod(boundmethod &&) = default;
boundmethod & operator = (boundmethod &) = default;
boundmethod & operator = (boundmethod &&) = default;
template <typename T>
boundmethod(const boundmethod<T, F> & m) : self(m.self), func(m.func) {}
template <typename T>
boundmethod(boundmethod<T, F> && m) : self(std::move(m.self)), func(m.func) {}
template <typename T>
boundmethod & operator = (boundmethod <T, F> & m) {
func = m.func;
self = m.self;
return *this;
}
template <typename T>
boundmethod & operator = (boundmethod <T, F> && m) {
func = std::move(m.func);
self = std::move(m.self);
return *this;
}
template <typename... Args>
auto operator () (Args &&... args) & {
return func(forward(self), std::forward<Args>(args)...);
}
template <typename... Args>
auto operator () (Args &&... args) && {
return func(forward(std::move(self)), std::forward<Args>(args)...);
}
template <typename T, typename G>
friend struct boundmethod;
template <meta::instance T, meta::method G>
friend auto bind(T &&, const G &);
template <meta::classtype T, meta::classmethod G>
friend auto bind(T &&, const G &);
template <meta::instance T, meta::classmethod G>
friend auto bind(T &&, const G &);
const F & _func_() const {
return func;
}
const S & _self_() const {
return self;
}
private://TODO
template <typename T>
boundmethod(T && self, F func) : self(std::forward<T>(self)), func(func) {}
[[no_unique_address]] S self;
[[no_unique_address]] F func;
};
namespace meta {
/* Specialisations for boundmethod */
template <boundmethod T>
struct pack_s<T> {
using U = std::remove_cvref_t<T>;
using type = referencemodel::boundmethod<
pack<typename U::Self>, typename U::Func>;
};
template <boundmethod T>
struct rc_s<T> {
using U = std::remove_cvref_t<T>;
using type = referencemodel::boundmethod<
rc<typename U::Self>, typename U::Func>;
};
template <boundmethod T>
struct arc_s<T> {
using U = std::remove_cvref_t<T>;
using type = referencemodel::boundmethod<
arc<typename U::Self>, typename U::Func>;
};
template <boundmethod T>
struct box_s<T> {
using U = std::remove_cvref_t<T>;
using type = referencemodel::boundmethod<
box<typename U::Self>, typename U::Func>;
};
template <boundmethod T>
struct ref_s<T> {
using U = std::remove_cvref_t<T>;
using type = referencemodel::boundmethod<
ref<typename U::Self>, typename U::Func>;
};
template <boundmethod T>
struct borrow_s<T> {
using U = std::remove_cvref_t<T>;
using type = referencemodel::boundmethod<
borrow<typename U::Self>, typename U::Func>;
};
template <boundmethod T>
struct forward_s<T> {
using U = std::remove_cvref_t<T>;
using type = referencemodel::boundmethod<
forward<typename U::Self>, typename U::Func>;
};
template <boundmethod T>
struct forward_s<T &&> {
using U = std::remove_cvref_t<T>;
using type = referencemodel::boundmethod<
forward<typename U::Self &&>, typename U::Func>;
};
template <boundmethod T>
struct recover_s<T> {
using U = std::remove_cvref_t<T>;
using type = referencemodel::boundmethod<
recover<typename U::Self>, typename U::Func>;
};
template <boundmethod T>
struct own_s<T> {
using U = std::remove_cvref_t<T>;
using type = referencemodel::boundmethod<
own<typename U::Self>, typename U::Func>;
};
} // namespace meta
/* Attribute access with on-the-fly method binding */
template <meta::instance S, meta::method F>
auto bind(S && self, const F & func) {
return boundmethod<meta::forward<S &&>, F>(std::forward<S>(self), func);
}
template <meta::classtype S, meta::classmethod F>
auto bind(S && self, const F & func) {
return boundmethod<std::remove_cvref_t<S>, F> { self, func };
}
template <meta::instance S, meta::classmethod F>
auto bind(S &&, const F & func) {
using type = typename meta::unwrap_all<S>::type;
static_assert(sizeof(type) == 1);
return boundmethod<type, F> { type {}, func };
}
template <typename S, typename A, typename... T>
decltype(auto) bind(S &&, const A & attr, T...) {
return attr;
}
} // namespace referencemodel
#define dot(OBJ, NAME)\
[](auto && obj) -> decltype(auto) {\
return referencemodel::bind(std::forward<decltype(obj)>(obj), obj->NAME);\
}(OBJ)
#endif // REFERENCEMODEL_H
# coding: utf-8 # coding: utf-8
# norun
# https://lab.nexedi.com/xavier_thompson/typon-snippets/tree/master/references # https://lab.nexedi.com/xavier_thompson/typon-snippets/tree/master/references
class Person: class Person:
name: str name: str
...@@ -12,14 +12,15 @@ class Person: ...@@ -12,14 +12,15 @@ class Person:
def afficher(self): def afficher(self):
print(self.name, self.age) print(self.name, self.age)
def creer(): # def creer():
return Person("jean", 123) # return Person("jean", 123)
if __name__ == "__main__": if __name__ == "__main__":
y = Person y = Person
x = creer() #x = creer()
x = Person("jean", 123)
print(x.name) print(x.name)
print(x.age) print(x.age)
x.afficher() x.afficher()
y.afficher(x) #y.afficher(x)
...@@ -67,11 +67,12 @@ class NodeVisitor(UniversalVisitor): ...@@ -67,11 +67,12 @@ class NodeVisitor(UniversalVisitor):
elif node is TY_STR: elif node is TY_STR:
yield "PyStr" yield "PyStr"
elif isinstance(node, UserType): elif isinstance(node, UserType):
if node.is_reference: # if node.is_reference:
yield "PyObj<" # yield "PyObj<"
yield f"decltype({node.name})" #yield "auto"
if node.is_reference: yield f"referencemodel::Rc<decltype(__main__::{node.name})::Obj>"
yield "::py_type>" # if node.is_reference:
# yield "::py_type>"
elif isinstance(node, TypeType): elif isinstance(node, TypeType):
yield "auto" # TODO yield "auto" # TODO
elif isinstance(node, FunctionType): elif isinstance(node, FunctionType):
......
...@@ -84,7 +84,7 @@ class ClassInnerVisitor(NodeVisitor): ...@@ -84,7 +84,7 @@ class ClassInnerVisitor(NodeVisitor):
# from transpiler.phases.emit_cpp.block import BlockVisitor # from transpiler.phases.emit_cpp.block import BlockVisitor
# yield from BlockVisitor(self.scope).visit_func_new(node, FunctionEmissionKind.METHOD, True) # yield from BlockVisitor(self.scope).visit_func_new(node, FunctionEmissionKind.METHOD, True)
# yield f"}} {node.name} {{ this }};" # yield f"}} {node.name} {{ this }};"
yield f"struct {node.name}_m_s : method {{" yield f"struct {node.name}_m_s : referencemodel::method {{"
from transpiler.phases.emit_cpp.block import BlockVisitor from transpiler.phases.emit_cpp.block import BlockVisitor
yield from BlockVisitor(self.scope).visit_func_new(node, FunctionEmissionKind.METHOD) yield from BlockVisitor(self.scope).visit_func_new(node, FunctionEmissionKind.METHOD)
yield f"}} static constexpr {node.name} {{}};" yield f"}} static constexpr {node.name} {{}};"
...@@ -109,3 +109,29 @@ class ClassOuterVisitor(NodeVisitor): ...@@ -109,3 +109,29 @@ class ClassOuterVisitor(NodeVisitor):
# from transpiler.phases.emit_cpp.block import BlockVisitor # from transpiler.phases.emit_cpp.block import BlockVisitor
# yield from BlockVisitor(self.scope).visit_func_new(node, FunctionEmissionKind.METHOD) # yield from BlockVisitor(self.scope).visit_func_new(node, FunctionEmissionKind.METHOD)
# yield f"}} static constexpr {node.name} {{}};" # yield f"}} static constexpr {node.name} {{}};"
@dataclass
class ClassInnerVisitor2(NodeVisitor):
scope: Scope
def visit_AnnAssign(self, node: ast.AnnAssign) -> Iterable[str]:
yield ""
def visit_FunctionDef(self, node: ast.FunctionDef) -> Iterable[str]:
yield "struct : referencemodel::method {"
from transpiler.phases.emit_cpp.block import BlockVisitor
yield from BlockVisitor(self.scope).visit_func_new(node, FunctionEmissionKind.METHOD)
yield f"}} static constexpr {node.name} {{}};"
@dataclass
class ClassInnerVisitor4(NodeVisitor):
scope: Scope
def visit_AnnAssign(self, node: ast.AnnAssign) -> Iterable[str]:
member = self.scope.obj_type.fields[node.target.id]
yield from self.visit(member.type)
yield node.target.id
yield ";"
def visit_FunctionDef(self, node: ast.FunctionDef) -> Iterable[str]:
yield ""
\ No newline at end of file
...@@ -227,6 +227,8 @@ class ExpressionVisitor(NodeVisitor): ...@@ -227,6 +227,8 @@ class ExpressionVisitor(NodeVisitor):
use_dot = "dotp" use_dot = "dotp"
else: else:
use_dot = "dot" use_dot = "dot"
if use_dot:
use_dot = "dot"
if use_dot: if use_dot:
yield use_dot yield use_dot
yield "((" yield "(("
......
...@@ -4,7 +4,8 @@ from dataclasses import dataclass ...@@ -4,7 +4,8 @@ from dataclasses import dataclass
from typing import Iterable from typing import Iterable
from transpiler.phases.emit_cpp.block import BlockVisitor from transpiler.phases.emit_cpp.block import BlockVisitor
from transpiler.phases.emit_cpp.module import ModuleVisitor, ModuleVisitor2, ModuleVisitorExt from transpiler.phases.emit_cpp.module import ModuleVisitor, ModuleVisitor2, ModuleVisitorExt, ModuleVisitor3, \
ModuleVisitor4
# noinspection PyPep8Naming # noinspection PyPep8Naming
...@@ -22,10 +23,26 @@ class FileVisitor(BlockVisitor): ...@@ -22,10 +23,26 @@ class FileVisitor(BlockVisitor):
code = [line for stmt in node.body for line in visitor.visit(stmt)] code = [line for stmt in node.body for line in visitor.visit(stmt)]
yield from visitor.includes yield from visitor.includes
yield "namespace PROGRAMNS {" yield "namespace PROGRAMNS {"
yield "struct __main__ : referencemodel::moduletype<__main__> {"
yield from code yield from code
visitor = ModuleVisitor2(self.scope)
# visitor = ModuleVisitor2(self.scope)
# code = [line for stmt in node.body for line in visitor.visit(stmt)]
# yield from code
visitor = ModuleVisitor4(self.scope)
code = [line for stmt in node.body for line in visitor.visit(stmt)] code = [line for stmt in node.body for line in visitor.visit(stmt)]
yield from code yield from code
visitor = ModuleVisitor3(self.scope)
code = [line for stmt in node.body for line in visitor.visit(stmt)]
yield from code
yield "auto operator -> () const { return this; }"
yield "} __main__;"
yield "}" yield "}"
yield "#ifdef TYPON_EXTENSION" yield "#ifdef TYPON_EXTENSION"
yield f"PYBIND11_MODULE({self.module_name}, m) {{" yield f"PYBIND11_MODULE({self.module_name}, m) {{"
...@@ -37,6 +54,6 @@ class FileVisitor(BlockVisitor): ...@@ -37,6 +54,6 @@ class FileVisitor(BlockVisitor):
yield "#else" yield "#else"
yield "int main(int argc, char* argv[]) {" yield "int main(int argc, char* argv[]) {"
yield "py_sys::all.argv = typon::PyList<PyStr>(std::vector<PyStr>(argv, argv + argc));" yield "py_sys::all.argv = typon::PyList<PyStr>(std::vector<PyStr>(argv, argv + argc));"
yield "PROGRAMNS::root().call();" yield "PROGRAMNS::__main__.root().call();"
yield "}" yield "}"
yield "#endif" yield "#endif"
...@@ -8,7 +8,7 @@ from transpiler.phases.typing import FunctionType ...@@ -8,7 +8,7 @@ from transpiler.phases.typing import FunctionType
from transpiler.phases.typing.scope import Scope from transpiler.phases.typing.scope import Scope
from transpiler.phases.emit_cpp import CoroutineMode, FunctionEmissionKind, NodeVisitor, join from transpiler.phases.emit_cpp import CoroutineMode, FunctionEmissionKind, NodeVisitor, join
from transpiler.phases.emit_cpp.block import BlockVisitor from transpiler.phases.emit_cpp.block import BlockVisitor
from transpiler.phases.emit_cpp.class_ import ClassVisitor from transpiler.phases.emit_cpp.class_ import ClassVisitor, ClassInnerVisitor, ClassInnerVisitor2, ClassInnerVisitor4
from transpiler.phases.emit_cpp.function import FunctionVisitor from transpiler.phases.emit_cpp.function import FunctionVisitor
from transpiler.utils import compare_ast, highlight from transpiler.utils import compare_ast, highlight
...@@ -100,7 +100,8 @@ class ModuleVisitor(BlockVisitor): ...@@ -100,7 +100,8 @@ class ModuleVisitor(BlockVisitor):
raise NotImplementedError(node) raise NotImplementedError(node)
def visit_ClassDef(self, node: ast.ClassDef) -> Iterable[str]: def visit_ClassDef(self, node: ast.ClassDef) -> Iterable[str]:
yield from ClassVisitor().visit(node) #yield from ClassVisitor().visit(node)
yield from ()
def visit_FunctionDef(self, node: ast.FunctionDef) -> Iterable[str]: def visit_FunctionDef(self, node: ast.FunctionDef) -> Iterable[str]:
yield from super().visit_free_func(node, FunctionEmissionKind.DECLARATION) yield from super().visit_free_func(node, FunctionEmissionKind.DECLARATION)
...@@ -116,6 +117,68 @@ class ModuleVisitor2(NodeVisitor): ...@@ -116,6 +117,68 @@ class ModuleVisitor2(NodeVisitor):
yield "" yield ""
pass pass
@dataclass
class ModuleVisitor3(NodeVisitor):
scope: Scope
def visit_ClassDef(self, node: ast.ClassDef) -> Iterable[str]:
yield from ()
return
if gen_instances := getattr(node, "gen_instances", None):
for args, inst in gen_instances.items():
yield from self.visit_ClassDef(inst)
return
yield f"static constexpr _detail_<__main__>::{node.name}<> {node.name} {{}};"
def visit_FunctionDef(self, node: ast.FunctionDef) -> Iterable[str]:
yield from BlockVisitor(self.scope).visit_free_func(node, FunctionEmissionKind.DEFINITION)
@dataclass
class ModuleVisitor4(NodeVisitor):
scope: Scope
def visit_ClassDef(self, node: ast.ClassDef) -> Iterable[str]:
if gen_instances := getattr(node, "gen_instances", None):
for args, inst in gen_instances.items():
yield from self.visit_ClassDef(inst)
return
yield f"struct {node.name} : referencemodel::classtype<{node.name}> {{"
yield f"template <typename _Base0 = referencemodel::object>"
yield f"struct body : referencemodel::classbodytype<_Base0, body<>> {{"
yield f"static constexpr std::string_view name = \"{node.name}\";"
inner = ClassInnerVisitor2(node.inner_scope)
for stmt in node.body:
yield from inner.visit(stmt)
yield "};"
yield "static constexpr body _body{};"
yield "static_assert(sizeof _body == 1);"
yield f"struct Obj : referencemodel::instance<{node.name}, Obj> {{"
inner = ClassInnerVisitor4(node.inner_scope)
for stmt in node.body:
yield from inner.visit(stmt)
yield "template <typename... U>"
yield "Obj(U&&... args) {"
yield "dot(this, __init__)(this, std::forward<U>(args)...);"
yield "}"
yield "};"
yield "template <typename _Unused = void, typename... T>"
yield "auto operator() (T&&... args) const {"
yield "return referencemodel::rc(Obj{std::forward<T>(args)...});"
yield "}"
yield f"}} static constexpr {node.name} {{}};"
def visit_FunctionDef(self, node: ast.FunctionDef) -> Iterable[str]:
yield from ()
@dataclass @dataclass
class ModuleVisitorExt(NodeVisitor): class ModuleVisitorExt(NodeVisitor):
scope: Scope scope: Scope
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment