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

Continue work on generics

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