disable coercion from str->bytes, fix coercion from str->object
[cython.git] / Cython / Compiler / Builtin.py
index c87905ccb161ec1f44ac689e8e7ee867693f3ca8..64f8969c677514422b65deeb83f2a5a90b485920 100644 (file)
@@ -3,23 +3,25 @@
 #
 
 from Symtab import BuiltinScope, StructOrUnionScope
-from Cython.Utils import UtilityCode
+from Code import UtilityCode
 from TypeSlots import Signature
 import PyrexTypes
+import Naming
 
 builtin_function_table = [
     # name,        args,   return,  C API func,           py equiv = "*"
     ('abs',        "O",    "O",     "PyNumber_Absolute"),
     #('chr',       "",     "",      ""),
     #('cmp', "",   "",     "",      ""), # int PyObject_Cmp(PyObject *o1, PyObject *o2, int *result)
-    #('compile',   "",     "",      ""), # PyObject* Py_CompileString( char *str, char *filename, int start)
+    #('compile',   "",     "",      ""), # PyObject* Py_CompileString(    char *str, char *filename, int start)
     ('delattr',    "OO",   "r",     "PyObject_DelAttr"),
     ('dir',        "O",    "O",     "PyObject_Dir"),
     ('divmod',     "OO",   "O",     "PyNumber_Divmod"),
+    ('exec',       "OOO",  "O",     "__Pyx_PyRun"),
     #('eval',      "",     "",      ""),
     #('execfile',  "",     "",      ""),
     #('filter',    "",     "",      ""),
-    ('getattr',    "OO",   "O",     "PyObject_GetAttr"),
+    #('getattr',    "OO",   "O",     "PyObject_GetAttr"),   # optimised later on
     ('getattr3',   "OOO",  "O",     "__Pyx_GetAttr3",       "getattr"),
     ('hasattr',    "OO",   "b",     "PyObject_HasAttr"),
     ('hash',       "O",    "l",     "PyObject_Hash"),
@@ -48,6 +50,7 @@ builtin_function_table = [
     #('round',     "",     "",      ""),
     ('setattr',    "OOO",  "r",     "PyObject_SetAttr"),
     #('sum',       "",     "",      ""),
+    ('type',       "O",    "O",     "PyObject_Type"),
     #('unichr',    "",     "",      ""),
     #('unicode',   "",     "",      ""),
     #('vars',      "",     "",      ""),
@@ -89,7 +92,10 @@ builtin_types_table = [
     ("int",     "PyInt_Type",      []),
     ("long",    "PyLong_Type",     []),
     ("float",   "PyFloat_Type",    []),
-    ("complex", "PyComplex_Type",  []),
+    
+# Until we have a way to access attributes of a type, 
+# we don't want to make this one builtin.    
+#    ("complex", "PyComplex_Type",  []),
 
     ("bytes",   "PyBytes_Type",    []),
     ("str",     "PyString_Type",   []),
@@ -97,14 +103,12 @@ builtin_types_table = [
 
     ("tuple",   "PyTuple_Type",    []),
 
-    ("list",    "PyList_Type",     [("append", "OO",   "i", "PyList_Append"),
-                                    ("insert", "OiO",  "i", "PyList_Insert"),
-                                    ("sort",   "O",    "i", "PyList_Sort"),
-                                    ("reverse","O",    "i", "PyList_Reverse")]),
+    ("list",    "PyList_Type",     [("insert", "OZO",  "i", "PyList_Insert")]),
 
     ("dict",    "PyDict_Type",     [("items", "O",   "O", "PyDict_Items"),
                                     ("keys",  "O",   "O", "PyDict_Keys"),
-                                    ("values","O",   "O", "PyDict_Values")]),
+                                    ("values","O",   "O", "PyDict_Values"),
+                                    ("copy",  "O",   "O", "PyDict_Copy")]),
 
     ("slice",   "PySlice_Type",    []),
     ("file",    "PyFile_Type",     []),
@@ -154,6 +158,83 @@ bad:
 }
 """)
 
+pyexec_utility_code = UtilityCode(
+proto = """
+#if PY_VERSION_HEX < 0x02040000
+#ifndef Py_EVAL_H
+#include "eval.h"
+#endif
+#endif
+static PyObject* __Pyx_PyRun(PyObject*, PyObject*, PyObject*);
+""",
+impl = """
+static PyObject* __Pyx_PyRun(PyObject* o, PyObject* globals, PyObject* locals) {
+    PyObject* result;
+    PyObject* s = 0;
+    char *code = 0;
+
+    if (!globals || globals == Py_None) {
+        globals = PyModule_GetDict(%s);""" % Naming.module_cname + """
+        if (!globals)
+            goto bad;
+    } else if (!PyDict_Check(globals)) {
+        PyErr_Format(PyExc_TypeError, "exec() arg 2 must be a dict, not %.100s",
+                     globals->ob_type->tp_name);
+        goto bad;
+    }
+    if (!locals || locals == Py_None) {
+        locals = globals;
+    }
+
+
+    if (PyDict_GetItemString(globals, "__builtins__") == NULL) {
+       PyDict_SetItemString(globals, "__builtins__", PyEval_GetBuiltins());
+    }
+
+    if (PyCode_Check(o)) {
+        if (PyCode_GetNumFree((PyCodeObject *)o) > 0) {
+            PyErr_SetString(PyExc_TypeError,
+                "code object passed to exec() may not contain free variables");
+            goto bad;
+        }
+       result = PyEval_EvalCode((PyCodeObject *)o, globals, locals);
+    } else {
+        PyCompilerFlags cf;
+        cf.cf_flags = 0;
+       if (PyUnicode_Check(o)) {
+            cf.cf_flags = PyCF_SOURCE_IS_UTF8;
+           s = PyUnicode_AsUTF8String(o);
+           if (!s) goto bad;
+           o = s;
+       #if PY_MAJOR_VERSION >= 3
+       } else if (!PyBytes_Check(o)) {
+       #else
+       } else if (!PyString_Check(o)) {
+       #endif
+           PyErr_SetString(PyExc_TypeError,
+               "exec: arg 1 must be string, bytes or code object");
+           goto bad;
+       }
+       #if PY_MAJOR_VERSION >= 3
+       code = PyBytes_AS_STRING(o);
+       #else
+       code = PyString_AS_STRING(o);
+       #endif
+       if (PyEval_MergeCompilerFlags(&cf)) {
+           result = PyRun_StringFlags(code, Py_file_input, globals, locals, &cf);
+        } else {
+           result = PyRun_String(code, Py_file_input, globals, locals);
+        }
+        Py_XDECREF(s);
+    }
+
+    return result;
+bad:
+    Py_XDECREF(s);
+    return 0;
+}
+""")
+
 intern_utility_code = UtilityCode(
 proto = """
 #if PY_MAJOR_VERSION >= 3
@@ -190,22 +271,22 @@ proto = """
     PySequence_Contains((anyset), (key))
 
 #define PySet_Pop(set) \\
-    PyObject_CallMethod(set, "pop", NULL)
+    PyObject_CallMethod(set, (char *)"pop", NULL)
 
 static INLINE int PySet_Clear(PyObject *set) {
-    PyObject *ret = PyObject_CallMethod(set, "clear", NULL);
+    PyObject *ret = PyObject_CallMethod(set, (char *)"clear", NULL);
     if (!ret) return -1;
     Py_DECREF(ret); return 0;
 }
 
 static INLINE int PySet_Discard(PyObject *set, PyObject *key) {
-    PyObject *ret = PyObject_CallMethod(set, "discard", "O", key);
+    PyObject *ret = PyObject_CallMethod(set, (char *)"discard", (char *)"O", key);
     if (!ret) return -1;
     Py_DECREF(ret); return 0;
 }
 
 static INLINE int PySet_Add(PyObject *set, PyObject *key) {
-    PyObject *ret = PyObject_CallMethod(set, "add", "O", key);
+    PyObject *ret = PyObject_CallMethod(set, (char *)"add", (char *)"O", key);
     if (!ret) return -1;
     Py_DECREF(ret); return 0;
 }
@@ -232,23 +313,17 @@ static PyTypeObject *__Pyx_PyFrozenSet_Type = NULL;
 static int __Pyx_Py23SetsImport(void) {
     PyObject *sets=0, *Set=0, *ImmutableSet=0;
 
-    sets = PyImport_ImportModule("sets");
+    sets = PyImport_ImportModule((char *)"sets");
     if (!sets) goto bad;
-    Set = PyObject_GetAttrString(sets, "Set");
+    Set = PyObject_GetAttrString(sets, (char *)"Set");
     if (!Set) goto bad;
-    ImmutableSet = PyObject_GetAttrString(sets, "ImmutableSet");
+    ImmutableSet = PyObject_GetAttrString(sets, (char *)"ImmutableSet");
     if (!ImmutableSet) goto bad;
     Py_DECREF(sets);
-  
+
     __Pyx_PySet_Type       = (PyTypeObject*) Set;
     __Pyx_PyFrozenSet_Type = (PyTypeObject*) ImmutableSet;
 
-    /* FIXME: this should be done in dedicated module cleanup code */
-    /*
-    Py_DECREF(Set);
-    Py_DECREF(ImmutableSet);
-    */
-
     return 0;
 
  bad:
@@ -267,12 +342,13 @@ static int __Pyx_Py23SetsImport(void) { return 0; }
 init = put_py23_set_init_utility_code,
 cleanup = """
 #if PY_VERSION_HEX < 0x02040000
-Py_XDECREF(__Pyx_PySet_Type);
-Py_XDECREF(__Pyx_PyFrozenSet_Type);
+Py_XDECREF(__Pyx_PySet_Type); __Pyx_PySet_Type = NULL;
+Py_XDECREF(__Pyx_PyFrozenSet_Type); __Pyx_PyFrozenSet_Type = NULL;
 #endif /* < Py2.4  */
 """)
 
 builtin_utility_code = {
+    'exec'      : pyexec_utility_code,
     'getattr3'  : getattr3_utility_code,
     'intern'    : intern_utility_code,
     'set'       : py23_set_utility_code,
@@ -291,10 +367,14 @@ def init_builtin_funcs():
     for desc in builtin_function_table:
         declare_builtin_func(*desc)
 
+builtin_types = {}
+
 def init_builtin_types():
+    global builtin_types
     for name, cname, funcs in builtin_types_table:
         utility = builtin_utility_code.get(name)
         the_type = builtin_scope.declare_builtin_type(name, cname, utility)
+        builtin_types[name] = the_type
         for name, args, ret, cname in funcs:
             sig = Signature(args, ret)
             the_type.scope.declare_cfunction(name, sig.function_type(), None, cname)
@@ -312,11 +392,15 @@ def init_builtins():
     init_builtin_funcs()
     init_builtin_types()
     init_builtin_structs()
-    global list_type, tuple_type, dict_type, unicode_type, type_type
+    global list_type, tuple_type, dict_type, set_type, type_type
+    global bytes_type, str_type, unicode_type
     type_type  = builtin_scope.lookup('type').type
     list_type  = builtin_scope.lookup('list').type
     tuple_type = builtin_scope.lookup('tuple').type
     dict_type  = builtin_scope.lookup('dict').type
+    set_type   = builtin_scope.lookup('set').type
+    bytes_type = builtin_scope.lookup('bytes').type
+    str_type   = builtin_scope.lookup('str').type
     unicode_type = builtin_scope.lookup('unicode').type
 
 init_builtins()