-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathPyGenericAlias.cpp
More file actions
103 lines (87 loc) · 3 KB
/
Copy pathPyGenericAlias.cpp
File metadata and controls
103 lines (87 loc) · 3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include "PyGenericAlias.hpp"
#include "MemoryError.hpp"
#include "PyString.hpp"
#include "PyTuple.hpp"
#include "RuntimeError.hpp"
#include "types/api.hpp"
#include "types/builtin.hpp"
#include "vm/VM.hpp"
namespace py {
template<> PyGenericAlias *as(PyObject *obj)
{
if (obj->type() == types::generic_alias()) { return static_cast<PyGenericAlias *>(obj); }
return nullptr;
}
template<> const PyGenericAlias *as(const PyObject *obj)
{
if (obj->type() == types::generic_alias()) { return static_cast<const PyGenericAlias *>(obj); }
return nullptr;
}
PyGenericAlias::PyGenericAlias(PyType *type) : PyBaseObject(type) {}
PyGenericAlias::PyGenericAlias(PyObject *origin, PyTuple *args, PyObject *parameters)
: PyBaseObject(types::BuiltinTypes::the().generic_alias()), m_origin(origin), m_args(args),
m_parameters(parameters)
{}
PyResult<PyGenericAlias *>
PyGenericAlias::create(PyObject *origin, PyObject *args, PyObject *parameters)
{
auto &heap = VirtualMachine::the().heap();
auto *args_as_tuple = as<PyTuple>(args);
if (!args_as_tuple) {
auto args_ = PyTuple::create(args);
if (args_.is_err()) return Err(args_.unwrap_err());
args_as_tuple = args_.unwrap();
}
if (auto *obj = heap.allocate<PyGenericAlias>(origin, args_as_tuple, parameters)) {
return Ok(obj);
}
return Err(memory_error(sizeof(PyGenericAlias)));
}
PyResult<PyGenericAlias *> PyGenericAlias::create(PyObject *origin, PyObject *args)
{
return PyGenericAlias::create(origin, args, nullptr);
}
std::string PyGenericAlias::to_string() const
{
return fmt::format("<generic_alias object at {}>", static_cast<const void *>(this));
}
PyResult<PyObject *> PyGenericAlias::__repr__() const
{
// FIXME: this is a very simplified (and incorrect) version of the actual way generic_alias
// should be represented
if (!m_origin) { return Err(runtime_error("generic_alias origin not set")); }
std::ostringstream os;
for (size_t i = 0; const auto &el : m_args->elements()) {
auto type_ = PyObject::from(el);
ASSERT(type_.is_ok());
ASSERT(as<PyType>(type_.unwrap()));
os << as<PyType>(type_.unwrap())->name();
if (++i != m_args->elements().size()) { os << ", "; }
}
ASSERT(as<PyType>(m_origin));
return PyString::create(fmt::format("{}[{}]", as<PyType>(m_origin)->name(), os.str()));
}
namespace {
std::once_flag generic_alias_flag;
std::unique_ptr<TypePrototype> register_generic_alias()
{
return std::move(klass<PyGenericAlias>("types.GenericAlias").type);
}
}// namespace
std::function<std::unique_ptr<TypePrototype>()> PyGenericAlias::type_factory()
{
return [] {
static std::unique_ptr<TypePrototype> type = nullptr;
std::call_once(generic_alias_flag, []() { type = register_generic_alias(); });
return std::move(type);
};
}
PyType *PyGenericAlias::static_type() const { return types::generic_alias(); }
void PyGenericAlias::visit_graph(Visitor &visitor)
{
PyObject::visit_graph(visitor);
if (m_origin) visitor.visit(*m_origin);
if (m_args) visitor.visit(*m_args);
if (m_parameters) visitor.visit(*m_parameters);
}
}// namespace py