from Cython.Utils import UtilityCode
from TypeSlots import Signature
import PyrexTypes
+import Naming
builtin_function_table = [
# name, args, return, C API func, py equiv = "*"
('delattr', "OO", "r", "PyObject_DelAttr"),
('dir', "O", "O", "PyObject_Dir"),
('divmod', "OO", "O", "PyNumber_Divmod"),
+ ('exec', "OOO", "O", "__Pyx_PyRun"),
#('eval', "", "", ""),
#('execfile', "", "", ""),
#('filter', "", "", ""),
}
""")
+pyexec_utility_code = UtilityCode(
+proto = """
+static PyObject* __Pyx_PyRun(PyObject*, PyObject*, PyObject*);
+""",
+impl = """
+static PyObject* __Pyx_PyRun(PyObject* o, PyObject* globals, PyObject* locals) {
+ PyObject* result;
+ PyObject* s = 0;
+
+ if (!locals && !globals) {
+ globals = PyModule_GetDict(%s);""" % Naming.module_cname + """
+ if (!globals)
+ goto bad;
+ locals = globals;
+ } else if (!locals) {
+ locals = globals;
+ } else if (!globals) {
+ globals = locals;
+ }
+
+ if (PyUnicode_Check(o)) {
+ s = PyUnicode_AsUTF8String(o);
+ if (!s) goto bad;
+ o = s;
+ } else if (!PyString_Check(o)) {
+ /* FIXME: support file objects and code objects */
+ PyErr_SetString(PyExc_TypeError,
+ "exec currently requires a string as code input.");
+ goto bad;
+ }
+
+ result = PyRun_String(
+ PyString_AS_STRING(o), 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
""")
builtin_utility_code = {
+ 'exec' : pyexec_utility_code,
'getattr3' : getattr3_utility_code,
'intern' : intern_utility_code,
'set' : py23_set_utility_code,
import string, sys, os, time, copy
import Code
+import Builtin
from Errors import error, warning, InternalError
import Naming
import PyrexTypes
self.arg_tuple.annotate(code)
+class ExecStatNode(StatNode):
+ # exec statement
+ #
+ # args [ExprNode]
+
+ child_attrs = ["args"]
+
+ def analyse_expressions(self, env):
+ for i, arg in enumerate(self.args):
+ arg.analyse_expressions(env)
+ arg = arg.coerce_to_pyobject(env)
+ arg.release_temp(env)
+ self.args[i] = arg
+ self.temp_result = env.allocate_temp_pyobject()
+ env.release_temp(self.temp_result)
+ env.use_utility_code(Builtin.pyexec_utility_code)
+ self.gil_check(env)
+
+ gil_message = "Python exec statement"
+
+ def generate_execution_code(self, code):
+ args = []
+ for arg in self.args:
+ arg.generate_evaluation_code(code)
+ args.append( arg.py_result() )
+ args = tuple(args + ['0', '0'][:3-len(args)])
+ code.putln("%s = __Pyx_PyRun(%s, %s, %s);" % (
+ (self.temp_result,) + args))
+ for arg in self.args:
+ arg.generate_disposal_code(code)
+ code.putln(
+ code.error_goto_if_null(self.temp_result, self.pos))
+ code.put_decref_clear(self.temp_result, py_object_type)
+
+ def annotate(self, code):
+ for arg in self.args:
+ arg.annotate(code)
+
+
class DelStatNode(StatNode):
# del statement
#
return Nodes.PrintStatNode(pos,
arg_tuple = arg_tuple, append_newline = not ends_with_comma)
+def p_exec_statement(s):
+ # s.sy == 'exec'
+ pos = s.position()
+ s.next()
+ args = [ p_bit_expr(s) ]
+ if s.sy == 'in':
+ s.next()
+ args.append(p_simple_expr(s))
+ if s.sy == ',':
+ s.next()
+ args.append(p_simple_expr(s))
+ else:
+ error(pos, "'exec' currently requires a target mapping (globals/locals)")
+ return Nodes.ExecStatNode(pos, args = args)
+
def p_del_statement(s):
# s.sy == 'del'
pos = s.position()
node = p_global_statement(s)
elif s.sy == 'print':
node = p_print_statement(s)
+ elif s.sy == 'exec':
+ node = p_exec_statement(s)
elif s.sy == 'del':
node = p_del_statement(s)
elif s.sy == 'break':
--- /dev/null
+__doc__ = """# no unicode string, not tested in Python3!
+#>>> a
+#>>> test_module_scope()
+#>>> a
+
+>>> test_dict_scope1()
+2
+
+>>> d = {}
+>>> test_dict_scope2(d)
+>>> print d['b']
+2
+
+>>> d1 = {}
+>>> test_dict_scope3(d1, d1)
+>>> print d1['b']
+2
+
+>>> d1, d2 = {}, {}
+>>> test_dict_scope3(d1, d2)
+>>> print d1.get('b'), d2.get('b')
+None 2
+
+>>> d1, d2 = {}, {}
+>>> test_dict_scope3(d1, d2)
+>>> print d1.get('b'), d2.get('b')
+None 2
+
+>>> d1, d2 = dict(a=11), dict(c=5)
+>>> test_dict_scope_ref(d1, d2)
+>>> print d1.get('b'), d2.get('b')
+None 16
+
+>>> d = dict(a=11, c=5)
+>>> test_dict_scope_ref(d, d)
+>>> print d['b']
+16
+"""
+
+#def test_module_scope():
+# global a
+# exec "a=1+1"
+# return __dict__['a']
+
+def test_dict_scope1():
+ cdef dict d = {}
+ exec "b=1+1" in d
+ return d['b']
+
+def test_dict_scope2(d):
+ exec "b=1+1" in d
+
+def test_dict_scope3(d1, d2):
+ exec "b=1+1" in d1, d2
+
+def test_dict_scope_ref(d1, d2):
+ exec "b=a+c" in d1, d2