コード例 #1
0
ファイル: pabstract.c プロジェクト: Galland/nodebox-opengl
/* the 'cimpl_xxx()' functions are called at run-time, to do things
   we give up to write at the meta-level in the PsycoXxx() functions. */
static PyObject* cimpl_oldstyle_binary_op1(PyObject* v, PyObject* w,
					   const int op_slot)
{
	int err = PyNumber_CoerceEx(&v, &w);
	if (err < 0) {
		return NULL;
	}
	if (err == 0) {
		PyNumberMethods *mv = v->ob_type->tp_as_number;
		if (mv) {
			binaryfunc slot;
			slot = *NB_BINOP(mv, op_slot);
			if (slot) {
				PyObject *x = slot(v, w);
				Py_DECREF(v);
				Py_DECREF(w);
				return x;
			}
		}
		/* CoerceEx incremented the reference counts */
		Py_DECREF(v);
		Py_DECREF(w);
	}
	Py_INCREF(Py_NotImplemented);
	return Py_NotImplemented;
}
コード例 #2
0
/* Try a 3-way comparison, returning an int.  Return:
   -2 for an exception;
   -1 if v <  w;
    0 if v == w;
    1 if v  > w;
    2 if this particular 3-way comparison is not implemented or undefined.
*/
static int
try_3way_compare(PyObject *v, PyObject *w)
{
	int c;
	cmpfunc f;

	/* Comparisons involving instances are given to instance_compare,
	   which has the same return conventions as this function. */

	f = v->ob_type->tp_compare;
	if (PyInstance_Check(v))
		return (*f)(v, w);
	if (PyInstance_Check(w))
		return (*w->ob_type->tp_compare)(v, w);

	/* If both have the same (non-NULL) tp_compare, use it. */
	if (f != NULL && f == w->ob_type->tp_compare) {
		c = (*f)(v, w);
		if (c < 0 && PyErr_Occurred())
			return -1;
		return c < 0 ? -1 : c > 0 ? 1 : 0;
	}

	/* If either tp_compare is _PyObject_SlotCompare, that's safe. */
	if (f == _PyObject_SlotCompare ||
	    w->ob_type->tp_compare == _PyObject_SlotCompare)
		return _PyObject_SlotCompare(v, w);

	/* Try coercion; if it fails, give up */
	c = PyNumber_CoerceEx(&v, &w);
	if (c < 0)
		return -2;
	if (c > 0)
		return 2;

	/* Try v's comparison, if defined */
	if ((f = v->ob_type->tp_compare) != NULL) {
		c = (*f)(v, w);
		Py_DECREF(v);
		Py_DECREF(w);
		if (c < 0 && PyErr_Occurred())
			return -2;
		return c < 0 ? -1 : c > 0 ? 1 : 0;
	}

	/* Try w's comparison, if defined */
	if ((f = w->ob_type->tp_compare) != NULL) {
		c = (*f)(w, v); /* swapped! */
		Py_DECREF(v);
		Py_DECREF(w);
		if (c < 0 && PyErr_Occurred())
			return -2;
		return c < 0 ? 1 : c > 0 ? -1 : 0; /* negated! */
	}

	/* No comparison defined */
	Py_DECREF(v);
	Py_DECREF(w);
	return 2;
}
コード例 #3
0
/* Coerce two numeric types to the "larger" one.
   Increment the reference count on each argument.
   Return -1 and raise an exception if no coercion is possible
   (and then no reference count is incremented).
*/
int
PyNumber_Coerce(PyObject **pv, PyObject **pw)
{
	int err = PyNumber_CoerceEx(pv, pw);
	if (err <= 0)
		return err;
	PyErr_SetString(PyExc_TypeError, "number coercion failed");
	return -1;
}
コード例 #4
0
ファイル: object.c プロジェクト: Charlian/python-cobra
/* Try a 3-way comparison, returning an int.  Return:
   -2 for an exception;
   -1 if v <  w;
    0 if v == w;
    1 if v  > w;
    2 if this particular 3-way comparison is not implemented or undefined.
*/
static int
try_3way_compare(PyObject *v, PyObject *w)
{
	int c;
	cmpfunc f;

	/* Comparisons involving instances are given to instance_compare,
	   which has the same return conventions as this function. */

	f = v->ob_type->tp_compare;
	if (PyInstance_Check(v))
		return (*f)(v, w);
	if (PyInstance_Check(w))
		return (*w->ob_type->tp_compare)(v, w);

	/* If both have the same (non-NULL) tp_compare, use it. */
	if (f != NULL && f == w->ob_type->tp_compare) {
		c = (*f)(v, w);
		return adjust_tp_compare(c);
	}

	/* If either tp_compare is _PyObject_SlotCompare, that's safe. */
	if (f == _PyObject_SlotCompare ||
	    w->ob_type->tp_compare == _PyObject_SlotCompare)
		return _PyObject_SlotCompare(v, w);

	/* If we're here, v and w,
	    a) are not instances;
	    b) have different types or a type without tp_compare; and
	    c) don't have a user-defined tp_compare.
	   tp_compare implementations in C assume that both arguments
	   have their type, so we give up if the coercion fails or if
	   it yields types which are still incompatible (which can
	   happen with a user-defined nb_coerce).
	*/
	c = PyNumber_CoerceEx(&v, &w);
	if (c < 0)
		return -2;
	if (c > 0)
		return 2;
	f = v->ob_type->tp_compare;
	if (f != NULL && f == w->ob_type->tp_compare) {
		c = (*f)(v, w);
		Py_DECREF(v);
		Py_DECREF(w);
		return adjust_tp_compare(c);
	}

	/* No comparison defined */
	Py_DECREF(v);
	Py_DECREF(w);
	return 2;
}
コード例 #5
0
ファイル: complexobject.c プロジェクト: santagada/wpython
static PyObject *
complex_richcompare(PyObject *v, PyObject *w, int op)
{
	int c;
	Py_complex i, j;
	PyObject *res;

	c = PyNumber_CoerceEx(&v, &w);
	if (c < 0)
		return NULL;
	if (c > 0) {
		Py_INCREF(Py_NotImplemented);
		return Py_NotImplemented;
	}
	/* Make sure both arguments are complex. */
	if (!(PyComplex_Check(v) && PyComplex_Check(w))) {
		Py_DECREF(v);
		Py_DECREF(w);
		Py_INCREF(Py_NotImplemented);
		return Py_NotImplemented;
	}

	i = ((PyComplexObject *)v)->cval;
	j = ((PyComplexObject *)w)->cval;
	Py_DECREF(v);
	Py_DECREF(w);

	if (op != Py_EQ && op != Py_NE) {
		PyErr_SetString(PyExc_TypeError,
			"no ordering relation is defined for complex numbers");
		return NULL;
	}

	if ((i.real == j.real && i.imag == j.imag) == (op == Py_EQ))
		res = Py_True;
	else
		res = Py_False;

	Py_INCREF(res);
	return res;
}
コード例 #6
0
static int
wrap_coerce(PyObject **p_self, PyObject **p_other)
{
    PyObject *self = *p_self;
    PyObject *other = *p_other;
    PyObject *object;
    PyObject *left;
    PyObject *right;
    int r;

    assert(Proxy_Check(self));
    object = Proxy_GET_OBJECT(self);

    left = object;
    right = other;
    r = PyNumber_CoerceEx(&left, &right);
    if (r != 0)
        return r;
    /* Now left and right have been INCREF'ed.  Any new value that
       comes out is proxied; any unchanged value is left unchanged. */
    if (left == object) {
        /* Keep the old proxy */
        Py_INCREF(self);
        Py_DECREF(left);
        left = self;
    }
#if 0
    else {
        /* ??? create proxy for left? */
    }
    if (right != other) {
        /* ??? create proxy for right? */
    }
#endif
    *p_self = left;
    *p_other = right;
    return 0;
}
コード例 #7
0
ファイル: operations.hpp プロジェクト: gitter-badger/Nuitka
NUITKA_MAY_BE_UNUSED static PyObject *BINARY_OPERATION_REMAINDER( PyObject *operand1, PyObject *operand2 )
{
    CHECK_OBJECT( operand1 );
    CHECK_OBJECT( operand2 );

    binaryfunc slot1 = NULL;
    binaryfunc slot2 = NULL;

    PyTypeObject *type1 = Py_TYPE( operand1 );
    PyTypeObject *type2 = Py_TYPE( operand2 );

    if ( type1->tp_as_number != NULL && NEW_STYLE_NUMBER( operand1 ) )
    {
        slot1 = type1->tp_as_number->nb_remainder;
    }

    if ( type1 != type2 )
    {
        if ( type2->tp_as_number != NULL && NEW_STYLE_NUMBER( operand2 ) )
        {
            slot2 = type2->tp_as_number->nb_remainder;

            if ( slot1 == slot2 )
            {
                slot2 = NULL;
            }
        }
    }

    if ( slot1 != NULL )
    {
        if ( slot2 && PyType_IsSubtype( type2, type1 ) )
        {
            PyObject *x = slot2( operand1, operand2 );

            if ( x != Py_NotImplemented )
            {
                if (unlikely( x == NULL ))
                {
                    return NULL;
                }

                return x;
            }

            Py_DECREF( x );
            slot2 = NULL;
        }

        PyObject *x = slot1( operand1, operand2 );

        if ( x != Py_NotImplemented )
        {
            if (unlikely( x == NULL ))
            {
                return NULL;
            }

            return x;
        }

        Py_DECREF( x );
    }

    if ( slot2 != NULL )
    {
        PyObject *x = slot2( operand1, operand2 );

        if ( x != Py_NotImplemented )
        {
            if (unlikely( x == NULL ))
            {
                return NULL;
            }

            return x;
        }

        Py_DECREF( x );
    }

#if PYTHON_VERSION < 300
    if ( !NEW_STYLE_NUMBER( operand1 ) || !NEW_STYLE_NUMBER( operand2 ) )
    {
        int err = PyNumber_CoerceEx( &operand1, &operand2 );

        if ( err < 0 )
        {
            return NULL;
        }

        if ( err == 0 )
        {
            PyNumberMethods *mv = Py_TYPE( operand1 )->tp_as_number;

            if ( mv )
            {
                binaryfunc slot = mv->nb_remainder;

                if ( slot != NULL )
                {
                    PyObject *x = slot( operand1, operand2 );

                    Py_DECREF( operand1 );
                    Py_DECREF( operand2 );

                    if (unlikely( x == NULL ))
                    {
                        return NULL;
                    }

                    return x;
                }
            }

            // CoerceEx did that
            Py_DECREF( operand1 );
            Py_DECREF( operand2 );
        }
    }
#endif

    PyErr_Format(
        PyExc_TypeError,
        "unsupported operand type(s) for %%: '%s' and '%s'",
        type1->tp_name,
        type2->tp_name
    );

    return NULL;
}
コード例 #8
0
ファイル: operations.hpp プロジェクト: gitter-badger/Nuitka
NUITKA_MAY_BE_UNUSED static PyObject *BINARY_OPERATION_ADD( PyObject *operand1, PyObject *operand2 )
{
    CHECK_OBJECT( operand1 );
    CHECK_OBJECT( operand2 );

#if PYTHON_VERSION < 300
    // Something similar for Python3 should exist too.
    if ( PyInt_CheckExact( operand1 ) && PyInt_CheckExact( operand2 ) )
    {
        long a, b, i;

        a = PyInt_AS_LONG( operand1 );
        b = PyInt_AS_LONG( operand2 );

        i = a + b;

        // Detect overflow, in which case, a "long" object would have to be
        // created, which we won't handle here.
        if (likely(!( (i^a) < 0 && (i^b) < 0 ) ))
        {
            return PyInt_FromLong( i );
        }
    }
#endif

    binaryfunc slot1 = NULL;
    binaryfunc slot2 = NULL;

    PyTypeObject *type1 = Py_TYPE( operand1 );
    PyTypeObject *type2 = Py_TYPE( operand2 );

    if ( type1->tp_as_number != NULL && NEW_STYLE_NUMBER( operand1 ) )
    {
        slot1 = type1->tp_as_number->nb_add;
    }

    if ( type1 != type2 )
    {
        if ( type2->tp_as_number != NULL && NEW_STYLE_NUMBER( operand2 ) )
        {
            slot2 = type2->tp_as_number->nb_add;

            if ( slot1 == slot2 )
            {
                slot2 = NULL;
            }
        }
    }

    if ( slot1 != NULL )
    {
        if ( slot2 && PyType_IsSubtype( type2, type1 ) )
        {
            PyObject *x = slot2( operand1, operand2 );

            if ( x != Py_NotImplemented )
            {
                if (unlikely( x == NULL ))
                {
                    return NULL;
                }

                return x;
            }

            Py_DECREF( x );
            slot2 = NULL;
        }

        PyObject *x = slot1( operand1, operand2 );

        if ( x != Py_NotImplemented )
        {
            if (unlikely( x == NULL ))
            {
                return NULL;
            }

            return x;
        }

        Py_DECREF( x );
    }

    if ( slot2 != NULL )
    {
        PyObject *x = slot2( operand1, operand2 );

        if ( x != Py_NotImplemented )
        {
            if (unlikely( x == NULL ))
            {
                return NULL;
            }

            return x;
        }

        Py_DECREF( x );
    }

#if PYTHON_VERSION < 300
    if ( !NEW_STYLE_NUMBER( operand1 ) || !NEW_STYLE_NUMBER( operand2 ) )
    {
        int err = PyNumber_CoerceEx( &operand1, &operand2 );

        if ( err < 0 )
        {
            return NULL;
        }

        if ( err == 0 )
        {
            PyNumberMethods *mv = Py_TYPE( operand1 )->tp_as_number;

            if ( mv )
            {
                binaryfunc slot = mv->nb_add;

                if ( slot != NULL )
                {
                    PyObject *x = slot( operand1, operand2 );

                    Py_DECREF( operand1 );
                    Py_DECREF( operand2 );

                    if (unlikely( x == NULL ))
                    {
                        return NULL;
                    }

                    return x;
                }
            }

            // CoerceEx did that
            Py_DECREF( operand1 );
            Py_DECREF( operand2 );
        }
    }
#endif

    // Special case for "+", also works as sequence concat.
    PySequenceMethods *seq_methods = Py_TYPE( operand1 )->tp_as_sequence;

    if ( seq_methods && seq_methods->sq_concat )
    {
        PyObject *result = (*seq_methods->sq_concat)( operand1, operand2 );

        if (unlikely( result == NULL ))
        {
            return NULL;
        }

        return result;
    }

    PyErr_Format(
        PyExc_TypeError,
        "unsupported operand type(s) for +: '%s' and '%s'",
        type1->tp_name,
        type2->tp_name
    );

    return NULL;
}
コード例 #9
0
ファイル: operations.hpp プロジェクト: gitter-badger/Nuitka
NUITKA_MAY_BE_UNUSED static PyObject *BINARY_OPERATION_MUL( PyObject *operand1, PyObject *operand2 )
{
    CHECK_OBJECT( operand1 );
    CHECK_OBJECT( operand2 );

    binaryfunc slot1 = NULL;
    binaryfunc slot2 = NULL;

    PyTypeObject *type1 = Py_TYPE( operand1 );
    PyTypeObject *type2 = Py_TYPE( operand2 );

    if ( type1->tp_as_number != NULL && NEW_STYLE_NUMBER( operand1 ) )
    {
        slot1 = type1->tp_as_number->nb_multiply;
    }

    if ( type1 != type2 )
    {
        if ( type2->tp_as_number != NULL && NEW_STYLE_NUMBER( operand2 ) )
        {
            slot2 = type2->tp_as_number->nb_multiply;

            if ( slot1 == slot2 )
            {
                slot2 = NULL;
            }
        }
    }

    if ( slot1 != NULL )
    {
        if ( slot2 && PyType_IsSubtype( type2, type1 ) )
        {
            PyObject *x = slot2( operand1, operand2 );

            if ( x != Py_NotImplemented )
            {
                if (unlikely( x == NULL ))
                {
                    return NULL;
                }

                return x;
            }

            Py_DECREF( x );
            slot2 = NULL;
        }

        PyObject *x = slot1( operand1, operand2 );

        if ( x != Py_NotImplemented )
        {
            if (unlikely( x == NULL ))
            {
                return NULL;
            }

            return x;
        }

        Py_DECREF( x );
    }

    if ( slot2 != NULL )
    {
        PyObject *x = slot2( operand1, operand2 );

        if ( x != Py_NotImplemented )
        {
            if (unlikely( x == NULL ))
            {
                return NULL;
            }

            return x;
        }

        Py_DECREF( x );
    }

#if PYTHON_VERSION < 300
    if ( !NEW_STYLE_NUMBER( operand1 ) || !NEW_STYLE_NUMBER( operand2 ) )
    {
        int err = PyNumber_CoerceEx( &operand1, &operand2 );

        if ( err < 0 )
        {
            return NULL;
        }

        if ( err == 0 )
        {
            PyNumberMethods *mv = Py_TYPE( operand1 )->tp_as_number;

            if ( mv )
            {
                binaryfunc slot = mv->nb_multiply;

                if ( slot != NULL )
                {
                    PyObject *x = slot( operand1, operand2 );

                    Py_DECREF( operand1 );
                    Py_DECREF( operand2 );

                    if (unlikely( x == NULL ))
                    {
                        return NULL;
                    }

                    return x;
                }
            }

            // CoerceEx did that
            Py_DECREF( operand1 );
            Py_DECREF( operand2 );
        }
    }
#endif

    // Special case for "+", also works as sequence concat.
    PySequenceMethods *seq_methods1 = Py_TYPE( operand1 )->tp_as_sequence;
    PySequenceMethods *seq_methods2 = Py_TYPE( operand2 )->tp_as_sequence;

    if  ( seq_methods1 != NULL && seq_methods1->sq_repeat )
    {
        return SEQUENCE_REPEAT( seq_methods1->sq_repeat, operand1, operand2 );
    }

    if  ( seq_methods2 != NULL && seq_methods2->sq_repeat )
    {
        return SEQUENCE_REPEAT( seq_methods2->sq_repeat, operand2, operand1 );
    }

    PyErr_Format(
        PyExc_TypeError,
        "unsupported operand type(s) for *: '%s' and '%s'",
        type1->tp_name,
        type2->tp_name
    );

    return NULL;
}