Commit cac97e27 authored by Robert Bradshaw's avatar Robert Bradshaw

merge

parents 17fabe5a cf8dc445
...@@ -6,6 +6,7 @@ from Symtab import BuiltinScope, StructOrUnionScope ...@@ -6,6 +6,7 @@ from Symtab import BuiltinScope, StructOrUnionScope
from Cython.Utils import UtilityCode from Cython.Utils import UtilityCode
from TypeSlots import Signature from TypeSlots import Signature
import PyrexTypes import PyrexTypes
import Naming
builtin_function_table = [ builtin_function_table = [
# name, args, return, C API func, py equiv = "*" # name, args, return, C API func, py equiv = "*"
...@@ -16,6 +17,7 @@ builtin_function_table = [ ...@@ -16,6 +17,7 @@ builtin_function_table = [
('delattr', "OO", "r", "PyObject_DelAttr"), ('delattr', "OO", "r", "PyObject_DelAttr"),
('dir', "O", "O", "PyObject_Dir"), ('dir', "O", "O", "PyObject_Dir"),
('divmod', "OO", "O", "PyNumber_Divmod"), ('divmod', "OO", "O", "PyNumber_Divmod"),
('exec', "OOO", "O", "__Pyx_PyRun"),
#('eval', "", "", ""), #('eval', "", "", ""),
#('execfile', "", "", ""), #('execfile', "", "", ""),
#('filter', "", "", ""), #('filter', "", "", ""),
...@@ -154,6 +156,48 @@ bad: ...@@ -154,6 +156,48 @@ bad:
} }
""") """)
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( intern_utility_code = UtilityCode(
proto = """ proto = """
#if PY_MAJOR_VERSION >= 3 #if PY_MAJOR_VERSION >= 3
...@@ -273,6 +317,7 @@ Py_XDECREF(__Pyx_PyFrozenSet_Type); __Pyx_PyFrozenSet_Type = NULL; ...@@ -273,6 +317,7 @@ Py_XDECREF(__Pyx_PyFrozenSet_Type); __Pyx_PyFrozenSet_Type = NULL;
""") """)
builtin_utility_code = { builtin_utility_code = {
'exec' : pyexec_utility_code,
'getattr3' : getattr3_utility_code, 'getattr3' : getattr3_utility_code,
'intern' : intern_utility_code, 'intern' : intern_utility_code,
'set' : py23_set_utility_code, 'set' : py23_set_utility_code,
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import string, sys, os, time, copy import string, sys, os, time, copy
import Code import Code
import Builtin
from Errors import error, warning, InternalError from Errors import error, warning, InternalError
import Naming import Naming
import PyrexTypes import PyrexTypes
...@@ -3088,6 +3089,45 @@ class PrintStatNode(StatNode): ...@@ -3088,6 +3089,45 @@ class PrintStatNode(StatNode):
self.arg_tuple.annotate(code) 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): class DelStatNode(StatNode):
# del statement # del statement
# #
......
...@@ -903,6 +903,21 @@ def p_print_statement(s): ...@@ -903,6 +903,21 @@ def p_print_statement(s):
return Nodes.PrintStatNode(pos, return Nodes.PrintStatNode(pos,
arg_tuple = arg_tuple, append_newline = not ends_with_comma) 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): def p_del_statement(s):
# s.sy == 'del' # s.sy == 'del'
pos = s.position() pos = s.position()
...@@ -1317,6 +1332,8 @@ def p_simple_statement(s, first_statement = 0): ...@@ -1317,6 +1332,8 @@ def p_simple_statement(s, first_statement = 0):
node = p_global_statement(s) node = p_global_statement(s)
elif s.sy == 'print': elif s.sy == 'print':
node = p_print_statement(s) node = p_print_statement(s)
elif s.sy == 'exec':
node = p_exec_statement(s)
elif s.sy == 'del': elif s.sy == 'del':
node = p_del_statement(s) node = p_del_statement(s)
elif s.sy == 'break': elif s.sy == 'break':
......
...@@ -20,12 +20,17 @@ the documentation. ...@@ -20,12 +20,17 @@ the documentation.
This code was modeled on Quixote's ptl_import. This code was modeled on Quixote's ptl_import.
""" """
import sys, os, shutil import sys, os, shutil
import imp, ihooks, glob, md5 import imp, ihooks, glob
import __builtin__ import __builtin__
import pyxbuild import pyxbuild
from distutils.dep_util import newer from distutils.dep_util import newer
from distutils.extension import Extension from distutils.extension import Extension
try:
import hashlib
except ImportError:
import md5 as hashlib
mod_name = "pyximport" mod_name = "pyximport"
assert sys.hexversion >= 0x20000b1, "need Python 2.0b1 or later" assert sys.hexversion >= 0x20000b1, "need Python 2.0b1 or later"
...@@ -54,7 +59,7 @@ def _load_pyrex(name, filename): ...@@ -54,7 +59,7 @@ def _load_pyrex(name, filename):
def get_distutils_extension(modname, pyxfilename): def get_distutils_extension(modname, pyxfilename):
extra = "_" + md5.md5(open(pyxfilename).read()).hexdigest() extra = "_" + hashlib.md5(open(pyxfilename).read()).hexdigest()
# modname = modname + extra # modname = modname + extra
extension_mod = handle_special_build(modname, pyxfilename) extension_mod = handle_special_build(modname, pyxfilename)
......
__doc__ = """# no unicode string, not tested in Python3!
#>>> a
#Traceback (most recent call last):
#NameError: name 'a' is not defined
#>>> 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
>>> d = dict(seq = [1,2,3,4])
>>> add_iter = test_def(d, 'seq')
>>> list(add_iter())
[2, 3, 4, 5]
>>> # errors
>>> d1, d2 = {}, {}
>>> test_dict_scope_ref(d1, d2)
Traceback (most recent call last):
NameError: name 'a' is not defined
"""
#def test_module_scope():
# 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
def test_def(d, varref):
exec """
def test():
for x in %s:
yield x+1
""" % varref in d
return d['test']
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment