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)
*/
......
This diff is collapsed.
......@@ -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:
......@@ -16,12 +16,37 @@ public:
TyBytes(size_t count, char ch) : std::string(count, ch) {}
template <class InputIterator>
TyBytes(InputIterator first, InputIterator last) : std::string(first, last) {}
TyBytes(InputIterator first, InputIterator last) : std::string(first, last) {}
//TyStr decode_inner(const std::string &encoding = "utf-8") const;
// TyStr decode_inner(const std::string &encoding = "utf-8") const;
METHOD(TyStr, decode, (Self self, const std::string &encoding = "utf-8"), ;)
};*/
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:
struct : method {
auto operator()(auto self, int value) const {
self->value = value;
}
} static constexpr oo__init__oo {};
struct : method {
auto operator()(auto self, auto other) const {
return Integer(dot(self, value) + dot(other, value));
}
} static constexpr oo__add__oo {};
auto operator () (int value) const {
struct Obj : instance<Integer__oo<>, Obj> {
int value;
};
auto obj = rc(Obj{});
dot(obj, oo__init__oo)(value);
return obj;
}
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, auto other) const {
return Obj(dot(self, value) + dot(other, value));
}
} static constexpr oo__add__oo{};
constexpr TyInt(int value) : value(value) {}
constexpr TyInt() : value(0) {}
operator int() const { return value; }
struct : method {
auto operator()(auto self, auto other) const {
return Obj(dot(self, value) - dot(other, value));
}
} static constexpr oo__sub__oo{};
// 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; }
struct : method {
auto operator()(auto self, auto other) const {
return Obj(dot(self, value) * dot(other, value));
}
} static constexpr oo__mul__oo{};
TyInt operator-() const { return -value; }
struct : method {
auto operator()(auto self, auto other) const {
return Obj(dot(self, value) & dot(other, value));
}
} static constexpr oo__and__oo{};
struct : method {
auto operator()(auto self) const { return Obj(-dot(self, value)); }
} static constexpr oo__neg__oo{};
struct : method {
auto operator()(auto self, auto other) const {
return dot(self, value) < dot(other, value);
}
} static constexpr oo__lt__oo{};
struct : method {
auto operator()(auto self, auto other) const {
return dot(self, value) > dot(other, value);
}
} static constexpr oo__gt__oo{};
private:
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 TyInt(dot(self, value) % dot(other, value));
}
} static constexpr oo__mod__oo{};
struct : method {
auto operator()(auto self, int value) const {
self->value = value;
}
} static constexpr oo__init__oo {};
struct : method {
auto operator()(auto self, auto other) const {
return dot(self, value) >= dot(other, value);
}
} static constexpr oo__ge__oo{};
struct : method {
auto operator()(auto self, auto other) const {
return TyInt(dot(self, value) + dot(other, value));
}
} static constexpr oo__add__oo {};
struct : method {
auto operator()(auto self) const {
return TyStr__oo<>::Obj(std::to_string(self->value));
}
} static constexpr oo__str__oo{};
struct Obj : value<Integer__oo<>, Obj> {
int value;
static constexpr auto oo__repr__oo = oo__str__oo;
Obj(int value=0) : value(value) {}
operator int() const { return value; }
};
struct Obj : value<TyInt__oo<>, Obj> {
int value;
auto operator () (int value) const {
auto obj = rc(Obj{});
dot(obj, oo__init__oo)(value);
return obj;
}
Obj(int value = 0) : value(value) {}
operator int() const { return value; }
};
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:
using value_type = T;
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 start < stop ? i : stop - (i - start);
});
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
......@@ -23,7 +23,7 @@ struct hashlib_t {
struct py_type {
py_type(TyObj<void> context, openssl_update update, openssl_final final,
int diglen)
int diglen)
: _context(context), _update(update), _final(final), _diglen(diglen) {
}
......@@ -60,30 +60,28 @@ struct hashlib_t {
auto ctx = tyObj<MD5_CTX>();
MD5_Init(ctx.get());
return tyObj<_Hash_s>(ctx, (openssl_update)MD5_Update,
(openssl_final)MD5_Final, MD5_DIGEST_LENGTH);
(openssl_final)MD5_Final, MD5_DIGEST_LENGTH);
})
FUNCTION(auto, sha1, (), {
auto ctx = tyObj<SHA_CTX>();
SHA1_Init(ctx.get());
return tyObj<_Hash_s>(ctx, (openssl_update)SHA1_Update,
(openssl_final)SHA1_Final, SHA_DIGEST_LENGTH);
(openssl_final)SHA1_Final, SHA_DIGEST_LENGTH);
})
FUNCTION(auto, sha256, (), {
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,11 +9,12 @@
namespace py_json {
struct json_t {
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());
})
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());
})
} all;
auto &get_all() { return all; }
......
......@@ -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);
......@@ -73,7 +73,7 @@ struct os_t {
}
py_type(const TyStr &basepath, struct dirent **namelist, int n,
int current = 0)
int current = 0)
: basepath(basepath), namelist(namelist), n(n), current(current) {
if (this->basepath[this->basepath.size() - 1] != '/') {
this->basepath += '/';
......@@ -95,31 +95,25 @@ struct os_t {
};
} _Scandiriterator;
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)) {
system_error(-err, "statx()");
}
co_return TyObj<Stat_Result_s>(new Stat_Result_s::py_type{
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_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_btime.tv_sec + statxbuf.stx_btime.tv_nsec / 1e9});
})
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)) {
system_error(-err, "statx()");
}
co_return TyObj<Stat_Result_s>(new Stat_Result_s::py_type{
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_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_btime.tv_sec + statxbuf.stx_btime.tv_nsec / 1e9});
})
FUNCTION(TyObj<_Scandiriterator_s>, scandir, (const TyStr &path), {
const char *path_c = path.c_str();
......@@ -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
This diff is collapsed.
......@@ -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,13 +25,15 @@ struct socket_t {
struct socket_s {
struct py_type {
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
})
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
})
METHOD(typon::Task<void>, close, (Self self),
{ co_await typon::io::close(self->fd); })
......@@ -43,23 +45,27 @@ struct socket_t {
}
})
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), {
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) {
system_error(errno, "bind()");
}
})
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), {
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) {
system_error(errno, "bind()");
}
})
METHOD(typon::Task<TyBytes>, recv, (Self self, int bufsize), {
TyBytes buf(bufsize, '\0');
......@@ -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,21 +97,26 @@ struct socket_t {
}
} socket;
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;
hints.ai_socktype = type_;
hints.ai_protocol = proto;
hints.ai_flags = flags;
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) {
system_error(err, "getaddrinfo()");
}
return res;
})
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;
hints.ai_socktype = type_;
hints.ai_protocol = proto;
hints.ai_flags = flags;
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) {
system_error(err, "getaddrinfo()");
}
return res;
})
} all;
auto &get_all() { return all; }
......
......@@ -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,9 +176,12 @@ 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:
yield "decltype("
yield from self.expr().visit(declare.initial_value)
yield ")"
if allow_auto:
yield "auto"
else:
yield "decltype("
yield from self.expr().visit(declare.initial_value)
yield ")"
#yield from self.visit(lvalue.type)
yield name
elif isinstance(lvalue, ast.Subscript):
......@@ -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):
return self.value.deref()
match self.generic_parent.kind:
case PromiseKind.TASK | PromiseKind.JOIN:
return self.value.deref()
case _:
return self
@dataclass(eq=False)
class PromiseType(UniqueTypeMixin, GenericType):
kind: PromiseKind
class TaskType(UniqueTypeMixin, GenericType):
def name(self):
return "Task"
match self.kind:
case PromiseKind.TASK:
return "Task"
case PromiseKind.JOIN:
return "Join"
case PromiseKind.FUTURE:
return "Future"
case PromiseKind.FORKED:
return "Forked"
case PromiseKind.GENERATOR:
return "Generator"
def _instantiate(self, args: list[ConcreteType]) -> GenericInstanceType:
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