Commit 2e7eaeb0 authored by Tom Niget's avatar Tom Niget

Continue work on generics

parent a577191a
...@@ -5,23 +5,19 @@ ...@@ -5,23 +5,19 @@
#ifndef TYPON_BASEDEF_HPP #ifndef TYPON_BASEDEF_HPP
#define TYPON_BASEDEF_HPP #define TYPON_BASEDEF_HPP
template<typename Self> template <typename Self> class TyBuiltin {
class TyBuiltin { template <typename... Args> auto sync_wrapper(Args &&...args) {
template <typename... Args> return static_cast<Self *>(this)->sync(std::forward<Args>(args)...);
auto sync_wrapper(Args&&... args)
{
return static_cast<Self*>(this)->sync(std::forward<Args>(args)...);
} }
public: public:
template <typename... Args> template <typename... Args>
auto operator()(Args&&... args) -> decltype(sync_wrapper(std::forward<Args>(args)...)) auto operator()(Args &&...args)
{ -> decltype(sync_wrapper(std::forward<Args>(args)...)) {
return sync_wrapper(std::forward<Args>(args)...); return sync_wrapper(std::forward<Args>(args)...);
} }
}; };
/* /*
struct method {}; struct method {};
...@@ -50,9 +46,10 @@ auto dot_bind(Obj, Attr attr) { ...@@ -50,9 +46,10 @@ auto dot_bind(Obj, Attr attr) {
return attr; return attr;
} }
#define dot(OBJ, NAME) [](auto && obj) -> auto { return dot_bind(obj, obj.NAME); }(OBJ) #define dot(OBJ, NAME) [](auto && obj) -> auto { return dot_bind(obj, obj.NAME);
#define dotp(OBJ, NAME) [](auto && obj) -> auto { return dot_bind(obj, obj->NAME); }(OBJ) }(OBJ) #define dotp(OBJ, NAME) [](auto && obj) -> auto { return dot_bind(obj,
#define dots(OBJ, NAME) [](auto && obj) -> auto { return std::remove_reference<decltype(obj)>::type::py_type::NAME; }(OBJ) obj->NAME); }(OBJ) #define dots(OBJ, NAME) [](auto && obj) -> auto { return
std::remove_reference<decltype(obj)>::type::py_type::NAME; }(OBJ)
*/ */
......
...@@ -25,18 +25,19 @@ ...@@ -25,18 +25,19 @@
#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 : referencemodel::method { \ static constexpr struct name##_s \
template <typename Self> ret operator() args const __VA_ARGS__ \ : referencemodel::method{template <typename Self> ret operator() \
} name{}; args const __VA_ARGS__} name {};
#define METHOD_GEN(gen, ret, name, args, ...) \ #define METHOD_GEN(gen, ret, name, args, ...) \
static constexpr struct name##_s : referencemodel::method { \ static constexpr struct name##_s \
template <typename Self, _Args gen> ret operator() args const __VA_ARGS__ \ : referencemodel::method{ \
} name{}; template <typename Self, _Args gen> ret operator() \
args const __VA_ARGS__} name {};
#define FUNCTION(ret, name, args, ...) \ #define FUNCTION(ret, name, args, ...) \
struct : referencemodel::staticmethod { \ struct : referencemodel::staticmethod { \
ret operator() args const __VA_ARGS__ \ ret operator() args const __VA_ARGS__ \
} static constexpr name{}; } static constexpr name{};
using namespace std::literals; using namespace std::literals;
...@@ -61,46 +62,58 @@ template <PySmartPtr T> struct RealType<T> { ...@@ -61,46 +62,58 @@ template <PySmartPtr T> struct RealType<T> {
namespace typon { namespace typon {
//template <typename T> using TyObj = std::shared_ptr<typename RealType<T>::type>; // template <typename T> using TyObj = std::shared_ptr<typename
// RealType<T>::type>;
template<typename T> template <typename T>
class TyObj : public std::shared_ptr<typename RealType<T>::type> { class TyObj : public std::shared_ptr<typename RealType<T>::type> {
public: public:
using inner = typename RealType<T>::type; using inner = typename RealType<T>::type;
/*template<typename... Args> /*template<typename... Args>
TyObj(Args&&... args) : std::shared_ptr<inner>(std::make_shared<inner>(std::forward<Args>(args)...)) {}*/ TyObj(Args&&... args) :
std::shared_ptr<inner>(std::make_shared<inner>(std::forward<Args>(args)...))
TyObj() : std::shared_ptr<inner>() {} {}*/
TyObj(std::nullptr_t) : std::shared_ptr<inner>(nullptr) {}
TyObj(inner *ptr) : std::shared_ptr<inner>(ptr) {} TyObj() : std::shared_ptr<inner>() {}
TyObj(const std::shared_ptr<inner> &ptr) : std::shared_ptr<inner>(ptr) {} TyObj(std::nullptr_t) : std::shared_ptr<inner>(nullptr) {}
TyObj(std::shared_ptr<inner> &&ptr) : std::shared_ptr<inner>(ptr) {} TyObj(inner *ptr) : std::shared_ptr<inner>(ptr) {}
TyObj(const TyObj &ptr) : std::shared_ptr<inner>(ptr) {} TyObj(const std::shared_ptr<inner> &ptr) : std::shared_ptr<inner>(ptr) {}
TyObj( TyObj &ptr) : std::shared_ptr<inner>(ptr) {} TyObj(std::shared_ptr<inner> &&ptr) : std::shared_ptr<inner>(ptr) {}
TyObj(TyObj &&ptr) : std::shared_ptr<inner>(ptr) {} TyObj(const TyObj &ptr) : std::shared_ptr<inner>(ptr) {}
TyObj &operator=(const TyObj &ptr) { std::shared_ptr<inner>::operator=(ptr); return *this; } TyObj(TyObj &ptr) : std::shared_ptr<inner>(ptr) {}
TyObj &operator=(TyObj &&ptr) { std::shared_ptr<inner>::operator=(ptr); return *this; } TyObj(TyObj &&ptr) : std::shared_ptr<inner>(ptr) {}
TyObj &operator=(std::nullptr_t) { std::shared_ptr<inner>::operator=(nullptr); return *this; } TyObj &operator=(const TyObj &ptr) {
TyObj &operator=(inner *ptr) { std::shared_ptr<inner>::operator=(ptr); return *this; } std::shared_ptr<inner>::operator=(ptr);
TyObj &operator=(const std::shared_ptr<inner> &ptr) { std::shared_ptr<inner>::operator=(ptr); return *this; } return *this;
}
template<typename U> TyObj &operator=(TyObj &&ptr) {
TyObj(const TyObj<U> &ptr) : std::shared_ptr<inner>(ptr) {} std::shared_ptr<inner>::operator=(ptr);
return *this;
}
TyObj &operator=(std::nullptr_t) {
std::shared_ptr<inner>::operator=(nullptr);
return *this;
}
TyObj &operator=(inner *ptr) {
std::shared_ptr<inner>::operator=(ptr);
return *this;
}
TyObj &operator=(const std::shared_ptr<inner> &ptr) {
std::shared_ptr<inner>::operator=(ptr);
return *this;
}
//TyObj(TyObj<U> &&ptr) : std::shared_ptr<inner>(ptr) {} template <typename U>
TyObj(const TyObj<U> &ptr) : std::shared_ptr<inner>(ptr) {}
// TyObj(TyObj<U> &&ptr) : std::shared_ptr<inner>(ptr) {}
// using make_shared // using make_shared
/*template<class U> /*template<class U>
TyObj(U&& other) : std::shared_ptr<inner>(std::make_shared<inner>(other)) {}*/ TyObj(U&& other) : std::shared_ptr<inner>(std::make_shared<inner>(other)) {}*/
template <class U> bool operator==(const TyObj<U> &other) const {
template<class U>
bool operator==(const TyObj<U> &other) const {
// check null // check null
if (this->get() == other.get()) { if (this->get() == other.get()) {
return true; return true;
...@@ -113,8 +126,7 @@ public: ...@@ -113,8 +126,7 @@ public:
return *this->get() == *other.get(); return *this->get() == *other.get();
} }
template<class U> template <class U> bool operator==(const U &other) const {
bool operator==(const U& other) const {
if (this->get() == nullptr) { if (this->get() == nullptr) {
return false; return false;
} }
...@@ -122,49 +134,50 @@ public: ...@@ -122,49 +134,50 @@ public:
return *this->get() == other; return *this->get() == other;
} }
template<class U> template <class U> bool py_is(const TyObj<U> &other) const {
bool py_is(const TyObj<U> &other) const {
return this->get() == other.get(); return this->get() == other.get();
} }
}; };
template <typename T, typename... Args> auto tyObj(Args &&...args) -> TyObj<typename RealType<T>::type> { template <typename T, typename... Args>
auto tyObj(Args &&...args) -> TyObj<typename RealType<T>::type> {
return std::make_shared<typename RealType<T>::type>( return std::make_shared<typename RealType<T>::type>(
std::forward<Args>(args)...); std::forward<Args>(args)...);
} }
template <typename T, typename... Args> auto pyobj_agg(Args &&...args) -> TyObj<T> { template <typename T, typename... Args>
return std::make_shared<typename RealType<T>::type>((typename RealType<T>::type) { std::forward<Args>(args)... }); auto pyobj_agg(Args &&...args) -> TyObj<T> {
return std::make_shared<typename RealType<T>::type>(
(typename RealType<T>::type){std::forward<Args>(args)...});
} }
class TyNone { class TyNone {};
};
} } // namespace typon
// typon_len // typon_len
template <typename T> template <typename T>
concept PyIterator = requires(T t) { concept PyIterator = requires(T t) {
{ t.py_next() } -> std::same_as<std::optional<T>>; { t.py_next() } -> std::same_as<std::optional<T>>;
}; };
template <typename T> template <typename T>
concept PyIterable = requires(T t) { concept PyIterable = requires(T t) {
{ t.py_iter() } -> PyIterator; { t.py_iter() } -> PyIterator;
}; };
template <PyIterable T, PyIterator U> U iter(const T &t) { return t.py_iter(); } template <PyIterable T, PyIterator U> U iter(const T &t) { return t.py_iter(); }
template <typename T> template <typename T>
concept CppSize = requires(const T &t) { concept CppSize = requires(const T &t) {
{ t.size() } -> std::same_as<size_t>; { t.size() } -> std::same_as<size_t>;
}; };
template <typename T> template <typename T>
concept PyLen = requires(const T &t) { concept PyLen = requires(const T &t) {
{ t.py_len() } -> std::same_as<size_t>; { t.py_len() } -> std::same_as<size_t>;
}; };
template <CppSize T> template <CppSize T>
requires(!PyLen<T>) requires(!PyLen<T>)
...@@ -176,8 +189,10 @@ template <PyLen T> size_t len(const T &t) { return t.py_len(); } ...@@ -176,8 +189,10 @@ template <PyLen T> size_t len(const T &t) { return t.py_len(); }
template <typename T> template <typename T>
concept PyNext = requires(T t) { concept PyNext = requires(T t) {
{ t.py_next() } -> std::same_as<std::optional<typename T::value_type>>; {
}; t.py_next()
} -> std::same_as<std::optional<typename T::value_type>>;
};
struct { struct {
template <PyNext T> template <PyNext T>
...@@ -193,8 +208,6 @@ std::ostream &operator<<(std::ostream &os, std::optional<T> const &opt) { ...@@ -193,8 +208,6 @@ std::ostream &operator<<(std::ostream &os, std::optional<T> const &opt) {
return opt ? os << opt.value() : os << "None"; return opt ? os << opt.value() : os << "None";
} }
bool is_cpp() { return true; }
static constexpr auto PyNone = std::nullopt; static constexpr auto PyNone = std::nullopt;
#define system_error(err, message) \ #define system_error(err, message) \
...@@ -203,8 +216,8 @@ static constexpr auto PyNone = std::nullopt; ...@@ -203,8 +216,8 @@ static constexpr auto PyNone = std::nullopt;
throw fmt::system_error(err, message); \ throw fmt::system_error(err, message); \
} while (0) } while (0)
// #include "builtins/complex.hpp"
#include "builtins/bool.hpp" #include "builtins/bool.hpp"
#include "builtins/complex.hpp"
#include "builtins/dict.hpp" #include "builtins/dict.hpp"
#include "builtins/int.hpp" #include "builtins/int.hpp"
#include "builtins/list.hpp" #include "builtins/list.hpp"
...@@ -214,61 +227,72 @@ static constexpr auto PyNone = std::nullopt; ...@@ -214,61 +227,72 @@ static constexpr auto PyNone = std::nullopt;
#include "builtins/slice.hpp" #include "builtins/slice.hpp"
#include "builtins/str.hpp" #include "builtins/str.hpp"
struct file_s { auto is_cpp() { return typon::TyBool(true); }
struct py_type {
METHOD( namespace typon {
typon::Task<TyStr>, read, (Self self, size_t size = -1), { using namespace referencemodel;
if (size == -1) { template <typename _Base0 = object>
size = self->len; struct TyFile__oo : classtype<_Base0, TyFile__oo<>> {
} struct : method {
TyStr buf(size, '\0'); Task<TyStr__oo<>::Obj> operator()(auto self, size_t size = -1) {
int nbytes = co_await typon::io::read(self->fd, buf.data(), size); if (size == -1) {
if (nbytes < 0) { size = self->len;
system_error(-nbytes, "read()"); }
} std::string buf(size, '\0');
buf.resize(nbytes); int nbytes = co_await typon::io::read(self->fd, buf.data(), size);
co_return std::move(buf); if (nbytes < 0) {
}) system_error(-nbytes, "read()");
METHOD( }
typon::Task<int>, write, (Self self, const std::string &buf), { buf.resize(nbytes);
int nbytes = co_await typon::io::write(self->fd, buf); co_return std::move(TyStr__oo<>::Obj(buf));
if (nbytes < 0) { }
system_error(-nbytes, "write()"); } static constexpr read{};
}
co_return nbytes; struct : method {
}) Task<TyInt__oo<>::Obj> operator()(auto self, auto buf) {
METHOD( int nbytes = co_await typon::io::write(self->fd, buf->value);
typon::Task<void>, close, (Self self), if (nbytes < 0) {
{ co_await typon::io::close(self->fd); }) system_error(-nbytes, "write()");
METHOD( }
typon::Task<void>, flush, (Self self), co_return TyInt(nbytes);
{ co_await typon::io::fsync(self->fd); }) }
} static constexpr write{};
py_type(int fd = -1, size_t len = 0) : fd(fd), len(len) {}
struct : method {
py_type(const py_type &other) Task<void> operator()(auto self) { co_await typon::io::close(self->fd); }
: fd(other.fd), len(other.len) {} } static constexpr close{};
METHOD( struct : method {
auto, py_enter, (Self self), { return self; }) Task<void> operator()(auto self) { co_await typon::io::fsync(self->fd); }
} static constexpr flush{};
METHOD(
typon::Task<bool>, py_exit, (Self self), { struct Obj : value<TyStr__oo<>, Obj> {
co_await dotp(self, close)(); Obj(int fd = -1, size_t len = 0) : fd(fd), len(len) {}
co_return true;
}) Obj(const Obj &other) : fd(other.fd), len(other.len) {}
int fd; int fd;
size_t len; size_t len;
}; };
} file;
namespace typon { struct : method {
using PyFile = TyObj<decltype(file)::py_type>; auto operator()(auto self) { return self; }
} } static constexpr __enter__{};
typon::Task<typon::PyFile> open(const TyStr &path, std::string_view mode) { struct : method {
const char *path_c = path.c_str(); Task<bool> operator()(auto self) {
co_await dot(self, close)();
co_return true;
}
} static constexpr __exit__{};
};
static constexpr TyFile__oo<> TyFile{};
} // namespace typon
typon::Task<typon::TyFile__oo<>::Obj> open(auto path, std::string_view mode) {
const char *path_c = path->value.c_str();
size_t len = 0; size_t len = 0;
struct statx statxbuf; struct statx statxbuf;
if (int err = co_await typon::io::statx(AT_FDCWD, path_c, 0, STATX_SIZE, if (int err = co_await typon::io::statx(AT_FDCWD, path_c, 0, STATX_SIZE,
...@@ -315,7 +339,7 @@ typon::Task<typon::PyFile> open(const TyStr &path, std::string_view mode) { ...@@ -315,7 +339,7 @@ typon::Task<typon::PyFile> open(const TyStr &path, std::string_view mode) {
std::cerr << path << "," << flags << std::endl; std::cerr << path << "," << flags << std::endl;
system_error(-fd, "openat()"); system_error(-fd, "openat()");
} }
co_return typon::tyObj<typon::PyFile>(fd, len); co_return typon::TyFile__oo<>::Obj(fd, len);
} }
#include <typon/generator.hpp> #include <typon/generator.hpp>
...@@ -326,55 +350,61 @@ namespace py = pybind11; ...@@ -326,55 +350,61 @@ namespace py = pybind11;
#include <utility> #include <utility>
template <typename Ref> template <typename Ref> struct lvalue_or_rvalue {
struct lvalue_or_rvalue {
Ref &&ref; Ref &&ref;
template <typename Arg> template <typename Arg>
constexpr lvalue_or_rvalue(Arg &&arg) noexcept constexpr lvalue_or_rvalue(Arg &&arg) noexcept : ref(std::move(arg)) {}
: ref(std::move(arg))
{ }
constexpr operator Ref& () const & noexcept { return ref; }
constexpr operator Ref&& () const && noexcept { return std::move(ref); }
constexpr Ref& operator*() const noexcept { return ref; }
constexpr Ref* operator->() const noexcept { return &ref; }
constexpr operator Ref &() const &noexcept { return ref; }
constexpr operator Ref &&() const &&noexcept { return std::move(ref); }
constexpr Ref &operator*() const noexcept { return ref; }
constexpr Ref *operator->() const noexcept { return &ref; }
}; };
namespace typon { namespace typon {
template< class... Types > template <class... Types> using PyTuple = std::tuple<Types...>;
using PyTuple = std::tuple<Types...>;
} }
template<typename T> template <typename T> auto &iter_fix_ref(T &obj) { return obj; }
auto& iter_fix_ref(T& obj) { return obj; }
template<PySmartPtr T> template <PySmartPtr T> auto &iter_fix_ref(T &obj) { return *obj; }
auto& iter_fix_ref(T& obj) { return *obj; }
namespace std { namespace std {
template <class T> auto begin(std::shared_ptr<T> &obj) { return dot(obj, begin)(); } template <class T> auto begin(std::shared_ptr<T> &obj) {
return dot(obj, begin)();
}
template <class T> auto end(std::shared_ptr<T> &obj) { return dot(obj, end)(); } template <class T> auto end(std::shared_ptr<T> &obj) { return dot(obj, end)(); }
} } // namespace std
template <typename T> template <typename T> struct AlwaysTrue { // (1)
struct AlwaysTrue { // (1) constexpr bool operator()(const T &) const { return true; }
constexpr bool operator()(const T&) const {
return true;
}
}; };
template <typename Seq> /*template <typename Seq>
struct ValueTypeEx { struct ValueTypeEx {
using type = decltype(*std::begin(std::declval<Seq&>())); using type = decltype(*std::begin(std::declval<Seq>()));
};*/
// has ::iterator type
template <typename T> struct ValueType {
using type = typename T::iterator::value_type;
};
template <typename T>
concept HasIterator = requires(T t) { typename T::iterator; };
template <HasIterator T> struct ValueType<T> {
using type = typename T::iterator::value_type;
}; };
// (2) // (2)
/*template <typename Map, typename Seq, typename Filt = AlwaysTrue<typename ValueTypeEx<Seq>::type>> /*template <typename Map, typename Seq, typename Filt = AlwaysTrue<typename
typon::Task< mapFilter(Map map, Seq seq, Filt filt = Filt()) { ValueTypeEx<Seq>::type>> typon::Task< mapFilter(Map map, Seq seq, Filt filt =
Filt()) {
//typedef typename Seq::value_type value_type; //typedef typename Seq::value_type value_type;
using value_type = typename ValueTypeEx<Seq>::type; using value_type = typename ValueTypeEx<Seq>::type;
...@@ -389,49 +419,53 @@ typon::Task< mapFilter(Map map, Seq seq, Filt filt = Filt()) { ...@@ -389,49 +419,53 @@ typon::Task< mapFilter(Map map, Seq seq, Filt filt = Filt()) {
return typon::TyList(std::move(result)); return typon::TyList(std::move(result));
}*/ }*/
#define MAP_FILTER(item, seq, map, filter) ({\ #define MAP_FILTER(item, seq, map, filter) \
using value_type = typename ValueTypeEx<decltype(seq)>::type;\ ({ \
value_type item;\ using value_type = ValueType<decltype(seq)>::type; \
std::vector<decltype(map)> result{};\ value_type item; \
for (auto item : seq) {\ std::vector<decltype(map)> result{}; \
if (filter) {\ for (auto item : seq) { \
result.push_back(map);\ if (filter) { \
}\ result.push_back(map); \
}\ } \
typon::TyList(std::move(result));\ } \
}) typon::TyList(std::move(result)); \
})
namespace PYBIND11_NAMESPACE { namespace PYBIND11_NAMESPACE {
namespace detail { namespace detail {
template <typename T> struct type_caster<typon::Task<T>> { template <typename T> struct type_caster<typon::Task<T>> {
using type = typon::Task<T>; using type = typon::Task<T>;
using res_conv = make_caster<T>; using res_conv = make_caster<T>;
public:
PYBIND11_TYPE_CASTER(type, const_name("Task[") + res_conv::name + const_name("]")); public:
PYBIND11_TYPE_CASTER(type,
template <typename U> const_name("Task[") + res_conv::name + const_name("]"));
static handle cast(U&& src, return_value_policy policy, handle parent) {
return res_conv::cast(std::forward<T>(std::move(src).call()), policy, parent); template <typename U>
} static handle cast(U &&src, return_value_policy policy, handle parent) {
}; return res_conv::cast(std::forward<T>(std::move(src).call()), policy,
} parent);
} }
};
} // namespace detail
} // namespace PYBIND11_NAMESPACE
#ifdef TYPON_EXTENSION #ifdef TYPON_EXTENSION
class InterpGuard { class InterpGuard {
PyThreadState* main; PyThreadState *main;
PyThreadState* sub; PyThreadState *sub;
public: public:
InterpGuard() { InterpGuard() {
/*main = PyThreadState_Get(); /*main = PyThreadState_Get();
sub = Py_NewInterpreter();*/ sub = Py_NewInterpreter();*/
} }
~InterpGuard() { ~InterpGuard() {
/*Py_EndInterpreter(sub); /*Py_EndInterpreter(sub);
PyThreadState_Swap(main);*/ PyThreadState_Swap(main);*/
} }
}; };
#else #else
using InterpGuard = py::scoped_interpreter; using InterpGuard = py::scoped_interpreter;
......
...@@ -7,10 +7,36 @@ ...@@ -7,10 +7,36 @@
#include <ostream> #include <ostream>
#include "print.hpp" #include "../referencemodel.hpp"
#include "str.hpp"
template <> void print_to<bool>(const bool &x, std::ostream &s) { namespace typon {
s << (x ? "True" : "False"); using namespace referencemodel;
} template <typename _Base0 = object>
struct TyBool__oo : classtype<_Base0, TyBool__oo<>> {
static constexpr std::string_view name = "TyBool";
struct : method {
auto operator()(auto self) const {
return TyStr(self->value ? "True" : "False");
}
} static constexpr oo__str__oo{};
static constexpr auto oo__repr__oo = oo__str__oo;
struct Obj : value<TyBool__oo<>, Obj> {
bool value;
constexpr Obj(bool value = false) : value(value) {}
constexpr operator bool() const { return value; }
};
/*static constexpr Obj TRUE = Obj(true);
static constexpr Obj FALSE = Obj(false);*/
auto operator()(bool value) const { return Obj(value); }
};
static constexpr TyBool__oo<> TyBool{};
} // namespace typon
#endif // TYPON_BOOL_HPP #endif // TYPON_BOOL_HPP
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#ifndef TYPON_BYTES_H #ifndef TYPON_BYTES_H
#define TYPON_BYTES_H #define TYPON_BYTES_H
class TyStr; /*class TyStr;
class TyBytes : public std::string { class TyBytes : public std::string {
public: public:
...@@ -16,12 +16,37 @@ public: ...@@ -16,12 +16,37 @@ public:
TyBytes(size_t count, char ch) : std::string(count, ch) {} TyBytes(size_t count, char ch) : std::string(count, ch) {}
template <class InputIterator> template <class InputIterator>
TyBytes(InputIterator first, InputIterator last) : std::string(first, last) {} TyBytes(InputIterator first, InputIterator last) : std::string(first, last) {}
//TyStr decode_inner(const std::string &encoding = "utf-8") const; // TyStr decode_inner(const std::string &encoding = "utf-8") const;
METHOD(TyStr, decode, (Self self, const std::string &encoding = "utf-8"), ;) METHOD(TyStr, decode, (Self self, const std::string &encoding = "utf-8"), ;)
};*/
namespace typon {
using namespace referencemodel;
template <typename _Base0 = object>
struct TyBytes__oo : classtype<_Base0, TyBytes__oo<>> {
static constexpr std::string_view name = "TyBytes";
struct : method {
auto operator()(auto self, auto other) const {
return Obj(dot(self, value) + dot(other, value));
}
} static constexpr oo__add__oo{};
struct Obj : value<TyBytes__oo<>, Obj> {
std::string value;
constexpr Obj() : value() {}
constexpr Obj(std::string value) : value(value) {}
operator std::string() const { return value; }
};
auto operator()(std::string value) const { return Obj(value); }
}; };
static constexpr TyBytes__oo<> TyBytes{};
#endif // TYPON_BYTES_H } // namespace typon
#endif // TYPON_BYTES_H
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
#ifndef TYPON_DICT_HPP #ifndef TYPON_DICT_HPP
#define TYPON_DICT_HPP #define TYPON_DICT_HPP
#include <unordered_map>
#include <pybind11/stl.h> #include <pybind11/stl.h>
#include <unordered_map>
/* /*
template <typename K, typename V> template <typename K, typename V>
...@@ -87,7 +87,7 @@ TyDict(std::initializer_list<std::pair<K, V>>) -> TyDict<K, V>;*/ ...@@ -87,7 +87,7 @@ TyDict(std::initializer_list<std::pair<K, V>>) -> TyDict<K, V>;*/
namespace typon { namespace typon {
template <typename K, typename V> class TyDict { /*template <typename K, typename V> class TyDict {
public: public:
TyDict(std::shared_ptr<std::unordered_map<K, V>> &&m) : _m(std::move(m)) {} TyDict(std::shared_ptr<std::unordered_map<K, V>> &&m) : _m(std::move(m)) {}
TyDict(std::unordered_map<K, V> &&m) TyDict(std::unordered_map<K, V> &&m)
...@@ -132,14 +132,87 @@ public: ...@@ -132,14 +132,87 @@ public:
private: private:
std::shared_ptr<std::unordered_map<K, V>> _m; std::shared_ptr<std::unordered_map<K, V>> _m;
};*/
} // namespace typon
/*namespace PYBIND11_NAMESPACE {
namespace detail {
template <typename K, typename V>
struct type_caster<typon::TyDict<K, V>>
: map_caster<typon::TyDict<K, V>, K, V> {};
} // namespace detail
} // namespace PYBIND11_NAMESPACE*/
namespace typon {
using namespace referencemodel;
template <typename _Base0 = object>
struct TyDict__oo : classtype<_Base0, TyDict__oo<>> {
struct : method {
template <typename Self> auto operator()(Self self) const {
std::stringstream s;
s << '{';
if (self->_m->size() > 0) {
s << repr(self->_m->begin()->first)->value;
s << ": ";
s << repr(self->_m->begin()->second)->value;
for (auto it = ++self->_m->begin(); it != self->_m->end(); it++) {
s << ", ";
s << repr(it->first)->value;
s << ": ";
s << repr(it->second)->value;
}
}
s << '}';
return typon::TyStr__oo<>::Obj(s.str());
}
} static constexpr oo__repr__oo{};
static constexpr auto oo__str__oo = oo__repr__oo;
template <typename K, typename V> struct Obj : instance<TyDict__oo<>, Obj<K, V>> {
std::shared_ptr<std::unordered_map<K, V>> _m;
Obj(std::shared_ptr<std::unordered_map<K, V>> &&m) : _m(std::move(m)) {}
Obj(std::unordered_map<K, V> &&m)
: _m(std::move(
std::make_shared<std::unordered_map<K, V>>(std::move(m)))) {}
Obj(std::initializer_list<std::pair<K, V>> &&m)
: _m(std::make_shared<std::unordered_map<K, V>>(std::move(m))) {}
Obj() : _m(std::make_shared<std::unordered_map<K, V>>()) {}
template <typename... Args>
Obj(Args &&...args)
: _m(std::make_shared<std::unordered_map<K, V>>(
std::forward<Args>(args)...)) {}
};
template <typename T> auto operator()(std::initializer_list<T> &&v) const {
return rc(Obj(std::move(v)));
}
template <typename... Args> auto operator()(Args &&...args) const {
return rc(Obj(std::forward<Args>(args)...));
}
}; };
} static constexpr TyDict__oo<> TyDict{};
} // namespace typon
/*template <typename T> auto dict(std::initializer_list<T> &&v) {
return typon::TyDict(std::move(v));
}*/
namespace PYBIND11_NAMESPACE { namespace PYBIND11_NAMESPACE {
namespace detail { namespace detail {
template <typename K, typename V> template <typename K, typename V>
struct type_caster<typon::TyDict<K, V>> : map_caster<typon::TyDict<K, V>, K, V> {}; struct type_caster<typon::TyDict__oo<>::Obj<K, V>>
}} : map_caster<typon::TyDict__oo<>::Obj<K, V>, K, V> {};
} // namespace detail
} // namespace PYBIND11_NAMESPACE
#endif // TYPON_DICT_HPP #endif // TYPON_DICT_HPP
...@@ -9,10 +9,10 @@ ...@@ -9,10 +9,10 @@
struct TyException_s { struct TyException_s {
struct py_type { struct py_type {
TyStr message; TyStr__oo<>::Obj message;
}; };
auto operator()(const TyStr &message) const { auto operator()(const TyStr__oo<>::Obj &message) const {
return py_type{message}; return py_type{message};
} }
}; };
......
...@@ -5,110 +5,98 @@ ...@@ -5,110 +5,98 @@
#ifndef TYPON_INT_HPP #ifndef TYPON_INT_HPP
#define TYPON_INT_HPP #define TYPON_INT_HPP
#include <algorithm>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <algorithm>
using namespace std::literals; using namespace std::literals;
#include "bytes.hpp" #include "str.hpp"
#include "print.hpp"
#include "slice.hpp"
// #include <format> // #include <format>
#include <fmt/format.h> #include <fmt/format.h>
#include <pybind11/cast.h> #include <pybind11/cast.h>
namespace typon { namespace typon {
/*template <typename _Base0 = object> using namespace referencemodel;
class TyInt__oo : classtype<_Base0, Integer__oo<>> {
public:
struct : method {
auto operator()(auto self, int value) const {
self->value = value;
}
} static constexpr oo__init__oo {};
struct : method {
auto operator()(auto self, auto other) const {
return Integer(dot(self, value) + dot(other, value));
}
} static constexpr oo__add__oo {};
auto operator () (int value) const {
struct Obj : instance<Integer__oo<>, Obj> {
int value;
};
auto obj = rc(Obj{});
dot(obj, oo__init__oo)(value);
return obj;
}
template <typename _Base0 = object>
struct TyInt__oo : classtype<_Base0, TyInt__oo<>> {
static constexpr std::string_view name = "TyInt";
struct : method {
auto operator()(auto self, auto other) const {
return Obj(dot(self, value) + dot(other, value));
}
} static constexpr oo__add__oo{};
constexpr TyInt(int value) : value(value) {} struct : method {
constexpr TyInt() : value(0) {} auto operator()(auto self, auto other) const {
return Obj(dot(self, value) - dot(other, value));
operator int() const { return value; } }
} static constexpr oo__sub__oo{};
// operators struct : method {
template <typename T> TyInt operator+(T x) const { return value + x; } auto operator()(auto self, auto other) const {
template <typename T> TyInt operator-(T x) const { return value - x; } return Obj(dot(self, value) * dot(other, value));
template <typename T> TyInt operator*(T x) const { return value * x; } }
template <typename T> TyInt operator/(T x) const { return value / x; } } static constexpr oo__mul__oo{};
template <typename T> TyInt operator%(T x) const { return value % x; }
template <typename T> TyInt operator&(T x) const { return value & x; }
template <typename T> TyInt operator|(T x) const { return value | x; }
template <typename T> TyInt operator^(T x) const { return value ^ x; }
template <typename T> TyInt operator<<(T x) const { return value << x; }
template <typename T> TyInt operator>>(T x) const { return value >> x; }
template <typename T> TyInt operator&&(T x) const { return value && x; }
template <typename T> TyInt operator||(T x) const { return value || x; }
template <typename T> TyInt operator==(T x) const { return value == x; }
template <typename T> TyInt operator<(T x) const { return value < x; }
TyInt operator-() const { return -value; } struct : method {
auto operator()(auto self, auto other) const {
return Obj(dot(self, value) & dot(other, value));
}
} static constexpr oo__and__oo{};
struct : method {
auto operator()(auto self) const { return Obj(-dot(self, value)); }
} static constexpr oo__neg__oo{};
struct : method {
auto operator()(auto self, auto other) const {
return dot(self, value) < dot(other, value);
}
} static constexpr oo__lt__oo{};
struct : method {
auto operator()(auto self, auto other) const {
return dot(self, value) > dot(other, value);
}
} static constexpr oo__gt__oo{};
private: struct : method {
int value; auto operator()(auto self, auto other) const {
};*/ return TyInt(dot(self, value) % dot(other, value));
using namespace referencemodel; }
template <typename _Base0 = object> } static constexpr oo__mod__oo{};
struct Integer__oo : classtype<_Base0, Integer__oo<>> {
static constexpr std::string_view name = "Integer";
struct : method { struct : method {
auto operator()(auto self, int value) const { auto operator()(auto self, auto other) const {
self->value = value; return dot(self, value) >= dot(other, value);
} }
} static constexpr oo__init__oo {}; } static constexpr oo__ge__oo{};
struct : method { struct : method {
auto operator()(auto self, auto other) const { auto operator()(auto self) const {
return TyInt(dot(self, value) + dot(other, value)); return TyStr__oo<>::Obj(std::to_string(self->value));
} }
} static constexpr oo__add__oo {}; } static constexpr oo__str__oo{};
struct Obj : value<Integer__oo<>, Obj> { static constexpr auto oo__repr__oo = oo__str__oo;
int value;
Obj(int value=0) : value(value) {} struct Obj : value<TyInt__oo<>, Obj> {
operator int() const { return value; } int value;
};
auto operator () (int value) const { Obj(int value = 0) : value(value) {}
auto obj = rc(Obj{}); operator int() const { return value; }
dot(obj, oo__init__oo)(value);
return obj;
}
}; };
static constexpr Integer__oo<> TyInt {};
} auto operator()(int value) const { return Obj(value); }
};
static constexpr TyInt__oo<> TyInt{};
} // namespace typon
inline auto operator ""_pi(unsigned long long int v) noexcept { inline auto operator""_pi(unsigned long long int v) noexcept {
return typon::TyInt(v); return typon::TyInt(v);
} }
...@@ -120,15 +108,8 @@ template <> struct std::hash<decltype(0_pi)> { ...@@ -120,15 +108,8 @@ template <> struct std::hash<decltype(0_pi)> {
namespace PYBIND11_NAMESPACE { namespace PYBIND11_NAMESPACE {
namespace detail { namespace detail {
template<> template <> struct type_caster<decltype(0_pi)> : type_caster<int> {};
struct type_caster<decltype(0_pi)> } // namespace detail
: type_caster<int> {}; } // namespace PYBIND11_NAMESPACE
}}
template <> void repr_to(const decltype(0_pi) &x, std::ostream &s) {
s << x;
}
template <> void print_to<decltype(0_pi)>(const decltype(0_pi) &x, std::ostream &s) { s << x; }
#endif // TYPON_INT_HPP #endif // TYPON_INT_HPP
...@@ -8,14 +8,90 @@ ...@@ -8,14 +8,90 @@
#include <algorithm> #include <algorithm>
#include <ostream> #include <ostream>
#include <vector> #include <vector>
//#include <nanobind/stl/detail/nb_list.h> // #include <nanobind/stl/detail/nb_list.h>
#include <pybind11/stl.h> #include <pybind11/stl.h>
namespace typon { namespace typon {
using namespace referencemodel;
template <typename _Base0 = object>
struct TyList__oo : classtype<_Base0, TyList__oo<>> {
template <typename T> class TyList { struct : method {
public: template <typename Self> auto operator()(Self self) const {
using value_type = T; return TyList__oo<>{}(self->_v);
}
} static constexpr copy{};
struct : method {
template <typename Self, typename Other>
auto operator()(Self self, Other other) const {
self->_v.reserve(self->_v.size() + other.size());
self->_v.insert(self->_v.end(), other.begin(), other.end());
}
} static constexpr extend{};
struct : method {
template <typename Self, typename Other>
auto operator()(Self self, Other other) const {
auto result = TyList__oo<>{}(self->_v);
dot(result, extend)(other);
return result;
}
} static constexpr oo__add__oo{};
struct : method {
template <typename Self, typename Other>
auto operator()(Self self, Other other) const {
auto result = TyList__oo<>{}(self->_v);
result->_v->reserve(result->_v->size() * other);
for (int i = 0; i < other - 1; i++) {
dot(result, extend)(self);
}
return result;
}
} static constexpr oo__mul__oo{};
struct : method {
template <typename Self> auto operator()(Self self) const {
std::stringstream s;
s << '[';
if (self->_v->size() > 0) {
s << repr(self->_v->operator[](0))->value;
for (size_t i = 1; i < self->_v->size(); i++) {
s << ", ";
s << repr(self->_v->operator[](i))->value;
}
}
s << ']';
return typon::TyStr__oo<>::Obj(s.str());
}
} static constexpr oo__repr__oo{};
static constexpr auto oo__str__oo = oo__repr__oo;
template <typename T> struct Obj : instance<TyList__oo<>, Obj<T>> {
using value_type = T;
std::shared_ptr<std::vector<T>> _v;
Obj(std::shared_ptr<std::vector<T>> &&v) : _v(std::move(v)) {}
Obj(std::vector<T> &&v)
: _v(std::move(std::make_shared<std::vector<T>>(std::move(v)))) {}
Obj(std::initializer_list<T> &&v)
: _v(std::make_shared<std::vector<T>>(std::move(v))) {}
Obj() : _v(std::make_shared<std::vector<T>>()) {}
};
template <typename T> auto operator()(std::initializer_list<T> &&v) const {
return rc(Obj(std::move(v)));
}
template <typename... Args> auto operator()(Args &&...args) const {
return rc(Obj(std::forward<Args>(args)...));
}
/*
TyList(std::shared_ptr<std::vector<T>> &&v) : _v(std::move(v)) {} TyList(std::shared_ptr<std::vector<T>> &&v) : _v(std::move(v)) {}
TyList(std::vector<T> &&v) TyList(std::vector<T> &&v)
: _v(std::move(std::make_shared<std::vector<T>>(std::move(v)))) {} : _v(std::move(std::make_shared<std::vector<T>>(std::move(v)))) {}
...@@ -41,7 +117,7 @@ public: ...@@ -41,7 +117,7 @@ public:
void push_back(const T &value) { _v->push_back(value); } void push_back(const T &value) { _v->push_back(value); }
void clear() { _v->clear(); } void clear() { _v->clear(); }*/
/*operator std::vector<T>() const { /*operator std::vector<T>() const {
return std::vector<T>(this->begin(), this->end()); return std::vector<T>(this->begin(), this->end());
...@@ -51,7 +127,7 @@ public: ...@@ -51,7 +127,7 @@ public:
return *reinterpret_cast<std::vector<T> *>(this); return *reinterpret_cast<std::vector<T> *>(this);
}*/ }*/
constexpr const T &operator[](size_t i) const { return _v->operator[](i); } /*constexpr const T &operator[](size_t i) const { return _v->operator[](i); }
constexpr T &operator[](size_t i) { return _v->operator[](i); } constexpr T &operator[](size_t i) { return _v->operator[](i); }
size_t py_len() const { return _v->size(); } size_t py_len() const { return _v->size(); }
...@@ -68,44 +144,24 @@ public: ...@@ -68,44 +144,24 @@ public:
s << ']'; s << ']';
} }
void py_print(std::ostream &s) const { py_repr(s); } void py_print(std::ostream &s) const { py_repr(s); }*/
TyList<T> operator+(const TyList<T> &other) const {
std::vector<T> v;
v.reserve(_v->size() + other._v->size());
v.insert(v.end(), _v->begin(), _v->end());
v.insert(v.end(), other._v->begin(), other._v->end());
return TyList<T>(std::move(v));
}
TyList<T> operator*(size_t n) const {
TyList<T> v{};
v._v->reserve(this->_v->size() * n);
for (size_t i = 0; i < n; i++) {
v._v->insert(v._v->end(), this->_v->begin(), this->_v->end());
}
return v;
}
private:
std::shared_ptr<std::vector<T>> _v;
}; };
static constexpr TyList__oo<> TyList{};
} // namespace typon
template <typename T> auto list(std::initializer_list<T> &&v) {
return typon::TyList(std::move(v));
}
template <typename T> typon::TyList<T> list(std::initializer_list<T> &&v) {
return typon::TyList<T>(std::move(v));
} }
namespace PYBIND11_NAMESPACE { namespace PYBIND11_NAMESPACE {
namespace detail { namespace detail {
template <typename Type> template <typename Type>
struct type_caster<typon::TyList<Type>> : list_caster<typon::TyList<Type>, Type> {}; struct type_caster<typon::TyList__oo<>::Obj<Type>>
}} : list_caster<typon::TyList__oo<>::Obj<Type>, Type> {};
} // namespace detail
} // namespace PYBIND11_NAMESPACE
/*NAMESPACE_BEGIN(NB_NAMESPACE) /*NAMESPACE_BEGIN(NB_NAMESPACE)
NAMESPACE_BEGIN(detail) NAMESPACE_BEGIN(detail)
......
...@@ -5,12 +5,12 @@ ...@@ -5,12 +5,12 @@
#ifndef TYPON_PRINT_HPP #ifndef TYPON_PRINT_HPP
#define TYPON_PRINT_HPP #define TYPON_PRINT_HPP
#include <functional>
#include <iostream> #include <iostream>
#include <ostream> #include <ostream>
#include <functional>
#include <typon/typon.hpp> #include <typon/typon.hpp>
template <typename T> /*template <typename T>
concept Streamable = requires(const T &x, std::ostream &s) { concept Streamable = requires(const T &x, std::ostream &s) {
{ s << x } -> std::same_as<std::ostream &>; { s << x } -> std::same_as<std::ostream &>;
}; };
...@@ -42,14 +42,14 @@ concept Printable = requires(const T &x, std::ostream &s) { ...@@ -42,14 +42,14 @@ concept Printable = requires(const T &x, std::ostream &s) {
template <typename T> template <typename T>
concept Reprable = requires(const T &x, std::ostream &s) { concept Reprable = requires(const T &x, std::ostream &s) {
{ repr_to(x, s) } -> std::same_as<void>; { repr_to(x, s) } -> std::same_as<void>;
}; };*/
template <typename T> template <typename T>
concept FunctionPointer = concept FunctionPointer =
std::is_function_v<T> or std::is_member_function_pointer_v<T> or std::is_function_v<T> or std::is_member_function_pointer_v<T> or
std::is_function_v<std::remove_pointer_t<T>>; std::is_function_v<std::remove_pointer_t<T>>;
template <Streamable T> /*template <Streamable T>
requires(FunctionPointer<T>) requires(FunctionPointer<T>)
void repr_to(const T &x, std::ostream &s) { void repr_to(const T &x, std::ostream &s) {
s << "<function at 0x" << std::hex << (size_t)x << std::dec << ">"; s << "<function at 0x" << std::hex << (size_t)x << std::dec << ">";
...@@ -57,7 +57,8 @@ void repr_to(const T &x, std::ostream &s) { ...@@ -57,7 +57,8 @@ void repr_to(const T &x, std::ostream &s) {
template <typename T> template <typename T>
void repr_to(const std::function<T> &x, std::ostream &s) { void repr_to(const std::function<T> &x, std::ostream &s) {
s << "<function at 0x" << std::hex << (size_t)x.template target<T*>() << std::dec s << "<function at 0x" << std::hex << (size_t)x.template target<T*>() <<
std::dec
<< ">"; << ">";
} }
...@@ -75,7 +76,7 @@ void print_to(const std::shared_ptr<T> &x, std::ostream &s) { ...@@ -75,7 +76,7 @@ void print_to(const std::shared_ptr<T> &x, std::ostream &s) {
template <Reprable T> template <Reprable T>
void repr_to(const std::shared_ptr<T> &x, std::ostream &s) { void repr_to(const std::shared_ptr<T> &x, std::ostream &s) {
repr_to(*x, s); repr_to(*x, s);
} }*/
/* /*
template <Printable T, Printable... Args> template <Printable T, Printable... Args>
...@@ -86,18 +87,19 @@ typon::Task<void> print(T const &head, Args const &...args) { ...@@ -86,18 +87,19 @@ typon::Task<void> print(T const &head, Args const &...args) {
}*/ }*/
struct { struct {
typon::TyNone operator()() { std::cout << '\n'; return {}; } typon::TyNone operator()() {
std::cout << '\n';
return {};
}
template <Printable T, Printable... Args> template <typename T, typename... Args>
typon::TyNone operator()(T const &head, Args const &...args) { typon::TyNone operator()(T const &head, Args const &...args) {
print_to(head, std::cout); std::cout << str(head)->value;
(((std::cout << ' '), print_to(args, std::cout)), ...); (((std::cout << ' '), (std::cout << str(args)->value)), ...);
std::cout << '\n'; std::cout << '\n';
return {}; return {};
} }
} print; } print;
// typon::Task<void> print() { std::cout << '\n'; co_return; } // typon::Task<void> print() { std::cout << '\n'; co_return; }
#endif // TYPON_PRINT_HPP #endif // TYPON_PRINT_HPP
...@@ -12,30 +12,30 @@ namespace view = std::views; ...@@ -12,30 +12,30 @@ namespace view = std::views;
#include <python/basedef.hpp> #include <python/basedef.hpp>
auto stride = [](int n) { auto stride = [](int n) {
return [s = -1, n](auto const&) mutable { s = (s + 1) % n; return !s; }; return [s = -1, n](auto const &) mutable {
s = (s + 1) % n;
return !s;
};
}; };
// todo: proper range support // todo: proper range support
struct range_s : TyBuiltin<range_s> struct range_s : TyBuiltin<range_s> {
{
auto sync(int start, int stop, int step = 1) { auto sync(int start, int stop, int step = 1) {
// https://www.modernescpp.com/index.php/c-20-pythons-map-function/ // https://www.modernescpp.com/index.php/c-20-pythons-map-function/
if(step == 0) { if (step == 0) {
throw std::invalid_argument("Step cannot be 0"); throw std::invalid_argument("Step cannot be 0");
} }
auto Step = start < stop ? step : -step; auto Step = start < stop ? step : -step;
auto Begin = std::min(start, stop); auto Begin = std::min(start, stop);
auto End = Step < 0 ? Begin : std::max(start, stop); auto End = Step < 0 ? Begin : std::max(start, stop);
return view::iota(Begin, End) return view::iota(Begin, End) | view::filter(stride(std::abs(Step))) |
| view::filter(stride(std::abs(Step))) view::transform([start, stop](std::size_t i) {
| view::transform([start, stop](std::size_t i){ return start < stop ? i : stop - (i - start);
return start < stop ? i : stop - (i - start); });
});
} }
auto sync(int stop) { return sync(0, stop); } auto sync(int stop) { return sync(0, stop); }
} range; } range;
#endif // TYPON_RANGE_HPP #endif // TYPON_RANGE_HPP
...@@ -71,7 +71,7 @@ public: ...@@ -71,7 +71,7 @@ public:
} }
}; };
} } // namespace typon
template <typename T> typon::TySet<T> set(std::initializer_list<T> &&s) { template <typename T> typon::TySet<T> set(std::initializer_list<T> &&s) {
return typon::TySet<T>(std::move(s)); return typon::TySet<T>(std::move(s));
......
...@@ -5,10 +5,10 @@ ...@@ -5,10 +5,10 @@
#ifndef TYPON_SLICE_HPP #ifndef TYPON_SLICE_HPP
#define TYPON_SLICE_HPP #define TYPON_SLICE_HPP
#include <optional>
#include <utility>
#include <Python.h> #include <Python.h>
#include <optional>
#include <stdint.h> #include <stdint.h>
#include <utility>
struct TySlice { struct TySlice {
TySlice() = default; TySlice() = default;
...@@ -17,7 +17,9 @@ struct TySlice { ...@@ -17,7 +17,9 @@ struct TySlice {
TySlice &operator=(const TySlice &) = default; TySlice &operator=(const TySlice &) = default;
TySlice &operator=(TySlice &&) = default; TySlice &operator=(TySlice &&) = default;
TySlice(std::optional<ssize_t> start, std::optional<ssize_t> stop, std::optional<ssize_t> step) : start(start), stop(stop), step(step) { TySlice(std::optional<ssize_t> start, std::optional<ssize_t> stop,
std::optional<ssize_t> step)
: start(start), stop(stop), step(step) {
if (step == 0) { if (step == 0) {
throw std::runtime_error("slice step cannot be zero"); throw std::runtime_error("slice step cannot be zero");
} }
...@@ -52,7 +54,8 @@ struct TySlice { ...@@ -52,7 +54,8 @@ struct TySlice {
res.stop = this->stop.value(); res.stop = this->stop.value();
} }
auto len = PySlice_AdjustIndices(seq_length, &res.start, &res.stop, res.step); auto len =
PySlice_AdjustIndices(seq_length, &res.start, &res.stop, res.step);
return {len, res}; return {len, res};
} }
......
...@@ -5,20 +5,19 @@ ...@@ -5,20 +5,19 @@
#ifndef TYPON_STR_HPP #ifndef TYPON_STR_HPP
#define TYPON_STR_HPP #define TYPON_STR_HPP
#include <algorithm>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <algorithm>
using namespace std::literals; using namespace std::literals;
#include "bytes.hpp" #include "bytes.hpp"
#include "print.hpp"
#include "slice.hpp" #include "slice.hpp"
// #include <format> // #include <format>
#include <fmt/format.h> #include <fmt/format.h>
#include <pybind11/cast.h> #include <pybind11/cast.h>
class TyStr : public std::string { /*class TyStr : public std::string {
public: public:
TyStr() : std::string() {} TyStr() : std::string() {}
TyStr(const std::string &s) : std::string(s) {} TyStr(const std::string &s) : std::string(s) {}
...@@ -108,8 +107,8 @@ inline constexpr TyStr operator""_ps(const char *s, size_t len) noexcept { ...@@ -108,8 +107,8 @@ inline constexpr TyStr operator""_ps(const char *s, size_t len) noexcept {
} }
template<typename Self> template<typename Self>
TyStr TyBytes::decode_s::operator()(Self self, const std::string &encoding) const { TyStr TyBytes::decode_s::operator()(Self self, const std::string &encoding)
return TyStr(self.begin(), self.end()); const { return TyStr(self.begin(), self.end());
} }
template <typename T> TyStr str(const T &x) { template <typename T> TyStr str(const T &x) {
...@@ -150,6 +149,84 @@ struct { ...@@ -150,6 +149,84 @@ struct {
std::getline(std::cin, input); std::getline(std::cin, input);
return input; return input;
} }
} input; } input;*/
namespace typon {
using namespace referencemodel;
template <typename _Base0 = object>
struct TyStr__oo : classtype<_Base0, TyStr__oo<>> {
static constexpr std::string_view name = "TyStr";
struct : method {
auto operator()(auto self, auto other) const {
return Obj(dot(self, value) + dot(other, value));
}
} static constexpr oo__add__oo{};
struct : method {
auto operator()(auto self) const { return Obj(self->value); }
} static constexpr oo__str__oo{};
struct : method {
auto operator()(auto self) const {
return Obj(fmt::format("\"{}\"", self->value));
}
} static constexpr oo__repr__oo{};
struct Obj : value<TyStr__oo<>, Obj> {
std::string value;
constexpr Obj() : value() {}
constexpr Obj(std::string value) : value(value) {}
operator std::string() const { return value; }
};
auto operator()(std::string value) const { return Obj(value); }
};
static constexpr TyStr__oo<> TyStr{};
} // namespace typon
inline constexpr auto operator""_ps(const char *s, size_t len) noexcept {
return typon::TyStr__oo<>::Obj(std::string(s, len));
}
/*template <typename T> auto str(const T &x) { return dot(x, oo__str__oo)(); }
template <typename T>
concept NoStr = not requires(T x) { dot(x, oo__str__oo)(); };
template <NoStr T> auto str(const T &x) {
std::stringstream s;
s << x;
return typon::TyStr__oo<>::Obj(s.str());
}
*/
template <typename T>
concept HasStr = requires(T x) { dot(x, oo__str__oo)(); };
template <typename T>
concept HasRepr = requires(T x) { dot(x, oo__repr__oo)(); };
template <typename T> auto str(const T &x) {
if constexpr (HasStr<T>) {
return dot(x, oo__str__oo)();
} else {
std::stringstream s;
s << x;
return typon::TyStr__oo<>::Obj(s.str());
}
}
template <typename T> auto repr(const T &x) {
if constexpr (HasRepr<T>) {
return dot(x, oo__repr__oo)();
} else {
std::stringstream s;
s << x;
return typon::TyStr__oo<>::Obj(s.str());
}
}
#endif // TYPON_STR_HPP #endif // TYPON_STR_HPP
...@@ -23,7 +23,7 @@ struct hashlib_t { ...@@ -23,7 +23,7 @@ struct hashlib_t {
struct py_type { struct py_type {
py_type(TyObj<void> context, openssl_update update, openssl_final final, py_type(TyObj<void> context, openssl_update update, openssl_final final,
int diglen) int diglen)
: _context(context), _update(update), _final(final), _diglen(diglen) { : _context(context), _update(update), _final(final), _diglen(diglen) {
} }
...@@ -60,30 +60,28 @@ struct hashlib_t { ...@@ -60,30 +60,28 @@ struct hashlib_t {
auto ctx = tyObj<MD5_CTX>(); auto ctx = tyObj<MD5_CTX>();
MD5_Init(ctx.get()); MD5_Init(ctx.get());
return tyObj<_Hash_s>(ctx, (openssl_update)MD5_Update, return tyObj<_Hash_s>(ctx, (openssl_update)MD5_Update,
(openssl_final)MD5_Final, MD5_DIGEST_LENGTH); (openssl_final)MD5_Final, MD5_DIGEST_LENGTH);
}) })
FUNCTION(auto, sha1, (), { FUNCTION(auto, sha1, (), {
auto ctx = tyObj<SHA_CTX>(); auto ctx = tyObj<SHA_CTX>();
SHA1_Init(ctx.get()); SHA1_Init(ctx.get());
return tyObj<_Hash_s>(ctx, (openssl_update)SHA1_Update, return tyObj<_Hash_s>(ctx, (openssl_update)SHA1_Update,
(openssl_final)SHA1_Final, SHA_DIGEST_LENGTH); (openssl_final)SHA1_Final, SHA_DIGEST_LENGTH);
}) })
FUNCTION(auto, sha256, (), { FUNCTION(auto, sha256, (), {
auto ctx = tyObj<SHA256_CTX>(); auto ctx = tyObj<SHA256_CTX>();
SHA256_Init(ctx.get()); SHA256_Init(ctx.get());
return tyObj<_Hash_s>(ctx, (openssl_update)SHA256_Update, return tyObj<_Hash_s>(ctx, (openssl_update)SHA256_Update,
(openssl_final)SHA256_Final, (openssl_final)SHA256_Final, SHA256_DIGEST_LENGTH);
SHA256_DIGEST_LENGTH);
}) })
FUNCTION(auto, sha512, (), { FUNCTION(auto, sha512, (), {
auto ctx = tyObj<SHA512_CTX>(); auto ctx = tyObj<SHA512_CTX>();
SHA512_Init(ctx.get()); SHA512_Init(ctx.get());
return tyObj<_Hash_s>(ctx, (openssl_update)SHA512_Update, return tyObj<_Hash_s>(ctx, (openssl_update)SHA512_Update,
(openssl_final)SHA512_Final, (openssl_final)SHA512_Final, SHA512_DIGEST_LENGTH);
SHA512_DIGEST_LENGTH);
}) })
} all; } all;
......
...@@ -9,11 +9,12 @@ ...@@ -9,11 +9,12 @@
namespace py_json { namespace py_json {
struct json_t { struct json_t {
FUNCTION(template <typename T> typon::Task<void>, dump, (const T &x, typon::PyFile &fp), { FUNCTION(template <typename T> typon::Task<void>, dump,
std::stringstream ss; (const T &x, typon::PyFile &fp), {
repr_to(x, ss); std::stringstream ss;
co_await dotp(fp, write)(ss.str()); repr_to(x, ss);
}) co_await dotp(fp, write)(ss.str());
})
} all; } all;
auto &get_all() { return all; } auto &get_all() { return all; }
......
...@@ -21,8 +21,7 @@ int no_special(const struct dirent *d) { ...@@ -21,8 +21,7 @@ int no_special(const struct dirent *d) {
namespace py_os { namespace py_os {
struct os_t { struct os_t {
FUNCTION( FUNCTION(auto, fsdecode, (std::string s), { return s; })
auto, fsdecode, (std::string s), { return s; })
struct Stat_Result_s { struct Stat_Result_s {
struct py_type { struct py_type {
...@@ -64,8 +63,9 @@ struct os_t { ...@@ -64,8 +63,9 @@ struct os_t {
}) })
METHOD(auto, begin, (Self self), { return *self; }) METHOD(auto, begin, (Self self), { return *self; })
METHOD(auto, end, (Self self), METHOD(auto, end, (Self self), {
{ return py_type(self->basepath, self->namelist, self->n, self->n); }) return py_type(self->basepath, self->namelist, self->n, self->n);
})
auto operator*() { auto operator*() {
auto name = TyStr(this->namelist[this->current]->d_name); auto name = TyStr(this->namelist[this->current]->d_name);
...@@ -73,7 +73,7 @@ struct os_t { ...@@ -73,7 +73,7 @@ struct os_t {
} }
py_type(const TyStr &basepath, struct dirent **namelist, int n, py_type(const TyStr &basepath, struct dirent **namelist, int n,
int current = 0) int current = 0)
: basepath(basepath), namelist(namelist), n(n), current(current) { : basepath(basepath), namelist(namelist), n(n), current(current) {
if (this->basepath[this->basepath.size() - 1] != '/') { if (this->basepath[this->basepath.size() - 1] != '/') {
this->basepath += '/'; this->basepath += '/';
...@@ -95,31 +95,25 @@ struct os_t { ...@@ -95,31 +95,25 @@ struct os_t {
}; };
} _Scandiriterator; } _Scandiriterator;
FUNCTION(typon::Task<TyObj<Stat_Result_s>>, stat, (const TyStr &path), FUNCTION(typon::Task<TyObj<Stat_Result_s>>, stat, (const TyStr &path), {
{ const char *path_c = path.c_str();
const char *path_c = path.c_str(); struct statx statxbuf;
struct statx statxbuf; if (int err = co_await typon::io::statx(AT_FDCWD, path_c, 0, STATX_SIZE,
if (int err = co_await typon::io::statx(AT_FDCWD, path_c, 0, &statxbuf)) {
STATX_SIZE, &statxbuf)) { system_error(-err, "statx()");
system_error(-err, "statx()"); }
} co_return TyObj<Stat_Result_s>(new Stat_Result_s::py_type{
co_return TyObj<Stat_Result_s>(new Stat_Result_s::py_type{ statxbuf.stx_mode, statxbuf.stx_ino,
statxbuf.stx_mode, makedev(statxbuf.stx_dev_major, statxbuf.stx_dev_minor),
statxbuf.stx_ino, statxbuf.stx_nlink, statxbuf.stx_uid, statxbuf.stx_gid,
makedev(statxbuf.stx_dev_major, statxbuf.stx_dev_minor), statxbuf.stx_size,
statxbuf.stx_nlink, statxbuf.stx_atime.tv_sec + statxbuf.stx_atime.tv_nsec / 1e9f,
statxbuf.stx_uid, statxbuf.stx_mtime.tv_sec + statxbuf.stx_mtime.tv_nsec / 1e9f,
statxbuf.stx_gid, statxbuf.stx_ctime.tv_sec + statxbuf.stx_ctime.tv_nsec / 1e9f,
statxbuf.stx_size, statxbuf.stx_blocks, statxbuf.stx_blksize,
statxbuf.stx_atime.tv_sec + statxbuf.stx_atime.tv_nsec / 1e9f, makedev(statxbuf.stx_rdev_major, statxbuf.stx_rdev_minor), 0,
statxbuf.stx_mtime.tv_sec + statxbuf.stx_mtime.tv_nsec / 1e9f, statxbuf.stx_btime.tv_sec + statxbuf.stx_btime.tv_nsec / 1e9});
statxbuf.stx_ctime.tv_sec + statxbuf.stx_ctime.tv_nsec / 1e9f, })
statxbuf.stx_blocks,
statxbuf.stx_blksize,
makedev(statxbuf.stx_rdev_major, statxbuf.stx_rdev_minor),
0,
statxbuf.stx_btime.tv_sec + statxbuf.stx_btime.tv_nsec / 1e9});
})
FUNCTION(TyObj<_Scandiriterator_s>, scandir, (const TyStr &path), { FUNCTION(TyObj<_Scandiriterator_s>, scandir, (const TyStr &path), {
const char *path_c = path.c_str(); const char *path_c = path.c_str();
...@@ -146,8 +140,8 @@ auto &get_all() { return all; } ...@@ -146,8 +140,8 @@ auto &get_all() { return all; }
} // namespace py_os } // namespace py_os
namespace typon { namespace typon {
using PyStat_Result = TyObj<py_os::os_t::Stat_Result_s>; using PyStat_Result = TyObj<py_os::os_t::Stat_Result_s>;
using Py_Scandiriterator = TyObj<py_os::os_t::_Scandiriterator_s>; using Py_Scandiriterator = TyObj<py_os::os_t::_Scandiriterator_s>;
} } // namespace typon
#endif // TYPON_OS_HPP #endif // TYPON_OS_HPP
...@@ -12,25 +12,19 @@ ...@@ -12,25 +12,19 @@
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
namespace referencemodel { namespace referencemodel {
/* Object model forward declarations */ /* Object model forward declarations */
struct object; struct object;
template <typename T, typename O> template <typename T, typename O> struct instance;
struct instance;
template <typename T, typename O> template <typename T, typename O> struct value;
struct value;
template <typename B, typename T> template <typename B, typename T> struct classtype;
struct classtype;
template <typename M> template <typename M> struct moduletype;
struct moduletype;
struct function; struct function;
...@@ -40,26 +34,19 @@ struct classmethod; ...@@ -40,26 +34,19 @@ struct classmethod;
struct staticmethod; struct staticmethod;
template <typename S, typename F> template <typename S, typename F> struct boundmethod;
struct boundmethod;
/* Reference model forward declarations */ /* Reference model forward declarations */
template <typename T> template <typename T> struct Pack;
struct Pack;
template <typename T> template <typename T> struct Rc;
struct Rc;
template <typename T> template <typename T> struct Arc;
struct Arc;
template <typename T> template <typename T> struct Box;
struct Box;
template <typename T> template <typename T> struct Ref;
struct Ref;
/* Meta-programming utilities */ /* Meta-programming utilities */
...@@ -67,148 +54,117 @@ namespace meta { ...@@ -67,148 +54,117 @@ namespace meta {
/* Meta-programming utilities: always_false */ /* Meta-programming utilities: always_false */
template <typename T> template <typename T> struct always_false_s {
struct always_false_s { constexpr static bool value{false};
constexpr static bool value {false};
}; };
template <typename T> template <typename T>
inline constexpr bool always_false = always_false_s<T>::value; inline constexpr bool always_false = always_false_s<T>::value;
/* Meta-programming utilities: unwrap_one */ /* Meta-programming utilities: unwrap_one */
template <typename T> template <typename T> struct unwrap_one_s {
struct unwrap_one_s {
using type = T; using type = T;
}; };
template <typename T> template <typename T> struct unwrap_one_s<Pack<T>> {
struct unwrap_one_s<Pack<T>> {
using type = T; using type = T;
}; };
template <typename T> template <typename T> struct unwrap_one_s<Rc<T>> {
struct unwrap_one_s<Rc<T>> {
using type = T; using type = T;
}; };
template <typename T> template <typename T> struct unwrap_one_s<Arc<T>> {
struct unwrap_one_s<Arc<T>> {
using type = T; using type = T;
}; };
template <typename T> template <typename T> struct unwrap_one_s<Box<T>> {
struct unwrap_one_s<Box<T>> {
using type = T; using type = T;
}; };
template <typename T> template <typename T> struct unwrap_one_s<Ref<T>> {
struct unwrap_one_s<Ref<T>> {
using type = T; using type = T;
}; };
template <typename T> template <typename T>
using unwrap_one = typename unwrap_one_s<std::remove_cvref_t<T>>::type; using unwrap_one = typename unwrap_one_s<std::remove_cvref_t<T>>::type;
/* Meta-programming utilities: unwrap_all */ /* Meta-programming utilities: unwrap_all */
template <typename T> template <typename T> struct unwrap_all_s {
struct unwrap_all_s {
using type = unwrap_one<T>; using type = unwrap_one<T>;
}; };
template <typename T> template <typename T> struct unwrap_all_s<Ref<Pack<T>>> {
struct unwrap_all_s<Ref<Pack<T>>> {
using type = T; using type = T;
}; };
template <typename T> template <typename T> struct unwrap_all_s<Ref<Arc<T>>> {
struct unwrap_all_s<Ref<Arc<T>>> {
using type = T; using type = T;
}; };
template <typename T> template <typename T> struct unwrap_all_s<Box<Pack<T>>> {
struct unwrap_all_s<Box<Pack<T>>> {
using type = T; using type = T;
}; };
template <typename T> template <typename T>
using unwrap_all = typename unwrap_all_s<std::remove_cvref_t<T>>::type; using unwrap_all = typename unwrap_all_s<std::remove_cvref_t<T>>::type;
/* Meta-programming utilities: unwrap_pack */ /* Meta-programming utilities: unwrap_pack */
template <typename T> template <typename T> struct unwrap_pack_s {
struct unwrap_pack_s {
using type = unwrap_all<T>; using type = unwrap_all<T>;
}; };
template <typename T> template <typename T> struct unwrap_pack_s<Pack<T>> {
struct unwrap_pack_s<Pack<T>> {
using type = Pack<T>; using type = Pack<T>;
}; };
template <typename T> template <typename T> struct unwrap_pack_s<Ref<Pack<T>>> {
struct unwrap_pack_s<Ref<Pack<T>>> {
using type = Pack<T>; using type = Pack<T>;
}; };
template <typename T> template <typename T> struct unwrap_pack_s<Ref<Arc<T>>> {
struct unwrap_pack_s<Ref<Arc<T>>> {
using type = Pack<T>; using type = Pack<T>;
}; };
template <typename T> template <typename T> struct unwrap_pack_s<Box<Pack<T>>> {
struct unwrap_pack_s<Box<Pack<T>>> {
using type = Pack<T>; using type = Pack<T>;
}; };
template <typename T> template <typename T>
using unwrap_pack = typename unwrap_pack_s<std::remove_cvref_t<T>>::type; using unwrap_pack = typename unwrap_pack_s<std::remove_cvref_t<T>>::type;
/* Meta-programming utilities for object model */ /* Meta-programming utilities for object model */
template <typename T> template <typename T>
concept object = std::derived_from<unwrap_all<T>, referencemodel::object>; concept object = std::derived_from<unwrap_all<T>, referencemodel::object>;
template <typename T> template <typename T>
concept instance = std::derived_from< concept instance = std::derived_from<
unwrap_all<T>, unwrap_all<T>,
referencemodel::instance<typename unwrap_all<T>::type, unwrap_all<T>> referencemodel::instance<typename unwrap_all<T>::type, unwrap_all<T>>>;
>;
template <typename T> template <typename T>
concept classtype = !instance<T> && std::derived_from< concept classtype = !
unwrap_all<T>, instance<T> &&std::derived_from<
referencemodel::classtype< unwrap_all<T>, referencemodel::classtype<typename unwrap_all<T>::base,
typename unwrap_all<T>::base, typename unwrap_all<T>::type typename unwrap_all<T>::type>>;
>
>;
template <typename F> template <typename F>
concept function = std::derived_from<F, referencemodel::function>; concept function = std::derived_from<F, referencemodel::function>;
template <typename F> template <typename F>
concept method = std::derived_from<F, referencemodel::method>; concept method = std::derived_from<F, referencemodel::method>;
template <typename F> template <typename F>
concept classmethod = std::derived_from<F, referencemodel::classmethod>; concept classmethod = std::derived_from<F, referencemodel::classmethod>;
template <typename F> template <typename F>
concept staticmethod = std::derived_from<F, referencemodel::staticmethod>; concept staticmethod = std::derived_from<F, referencemodel::staticmethod>;
template <typename T> struct boundmethod_s {
template <typename T>
struct boundmethod_s {
static constexpr bool value = false; static constexpr bool value = false;
}; };
...@@ -220,18 +176,14 @@ struct boundmethod_s<referencemodel::boundmethod<S, F>> { ...@@ -220,18 +176,14 @@ struct boundmethod_s<referencemodel::boundmethod<S, F>> {
template <typename T> template <typename T>
concept boundmethod = boundmethod_s<std::remove_cvref_t<T>>::value; concept boundmethod = boundmethod_s<std::remove_cvref_t<T>>::value;
template <typename T> struct value_s {
template <typename T>
struct value_s {
static constexpr bool value = true; static constexpr bool value = true;
}; };
template <instance T> template <instance T> struct value_s<T> {
struct value_s<T> {
static constexpr bool value = std::derived_from< static constexpr bool value = std::derived_from<
unwrap_all<T>, unwrap_all<T>,
referencemodel::value<typename unwrap_all<T>::type, unwrap_all<T>> referencemodel::value<typename unwrap_all<T>::type, unwrap_all<T>>>;
>;
}; };
template <typename S, typename F> template <typename S, typename F>
...@@ -242,222 +194,175 @@ struct value_s<referencemodel::boundmethod<S, F>> { ...@@ -242,222 +194,175 @@ struct value_s<referencemodel::boundmethod<S, F>> {
template <typename T> template <typename T>
concept value = value_s<std::remove_cvref_t<T>>::value; concept value = value_s<std::remove_cvref_t<T>>::value;
/* Meta-programming utilities: wrapped and unwrapped */ /* Meta-programming utilities: wrapped and unwrapped */
template <typename T> template <typename T>
concept unwrapped = std::is_same_v<T, unwrap_one<T>>; concept unwrapped = std::is_same_v<T, unwrap_one<T>>;
template <typename T> template <typename T>
concept wrapped = !unwrapped<T>; concept wrapped = !
unwrapped<T>;
/* Meta-programming utilities: wrapped_by */ /* Meta-programming utilities: wrapped_by */
template <typename T, template <typename> typename M> template <typename T, template <typename> typename M> struct wrapped_by_s {
struct wrapped_by_s { static constexpr bool value{false};
static constexpr bool value {false};
}; };
template <typename T, template <typename> typename M> template <typename T, template <typename> typename M>
struct wrapped_by_s<M<T>, M> { struct wrapped_by_s<M<T>, M> {
static constexpr bool value {true}; static constexpr bool value{true};
}; };
template <typename T, template <typename> typename M> template <typename T, template <typename> typename M>
concept wrapped_by = wrapped_by_s<std::remove_cvref<T>, M>::value; concept wrapped_by = wrapped_by_s<std::remove_cvref<T>, M>::value;
/* Meta-programming utilities: pack */ /* Meta-programming utilities: pack */
template <typename T> template <typename T> struct pack_s {
struct pack_s {
using type = Pack<unwrap_all<T>>; using type = Pack<unwrap_all<T>>;
}; };
template <value T> template <value T> struct pack_s<T> {
struct pack_s<T> {
using type = T; using type = T;
}; };
template <typename T> template <typename T> using pack = typename pack_s<T>::type;
using pack = typename pack_s<T>::type;
/* Meta-programming utilities: rc */ /* Meta-programming utilities: rc */
template <typename T> template <typename T> struct rc_s {
struct rc_s {
using type = Rc<unwrap_all<T>>; using type = Rc<unwrap_all<T>>;
}; };
template <value T> template <value T> struct rc_s<T> {
struct rc_s<T> {
using type = T; using type = T;
}; };
template <typename T> template <typename T> using rc = typename rc_s<T>::type;
using rc = typename rc_s<T>::type;
/* Meta-programming utilities: arc */ /* Meta-programming utilities: arc */
template <typename T> template <typename T> struct arc_s {
struct arc_s {
using type = Arc<unwrap_all<T>>; using type = Arc<unwrap_all<T>>;
}; };
template <value T> template <value T> struct arc_s<T> {
struct arc_s<T> {
using type = T; using type = T;
}; };
template <typename T> template <typename T> using arc = typename arc_s<T>::type;
using arc = typename arc_s<T>::type;
/* Meta-programming utilities: box */ /* Meta-programming utilities: box */
template <typename T> template <typename T> struct box_s {
struct box_s {
using type = Box<unwrap_pack<T>>; using type = Box<unwrap_pack<T>>;
}; };
template <value T> template <value T> struct box_s<T> {
struct box_s<T> {
using type = T; using type = T;
}; };
template <typename T> template <typename T> using box = typename box_s<T>::type;
using box = typename box_s<T>::type;
/* Meta-programming utilities: ref */ /* Meta-programming utilities: ref */
template <typename T> template <typename T> struct ref_s {
struct ref_s {
using type = Ref<unwrap_all<T>>; using type = Ref<unwrap_all<T>>;
}; };
template <value T> template <value T> struct ref_s<T> {
struct ref_s<T> {
using type = T; using type = T;
}; };
template <typename T> template <typename T> using ref = typename ref_s<T>::type;
using ref = typename ref_s<T>::type;
/* Meta-programming utilities: borrow */ /* Meta-programming utilities: borrow */
template <typename T> template <typename T> struct borrow_s {
struct borrow_s {
using type = ref<T>; using type = ref<T>;
}; };
template <typename T> template <typename T> struct borrow_s<Rc<T>> {
struct borrow_s<Rc<T>> {
using type = Ref<Pack<T>>; using type = Ref<Pack<T>>;
}; };
template <typename T> template <typename T> struct borrow_s<Ref<Pack<T>>> {
struct borrow_s<Ref<Pack<T>>> {
using type = Ref<Pack<T>>; using type = Ref<Pack<T>>;
}; };
template <typename T> template <typename T> struct borrow_s<Arc<T>> {
struct borrow_s<Arc<T>> {
using type = Ref<Arc<T>>; using type = Ref<Arc<T>>;
}; };
template <typename T> template <typename T> struct borrow_s<Ref<Arc<T>>> {
struct borrow_s<Ref<Arc<T>>> {
using type = Ref<Arc<T>>; using type = Ref<Arc<T>>;
}; };
template <typename T> template <typename T>
using borrow = typename borrow_s<std::remove_cvref_t<T>>::type; using borrow = typename borrow_s<std::remove_cvref_t<T>>::type;
/* Meta-programming utilities: forward */ /* Meta-programming utilities: forward */
template <typename T> template <typename T> struct forward_s {
struct forward_s {
using type = borrow<T>; using type = borrow<T>;
}; };
template <typename T> template <typename T> struct forward_s<Box<T> &&> {
struct forward_s<Box<T> &&> {
using type = Box<T>; using type = Box<T>;
}; };
template <typename T> template <typename T> using forward = typename forward_s<T>::type;
using forward = typename forward_s<T>::type;
/* Meta-programming utilities: recover */ /* Meta-programming utilities: recover */
template <typename T> template <typename T> struct recover_s {
struct recover_s {
using type = T; using type = T;
}; };
template <value T> template <value T> struct recover_s<T> {
struct recover_s<T> {
using type = T; using type = T;
}; };
template <typename T> template <typename T> struct recover_s<Ref<Pack<T>>> {
struct recover_s<Ref<Pack<T>>> {
using type = Rc<T>; using type = Rc<T>;
}; };
template <typename T> template <typename T> struct recover_s<Ref<Arc<T>>> {
struct recover_s<Ref<Arc<T>>> {
using type = Arc<T>; using type = Arc<T>;
}; };
template <typename T> template <typename T>
using recover = typename recover_s<std::remove_cvref_t<T>>::type; using recover = typename recover_s<std::remove_cvref_t<T>>::type;
/* Meta-programming utilities: own */ /* Meta-programming utilities: own */
template <typename T> template <typename T> struct own_s {
struct own_s {
using type = recover<T>; using type = recover<T>;
}; };
template <unwrapped T> template <unwrapped T> struct own_s<Ref<T>> {
struct own_s<Ref<T>> {
static_assert(always_false<T>, "Ref<T> cannot be owned"); static_assert(always_false<T>, "Ref<T> cannot be owned");
}; };
template <typename T> template <typename T> using own = typename own_s<std::remove_cvref_t<T>>::type;
using own = typename own_s<std::remove_cvref_t<T>>::type;
/* Meta-programming utilities: common_forward */ /* Meta-programming utilities: common_forward */
template <typename...> template <typename...> struct common_forward_s {};
struct common_forward_s {};
template <typename... T> template <typename... T>
using common_forward = typename common_forward_s<T...>::type; using common_forward = typename common_forward_s<T...>::type;
template <typename T> template <typename T> struct common_forward_s<T> {
struct common_forward_s<T> {
using type = forward<T>; using type = forward<T>;
}; };
template <typename T, typename U> template <typename T, typename U> struct common_forward_s<T, U> {
struct common_forward_s<T, U> {
using type = std::common_type_t<forward<T>, forward<U>>; using type = std::common_type_t<forward<T>, forward<U>>;
}; };
template <typename T> template <typename T> struct common_forward_s<T, T> {
struct common_forward_s<T, T> {
using type = forward<T>; using type = forward<T>;
}; };
...@@ -468,8 +373,8 @@ struct common_forward_s<T, U> { ...@@ -468,8 +373,8 @@ struct common_forward_s<T, U> {
}; };
template <instance T, instance U> template <instance T, instance U>
requires std::is_same_v<unwrap_all<T>, unwrap_all<U>> requires std::is_same_v<unwrap_all<T>, unwrap_all<U>> &&
&& (!std::is_same_v<forward<T>, forward<U>>) (!std::is_same_v<forward<T>, forward<U>>)
struct common_forward_s<T, U> { struct common_forward_s<T, U> {
static_assert(!std::is_same_v<T, Box<unwrap_all<T>> &&>); static_assert(!std::is_same_v<T, Box<unwrap_all<T>> &&>);
static_assert(!std::is_same_v<U, Box<unwrap_all<U>> &&>); static_assert(!std::is_same_v<U, Box<unwrap_all<U>> &&>);
...@@ -481,69 +386,52 @@ struct common_forward_s<T, U, V...> { ...@@ -481,69 +386,52 @@ struct common_forward_s<T, U, V...> {
using type = common_forward<common_forward<T, U>, V...>; using type = common_forward<common_forward<T, U>, V...>;
}; };
} // namespace meta } // namespace meta
/* Conversion functions */ /* Conversion functions */
template <typename T> template <typename T> auto pack(T &&t) {
auto pack(T && t) {
return meta::pack<T>(std::forward<T>(t)); return meta::pack<T>(std::forward<T>(t));
} }
template <typename T> template <typename T> auto rc(T &&t) { return meta::rc<T>(std::forward<T>(t)); }
auto rc(T && t) {
return meta::rc<T>(std::forward<T>(t));
}
template <typename T> template <typename T> auto arc(T &&t) {
auto arc(T && t) {
return meta::arc<T>(std::forward<T>(t)); return meta::arc<T>(std::forward<T>(t));
} }
template <typename T> template <typename T> auto box(T &&t) {
auto box(T && t) {
return meta::box<T>(std::forward<T>(t)); return meta::box<T>(std::forward<T>(t));
} }
template <typename T> template <typename T> auto ref(T &&t) {
auto ref(T && t) {
return meta::ref<T>(std::forward<T>(t)); return meta::ref<T>(std::forward<T>(t));
} }
template <typename T> template <typename T> auto borrow(T &&t) {
auto borrow(T && t) {
return meta::borrow<T>(std::forward<T>(t)); return meta::borrow<T>(std::forward<T>(t));
} }
template <typename T> template <typename T> auto forward(T &&t) {
auto forward(T && t) {
return meta::forward<T &&>(std::forward<T>(t)); return meta::forward<T &&>(std::forward<T>(t));
} }
template <typename T> template <typename T> auto recover(T &&t) {
auto recover(T && t) {
return meta::recover<T>(std::forward<T>(t)); return meta::recover<T>(std::forward<T>(t));
} }
template <typename T> template <typename T> auto own(T &&t) {
auto own(T && t) {
return meta::own<T>(std::forward<T>(t)); return meta::own<T>(std::forward<T>(t));
} }
/* Utilities: NonNull */ /* Utilities: NonNull */
template <typename T> template <typename T> struct NonNull {
struct NonNull {
NonNull() = default; NonNull() = default;
NonNull(T * some) : ptr(some) { NonNull(T *some) : ptr(some) { assert(ptr); };
assert(ptr);
};
NonNull & operator = (const T * some) { NonNull &operator=(const T *some) {
ptr = some; ptr = some;
assert(ptr); assert(ptr);
return *this; return *this;
...@@ -551,38 +439,36 @@ struct NonNull { ...@@ -551,38 +439,36 @@ struct NonNull {
NonNull(std::nullptr_t) : ptr(nullptr) {} NonNull(std::nullptr_t) : ptr(nullptr) {}
NonNull & operator = (std::nullptr_t) { NonNull &operator=(std::nullptr_t) {
ptr = nullptr; ptr = nullptr;
return *this; return *this;
} }
T * operator -> () const { return ptr; } T *operator->() const { return ptr; }
operator T * () const { return ptr; } operator T *() const { return ptr; }
operator bool () const { return ptr; } operator bool() const { return ptr; }
private: private:
T * ptr; T *ptr;
}; };
/* Reference model */ /* Reference model */
template <typename T> template <typename T> struct Pack {
struct Pack {
static_assert(std::is_same_v<T, meta::unwrap_all<T>>); static_assert(std::is_same_v<T, meta::unwrap_all<T>>);
static_assert(std::atomic_ref<std::uint32_t>::is_always_lock_free); static_assert(std::atomic_ref<std::uint32_t>::is_always_lock_free);
Pack() = default; Pack() = default;
Pack(T && t) : rc(1), value(std::move(t)) {} Pack(T &&t) : rc(1), value(std::move(t)) {}
Pack(Pack &&) = default; Pack(Pack &&) = default;
const T * operator -> () const { return std::addressof(value); } const T *operator->() const { return std::addressof(value); }
T * operator -> () { return std::addressof(value); } T *operator->() { return std::addressof(value); }
auto read_count() const { return rc; } auto read_count() const { return rc; }
...@@ -597,48 +483,42 @@ struct Pack { ...@@ -597,48 +483,42 @@ struct Pack {
friend struct Ref<Pack>; friend struct Ref<Pack>;
friend struct Ref<Arc<T>>; friend struct Ref<Arc<T>>;
private: private:
std::uint32_t rc = 1; std::uint32_t rc = 1;
T value; T value;
}; };
template <typename T> struct Rc {
template <typename T>
struct Rc {
static_assert(std::is_same_v<T, meta::unwrap_all<T>>); static_assert(std::is_same_v<T, meta::unwrap_all<T>>);
Rc() : ptr(nullptr) {} Rc() : ptr(nullptr) {}
Rc(std::nullptr_t) : ptr(nullptr) {} Rc(std::nullptr_t) : ptr(nullptr) {}
Rc(T && t) : ptr(new Pack<T>(std::move(t))) {} 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(new Pack<T>(std::move(pack))) {}
Rc(Pack<T> & pack) : ptr(&pack) { Rc(Pack<T> &pack) : ptr(&pack) { ptr->rc++; }
ptr->rc++;
}
Rc(Rc && rc) : ptr(std::exchange(rc.ptr, nullptr)) {} Rc(Rc &&rc) : ptr(std::exchange(rc.ptr, nullptr)) {}
Rc(const Rc & rc) : ptr(rc.ptr) { Rc(const Rc &rc) : ptr(rc.ptr) { ptr->rc++; }
ptr->rc++;
}
Rc(const Ref<Pack<T>> & ref) : ptr(ref.ptr) { Rc(const Ref<Pack<T>> &ref) : ptr(ref.ptr) {
assert(ptr->read_count()); assert(ptr->read_count());
ptr->rc++; ptr->rc++;
} }
Rc(Box<Pack<T>> & box) : ptr(std::exchange(box.ptr, nullptr)) { Rc(Box<Pack<T>> &box) : ptr(std::exchange(box.ptr, nullptr)) {
assert(!ptr->rc++); assert(!ptr->rc++);
} }
Rc(Box<Pack<T>> && box) : ptr(std::exchange(box.ptr, nullptr)) { Rc(Box<Pack<T>> &&box) : ptr(std::exchange(box.ptr, nullptr)) {
assert(!ptr->rc++); assert(!ptr->rc++);
} }
Rc & operator = (Rc rc) { Rc &operator=(Rc rc) {
std::swap(ptr, rc.ptr); std::swap(ptr, rc.ptr);
return *this; return *this;
} }
...@@ -651,7 +531,7 @@ struct Rc { ...@@ -651,7 +531,7 @@ struct Rc {
} }
} }
T* operator -> () const { return std::addressof(ptr->value); } T *operator->() const { return std::addressof(ptr->value); }
auto read_count() const { return ptr->read_count(); } auto read_count() const { return ptr->read_count(); }
...@@ -659,56 +539,54 @@ struct Rc { ...@@ -659,56 +539,54 @@ struct Rc {
friend struct Ref<T>; friend struct Ref<T>;
friend struct Ref<Pack<T>>; friend struct Ref<Pack<T>>;
private: private:
NonNull<Pack<T>> ptr; NonNull<Pack<T>> ptr;
}; };
template <typename T> struct Arc {
template <typename T>
struct Arc {
static_assert(std::is_same_v<T, meta::unwrap_all<T>>); static_assert(std::is_same_v<T, meta::unwrap_all<T>>);
Arc() : ptr(nullptr) {} Arc() : ptr(nullptr) {}
Arc(std::nullptr_t) : ptr(nullptr) {} Arc(std::nullptr_t) : ptr(nullptr) {}
Arc(T && t) : ptr(new Pack<T>(std::move(t))) {} Arc(T &&t) : ptr(new Pack<T>(std::move(t))) {}
Arc(Arc && arc) : ptr(std::exchange(arc.ptr, nullptr)) {} Arc(Arc &&arc) : ptr(std::exchange(arc.ptr, nullptr)) {}
Arc(const Arc & arc) : ptr(arc.ptr) { Arc(const Arc &arc) : ptr(arc.ptr) {
std::atomic_ref(ptr->rc).fetch_add(1, std::memory_order_relaxed); std::atomic_ref(ptr->rc).fetch_add(1, std::memory_order_relaxed);
} }
Arc(const Ref<Arc<T>> & ref) : ptr(ref.ptr) { Arc(const Ref<Arc<T>> &ref) : ptr(ref.ptr) {
assert(ptr->atomic_read_count()); assert(ptr->atomic_read_count());
std::atomic_ref(ptr->rc).fetch_add(1, std::memory_order_relaxed); std::atomic_ref(ptr->rc).fetch_add(1, std::memory_order_relaxed);
} }
Arc(Box<Pack<T>> & box) : ptr(std::exchange(box.ptr, nullptr)) { Arc(Box<Pack<T>> &box) : ptr(std::exchange(box.ptr, nullptr)) {
assert(!std::atomic_ref(ptr->rc).fetch_add(1, std::memory_order_relaxed)); assert(!std::atomic_ref(ptr->rc).fetch_add(1, std::memory_order_relaxed));
} }
Arc(Box<Pack<T>> && box) : ptr(std::exchange(box.ptr, nullptr)) { Arc(Box<Pack<T>> &&box) : ptr(std::exchange(box.ptr, nullptr)) {
assert(!std::atomic_ref(ptr->rc).fetch_add(1, std::memory_order_relaxed)); assert(!std::atomic_ref(ptr->rc).fetch_add(1, std::memory_order_relaxed));
} }
Arc & operator = (Arc arc) { Arc &operator=(Arc arc) {
std::swap(ptr, arc.ptr); std::swap(ptr, arc.ptr);
return *this; return *this;
} }
~Arc() { ~Arc() {
if (ptr) { // null only if (swapped with a) moved from or uninitialised 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) if (std::atomic_ref(ptr->rc).fetch_sub(1, std::memory_order_release) ==
{ 1) {
std::atomic_thread_fence(std::memory_order_acquire); std::atomic_thread_fence(std::memory_order_acquire);
delete ptr; delete ptr;
} }
} }
} }
T* operator -> () const { return std::addressof(ptr->value); } T *operator->() const { return std::addressof(ptr->value); }
auto read_count() const { return ptr->atomic_read_count(); } auto read_count() const { return ptr->atomic_read_count(); }
...@@ -716,26 +594,24 @@ struct Arc { ...@@ -716,26 +594,24 @@ struct Arc {
friend struct Ref<T>; friend struct Ref<T>;
friend struct Ref<Arc<T>>; friend struct Ref<Arc<T>>;
private: private:
NonNull<Pack<T>> ptr; NonNull<Pack<T>> ptr;
}; };
template <typename T> struct Box {
template <typename T>
struct Box {
static_assert(std::is_same_v<T, meta::unwrap_all<T>>); static_assert(std::is_same_v<T, meta::unwrap_all<T>>);
Box() : ptr(nullptr) {} Box() : ptr(nullptr) {}
Box(std::nullptr_t) : ptr(nullptr) {} Box(std::nullptr_t) : ptr(nullptr) {}
Box(T && t) : ptr(new T(std::move(t))) {} 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(Box && box) : ptr(std::exchange(box.ptr, nullptr)) {} Box(Box &&box) : ptr(std::exchange(box.ptr, nullptr)) {}
Box & operator = (Box box) { Box &operator=(Box box) {
std::swap(ptr, box.ptr); std::swap(ptr, box.ptr);
return *this; return *this;
} }
...@@ -746,43 +622,37 @@ struct Box { ...@@ -746,43 +622,37 @@ struct Box {
} }
} }
T* operator ->() const { return ptr; } T *operator->() const { return ptr; }
friend struct Ref<T>; friend struct Ref<T>;
private: private:
NonNull<T> ptr; NonNull<T> ptr;
}; };
template <typename T> struct Box<Pack<T>> {
template <typename T>
struct Box<Pack<T>> {
Box() : ptr(nullptr) {} Box() : ptr(nullptr) {}
Box(std::nullptr_t) : ptr(nullptr) {} Box(std::nullptr_t) : ptr(nullptr) {}
Box(T && t) : ptr(new Pack<T>(std::move(t))) { Box(T &&t) : ptr(new Pack<T>(std::move(t))) { assert(!--(ptr->rc)); }
assert(!--(ptr->rc));
}
Box(Pack<T> && pack) : ptr(new Pack<T>(std::move(pack))) { Box(Pack<T> &&pack) : ptr(new Pack<T>(std::move(pack))) {
assert(!--(ptr->rc)); assert(!--(ptr->rc));
} }
Box(Rc<T> && rc) : ptr(rc.ptr) { Box(Rc<T> &&rc) : ptr(rc.ptr) { assert(!--(ptr->rc)); }
assert(!--(ptr->rc));
}
Box(Arc<T> && rc) : ptr(rc.ptr) { Box(Arc<T> &&rc) : ptr(rc.ptr) {
assert( assert(std::atomic_ref(ptr->rc).fetch_sub(1, std::memory_order_relaxed) ==
std::atomic_ref(ptr->rc).fetch_sub(1, std::memory_order_relaxed) == 1); 1);
} }
Box(Box & box) : ptr(std::exchange(box.ptr, nullptr)) {} Box(Box &box) : ptr(std::exchange(box.ptr, nullptr)) {}
Box(Box && box) : ptr(std::exchange(box.ptr, nullptr)) {} Box(Box &&box) : ptr(std::exchange(box.ptr, nullptr)) {}
Box & operator = (Box box) { Box &operator=(Box box) {
std::swap(ptr, box.ptr); std::swap(ptr, box.ptr);
return *this; return *this;
} }
...@@ -793,153 +663,135 @@ struct Box<Pack<T>> { ...@@ -793,153 +663,135 @@ struct Box<Pack<T>> {
} }
} }
T* operator ->() const { return ptr; } T *operator->() const { return ptr; }
friend struct Rc<T>; friend struct Rc<T>;
friend struct Arc<T>; friend struct Arc<T>;
friend struct Ref<T>; friend struct Ref<T>;
private: private:
NonNull<Pack<T>> ptr; NonNull<Pack<T>> ptr;
}; };
template <typename T> struct Ref {
template <typename T>
struct Ref {
static_assert(std::is_same_v<T, meta::unwrap_all<T>>); static_assert(std::is_same_v<T, meta::unwrap_all<T>>);
Ref() = default; Ref() = default;
Ref(T & t) : ptr(std::addressof(t)) {} Ref(T &t) : ptr(std::addressof(t)) {}
Ref(const Ref &) = default; Ref(const Ref &) = default;
Ref(Ref &&) = default; Ref(Ref &&) = default;
Ref & operator = (Ref ref) { Ref &operator=(Ref ref) {
ptr = ref.ptr; ptr = ref.ptr;
return *this; return *this;
} }
Ref(Pack<T> & pack) : ptr(std::addressof(pack.value)) {} Ref(Pack<T> &pack) : ptr(std::addressof(pack.value)) {}
Ref(const Rc<T> & rc) : ptr(std::addressof(rc.ptr->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 Arc<T> &arc) : ptr(std::addressof(arc.ptr->value)) {}
Ref(const Ref<Pack<T>> & ref) : ptr(std::addressof(ref.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 Ref<Arc<T>> &ref) : ptr(std::addressof(ref.ptr->value)) {}
Ref(const Box<T> & box) : ptr(box.ptr) {} Ref(const Box<T> &box) : ptr(box.ptr) {}
Ref(const Box<Pack<T>> & box) : ptr(box.ptr) {} Ref(const Box<Pack<T>> &box) : ptr(box.ptr) {}
T * operator ->() const { return ptr; } T *operator->() const { return ptr; }
private: private:
NonNull<T> ptr; NonNull<T> ptr;
}; };
template <typename T> struct Ref<Pack<T>> {
template <typename T>
struct Ref<Pack<T>> {
Ref() = default; Ref() = default;
Ref(Pack<T> & pack) : ptr(std::addressof(pack)) {} Ref(Pack<T> &pack) : ptr(std::addressof(pack)) {}
Ref(const Ref &) = default; Ref(const Ref &) = default;
Ref(Ref &&) = default; Ref(Ref &&) = default;
Ref & operator = (Ref ref) { Ref &operator=(Ref ref) {
ptr = ref.ptr; ptr = ref.ptr;
return *this; return *this;
} }
Ref(const Rc<T> & rc) : ptr(rc.ptr) {} Ref(const Rc<T> &rc) : ptr(rc.ptr) {}
T * operator ->() const { return std::addressof(ptr->value); } T *operator->() const { return std::addressof(ptr->value); }
friend struct Rc<T>; friend struct Rc<T>;
friend struct Ref<T>; friend struct Ref<T>;
private: private:
NonNull<Pack<T>> ptr; NonNull<Pack<T>> ptr;
}; };
template <typename T> struct Ref<Arc<T>> {
template <typename T>
struct Ref<Arc<T>> {
Ref() = default; Ref() = default;
Ref(const Ref &) = default; Ref(const Ref &) = default;
Ref(Ref &&) = default; Ref(Ref &&) = default;
Ref & operator = (Ref ref) { Ref &operator=(Ref ref) {
ptr = ref.ptr; ptr = ref.ptr;
return *this; return *this;
} }
Ref(const Arc<T> & arc) : ptr(arc.ptr) {} Ref(const Arc<T> &arc) : ptr(arc.ptr) {}
T * operator ->() const { return std::addressof(ptr->value); } T *operator->() const { return std::addressof(ptr->value); }
friend struct Arc<T>; friend struct Arc<T>;
friend struct Ref<T>; friend struct Ref<T>;
private: private:
NonNull<Pack<T>> ptr; NonNull<Pack<T>> ptr;
}; };
template <typename T> Ref(Rc<T> &) -> Ref<T>;
template <typename T> template <typename T> Ref(Rc<T> &&) -> Ref<T>;
Ref(Rc<T> &) -> Ref<T>;
template <typename T>
Ref(Rc<T> &&) -> Ref<T>;
template <typename T> template <typename T> Ref(Arc<T> &) -> Ref<T>;
Ref(Arc<T> &) -> Ref<T>;
template <typename T>
Ref(Arc<T> &&) -> Ref<T>;
template <typename T> template <typename T> Ref(Arc<T> &&) -> Ref<T>;
Ref(Box<T> &) -> Ref<meta::unwrap_all<T>>;
template <typename T> template <typename T> Ref(Box<T> &) -> Ref<meta::unwrap_all<T>>;
Ref(Box<T> &&) -> Ref<meta::unwrap_all<T>>;
template <meta::wrapped T> template <typename T> Ref(Box<T> &&) -> Ref<meta::unwrap_all<T>>;
Ref(Ref<T> &) -> Ref<meta::unwrap_all<T>>;
template <meta::wrapped T> template <meta::wrapped T> Ref(Ref<T> &) -> Ref<meta::unwrap_all<T>>;
Ref(Ref<T> &&) -> Ref<meta::unwrap_all<T>>;
template <meta::wrapped T> Ref(Ref<T> &&) -> Ref<meta::unwrap_all<T>>;
/* Equality */ /* Equality */
template <typename T, typename U> template <typename T, typename U>
requires meta::wrapped<T> || meta::wrapped<U> requires meta::wrapped<T> || meta::wrapped<U> bool
bool operator == (const T & t, const U & u) { operator==(const T &t, const U &u) {
return t.operator -> () == u.operator -> (); return t.operator->() == u.operator->();
} }
namespace meta { namespace meta {
/* Compile-time string concatenation */ /* Compile-time string concatenation */
// taken from https://stackoverflow.com/a/62823211 // taken from https://stackoverflow.com/a/62823211
template <std::string_view const&... Strs> template <std::string_view const &...Strs> struct join_s {
struct join_s {
// Join all strings into a single std::array of chars // Join all strings into a single std::array of chars
static constexpr auto impl() noexcept static constexpr auto impl() noexcept {
{
constexpr std::size_t len = (Strs.size() + ... + 0); constexpr std::size_t len = (Strs.size() + ... + 0);
std::array<char, len + 1> arr{}; std::array<char, len + 1> arr{};
auto append = [i = 0, &arr](auto const& s) mutable { auto append = [i = 0, &arr](auto const &s) mutable {
for (auto c : s) arr[i++] = c; for (auto c : s)
arr[i++] = c;
}; };
(append(Strs), ...); (append(Strs), ...);
arr[len] = 0; arr[len] = 0;
...@@ -948,110 +800,87 @@ struct join_s { ...@@ -948,110 +800,87 @@ struct join_s {
// Give the joined string static storage // Give the joined string static storage
static constexpr auto arr = impl(); static constexpr auto arr = impl();
// View as a std::string_view // View as a std::string_view
static constexpr std::string_view value {arr.data(), arr.size() - 1}; static constexpr std::string_view value{arr.data(), arr.size() - 1};
}; };
template <std::string_view const&... Strs> template <std::string_view const &...Strs>
static constexpr auto join = join_s<Strs...>::value; static constexpr auto join = join_s<Strs...>::value;
} // namespace meta } // namespace meta
/* Object model */ /* Object model */
struct object { struct object {
template <typename T, typename O> template <typename T, typename O> friend struct instance;
friend struct instance;
template <typename B, typename T> template <typename B, typename T> friend struct classtype;
friend struct classtype;
template <typename M> template <typename M> friend struct moduletype;
friend struct moduletype;
private: private:
static constexpr std::string_view object_of_ = "object of "; static constexpr std::string_view object_of_ = "object of ";
static constexpr std::string_view class_ = "class "; static constexpr std::string_view class_ = "class ";
static constexpr std::string_view module_ = "module "; static constexpr std::string_view module_ = "module ";
}; };
template <typename T, typename O> struct instance : T {
template <typename T, typename O>
struct instance : T {
using type = T; using type = T;
static constexpr std::string_view repr = meta::join<object::object_of_, T::repr>; static constexpr std::string_view repr =
meta::join<object::object_of_, T::repr>;
const O * operator -> () const { return static_cast<const O *>(this); }
O * operator -> () { return static_cast<O *>(this); }
const O *operator->() const { return static_cast<const O *>(this); }
O *operator->() { return static_cast<O *>(this); }
}; };
template <typename T, typename O> struct value : instance<T, O> {};
template <typename T, typename O> template <typename B, typename T> struct classtype : B {
struct value : instance<T, O> {};
template <typename B, typename T>
struct classtype : B {
using base = B; using base = B;
using type = T; using type = T;
static constexpr std::string_view repr = meta::join<object::class_, T::name>; static constexpr std::string_view repr = meta::join<object::class_, T::name>;
const T * operator -> () const { return static_cast<const T *>(this); } const T *operator->() const { return static_cast<const T *>(this); }
T * operator -> () { return static_cast<T *>(this); } T *operator->() { return static_cast<T *>(this); }
}; };
namespace meta { namespace meta {
/* Class rebasing */ /* Class rebasing */
template <typename T> template <typename T> struct rebase_s {
struct rebase_s {
static_assert(always_false<T>, "Cannot rebase this type"); static_assert(always_false<T>, "Cannot rebase this type");
}; };
template <template <typename> typename Class, typename Base> template <template <typename> typename Class, typename Base>
struct rebase_s<Class<Base>> { struct rebase_s<Class<Base>> {
template <typename Rebase> template <typename Rebase> using type = Class<Rebase>;
using type = Class<Rebase>;
}; };
template <typename T, typename Rebase> template <typename T, typename Rebase>
using rebase = typename rebase_s<std::remove_cvref_t<T>>::template type<Rebase>; using rebase = typename rebase_s<std::remove_cvref_t<T>>::template type<Rebase>;
} // namespace meta } // namespace meta
template <typename M> struct moduletype : object {
template <typename M>
struct moduletype : object {
using type = M; using type = M;
static constexpr std::string_view repr = meta::join<object::module_, M::name>; static constexpr std::string_view repr = meta::join<object::module_, M::name>;
const M * operator -> () const { return static_cast<const M *>(this); } const M *operator->() const { return static_cast<const M *>(this); }
M * operator -> () { return static_cast<M *>(this); } M *operator->() { return static_cast<M *>(this); }
}; };
struct function {}; struct function {};
struct method : function {}; struct method : function {};
struct classmethod : function {}; struct classmethod : function {};
struct staticmethod : function {}; struct staticmethod : function {};
template <typename S, typename F> struct boundmethod : object {
template <typename S, typename F>
struct boundmethod : object {
using Self = S; using Self = S;
using Func = F; using Func = F;
...@@ -1059,44 +888,38 @@ struct boundmethod : object { ...@@ -1059,44 +888,38 @@ struct boundmethod : object {
boundmethod(boundmethod &) = default; boundmethod(boundmethod &) = default;
boundmethod(boundmethod &&) = default; boundmethod(boundmethod &&) = default;
boundmethod & operator = (boundmethod &) = default; boundmethod &operator=(boundmethod &) = default;
boundmethod & operator = (boundmethod &&) = default; boundmethod &operator=(boundmethod &&) = default;
template <typename T> template <typename T>
boundmethod(const boundmethod<T, F> & m) : self(m.self), func(m.func) {} boundmethod(const boundmethod<T, F> &m) : self(m.self), func(m.func) {}
template <typename T> template <typename T>
boundmethod(boundmethod<T, F> && m) : self(std::move(m.self)), func(m.func) {} boundmethod(boundmethod<T, F> &&m) : self(std::move(m.self)), func(m.func) {}
template <typename T> template <typename T> boundmethod &operator=(boundmethod<T, F> &m) {
boundmethod & operator = (boundmethod <T, F> & m) {
func = m.func; func = m.func;
self = m.self; self = m.self;
return *this; return *this;
} }
template <typename T> template <typename T> boundmethod &operator=(boundmethod<T, F> &&m) {
boundmethod & operator = (boundmethod <T, F> && m) {
func = std::move(m.func); func = std::move(m.func);
self = std::move(m.self); self = std::move(m.self);
return *this; return *this;
} }
template <typename... Args> template <typename... Args> auto operator()(Args &&...args) & {
auto operator () (Args &&... args) & {
return func(forward(self), std::forward<Args>(args)...); return func(forward(self), std::forward<Args>(args)...);
} }
template <typename... Args> template <typename... Args> auto operator()(Args &&...args) && {
auto operator () (Args &&... args) && {
return func(forward(std::move(self)), std::forward<Args>(args)...); return func(forward(std::move(self)), std::forward<Args>(args)...);
} }
template <typename T, typename G> template <typename T, typename G> friend struct boundmethod;
friend struct boundmethod;
template <meta::instance T, meta::method G> template <meta::instance T, meta::method G> friend auto bind(T &&, const G &);
friend auto bind(T &&, const G &);
template <meta::classtype T, meta::classmethod G> template <meta::classtype T, meta::classmethod G>
friend auto bind(T &&, const G &); friend auto bind(T &&, const G &);
...@@ -1104,139 +927,152 @@ struct boundmethod : object { ...@@ -1104,139 +927,152 @@ struct boundmethod : object {
template <meta::instance T, meta::classmethod G> template <meta::instance T, meta::classmethod G>
friend auto bind(T &&, const G &); friend auto bind(T &&, const G &);
const F & _func_() const { const F &_func_() const { return func; }
return func;
}
const S & _self_() const { const S &_self_() const { return self; }
return self;
}
private: private:
template <typename T> template <typename T>
boundmethod(T && self, F func) : self(std::forward<T>(self)), func(func) {} boundmethod(T &&self, F func) : self(std::forward<T>(self)), func(func) {}
[[no_unique_address]] S self; [[no_unique_address]] S self;
[[no_unique_address]] F func; [[no_unique_address]] F func;
}; };
namespace meta { namespace meta {
/* Specialisations for boundmethod */ /* Specialisations for boundmethod */
template <boundmethod T> template <boundmethod T> struct pack_s<T> {
struct pack_s<T> {
using U = std::remove_cvref_t<T>; using U = std::remove_cvref_t<T>;
using type = referencemodel::boundmethod< using type =
pack<typename U::Self>, typename U::Func>; referencemodel::boundmethod<pack<typename U::Self>, typename U::Func>;
}; };
template <boundmethod T> template <boundmethod T> struct rc_s<T> {
struct rc_s<T> {
using U = std::remove_cvref_t<T>; using U = std::remove_cvref_t<T>;
using type = referencemodel::boundmethod< using type =
rc<typename U::Self>, typename U::Func>; referencemodel::boundmethod<rc<typename U::Self>, typename U::Func>;
}; };
template <boundmethod T> template <boundmethod T> struct arc_s<T> {
struct arc_s<T> {
using U = std::remove_cvref_t<T>; using U = std::remove_cvref_t<T>;
using type = referencemodel::boundmethod< using type =
arc<typename U::Self>, typename U::Func>; referencemodel::boundmethod<arc<typename U::Self>, typename U::Func>;
}; };
template <boundmethod T> template <boundmethod T> struct box_s<T> {
struct box_s<T> {
using U = std::remove_cvref_t<T>; using U = std::remove_cvref_t<T>;
using type = referencemodel::boundmethod< using type =
box<typename U::Self>, typename U::Func>; referencemodel::boundmethod<box<typename U::Self>, typename U::Func>;
}; };
template <boundmethod T> template <boundmethod T> struct ref_s<T> {
struct ref_s<T> {
using U = std::remove_cvref_t<T>; using U = std::remove_cvref_t<T>;
using type = referencemodel::boundmethod< using type =
ref<typename U::Self>, typename U::Func>; referencemodel::boundmethod<ref<typename U::Self>, typename U::Func>;
}; };
template <boundmethod T> template <boundmethod T> struct borrow_s<T> {
struct borrow_s<T> {
using U = std::remove_cvref_t<T>; using U = std::remove_cvref_t<T>;
using type = referencemodel::boundmethod< using type =
borrow<typename U::Self>, typename U::Func>; referencemodel::boundmethod<borrow<typename U::Self>, typename U::Func>;
}; };
template <boundmethod T> template <boundmethod T> struct forward_s<T> {
struct forward_s<T> {
using U = std::remove_cvref_t<T>; using U = std::remove_cvref_t<T>;
using type = referencemodel::boundmethod< using type =
forward<typename U::Self>, typename U::Func>; referencemodel::boundmethod<forward<typename U::Self>, typename U::Func>;
}; };
template <boundmethod T> template <boundmethod T> struct forward_s<T &&> {
struct forward_s<T &&> {
using U = std::remove_cvref_t<T>; using U = std::remove_cvref_t<T>;
using type = referencemodel::boundmethod< using type = referencemodel::boundmethod<forward<typename U::Self &&>,
forward<typename U::Self &&>, typename U::Func>; typename U::Func>;
}; };
template <boundmethod T> template <boundmethod T> struct recover_s<T> {
struct recover_s<T> {
using U = std::remove_cvref_t<T>; using U = std::remove_cvref_t<T>;
using type = referencemodel::boundmethod< using type =
recover<typename U::Self>, typename U::Func>; referencemodel::boundmethod<recover<typename U::Self>, typename U::Func>;
}; };
template <boundmethod T> template <boundmethod T> struct own_s<T> {
struct own_s<T> {
using U = std::remove_cvref_t<T>; using U = std::remove_cvref_t<T>;
using type = referencemodel::boundmethod< using type =
own<typename U::Self>, typename U::Func>; referencemodel::boundmethod<own<typename U::Self>, typename U::Func>;
}; };
} // namespace meta } // namespace meta
/* Attribute access with on-the-fly method binding */ /* Attribute access with on-the-fly method binding */
template <meta::instance S, meta::method F> template <meta::instance S, meta::method F> auto bind(S &&self, const F &func) {
auto bind(S && self, const F & func) {
return boundmethod<meta::forward<S &&>, F>(std::forward<S>(self), func); return boundmethod<meta::forward<S &&>, F>(std::forward<S>(self), func);
} }
template <meta::classtype S, meta::classmethod F> template <meta::classtype S, meta::classmethod F>
auto bind(S && self, const F & func) { auto bind(S &&self, const F &func) {
return boundmethod<std::remove_cvref_t<S>, F> { self, func }; return boundmethod<std::remove_cvref_t<S>, F>{self, func};
} }
template <meta::instance S, meta::classmethod F> template <meta::instance S, meta::classmethod F>
auto bind(S &&, const F & func) { auto bind(S &&, const F &func) {
using type = typename meta::unwrap_all<S>::type; using type = typename meta::unwrap_all<S>::type;
static_assert(sizeof(type) == 1); static_assert(sizeof(type) == 1);
return boundmethod<type, F> { type {}, func }; return boundmethod<type, F>{type{}, func};
} }
template <typename S, typename A, typename... T> template <typename S, typename A, typename... T>
decltype(auto) bind(S &&, const A & attr, T...) { decltype(auto) bind(S &&, const A &attr, T...) {
return attr; return attr;
} }
#define dot(OBJ, NAME)\ #define dot(OBJ, NAME) \
[](auto && obj) -> decltype(auto) {\ [](auto &&obj) -> decltype(auto) { \
return referencemodel::bind(std::forward<decltype(obj)>(obj), obj->NAME);\ return referencemodel::bind(std::forward<decltype(obj)>(obj), obj->NAME); \
}(OBJ) }(OBJ)
/* Operators */ /* Operators */
namespace meta { namespace meta {
// note: using dot here would cause hard failure instead of invalid constraint
/* + */ /* + */
template <typename Left, typename Right> #define LR_OP(OP, DUNDER) \
namespace meta { \
template <typename Left, typename Right> \
concept Left##DUNDER##able = requires(Left left, Right right) { \
left->oo__##DUNDER##__oo(left, right); \
}; \
\
template <typename Left, typename Right> \
concept Right##DUNDER##able = requires(Left left, Right right) { \
right->oo__r##DUNDER##__oo(right, left); \
}; \
\
template <typename Left, typename Right> \
concept DUNDER##able = \
Left##DUNDER##able<Left, Right> || Right##DUNDER##able<Left, Right>; \
} \
template <meta::object Left, meta::object Right> \
requires meta::DUNDER \
##able<Left, Right> auto operator OP(Left &&left, Right &&right) { \
if constexpr (meta::Left##DUNDER##able<Left, Right>) { \
return dot(std::forward<Left>(left), \
oo__##DUNDER##__oo)(std::forward<Right>(right)); \
} else { \
if constexpr (meta::Right##DUNDER##able<Left, Right>) { \
return dot(std::forward<Right>(right), \
oo__r##DUNDER##__oo)(std::forward<Left>(left)); \
} \
} \
}
/*template <typename Left, typename Right>
concept LeftAddable = requires (Left left, Right right) { concept LeftAddable = requires (Left left, Right right) {
// note: using dot here would cause hard failure instead of invalid constraint
left->oo__add__oo(left, right); left->oo__add__oo(left, right);
}; };
...@@ -1247,15 +1083,13 @@ concept RightAddable = requires (Left left, Right right) { ...@@ -1247,15 +1083,13 @@ concept RightAddable = requires (Left left, Right right) {
}; };
template <typename Left, typename Right> template <typename Left, typename Right>
concept Addable = LeftAddable<Left, Right> || RightAddable<Left, Right>; concept Addable = LeftAddable<Left, Right> || RightAddable<Left, Right>;*/
}
} // namespace meta
/* + */ /* + */
template <meta::object Left, meta::object Right> /*template <meta::object Left, meta::object Right>
requires meta::Addable<Left, Right> requires meta::Addable<Left, Right>
auto operator + (Left && left, Right && right) { auto operator + (Left && left, Right && right) {
if constexpr (meta::LeftAddable<Left, Right>) { if constexpr (meta::LeftAddable<Left, Right>) {
...@@ -1269,12 +1103,19 @@ auto operator + (Left && left, Right && right) { ...@@ -1269,12 +1103,19 @@ auto operator + (Left && left, Right && right) {
} }
} }
} }
*/
LR_OP(+, add)
LR_OP(-, sub)
LR_OP(*, mul)
LR_OP(/, truediv)
LR_OP(%, mod)
LR_OP(<<, lshift)
LR_OP(>>, rshift)
LR_OP(&, and)
LR_OP(|, or)
LR_OP(^, xor)
} // namespace referencemodel } // namespace referencemodel
#endif // REFERENCEMODEL_H #endif // REFERENCEMODEL_H
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
#define TYPON_SOCKET_HPP #define TYPON_SOCKET_HPP
#include "builtins.hpp" #include "builtins.hpp"
#include <netinet/in.h>
#include <netdb.h> #include <netdb.h>
#include <netinet/in.h>
#include <tuple> #include <tuple>
namespace py_socket { namespace py_socket {
...@@ -25,13 +25,15 @@ struct socket_t { ...@@ -25,13 +25,15 @@ struct socket_t {
struct socket_s { struct socket_s {
struct py_type { struct py_type {
METHOD(typon::Task<std::tuple<TyObj<py_type> COMMA() std::string>>, accept, (Self self), { METHOD(typon::Task<std::tuple<TyObj<py_type> COMMA() std::string>>,
int connfd = co_await typon::io::accept(self->fd, NULL, NULL); accept, (Self self), {
if (connfd < 0) { int connfd = co_await typon::io::accept(self->fd, NULL, NULL);
system_error(-connfd, "accept()"); if (connfd < 0) {
} system_error(-connfd, "accept()");
co_return std::make_tuple(tyObj<py_type>(connfd), std::string("")); // TODO }
}) co_return std::make_tuple(tyObj<py_type>(connfd),
std::string("")); // TODO
})
METHOD(typon::Task<void>, close, (Self self), METHOD(typon::Task<void>, close, (Self self),
{ co_await typon::io::close(self->fd); }) { co_await typon::io::close(self->fd); })
...@@ -43,23 +45,27 @@ struct socket_t { ...@@ -43,23 +45,27 @@ struct socket_t {
} }
}) })
METHOD(void, setsockopt, (Self self, int level, int optname, int optval), { METHOD(void, setsockopt, (Self self, int level, int optname, int optval),
if (::setsockopt(self->fd, level, optname, &optval, sizeof(int)) < 0) { {
system_error(errno, "setsockopt()"); if (::setsockopt(self->fd, level, optname, &optval,
} sizeof(int)) < 0) {
}) system_error(errno, "setsockopt()");
}
METHOD(void, bind, (Self self, std::tuple<std::string COMMA() int> address), { })
auto [host, port] = address;
sockaddr_in6 addr; METHOD(void, bind,
std::memset(&addr, 0, sizeof(addr)); (Self self, std::tuple<std::string COMMA() int> address), {
addr.sin6_family = AF_INET6; auto [host, port] = address;
addr.sin6_port = htons(port); sockaddr_in6 addr;
addr.sin6_addr = in6addr_any; std::memset(&addr, 0, sizeof(addr));
if (::bind(self->fd, (const sockaddr *)&addr, sizeof(addr)) < 0) { addr.sin6_family = AF_INET6;
system_error(errno, "bind()"); addr.sin6_port = htons(port);
} addr.sin6_addr = in6addr_any;
}) if (::bind(self->fd, (const sockaddr *)&addr, sizeof(addr)) <
0) {
system_error(errno, "bind()");
}
})
METHOD(typon::Task<TyBytes>, recv, (Self self, int bufsize), { METHOD(typon::Task<TyBytes>, recv, (Self self, int bufsize), {
TyBytes buf(bufsize, '\0'); TyBytes buf(bufsize, '\0');
...@@ -77,8 +83,7 @@ struct socket_t { ...@@ -77,8 +83,7 @@ struct socket_t {
py_type(int fd = -1) : fd(fd) {} py_type(int fd = -1) : fd(fd) {}
py_type(const py_type &other) py_type(const py_type &other) : fd(other.fd) {}
: fd(other.fd) {}
int fd; int fd;
}; };
...@@ -92,21 +97,26 @@ struct socket_t { ...@@ -92,21 +97,26 @@ struct socket_t {
} }
} socket; } socket;
FUNCTION(auto, getaddrinfo, (std::string host, int port, int family=0, int type_=0, int proto=0, int flags=0), { FUNCTION(auto, getaddrinfo,
addrinfo hints; (std::string host, int port, int family = 0, int type_ = 0,
std::memset(&hints, 0, sizeof(hints)); int proto = 0, int flags = 0),
hints.ai_family = family; {
hints.ai_socktype = type_; addrinfo hints;
hints.ai_protocol = proto; std::memset(&hints, 0, sizeof(hints));
hints.ai_flags = flags; hints.ai_family = family;
addrinfo *res; hints.ai_socktype = type_;
// convert port to string hints.ai_protocol = proto;
std::string port_str = std::to_string(port); hints.ai_flags = flags;
if (int err = ::getaddrinfo(host.c_str(), port_str.c_str(), &hints, &res); err != 0) { addrinfo *res;
system_error(err, "getaddrinfo()"); // convert port to string
} std::string port_str = std::to_string(port);
return res; if (int err = ::getaddrinfo(host.c_str(), port_str.c_str(), &hints,
}) &res);
err != 0) {
system_error(err, "getaddrinfo()");
}
return res;
})
} all; } all;
auto &get_all() { return all; } auto &get_all() { return all; }
......
...@@ -5,24 +5,20 @@ ...@@ -5,24 +5,20 @@
#ifndef TYPON_SYS_HPP #ifndef TYPON_SYS_HPP
#define TYPON_SYS_HPP #define TYPON_SYS_HPP
#include <iostream>
#include "builtins.hpp" #include "builtins.hpp"
#include <iostream>
namespace py_sys { namespace py_sys {
struct sys_t { struct sys_t {
static constexpr auto &stdin = std::cin; static constexpr auto &stdin = std::cin;
static constexpr auto &stdout = std::cout; static constexpr auto &stdout = std::cout;
static constexpr auto &stderr = std::cerr; static constexpr auto &stderr = std::cerr;
typon::TyList<TyStr> argv; typon::TyList__oo<>::Obj<typon::TyStr__oo<>::Obj> argv;
FUNCTION(void, exit, (int code), { FUNCTION(void, exit, (int code), { std::exit(code); })
std::exit(code);
})
} all; } all;
auto& get_all() { auto &get_all() { return all; }
return all;
}
} // namespace py_sys } // namespace py_sys
#endif // TYPON_SYS_HPP #endif // TYPON_SYS_HPP
...@@ -42,15 +42,19 @@ if __name__ == "__main__": ...@@ -42,15 +42,19 @@ if __name__ == "__main__":
sum = 0 sum = 0
for i in range(15): for i in range(15):
sum = sum + i sum = sum + i
a = [n for n in range(10)] # a = [n for n in range(10)]
#b = [x for x in a if x % 2 == 0] # b = [x for x in a if x % 2 == 0]
#c = [y * y for y in b] #c = [y * y for y in b]
print("C++ " if is_cpp() else "Python", print("C++ " if is_cpp() else "Python",
"res=", 5, ".", True, [4, 5, 6], {7, 8, 9}, "res=", 5, ".", True, [4, 5, 6],
#[1, 2] + [3, 4], [5, 6] * 3, {1: 7, 9: 3}, #{7, 8, 9},
#0x55 & 7 == 5, # #[1, 2] + [3, 4], [5, 6] * 3,
#3j, {1: 7, 9: 3},
# 0x55 & 7 == 5,
# #3j,
sum, sum,
a) # # a,
# # b
)
print("Typon") print("Typon")
print() print()
...@@ -6,17 +6,12 @@ from socket import socket, SOCK_STREAM, AF_INET6, SOL_SOCKET, SO_REUSEADDR ...@@ -6,17 +6,12 @@ from socket import socket, SOCK_STREAM, AF_INET6, SOL_SOCKET, SO_REUSEADDR
from typon import fork from typon import fork
#fork = lambda x: x() #fork = lambda x: x()
BACKLOG = 1024
PORT = 8000
response_fmt = \
"HTTP/1.0 200 OK\r\n" \
"Content-type: text/plain\r\n" \
"Content-length: {}\r\n" \
"\r\n" \
"{}"
def create_listening_socket(port): def create_listening_socket(port):
BACKLOG = 1024
sockfd = socket(AF_INET6, SOCK_STREAM) sockfd = socket(AF_INET6, SOCK_STREAM)
sockfd.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) sockfd.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
sockfd.bind(("", port)) sockfd.bind(("", port))
...@@ -33,6 +28,12 @@ def handle_connection(connfd, filepath): ...@@ -33,6 +28,12 @@ def handle_connection(connfd, filepath):
buf = connfd.recv(1024).decode("utf-8") buf = connfd.recv(1024).decode("utf-8")
length = buf.find("\r\n\r\n") length = buf.find("\r\n\r\n")
content = read_file(filepath) content = read_file(filepath)
response_fmt = \
"HTTP/1.0 200 OK\r\n" \
"Content-type: text/plain\r\n" \
"Content-length: {}\r\n" \
"\r\n" \
"{}"
response = response_fmt.format(len(content), content) response = response_fmt.format(len(content), content)
connfd.send(response.encode("utf-8")) connfd.send(response.encode("utf-8"))
connfd.close() connfd.close()
...@@ -44,6 +45,8 @@ def server_loop(sockfd, filepath): ...@@ -44,6 +45,8 @@ def server_loop(sockfd, filepath):
fork(lambda: handle_connection(connfd, filepath)) fork(lambda: handle_connection(connfd, filepath))
if __name__ == "__main__": if __name__ == "__main__":
PORT = 8000
if len(sys.argv) > 2: if len(sys.argv) > 2:
print("Usage: webserver [ filepath ]") print("Usage: webserver [ filepath ]")
sys.exit(1) sys.exit(1)
......
...@@ -33,7 +33,8 @@ class DesugarCompare(ast.NodeTransformer): ...@@ -33,7 +33,8 @@ class DesugarCompare(ast.NodeTransformer):
) )
if type(op) in (ast.NotIn, ast.IsNot): if type(op) in (ast.NotIn, ast.IsNot):
call = ast.UnaryOp(ast.Not(), call, **lnd) call = ast.UnaryOp(ast.Not(), call, **lnd)
call.orig_node = ast.Compare(left, [op], [right], **lnd)
res.values.append(call) res.values.append(call)
if len(res.values) == 1: if len(res.values) == 1:
return res.values[0] res = res.values[0]
return res return res
\ No newline at end of file
...@@ -57,7 +57,7 @@ class ExpressionVisitor(NodeVisitor): ...@@ -57,7 +57,7 @@ class ExpressionVisitor(NodeVisitor):
# TODO: escape sequences # TODO: escape sequences
yield f"\"{repr(node.value)[1:-1]}\"_ps" yield f"\"{repr(node.value)[1:-1]}\"_ps"
elif isinstance(node.value, bool): elif isinstance(node.value, bool):
yield str(node.value).lower() yield f"typon::TyBool({str(node.value).lower()})"
elif isinstance(node.value, int): elif isinstance(node.value, int):
# TODO: bigints # TODO: bigints
yield str(node.value) + "_pi" yield str(node.value) + "_pi"
...@@ -189,7 +189,7 @@ class ExpressionVisitor(NodeVisitor): ...@@ -189,7 +189,7 @@ class ExpressionVisitor(NodeVisitor):
yield from self.visit(node.type.deref().return_type) yield from self.visit(node.type.deref().return_type)
yield "{" yield "{"
yield "return" yield "return"
yield from self.reset().visit(node.body) yield from self.visit(node.body)
yield ";" yield ";"
yield "}" yield "}"
...@@ -239,9 +239,9 @@ class ExpressionVisitor(NodeVisitor): ...@@ -239,9 +239,9 @@ class ExpressionVisitor(NodeVisitor):
def visit_List(self, node: ast.List) -> Iterable[str]: def visit_List(self, node: ast.List) -> Iterable[str]:
if node.elts: if node.elts:
yield "typon::TyList{" yield "typon::TyList({"
yield from join(", ", map(self.visit, node.elts)) yield from join(", ", map(self.visit, node.elts))
yield "}" yield "})"
else: else:
yield from self.visit(node.type) yield from self.visit(node.type)
yield "{}" yield "{}"
...@@ -264,21 +264,24 @@ class ExpressionVisitor(NodeVisitor): ...@@ -264,21 +264,24 @@ class ExpressionVisitor(NodeVisitor):
yield "}" yield "}"
if node.keys: if node.keys:
yield from self.visit(node.type) #yield from self.visit(node.type)
yield "typon::TyDict("
yield "{" yield "{"
yield from join(", ", map(visit_item, node.keys, node.values)) yield from join(", ", map(visit_item, node.keys, node.values))
yield "}" yield "}"
yield ")"
else: else:
yield from self.visit(node.type) yield from self.visit(node.type)
yield "{}" yield "{}"
def visit_Subscript(self, node: ast.Subscript) -> Iterable[str]: def visit_Subscript(self, node: ast.Subscript) -> Iterable[str]:
if isinstance(node.type, TypeType) and isinstance(node.type.type_object, MonomorphizedUserType): # if isinstance(node.type, TypeType) and isinstance(node.type.type_object, MonomorphizedUserType):
yield node.type.type_object.name # yield node.type.type_object.name
return # return
yield from self.prec("[]").visit(node.value) yield "("
yield "[" yield from self.visit(node.value)
yield from self.reset().visit(node.slice) yield ")["
yield from self.visit(node.slice)
yield "]" yield "]"
def visit_UnaryOp(self, node: ast.UnaryOp) -> Iterable[str]: def visit_UnaryOp(self, node: ast.UnaryOp) -> Iterable[str]:
......
...@@ -5,7 +5,7 @@ from typing import Iterable, Optional ...@@ -5,7 +5,7 @@ from typing import Iterable, Optional
from transpiler.phases.emit_cpp.expr import ExpressionVisitor from transpiler.phases.emit_cpp.expr import ExpressionVisitor
from transpiler.phases.typing.common import IsDeclare from transpiler.phases.typing.common import IsDeclare
from transpiler.phases.typing.scope import Scope from transpiler.phases.typing.scope import Scope
from transpiler.phases.emit_cpp.visitors import NodeVisitor, flatmap, CoroutineMode from transpiler.phases.emit_cpp.visitors import NodeVisitor, flatmap, CoroutineMode, join
from transpiler.phases.typing.types import CallableInstanceType, BaseType from transpiler.phases.typing.types import CallableInstanceType, BaseType
...@@ -13,11 +13,15 @@ def emit_function(name: str, func: CallableInstanceType) -> Iterable[str]: ...@@ -13,11 +13,15 @@ def emit_function(name: str, func: CallableInstanceType) -> Iterable[str]:
yield f"struct : referencemodel::function {{" yield f"struct : referencemodel::function {{"
yield "typon::Task<typon::TyNone> operator()(" yield "typon::Task<typon::TyNone> operator()("
for arg, ty in zip(func.block_data.node.args.args, func.parameters): def emit_arg(arg, ty):
yield "auto " yield "auto"
yield arg yield arg.arg
yield from join(",", (emit_arg(arg, ty) for arg, ty in zip(func.block_data.node.args.args, func.parameters)))
yield ") const {" yield ") const {"
for rd in func.block_data.scope.root_decls:
pass
yield from BlockVisitor(func.block_data.scope, generator=CoroutineMode.TASK).visit(func.block_data.node.body) yield from BlockVisitor(func.block_data.scope, generator=CoroutineMode.TASK).visit(func.block_data.node.body)
yield "co_return {};" yield "co_return {};"
yield "}" yield "}"
...@@ -152,14 +156,15 @@ class BlockVisitor(NodeVisitor): ...@@ -152,14 +156,15 @@ class BlockVisitor(NodeVisitor):
# #
# yield "}" # yield "}"
# #
def visit_lvalue(self, lvalue: ast.expr, declare: IsDeclare) -> Iterable[str]: def visit_lvalue(self, lvalue: ast.expr, declare: IsDeclare, allow_auto: bool = False) -> Iterable[str]:
if isinstance(lvalue, ast.Tuple): if isinstance(lvalue, ast.Tuple):
raise NotImplementedError()
# for name, decl, ty in zip(lvalue.elts, declare, lvalue.type.args): # for name, decl, ty in zip(lvalue.elts, declare, lvalue.type.args):
# if decl: # if decl:
# yield from self.visit_lvalue(name, True) # yield from self.visit_lvalue(name, True)
# yield ";" # yield ";"
# yield f"std::tie({', '.join(flatmap(self.visit_lvalue, lvalue.elts))})" def helper(args):
return self.visit_lvalue(*args)
yield f"std::tie({', '.join(flatmap(helper, zip(lvalue.elts, declare.detail)))})"
elif isinstance(lvalue, ast.Name): elif isinstance(lvalue, ast.Name):
if lvalue.id == "_": if lvalue.id == "_":
if not declare: if not declare:
...@@ -171,9 +176,12 @@ class BlockVisitor(NodeVisitor): ...@@ -171,9 +176,12 @@ class BlockVisitor(NodeVisitor):
# yield self.scope.declare(name, (" ".join(self.expr().visit(val)), val) if val else None, # yield self.scope.declare(name, (" ".join(self.expr().visit(val)), val) if val else None,
# getattr(val, "is_future", False)) # getattr(val, "is_future", False))
if declare: if declare:
yield "decltype(" if allow_auto:
yield from self.expr().visit(declare.initial_value) yield "auto"
yield ")" else:
yield "decltype("
yield from self.expr().visit(declare.initial_value)
yield ")"
#yield from self.visit(lvalue.type) #yield from self.visit(lvalue.type)
yield name yield name
elif isinstance(lvalue, ast.Subscript): elif isinstance(lvalue, ast.Subscript):
...@@ -186,18 +194,30 @@ class BlockVisitor(NodeVisitor): ...@@ -186,18 +194,30 @@ class BlockVisitor(NodeVisitor):
def visit_Assign(self, node: ast.Assign) -> Iterable[str]: def visit_Assign(self, node: ast.Assign) -> Iterable[str]:
if len(node.targets) != 1: if len(node.targets) != 1:
raise NotImplementedError(node) raise NotImplementedError(node)
yield from self.visit_lvalue(node.targets[0], node.is_declare) yield from self.visit_lvalue(node.targets[0], node.is_declare, True)
yield " = " yield " = "
yield from self.expr().visit(node.value) yield from self.expr().visit(node.value)
yield ";" yield ";"
def visit_AnnAssign(self, node: ast.AnnAssign) -> Iterable[str]: def visit_AnnAssign(self, node: ast.AnnAssign) -> Iterable[str]:
yield from self.visit_lvalue(node.target, node.is_declare) yield from self.visit_lvalue(node.target, node.is_declare, node.value is not None)
if node.value: if node.value:
yield " = " yield " = "
yield from self.expr().visit(node.value) yield from self.expr().visit(node.value)
yield ";" yield ";"
def visit_If(self, node: ast.If) -> Iterable[str]:
yield "if ("
yield from self.expr().visit(node.test)
yield ")"
yield from self.emit_block(node.inner_scope, node.body)
if node.orelse:
yield "else "
if isinstance(node.orelse, ast.If):
yield from self.visit(node.orelse)
else:
yield from self.emit_block(node.orelse_scope, node.orelse)
def visit_For(self, node: ast.For) -> Iterable[str]: def visit_For(self, node: ast.For) -> Iterable[str]:
if not isinstance(node.target, ast.Name): if not isinstance(node.target, ast.Name):
...@@ -216,8 +236,35 @@ class BlockVisitor(NodeVisitor): ...@@ -216,8 +236,35 @@ class BlockVisitor(NodeVisitor):
yield ")" yield ")"
yield from self.emit_block(node.inner_scope, node.orelse) yield from self.emit_block(node.inner_scope, node.orelse)
def visit_While(self, node: ast.While) -> Iterable[str]:
if node.orelse:
yield "auto"
yield node.orelse_variable
yield "= true;"
yield "while ("
yield from self.expr().visit(node.test)
yield ")"
yield from self.emit_block(node.inner_scope, node.body)
if node.orelse:
yield "if ("
yield node.orelse_variable
yield ")"
yield from self.emit_block(node.inner_scope, node.orelse)
def emit_block(self, scope: Scope, items: Iterable[ast.stmt]) -> Iterable[str]: def emit_block(self, scope: Scope, items: Iterable[ast.stmt]) -> Iterable[str]:
yield "{" yield "{"
for child in items: for child in items:
yield from BlockVisitor(scope, generator=self.generator).visit(child) yield from BlockVisitor(scope, generator=self.generator).visit(child)
yield "}" yield "}"
def visit_Return(self, node: ast.Return) -> Iterable[str]:
if CoroutineMode.ASYNC in self.generator:
yield "co_return "
else:
yield "return "
if node.value:
yield from self.expr().visit(node.value)
yield ";"
...@@ -3,7 +3,7 @@ from typing import Iterable ...@@ -3,7 +3,7 @@ from typing import Iterable
from transpiler.phases.emit_cpp.class_ import emit_class from transpiler.phases.emit_cpp.class_ import emit_class
from transpiler.phases.emit_cpp.function import emit_function from transpiler.phases.emit_cpp.function import emit_function
from transpiler.phases.typing.modules import ModuleType from transpiler.phases.typing.modules import ModuleType
from transpiler.phases.typing.types import CallableInstanceType, ClassTypeType from transpiler.phases.typing.types import CallableInstanceType, ClassTypeType, TypeVariable
def emit_module(mod: ModuleType) -> Iterable[str]: def emit_module(mod: ModuleType) -> Iterable[str]:
...@@ -17,6 +17,8 @@ def emit_module(mod: ModuleType) -> Iterable[str]: ...@@ -17,6 +17,8 @@ def emit_module(mod: ModuleType) -> Iterable[str]:
if not field.in_class_def: if not field.in_class_def:
continue continue
ty = field.type.deref() ty = field.type.deref()
from transpiler.phases.typing.expr import ScoperExprVisitor
ScoperExprVisitor(ty.block_data.scope).visit_function_call(ty, [TypeVariable() for _ in ty.parameters])
x = 5 x = 5
match ty: match ty:
case CallableInstanceType(): case CallableInstanceType():
......
...@@ -69,7 +69,9 @@ class NodeVisitor(UniversalVisitor): ...@@ -69,7 +69,9 @@ class NodeVisitor(UniversalVisitor):
case types.TY_STR: case types.TY_STR:
yield "typon::TyStr" yield "typon::TyStr"
case types.TypeVariable(name): case types.TypeVariable(name):
raise UnresolvedTypeVariableError(node) yield f"$VAR__{name}"
#raise UnresolvedTypeVariableError(node)
case types.GenericInstanceType(): case types.GenericInstanceType():
yield from self.visit(node.generic_parent) yield from self.visit(node.generic_parent)
yield "<" yield "<"
......
...@@ -72,9 +72,9 @@ PRECEDENCE_LEVELS = {op: i for i, ops in enumerate(PRECEDENCE) for op in ops} ...@@ -72,9 +72,9 @@ PRECEDENCE_LEVELS = {op: i for i, ops in enumerate(PRECEDENCE) for op in ops}
"""Mapping of C++ operators to their precedence level.""" """Mapping of C++ operators to their precedence level."""
MAPPINGS = { MAPPINGS = {
"True": "true", "True": "typon::TyBool(true)",
"False": "false", "False": "typon::TyBool(false)",
"None": "nullptr", "None": "typon::TyNone{}",
"operator": "operator_", "operator": "operator_",
} }
"""Mapping of Python builtin constants to C++ equivalents.""" """Mapping of Python builtin constants to C++ equivalents."""
from transpiler.phases.typing.common import PRELUDE from transpiler.phases.typing.common import PRELUDE
from transpiler.phases.typing.scope import VarKind, VarDecl from transpiler.phases.typing.scope import VarKind, VarDecl
from transpiler.phases.typing.types import TY_TASK, TY_CALLABLE, TY_OPTIONAL, TY_CPP_TYPE, TY_BUILTIN_FEATURE, TY_TUPLE, \ from transpiler.phases.typing.types import TY_TASK, TY_CALLABLE, TY_OPTIONAL, TY_CPP_TYPE, TY_BUILTIN_FEATURE, TY_TUPLE, \
TY_DICT, TY_SET, TY_LIST, TY_COMPLEX, TY_BYTES, TY_STR, TY_FLOAT, TY_INT, TY_BOOL, TY_OBJECT TY_DICT, TY_SET, TY_LIST, TY_COMPLEX, TY_BYTES, TY_STR, TY_FLOAT, TY_INT, TY_BOOL, TY_OBJECT, TY_JOIN, TY_FUTURE, \
TY_FORKED, TY_GENERATOR
prelude_vars = { prelude_vars = {
"object": TY_OBJECT, "object": TY_OBJECT,
...@@ -17,7 +18,11 @@ prelude_vars = { ...@@ -17,7 +18,11 @@ prelude_vars = {
"tuple": TY_TUPLE, "tuple": TY_TUPLE,
"BuiltinFeature": TY_BUILTIN_FEATURE, "BuiltinFeature": TY_BUILTIN_FEATURE,
"CppType": TY_CPP_TYPE, "CppType": TY_CPP_TYPE,
"Task": TY_TASK "Task": TY_TASK,
"Join": TY_JOIN,
"Future": TY_FUTURE,
"Forked": TY_FORKED,
"Generator": TY_GENERATOR,
} }
PRELUDE.vars.update({name: VarDecl(VarKind.LOCAL, ty.type_type()) for name, ty in prelude_vars.items()}) PRELUDE.vars.update({name: VarDecl(VarKind.LOCAL, ty.type_type()) for name, ty in prelude_vars.items()})
......
...@@ -5,7 +5,8 @@ import importlib ...@@ -5,7 +5,8 @@ import importlib
from dataclasses import dataclass from dataclasses import dataclass
from transpiler.exceptions import CompileError from transpiler.exceptions import CompileError
from transpiler.phases.typing.types import BaseType, TypeVariable from transpiler.phases.typing.types import BaseType, TypeVariable, CallableInstanceType, TY_NONE, PromiseInstanceType, \
TupleInstanceType, RuntimeValue, PromiseKind
from transpiler.utils import highlight, linenodata from transpiler.utils import highlight, linenodata
from transpiler.phases.typing.common import ScoperVisitor, is_builtin, DeclareInfo from transpiler.phases.typing.common import ScoperVisitor, is_builtin, DeclareInfo
from transpiler.phases.typing.expr import ScoperExprVisitor, DUNDER from transpiler.phases.typing.expr import ScoperExprVisitor, DUNDER
...@@ -80,8 +81,8 @@ class ScoperBlockVisitor(ScoperVisitor): ...@@ -80,8 +81,8 @@ class ScoperBlockVisitor(ScoperVisitor):
raise NotImplementedError(node) raise NotImplementedError(node)
target = node.targets[0] target = node.targets[0]
ty = self.get_type(node.value) ty = self.get_type(node.value)
decl = self.visit_assign_target(target, ty) decl = self.visit_assign_target(target, ty, node.value)
node.is_declare = DeclareInfo(node.value) if decl else None node.is_declare = DeclareInfo(decl, node.value) if decl else None
def visit_AnnAssign(self, node: ast.AnnAssign): def visit_AnnAssign(self, node: ast.AnnAssign):
if node.simple != 1: if node.simple != 1:
...@@ -89,14 +90,14 @@ class ScoperBlockVisitor(ScoperVisitor): ...@@ -89,14 +90,14 @@ class ScoperBlockVisitor(ScoperVisitor):
if not isinstance(node.target, ast.Name): if not isinstance(node.target, ast.Name):
raise NotImplementedError(node) raise NotImplementedError(node)
ty = self.visit_annotation(node.annotation) ty = self.visit_annotation(node.annotation)
decl = self.visit_assign_target(node.target, ty) decl = self.visit_assign_target(node.target, ty, node.value)
node.is_declare = DeclareInfo(node.value) if decl else None node.is_declare = DeclareInfo(decl, node.value) if decl else None
if node.value is not None: if node.value is not None:
ty_val = self.get_type(node.value) ty_val = self.get_type(node.value)
__TB__ = f"unifying annotation {highlight(node.annotation)} with value {highlight(node.value)} of type {highlight(ty_val)}" __TB__ = f"unifying annotation {highlight(node.annotation)} with value {highlight(node.value)} of type {highlight(ty_val)}"
ty.unify(ty_val) ty.unify(ty_val)
def visit_assign_target(self, target, decl_val: BaseType) -> bool: def visit_assign_target(self, target, decl_val: BaseType, val: ast.expr = None) -> bool:
__TB__ = f"analyzing assignment target {highlight(target)} with value {highlight(decl_val)}" __TB__ = f"analyzing assignment target {highlight(target)} with value {highlight(decl_val)}"
if isinstance(target, ast.Name): if isinstance(target, ast.Name):
if target.id == "_": if target.id == "_":
...@@ -107,20 +108,26 @@ class ScoperBlockVisitor(ScoperVisitor): ...@@ -107,20 +108,26 @@ class ScoperBlockVisitor(ScoperVisitor):
vdecl.type.unify(decl_val) vdecl.type.unify(decl_val)
return False return False
else: else:
self.scope.vars[target.id] = VarDecl(VarKind.LOCAL, decl_val) # self.scope.vars[target.id] = VarDecl(VarKind.LOCAL, decl_val)
# if self.scope.kind == ScopeKind.FUNCTION_INNER:
# self.root_decls[target.id] = VarDecl(VarKind.OUTER_DECL, decl_val)
# return False
# return True
val = val or RuntimeValue()
self.scope.function.vars[target.id] = VarDecl(VarKind.LOCAL, decl_val, val)
if self.scope.kind == ScopeKind.FUNCTION_INNER: if self.scope.kind == ScopeKind.FUNCTION_INNER:
self.root_decls[target.id] = VarDecl(VarKind.OUTER_DECL, decl_val) self.scope.function.root_decls[target.id] = val
return False return False
return True return True
elif isinstance(target, ast.Tuple): elif isinstance(target, ast.Tuple):
if not isinstance(decl_val, TupleType): if not isinstance(decl_val, TupleInstanceType):
from transpiler.phases.typing.exceptions import InvalidUnpackError from transpiler.phases.typing.exceptions import InvalidUnpackError
raise InvalidUnpackError(decl_val) raise InvalidUnpackError(decl_val)
if len(target.elts) != len(decl_val.args): if len(target.elts) != len(decl_val.fields):
from transpiler.phases.typing.exceptions import InvalidUnpackCountError from transpiler.phases.typing.exceptions import InvalidUnpackCountError
raise InvalidUnpackCountError(decl_val, len(target.elts)) raise InvalidUnpackCountError(decl_val, len(target.elts))
target.type = decl_val target.type = decl_val
decls = [self.visit_assign_target(t, ty) for t, ty in zip(target.elts, decl_val.args)] # eager evaluated decls = [self.visit_assign_target(t, ty, ast.Name(str(t))) for t, ty in zip(target.elts, decl_val.fields)] # eager evaluated
return decls return decls
elif isinstance(target, ast.Attribute): elif isinstance(target, ast.Attribute):
attr_type = self.expr().visit(target) attr_type = self.expr().visit(target)
...@@ -202,9 +209,11 @@ class ScoperBlockVisitor(ScoperVisitor): ...@@ -202,9 +209,11 @@ class ScoperBlockVisitor(ScoperVisitor):
from transpiler.phases.typing.exceptions import OutsideFunctionError from transpiler.phases.typing.exceptions import OutsideFunctionError
raise OutsideFunctionError() raise OutsideFunctionError()
ftype = fct.obj_type ftype = fct.obj_type
assert isinstance(ftype, FunctionType) assert isinstance(ftype, CallableInstanceType)
vtype = self.expr().visit(node.value) if node.value else TY_NONE vtype = self.expr().visit(node.value) if node.value else TY_NONE
vtype.unify(ftype.return_type.return_type if isinstance(ftype.return_type, Promise) else ftype.return_type) vtype.unify(ftype.return_type.deref()
if isinstance(ftype.return_type.resolve(), PromiseInstanceType)
else ftype.return_type)
self.scope.diverges = True self.scope.diverges = True
#fct.has_return = True #fct.has_return = True
......
...@@ -129,6 +129,7 @@ def is_builtin(x, feature): ...@@ -129,6 +129,7 @@ def is_builtin(x, feature):
@dataclass @dataclass
class DeclareInfo: class DeclareInfo:
detail: bool | list[bool]
initial_value: Optional[ast.expr] = None initial_value: Optional[ast.expr] = None
......
...@@ -8,7 +8,7 @@ from transpiler.phases.typing.common import ScoperVisitor, is_builtin ...@@ -8,7 +8,7 @@ from transpiler.phases.typing.common import ScoperVisitor, is_builtin
from transpiler.phases.typing.exceptions import ArgumentCountMismatchError, TypeMismatchKind, TypeMismatchError from transpiler.phases.typing.exceptions import ArgumentCountMismatchError, TypeMismatchKind, TypeMismatchError
from transpiler.phases.typing.types import BaseType, TY_STR, TY_BOOL, TY_INT, TY_COMPLEX, TY_FLOAT, TY_NONE, \ from transpiler.phases.typing.types import BaseType, TY_STR, TY_BOOL, TY_INT, TY_COMPLEX, TY_FLOAT, TY_NONE, \
ClassTypeType, ResolvedConcreteType, GenericType, CallableInstanceType, TY_LIST, TY_SET, TY_DICT, RuntimeValue, \ ClassTypeType, ResolvedConcreteType, GenericType, CallableInstanceType, TY_LIST, TY_SET, TY_DICT, RuntimeValue, \
TypeVariable, TY_LAMBDA, TypeListType, MethodType, TY_TUPLE TypeVariable, TY_LAMBDA, TypeListType, MethodType, TY_TUPLE, PromiseInstanceType
from transpiler.phases.typing.scope import ScopeKind, VarDecl, VarKind from transpiler.phases.typing.scope import ScopeKind, VarDecl, VarKind
from transpiler.utils import linenodata from transpiler.utils import linenodata
...@@ -52,7 +52,7 @@ class ScoperExprVisitor(ScoperVisitor): ...@@ -52,7 +52,7 @@ class ScoperExprVisitor(ScoperVisitor):
return res return res
def visit_Tuple(self, node: ast.Tuple) -> BaseType: def visit_Tuple(self, node: ast.Tuple) -> BaseType:
return TY_TUPLE.instantiate_(*[self.visit(e) for e in node.elts]) return TY_TUPLE.instantiate([self.visit(e) for e in node.elts])
def visit_Slice(self, node: ast.Slice) -> BaseType: def visit_Slice(self, node: ast.Slice) -> BaseType:
for n in ("lower", "upper", "step"): for n in ("lower", "upper", "step"):
...@@ -112,13 +112,13 @@ class ScoperExprVisitor(ScoperVisitor): ...@@ -112,13 +112,13 @@ class ScoperExprVisitor(ScoperVisitor):
rtype = self.visit_function_call(ftype, [self.visit(arg) for arg in node.args]) rtype = self.visit_function_call(ftype, [self.visit(arg) for arg in node.args])
actual = rtype actual = rtype
node.is_await = False node.is_await = False
# if isinstance(actual, Promise) and actual.kind != PromiseKind.GENERATOR: if isinstance(actual, PromiseInstanceType): # and actual.kind != PromiseKind.GENERATOR: TODO
# node.is_await = True node.is_await = True
# actual = actual.return_type.resolve() actual = actual.value.resolve()
#
# if self.scope.function and isinstance(actual, Promise) and actual.kind == PromiseKind.FORKED \ if self.scope.function and isinstance(actual, Promise) and actual.kind == PromiseKind.FORKED \
# and isinstance(fty := self.scope.function.obj_type.return_type, Promise): and isinstance(fty := self.scope.function.obj_type.return_type, Promise):
# fty.kind = PromiseKind.JOIN fty.kind = PromiseKind.JOIN
return actual return actual
...@@ -141,11 +141,17 @@ class ScoperExprVisitor(ScoperVisitor): ...@@ -141,11 +141,17 @@ class ScoperExprVisitor(ScoperVisitor):
if not a.try_assign(b): if not a.try_assign(b):
raise TypeMismatchError(a, b, TypeMismatchKind.DIFFERENT_TYPE) raise TypeMismatchError(a, b, TypeMismatchKind.DIFFERENT_TYPE)
if not ftype.is_native:
pname = ftype.block_data.node.args.args[i].arg
ftype.block_data.scope.declare_local(pname, b)
if not ftype.is_native: if not ftype.is_native:
from transpiler.phases.typing.block import ScoperBlockVisitor from transpiler.phases.typing.block import ScoperBlockVisitor
vis = ScoperBlockVisitor(ftype.block_data.scope) scope = ftype.block_data.scope
vis = ScoperBlockVisitor(scope)
for stmt in ftype.block_data.node.body: for stmt in ftype.block_data.node.body:
vis.visit(stmt) vis.visit(stmt)
#ftype.generic_parent.cache_instance(ftype)
return ftype.return_type.resolve() return ftype.return_type.resolve()
# if isinstance(ftype, TypeType):# and isinstance(ftype.type_object, UserType): # if isinstance(ftype, TypeType):# and isinstance(ftype.type_object, UserType):
# init: FunctionType = self.visit_getattr(ftype, "__init__").remove_self() # init: FunctionType = self.visit_getattr(ftype, "__init__").remove_self()
...@@ -311,7 +317,7 @@ class ScoperExprVisitor(ScoperVisitor): ...@@ -311,7 +317,7 @@ class ScoperExprVisitor(ScoperVisitor):
gen: ast.comprehension = node.generators[0] gen: ast.comprehension = node.generators[0]
iter_type = self.get_iter(self.visit(gen.iter)) iter_type = self.get_iter(self.visit(gen.iter))
node.input_item_type = self.get_next(iter_type) node.input_item_type = self.get_next(iter_type)
virt_scope = self.scope.child(ScopeKind.FUNCTION_INNER) virt_scope = self.scope.child(ScopeKind.FUNCTION)
from transpiler.phases.typing.block import ScoperBlockVisitor from transpiler.phases.typing.block import ScoperBlockVisitor
visitor = ScoperBlockVisitor(virt_scope) visitor = ScoperBlockVisitor(virt_scope)
visitor.visit_assign_target(gen.target, node.input_item_type) visitor.visit_assign_target(gen.target, node.input_item_type)
......
...@@ -54,6 +54,7 @@ class Scope: ...@@ -54,6 +54,7 @@ class Scope:
diverges: bool = False diverges: bool = False
class_: Optional["Scope"] = None class_: Optional["Scope"] = None
is_loop: Optional[ast.For | ast.While] = None is_loop: Optional[ast.For | ast.While] = None
root_decls: Dict[str, ast.expr] = field(default_factory=dict)
@staticmethod @staticmethod
def make_global(): def make_global():
......
...@@ -15,7 +15,7 @@ from transpiler.phases.typing.scope import Scope, VarDecl, VarKind, ScopeKind ...@@ -15,7 +15,7 @@ from transpiler.phases.typing.scope import Scope, VarDecl, VarKind, ScopeKind
from transpiler.phases.typing.types import BaseType, BuiltinGenericType, BuiltinType, create_builtin_generic_type, \ from transpiler.phases.typing.types import BaseType, BuiltinGenericType, BuiltinType, create_builtin_generic_type, \
create_builtin_type, ConcreteType, GenericInstanceType, TypeListType, TypeTupleType, GenericParameter, \ create_builtin_type, ConcreteType, GenericInstanceType, TypeListType, TypeTupleType, GenericParameter, \
GenericParameterKind, TypeVariable, ResolvedConcreteType, MemberDef, ClassTypeType, CallableInstanceType, \ GenericParameterKind, TypeVariable, ResolvedConcreteType, MemberDef, ClassTypeType, CallableInstanceType, \
MethodType, UniqueTypeMixin, GenericType, BlockData MethodType, UniqueTypeMixin, GenericType, BlockData, TY_TASK
from transpiler.phases.utils import NodeVisitorSeq from transpiler.phases.utils import NodeVisitorSeq
def visit_generic_item( def visit_generic_item(
...@@ -158,6 +158,8 @@ class StdlibVisitor(NodeVisitorSeq): ...@@ -158,6 +158,8 @@ class StdlibVisitor(NodeVisitorSeq):
def visit_FunctionDef(self, node: ast.FunctionDef): def visit_FunctionDef(self, node: ast.FunctionDef):
def visit_nongeneric(scope, output: CallableInstanceType): def visit_nongeneric(scope, output: CallableInstanceType):
scope = scope.child(ScopeKind.FUNCTION) scope = scope.child(ScopeKind.FUNCTION)
scope.function = scope
scope.obj_type = output
arg_visitor = TypeAnnotationVisitor(scope) arg_visitor = TypeAnnotationVisitor(scope)
output.block_data = BlockData(node, scope) output.block_data = BlockData(node, scope)
output.parameters = [arg_visitor.visit(arg.annotation) for arg in node.args.args] output.parameters = [arg_visitor.visit(arg.annotation) for arg in node.args.args]
...@@ -165,6 +167,8 @@ class StdlibVisitor(NodeVisitorSeq): ...@@ -165,6 +167,8 @@ class StdlibVisitor(NodeVisitorSeq):
output.optional_at = len(node.args.args) - len(node.args.defaults) output.optional_at = len(node.args.args) - len(node.args.defaults)
output.is_variadic = args.vararg is not None output.is_variadic = args.vararg is not None
output.is_native = self.is_native output.is_native = self.is_native
if not self.is_native:
output.return_type = TY_TASK.instantiate([output.return_type])
@dataclass(eq=False, init=False) @dataclass(eq=False, init=False)
class InstanceType(CallableInstanceType): class InstanceType(CallableInstanceType):
......
...@@ -147,6 +147,11 @@ class TypeVariable(ConcreteType): ...@@ -147,6 +147,11 @@ class TypeVariable(ConcreteType):
def contains_internal(self, other: BaseType) -> bool: def contains_internal(self, other: BaseType) -> bool:
return self.resolve() is other.resolve() return self.resolve() is other.resolve()
def deref(self):
if self.resolved is None:
return self
return self.resolved.deref()
@dataclass(eq=False) @dataclass(eq=False)
...@@ -282,6 +287,13 @@ class GenericInstanceType(ResolvedConcreteType): ...@@ -282,6 +287,13 @@ class GenericInstanceType(ResolvedConcreteType):
# is this correct? # is this correct?
return self == other or any(a.contains(other) for a in self.generic_args) return self == other or any(a.contains(other) for a in self.generic_args)
class PromiseKind(enum.Enum):
TASK = 0
JOIN = 1
FUTURE = 2
FORKED = 3
GENERATOR = 4
class GenericParameterKind(enum.Enum): class GenericParameterKind(enum.Enum):
NORMAL = enum.auto() NORMAL = enum.auto()
TUPLE = enum.auto() TUPLE = enum.auto()
...@@ -303,6 +315,7 @@ class GenericConstraint: ...@@ -303,6 +315,7 @@ class GenericConstraint:
@dataclass(eq=False, init=False) @dataclass(eq=False, init=False)
class GenericType(BaseType): class GenericType(BaseType):
parameters: list[GenericParameter] parameters: list[GenericParameter]
instance_cache: dict[object, GenericInstanceType] = field(default_factory=dict, init=False)
def constraints(self, args: list[ConcreteType]) -> list[GenericConstraint]: def constraints(self, args: list[ConcreteType]) -> list[GenericConstraint]:
return [] return []
...@@ -329,6 +342,11 @@ class GenericType(BaseType): ...@@ -329,6 +342,11 @@ class GenericType(BaseType):
def deref(self): def deref(self):
return self.instantiate_default().deref() return self.instantiate_default().deref()
def cache_instance(self, instance):
if not hasattr(self, "instance_cache"):
self.instance_cache = {}
self.instance_cache[tuple(instance.generic_args)] = instance
@dataclass(eq=False, init=False) @dataclass(eq=False, init=False)
class BuiltinGenericType(UniqueTypeMixin, GenericType): class BuiltinGenericType(UniqueTypeMixin, GenericType):
...@@ -388,23 +406,45 @@ TY_DICT = create_builtin_generic_type("dict") ...@@ -388,23 +406,45 @@ TY_DICT = create_builtin_generic_type("dict")
TY_TUPLE = create_builtin_generic_type("tuple") TY_TUPLE = create_builtin_generic_type("tuple")
@dataclass(eq=False) @dataclass(eq=False)
class TaskInstanceType(GenericInstanceType): class PromiseInstanceType(GenericInstanceType):
value: ConcreteType value: ConcreteType
def deref(self): def deref(self):
return self.value.deref() match self.generic_parent.kind:
case PromiseKind.TASK | PromiseKind.JOIN:
return self.value.deref()
case _:
return self
@dataclass(eq=False)
class PromiseType(UniqueTypeMixin, GenericType):
kind: PromiseKind
class TaskType(UniqueTypeMixin, GenericType):
def name(self): def name(self):
return "Task" match self.kind:
case PromiseKind.TASK:
return "Task"
case PromiseKind.JOIN:
return "Join"
case PromiseKind.FUTURE:
return "Future"
case PromiseKind.FORKED:
return "Forked"
case PromiseKind.GENERATOR:
return "Generator"
def _instantiate(self, args: list[ConcreteType]) -> GenericInstanceType: def _instantiate(self, args: list[ConcreteType]) -> GenericInstanceType:
assert len(args) == 1 assert len(args) == 1
return TaskInstanceType(args[0]) return PromiseInstanceType(args[0])
TY_TASK = PromiseType([GenericParameter("T")], PromiseKind.TASK)
TY_JOIN = PromiseType([GenericParameter("T")], PromiseKind.JOIN)
TY_FUTURE = PromiseType([GenericParameter("T")], PromiseKind.FUTURE)
TY_FORKED = PromiseType([GenericParameter("T")], PromiseKind.FORKED)
TY_GENERATOR = PromiseType([GenericParameter("T")], PromiseKind.GENERATOR)
TY_TASK = TaskType()
TY_TUPLE.instantiate_ = lambda args: TupleInstanceType(args) TY_TUPLE.instantiate_ = lambda args: TupleInstanceType(args)
......
...@@ -63,12 +63,15 @@ def transpile(source, name: str, path: Path): ...@@ -63,12 +63,15 @@ def transpile(source, name: str, path: Path):
yield f"co_await dot(PROGRAMNS::{module.name()}, main)();" yield f"co_await dot(PROGRAMNS::{module.name()}, main)();"
yield "}" yield "}"
yield "int main(int argc, char* argv[]) {" yield "int main(int argc, char* argv[]) {"
yield "py_sys::all.argv = typon::TyList<TyStr>(std::vector<TyStr>(argv, argv + argc));" yield "py_sys::all.argv = typon::TyList__oo<>::Obj(std::vector<typon::TyStr__oo<>::Obj>(argv, argv + argc));"
yield f"root().call();" yield f"root().call();"
yield "}" yield "}"
yield "#endif" yield "#endif"
code = "\n".join(filter(None, main_module())) code = main_module()
code = filter(None, code)
code = list(code)
code = "\n".join(code)
return code return code
......
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