1 /*-----------------------------------------------------------------------------
2 | Copyright (c) 2013-2017, Nucleic Development Team.
3 |
4 | Distributed under the terms of the Modified BSD License.
5 |
6 | The full license is in the file COPYING.txt, distributed with this software.
7 |----------------------------------------------------------------------------*/
8 #include <Python.h>
9 #include <kiwi/kiwi.h>
10 #include "pythonhelpers.h"
11 #include "symbolics.h"
12 #include "types.h"
13 #include "util.h"
14
15
16 using namespace PythonHelpers;
17
18
19 static PyObject*
Variable_new(PyTypeObject * type,PyObject * args,PyObject * kwargs)20 Variable_new( PyTypeObject* type, PyObject* args, PyObject* kwargs )
21 {
22 static const char *kwlist[] = { "name", "context", 0 };
23 PyObject* context = 0;
24 PyObject* name = 0;
25
26 if( !PyArg_ParseTupleAndKeywords(
27 args, kwargs, "|OO:__new__", const_cast<char**>( kwlist ),
28 &name, &context ) )
29 return 0;
30
31 PyObjectPtr pyvar( PyType_GenericNew( type, args, kwargs ) );
32 if( !pyvar )
33 return 0;
34
35 Variable* self = reinterpret_cast<Variable*>( pyvar.get() );
36 self->context = xnewref( context );
37
38 if( name != 0 )
39 {
40 #if PY_MAJOR_VERSION >= 3
41 if( !PyUnicode_Check( name ) )
42 return py_expected_type_fail( name, "unicode" );
43 #else
44 if( !( PyString_Check( name ) | PyUnicode_Check( name ) ) )
45 {
46 return py_expected_type_fail( name, "str or unicode" );
47 }
48 #endif
49 std::string c_name;
50 if( !convert_pystr_to_str(name, c_name) )
51 return 0; // LCOV_EXCL_LINE
52 new( &self->variable ) kiwi::Variable( c_name );
53 }
54 else
55 {
56 new( &self->variable ) kiwi::Variable();
57 }
58
59 return pyvar.release();
60 }
61
62
63 static void
Variable_clear(Variable * self)64 Variable_clear( Variable* self )
65 {
66 Py_CLEAR( self->context );
67 }
68
69
70 static int
Variable_traverse(Variable * self,visitproc visit,void * arg)71 Variable_traverse( Variable* self, visitproc visit, void* arg )
72 {
73 Py_VISIT( self->context );
74 return 0;
75 }
76
77
78 static void
Variable_dealloc(Variable * self)79 Variable_dealloc( Variable* self )
80 {
81 PyObject_GC_UnTrack( self );
82 Variable_clear( self );
83 self->variable.~Variable();
84 Py_TYPE( self )->tp_free( pyobject_cast( self ) );
85 }
86
87
88 static PyObject*
Variable_repr(Variable * self)89 Variable_repr( Variable* self )
90 {
91 return FROM_STRING( self->variable.name().c_str() );
92 }
93
94
95 static PyObject*
Variable_name(Variable * self)96 Variable_name( Variable* self )
97 {
98 return FROM_STRING( self->variable.name().c_str() );
99 }
100
101
102 static PyObject*
Variable_setName(Variable * self,PyObject * pystr)103 Variable_setName( Variable* self, PyObject* pystr )
104 {
105 #if PY_MAJOR_VERSION >= 3
106 if( !PyUnicode_Check( pystr ) )
107 return py_expected_type_fail( pystr, "unicode" );
108 #else
109 if( !(PyString_Check( pystr ) | PyUnicode_Check( pystr ) ) )
110 {
111 return py_expected_type_fail( pystr, "str or unicode" );
112 }
113 #endif
114 std::string str;
115 if( !convert_pystr_to_str( pystr, str ) )
116 return 0;
117 self->variable.setName( str );
118 Py_RETURN_NONE;
119 }
120
121
122 static PyObject*
Variable_context(Variable * self)123 Variable_context( Variable* self )
124 {
125 if( self->context )
126 return newref( self->context );
127 Py_RETURN_NONE;
128 }
129
130
131 static PyObject*
Variable_setContext(Variable * self,PyObject * value)132 Variable_setContext( Variable* self, PyObject* value )
133 {
134 if( value != self->context )
135 {
136 PyObject* temp = self->context;
137 self->context = newref( value );
138 Py_XDECREF( temp );
139 }
140 Py_RETURN_NONE;
141 }
142
143
144 static PyObject*
Variable_value(Variable * self)145 Variable_value( Variable* self )
146 {
147 return PyFloat_FromDouble( self->variable.value() );
148 }
149
150
151 static PyObject*
Variable_add(PyObject * first,PyObject * second)152 Variable_add( PyObject* first, PyObject* second )
153 {
154 return BinaryInvoke<BinaryAdd, Variable>()( first, second );
155 }
156
157
158 static PyObject*
Variable_sub(PyObject * first,PyObject * second)159 Variable_sub( PyObject* first, PyObject* second )
160 {
161 return BinaryInvoke<BinarySub, Variable>()( first, second );
162 }
163
164
165 static PyObject*
Variable_mul(PyObject * first,PyObject * second)166 Variable_mul( PyObject* first, PyObject* second )
167 {
168 return BinaryInvoke<BinaryMul, Variable>()( first, second );
169 }
170
171
172 static PyObject*
Variable_div(PyObject * first,PyObject * second)173 Variable_div( PyObject* first, PyObject* second )
174 {
175 return BinaryInvoke<BinaryDiv, Variable>()( first, second );
176 }
177
178
179 static PyObject*
Variable_neg(PyObject * value)180 Variable_neg( PyObject* value )
181 {
182 return UnaryInvoke<UnaryNeg, Variable>()( value );
183 }
184
185
186 static PyObject*
Variable_richcmp(PyObject * first,PyObject * second,int op)187 Variable_richcmp( PyObject* first, PyObject* second, int op )
188 {
189 switch( op )
190 {
191 case Py_EQ:
192 return BinaryInvoke<CmpEQ, Variable>()( first, second );
193 case Py_LE:
194 return BinaryInvoke<CmpLE, Variable>()( first, second );
195 case Py_GE:
196 return BinaryInvoke<CmpGE, Variable>()( first, second );
197 default:
198 break;
199 }
200 PyErr_Format(
201 PyExc_TypeError,
202 "unsupported operand type(s) for %s: "
203 "'%.100s' and '%.100s'",
204 pyop_str( op ),
205 first->ob_type->tp_name,
206 second->ob_type->tp_name
207 );
208 return 0;
209 }
210
211
212 static PyMethodDef
213 Variable_methods[] = {
214 { "name", ( PyCFunction )Variable_name, METH_NOARGS,
215 "Get the name of the variable." },
216 { "setName", ( PyCFunction )Variable_setName, METH_O,
217 "Set the name of the variable." },
218 { "context", ( PyCFunction )Variable_context, METH_NOARGS,
219 "Get the context object associated with the variable." },
220 { "setContext", ( PyCFunction )Variable_setContext, METH_O,
221 "Set the context object associated with the variable." },
222 { "value", ( PyCFunction )Variable_value, METH_NOARGS,
223 "Get the current value of the variable." },
224 { 0 } // sentinel
225 };
226
227
228 static PyNumberMethods
229 Variable_as_number = {
230 (binaryfunc)Variable_add, /* nb_add */
231 (binaryfunc)Variable_sub, /* nb_subtract */
232 (binaryfunc)Variable_mul, /* nb_multiply */
233 #if PY_MAJOR_VERSION < 3
234 (binaryfunc)Variable_div, /* nb_divide */
235 #endif
236 0, /* nb_remainder */
237 0, /* nb_divmod */
238 0, /* nb_power */
239 (unaryfunc)Variable_neg, /* nb_negative */
240 0, /* nb_positive */
241 0, /* nb_absolute */
242 #if PY_MAJOR_VERSION >= 3
243 0, /* nb_bool */
244 #else
245 0, /* nb_nonzero */
246 #endif
247 0, /* nb_invert */
248 0, /* nb_lshift */
249 0, /* nb_rshift */
250 0, /* nb_and */
251 0, /* nb_xor */
252 (binaryfunc)0, /* nb_or */
253 #if PY_MAJOR_VERSION < 3
254 0, /* nb_coerce */
255 #endif
256 0, /* nb_int */
257 0, /* nb_long */
258 0, /* nb_float */
259 #if PY_MAJOR_VERSION < 3
260 0, /* nb_oct */
261 0, /* nb_hex */
262 #endif
263 0, /* nb_inplace_add */
264 0, /* nb_inplace_subtract */
265 0, /* nb_inplace_multiply */
266 #if PY_MAJOR_VERSION < 3
267 0, /* nb_inplace_divide */
268 #endif
269 0, /* nb_inplace_remainder */
270 0, /* nb_inplace_power */
271 0, /* nb_inplace_lshift */
272 0, /* nb_inplace_rshift */
273 0, /* nb_inplace_and */
274 0, /* nb_inplace_xor */
275 0, /* nb_inplace_or */
276 (binaryfunc)0, /* nb_floor_divide */
277 (binaryfunc)Variable_div, /* nb_true_divide */
278 0, /* nb_inplace_floor_divide */
279 0, /* nb_inplace_true_divide */
280 #if PY_VERSION_HEX >= 0x02050000
281 (unaryfunc)0, /* nb_index */
282 #endif
283 #if PY_VERSION_HEX >= 0x03050000
284 (binaryfunc)0, /* nb_matrix_multiply */
285 (binaryfunc)0, /* nb_inplace_matrix_multiply */
286 #endif
287 };
288
289
290 PyTypeObject Variable_Type = {
291 PyVarObject_HEAD_INIT( &PyType_Type, 0 )
292 "kiwisolver.Variable", /* tp_name */
293 sizeof( Variable ), /* tp_basicsize */
294 0, /* tp_itemsize */
295 (destructor)Variable_dealloc, /* tp_dealloc */
296 (printfunc)0, /* tp_print */
297 (getattrfunc)0, /* tp_getattr */
298 (setattrfunc)0, /* tp_setattr */
299 #if PY_VERSION_HEX >= 0x03050000
300 ( PyAsyncMethods* )0, /* tp_as_async */
301 #elif PY_VERSION_HEX >= 0x03000000
302 ( void* ) 0, /* tp_reserved */
303 #else
304 ( cmpfunc )0, /* tp_compare */
305 #endif
306 (reprfunc)Variable_repr, /* tp_repr */
307 (PyNumberMethods*)&Variable_as_number, /* tp_as_number */
308 (PySequenceMethods*)0, /* tp_as_sequence */
309 (PyMappingMethods*)0, /* tp_as_mapping */
310 (hashfunc)0, /* tp_hash */
311 (ternaryfunc)0, /* tp_call */
312 (reprfunc)0, /* tp_str */
313 (getattrofunc)0, /* tp_getattro */
314 (setattrofunc)0, /* tp_setattro */
315 (PyBufferProcs*)0, /* tp_as_buffer */
316 #if PY_MAJOR_VERSION >= 3
317 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC|Py_TPFLAGS_BASETYPE, /* tp_flags */
318 #else
319 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_CHECKTYPES, /* tp_flags */
320 #endif
321 0, /* Documentation string */
322 (traverseproc)Variable_traverse, /* tp_traverse */
323 (inquiry)Variable_clear, /* tp_clear */
324 (richcmpfunc)Variable_richcmp, /* tp_richcompare */
325 0, /* tp_weaklistoffset */
326 (getiterfunc)0, /* tp_iter */
327 (iternextfunc)0, /* tp_iternext */
328 (struct PyMethodDef*)Variable_methods, /* tp_methods */
329 (struct PyMemberDef*)0, /* tp_members */
330 0, /* tp_getset */
331 0, /* tp_base */
332 0, /* tp_dict */
333 (descrgetfunc)0, /* tp_descr_get */
334 (descrsetfunc)0, /* tp_descr_set */
335 0, /* tp_dictoffset */
336 (initproc)0, /* tp_init */
337 (allocfunc)PyType_GenericAlloc, /* tp_alloc */
338 (newfunc)Variable_new, /* tp_new */
339 (freefunc)PyObject_GC_Del, /* tp_free */
340 (inquiry)0, /* tp_is_gc */
341 0, /* tp_bases */
342 0, /* tp_mro */
343 0, /* tp_cache */
344 0, /* tp_subclasses */
345 0, /* tp_weaklist */
346 (destructor)0 /* tp_del */
347 };
348
349
import_variable()350 int import_variable()
351 {
352 return PyType_Ready( &Variable_Type );
353 }
354