Alexandria  2.25.0
SDC-CH common library for the Euclid project
NodeConverter.h
Go to the documentation of this file.
1 
19 #ifndef PYSTON_NODECONVERTER_H
20 #define PYSTON_NODECONVERTER_H
21 
22 #include "Pyston/Graph/Constant.h"
23 #include <boost/python.hpp>
24 
25 namespace Pyston {
26 
38 template <typename To, typename From>
39 static bool createCastNode(boost::python::object& object, void* storage) {
40  using boost::python::extract;
41 
42  extract<std::shared_ptr<Node<From>>> extractor(object);
43  if (!extractor.check())
44  return false;
45 
46  new (storage) std::shared_ptr<Node<To>>(new Cast<To, From>(extractor));
47 
48  return true;
49 }
50 
56 template <typename T>
57 struct NodeCast {
62  static bool isUpcast(PyObject*) {
63  return false;
64  }
65 
71  static bool cast(PyObject*, void*) {
72  return false;
73  }
74 };
75 
80 template <>
81 struct NodeCast<double> {
82 
86  static bool isUpcast(PyObject* obj_ptr) {
87  using boost::python::borrowed;
88  using boost::python::extract;
89  using boost::python::handle;
90  using boost::python::object;
91 
92  object object(handle<>(borrowed(obj_ptr)));
93  extract<Node<bool>> bool_extract(object);
94  extract<Node<int64_t>> int_extract(object);
95 
96  if (bool_extract.check() || int_extract.check()) {
97  return true;
98  }
99 
100  return false;
101  }
102 
106  static bool cast(PyObject* obj_ptr, void* storage) {
107  using boost::python::borrowed;
108  using boost::python::handle;
109  using boost::python::object;
110 
111  object object(handle<>(borrowed(obj_ptr)));
112 
113  return createCastNode<double, bool>(object, storage) || createCastNode<double, int64_t>(object, storage);
114  }
115 };
116 
121 template <>
122 struct NodeCast<int64_t> {
123 
127  static bool isUpcast(PyObject* obj_ptr) {
128  using boost::python::borrowed;
129  using boost::python::extract;
130  using boost::python::handle;
131  using boost::python::object;
132 
133  object object(handle<>(borrowed(obj_ptr)));
134  extract<Node<bool>> bool_extract(object);
135 
136  return bool_extract.check();
137  }
138 
142  static bool cast(PyObject* obj_ptr, void* storage) {
143  using boost::python::borrowed;
144  using boost::python::handle;
145  using boost::python::object;
146 
147  object object(handle<>(borrowed(obj_ptr)));
148 
149  return createCastNode<int64_t, bool>(object, storage);
150  }
151 };
152 
158 template <typename T>
167  static void* isConvertible(PyObject* obj_ptr) {
168  using boost::python::borrowed;
169  using boost::python::extract;
170  using boost::python::handle;
171  using boost::python::object;
172  using boost::python::converter::registry::query;
173 
174  // Primitive numeric types are ok
175 #if PY_MAJOR_VERSION >= 3
176  if (PyFloat_Check(obj_ptr) || PyLong_Check(obj_ptr) || PyBool_Check(obj_ptr)) {
177  return obj_ptr;
178  }
179 #else
180  if (PyFloat_Check(obj_ptr) || PyLong_Check(obj_ptr) || PyBool_Check(obj_ptr) || PyInt_Check(obj_ptr)) {
181  return obj_ptr;
182  }
183 #endif
184 
185  // Upcasting one type of node to another is too
186  if (NodeCast<T>::isUpcast(obj_ptr)) {
187  return obj_ptr;
188  }
189 
190  // Can't
191  return nullptr;
192  }
193 
203  static bool fromPrimitive(PyObject* obj_ptr, void* storage) {
204  // Rely on the casting done by C++
205  T value = 0;
206  if (PyFloat_Check(obj_ptr)) {
207  value = PyFloat_AsDouble(obj_ptr);
208  } else if (PyLong_Check(obj_ptr)) {
209  value = PyLong_AsLong(obj_ptr);
210  } else if (PyBool_Check(obj_ptr)) {
211  value = (obj_ptr == Py_True);
212 #if PY_MAJOR_VERSION < 3
213  } else if (PyInt_Check(obj_ptr)) {
214  value = PyInt_AsLong(obj_ptr);
215 #endif
216  } else {
217  return false;
218  }
219 
220  new (storage) std::shared_ptr<Node<T>>(new Constant<T>(value));
221  return true;
222  }
223 
231  static void construct(PyObject* obj_ptr, boost::python::converter::rvalue_from_python_stage1_data* data) {
232  // Memory area where to store the new type
233  void* storage =
234  ((boost::python::converter::rvalue_from_python_storage<std::shared_ptr<Node<T>>>*)data)->storage.bytes;
235 
236  // Abort if can not convert, because isConvertible hasn't done its job
237  if (!fromPrimitive(obj_ptr, storage) && !NodeCast<T>::cast(obj_ptr, storage))
238  abort();
239 
240  data->convertible = storage;
241  }
242 };
243 
244 } // end of namespace Pyston
245 
246 #endif // PYSTON_NODECONVERTER_H
static bool createCastNode(boost::python::object &object, void *storage)
Definition: NodeConverter.h:39
static bool isUpcast(PyObject *obj_ptr)
Definition: NodeConverter.h:86
static bool cast(PyObject *obj_ptr, void *storage)
static bool cast(PyObject *obj_ptr, void *storage)
static bool isUpcast(PyObject *obj_ptr)
static bool isUpcast(PyObject *)
Definition: NodeConverter.h:62
static bool cast(PyObject *, void *)
Definition: NodeConverter.h:71
static bool fromPrimitive(PyObject *obj_ptr, void *storage)
static void construct(PyObject *obj_ptr, boost::python::converter::rvalue_from_python_stage1_data *data)
static void * isConvertible(PyObject *obj_ptr)