/*
   gcc intrinsics.c -o intrinsics.so -shared -lpython2.3 \
     -I/usr/local/include/python2.3 -L/usr/local/lib/python2.3/config \
     -Wall
 */
 
#include <Python.h>

static PyObject* replace_error;

PyObject*
intrinsics_replace(PyObject* self, PyObject* args) {
    static PyTypeObject* const types[] = {
        &PyInt_Type,    &PyLong_Type,         &PyFloat_Type, &PyComplex_Type,
        &PyBool_Type,   &PyBaseObject_Type,   &PyDict_Type,  &PyTuple_Type,
        &PyBuffer_Type, &PyClassMethod_Type,  &PyEnum_Type,  &PyProperty_Type,
        &PyList_Type,   &PyStaticMethod_Type, &PySlice_Type, &PySuper_Type,
        &PyType_Type,   &PyRange_Type,        &PyFile_Type,  &PyUnicode_Type,
        &PyString_Type,
        NULL
    };

    int i = 0;
    PyObject *old, *new;
    PyTypeObject* space;

    if (!PyArg_ParseTuple(args, "OO:replace", &old, &new))
        return NULL;

    while (types[i]) {
        if (types[i] == (PyTypeObject*)old) {
            space = PyObject_New(PyTypeObject, &PyType_Type);
            *space = *(types[i]);
            *(types[i]) = *(PyTypeObject*)new;
            break;
        }
        ++i;
    }
    if (!types[i]) {
        PyErr_SetString(replace_error, "unknown type");
        return NULL;
    }
    Py_INCREF(new);
    Py_INCREF(space);
    return (PyObject*)space;
}

PyMethodDef intrinsics_methods[] = {
    {"replace", intrinsics_replace, METH_VARARGS, NULL},
    {NULL, NULL}
};

PyMODINIT_FUNC initintrinsics(void) {
   PyObject* m = Py_InitModule("intrinsics", intrinsics_methods);
	replace_error = PyErr_NewException("intrinsic.error", replace_error, NULL);
   Py_INCREF(replace_error);
   PyModule_AddObject(m, "error", replace_error);
}

