Example #1
0
///////////////////////////////////////////////////////////////////////////
// Numeric interface
inline CObject operator+ (const CObject& a)
{
    PyObject* tmp_obj = PyNumber_Positive(a.Get());
    if ( !tmp_obj ) {
        throw CArithmeticError("PyNumber_Positive");
    }
    return CObject(tmp_obj, eTakeOwnership);
}
Example #2
0
static int
fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts)
{
    PyObject *newconst=NULL, *v;
    Py_ssize_t len_consts;
    int opcode;

    /* Pre-conditions */
    assert(PyList_CheckExact(consts));
    assert(codestr[0] == LOAD_CONST);

    /* Create new constant */
    v = PyList_GET_ITEM(consts, GETARG(codestr, 0));
    opcode = codestr[3];
    switch (opcode) {
        case UNARY_NEGATIVE:
            /* Preserve the sign of -0.0 */
            if (PyObject_IsTrue(v) == 1)
                newconst = PyNumber_Negative(v);
            break;
        case UNARY_INVERT:
            newconst = PyNumber_Invert(v);
            break;
        case UNARY_POSITIVE:
            newconst = PyNumber_Positive(v);
            break;
        default:
            /* Called with an unknown opcode */
            PyErr_Format(PyExc_SystemError,
                 "unexpected unary operation %d on a constant",
                     opcode);
            return 0;
    }
    if (newconst == NULL) {
        if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
            PyErr_Clear();
        return 0;
    }

    /* Append folded constant into consts table */
    len_consts = PyList_GET_SIZE(consts);
    if (PyList_Append(consts, newconst)) {
        Py_DECREF(newconst);
        return 0;
    }
    Py_DECREF(newconst);

    /* Write NOP LOAD_CONST newconst */
    codestr[0] = NOP;
    codestr[1] = LOAD_CONST;
    SETARG(codestr, 1, len_consts);
    return 1;
}
static PyObject *Proxy_positive(ProxyObject *self)
{
    Proxy__ENSURE_WRAPPED_OR_RETURN_NULL(self);

    return PyNumber_Positive(self->wrapped);
}
/* Replace LOAD_CONST c1. LOAD_CONST c2 BINOP
   with    LOAD_CONST binop(c1,c2)
   The consts table must still be in list form so that the
   new constant can be appended.
   Called with codestr pointing to the first LOAD_CONST.
   Abandons the transformation if the folding fails (i.e.  1+'a').
   If the new constant is a sequence, only folds when the size
   is below a threshold value.  That keeps pyc files from
   becoming large in the presence of code like:  (None,)*1000.
*/
static int
fold_binops_on_constants(unsigned char *codestr, PyObject *consts)
{
    PyObject *newconst, *v, *w;
    Py_ssize_t len_consts, size;
    int opcode;

    /* Pre-conditions */
    assert(PyList_CheckExact(consts));
    assert(codestr[0] == LOAD_CONST);
    assert(codestr[3] == LOAD_CONST);

    /* Create new constant */
    v = PyList_GET_ITEM(consts, GETARG(codestr, 0));
    w = PyList_GET_ITEM(consts, GETARG(codestr, 3));
    opcode = codestr[6];
    switch (opcode) {
        case BINARY_POWER:
            newconst = PyNumber_Power(v, w, Py_None);
            break;
        case BINARY_MULTIPLY:
            newconst = PyNumber_Multiply(v, w);
            break;
        case BINARY_TRUE_DIVIDE:
            newconst = PyNumber_TrueDivide(v, w);
            break;
        case BINARY_FLOOR_DIVIDE:
            newconst = PyNumber_FloorDivide(v, w);
            break;
        case BINARY_MODULO:
            newconst = PyNumber_Remainder(v, w);
            break;
        case BINARY_ADD:
            newconst = PyNumber_Add(v, w);
            break;
        case BINARY_SUBTRACT:
            newconst = PyNumber_Subtract(v, w);
            break;
        case BINARY_SUBSCR:
            newconst = PyObject_GetItem(v, w);
            /* #5057: if v is unicode, there might be differences between
               wide and narrow builds in cases like '\U00012345'[0].
               Wide builds will return a non-BMP char, whereas narrow builds
               will return a surrogate.  In both the cases skip the
               optimization in order to produce compatible pycs.
             */
            if (newconst != NULL &&
                PyUnicode_Check(v) && PyUnicode_Check(newconst)) {
                Py_UNICODE ch = PyUnicode_AS_UNICODE(newconst)[0];
#ifdef Py_UNICODE_WIDE
                if (ch > 0xFFFF) {
#else
                if (ch >= 0xD800 && ch <= 0xDFFF) {
#endif
                    Py_DECREF(newconst);
                    return 0;
                }
            }
            break;
        case BINARY_LSHIFT:
            newconst = PyNumber_Lshift(v, w);
            break;
        case BINARY_RSHIFT:
            newconst = PyNumber_Rshift(v, w);
            break;
        case BINARY_AND:
            newconst = PyNumber_And(v, w);
            break;
        case BINARY_XOR:
            newconst = PyNumber_Xor(v, w);
            break;
        case BINARY_OR:
            newconst = PyNumber_Or(v, w);
            break;
        default:
            /* Called with an unknown opcode */
            PyErr_Format(PyExc_SystemError,
                 "unexpected binary operation %d on a constant",
                     opcode);
            return 0;
    }
    if (newconst == NULL) {
        if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
            PyErr_Clear();
        return 0;
    }
    size = PyObject_Size(newconst);
    if (size == -1) {
        if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
            return 0;
        PyErr_Clear();
    } else if (size > 20) {
        Py_DECREF(newconst);
        return 0;
    }

    /* Append folded constant into consts table */
    len_consts = PyList_GET_SIZE(consts);
    if (PyList_Append(consts, newconst)) {
        Py_DECREF(newconst);
        return 0;
    }
    Py_DECREF(newconst);

    /* Write NOP NOP NOP NOP LOAD_CONST newconst */
    memset(codestr, NOP, 4);
    codestr[4] = LOAD_CONST;
    SETARG(codestr, 4, len_consts);
    return 1;
}

static int
fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts)
{
    PyObject *newconst=NULL, *v;
    Py_ssize_t len_consts;
    int opcode;

    /* Pre-conditions */
    assert(PyList_CheckExact(consts));
    assert(codestr[0] == LOAD_CONST);

    /* Create new constant */
    v = PyList_GET_ITEM(consts, GETARG(codestr, 0));
    opcode = codestr[3];
    switch (opcode) {
        case UNARY_NEGATIVE:
            /* Preserve the sign of -0.0 */
            if (PyObject_IsTrue(v) == 1)
                newconst = PyNumber_Negative(v);
            break;
        case UNARY_INVERT:
            newconst = PyNumber_Invert(v);
            break;
        case UNARY_POSITIVE:
            newconst = PyNumber_Positive(v);
            break;
        default:
            /* Called with an unknown opcode */
            PyErr_Format(PyExc_SystemError,
                 "unexpected unary operation %d on a constant",
                     opcode);
            return 0;
    }
    if (newconst == NULL) {
        if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
            PyErr_Clear();
        return 0;
    }

    /* Append folded constant into consts table */
    len_consts = PyList_GET_SIZE(consts);
    if (PyList_Append(consts, newconst)) {
        Py_DECREF(newconst);
        return 0;
    }
    Py_DECREF(newconst);

    /* Write NOP LOAD_CONST newconst */
    codestr[0] = NOP;
    codestr[1] = LOAD_CONST;
    SETARG(codestr, 1, len_consts);
    return 1;
}