Commit 26634fc5 authored by Stefan Behnel's avatar Stefan Behnel

merged in changes from Cython 0.9.6.7

parents df831940 997ac5b6
...@@ -85,7 +85,8 @@ class CCodeWriter: ...@@ -85,7 +85,8 @@ class CCodeWriter:
try: try:
return self.input_file_contents[file] return self.input_file_contents[file]
except KeyError: except KeyError:
F = open(file).readlines() F = [line.replace('*/', '*[inserted by cython to avoid comment closer]/')
for line in open(file).readlines()]
self.input_file_contents[file] = F self.input_file_contents[file] = F
return F return F
......
This diff is collapsed.
...@@ -125,6 +125,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -125,6 +125,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("") code.putln("")
code.putln("/* Implementation of %s */" % env.qualified_name) code.putln("/* Implementation of %s */" % env.qualified_name)
self.generate_const_definitions(env, code) self.generate_const_definitions(env, code)
self.generate_interned_num_decls(env, code)
self.generate_interned_name_decls(env, code) self.generate_interned_name_decls(env, code)
self.generate_py_string_decls(env, code) self.generate_py_string_decls(env, code)
self.generate_cached_builtins_decls(env, code) self.generate_cached_builtins_decls(env, code)
...@@ -995,7 +996,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -995,7 +996,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
"static struct PyMethodDef %s[] = {" % "static struct PyMethodDef %s[] = {" %
env.method_table_cname) env.method_table_cname)
for entry in env.pyfunc_entries: for entry in env.pyfunc_entries:
code.put_pymethoddef(entry, ",") code.put_pymethoddef(entry, ",")
code.putln( code.putln(
"{0, 0, 0, 0}") "{0, 0, 0, 0}")
code.putln( code.putln(
...@@ -1238,6 +1239,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1238,6 +1239,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.error_goto(self.pos))); code.error_goto(self.pos)));
def generate_intern_code(self, env, code): def generate_intern_code(self, env, code):
for entry in env.pynum_entries:
code.putln("%s = PyInt_FromLong(%s); %s;" % (
entry.cname,
entry.init,
code.error_goto_if_null(entry.cname, self.pos)))
if env.intern_map: if env.intern_map:
env.use_utility_code(Nodes.init_intern_tab_utility_code); env.use_utility_code(Nodes.init_intern_tab_utility_code);
code.putln( code.putln(
......
...@@ -21,6 +21,7 @@ pymethdef_prefix = pyrex_prefix + "mdef_" ...@@ -21,6 +21,7 @@ pymethdef_prefix = pyrex_prefix + "mdef_"
methtab_prefix = pyrex_prefix + "methods_" methtab_prefix = pyrex_prefix + "methods_"
memtab_prefix = pyrex_prefix + "members_" memtab_prefix = pyrex_prefix + "members_"
interned_prefix = pyrex_prefix + "n_" interned_prefix = pyrex_prefix + "n_"
interned_num_prefix = pyrex_prefix + "num_"
objstruct_prefix = pyrex_prefix + "obj_" objstruct_prefix = pyrex_prefix + "obj_"
typeptr_prefix = pyrex_prefix + "ptype_" typeptr_prefix = pyrex_prefix + "ptype_"
prop_set_prefix = pyrex_prefix + "setprop_" prop_set_prefix = pyrex_prefix + "setprop_"
...@@ -56,3 +57,7 @@ c_api_tab_cname = pyrex_prefix + "c_api_tab" ...@@ -56,3 +57,7 @@ c_api_tab_cname = pyrex_prefix + "c_api_tab"
gilstate_cname = pyrex_prefix + "state" gilstate_cname = pyrex_prefix + "state"
extern_c_macro = pyrex_prefix.upper() + "EXTERN_C" extern_c_macro = pyrex_prefix.upper() + "EXTERN_C"
def py_version_hex(major, minor=0, micro=0, release_level=0, release_serial=0):
return (major << 24) | (minor << 16) | (micro << 8) | (release_level << 4) | (release_serial)
This diff is collapsed.
...@@ -1209,13 +1209,21 @@ def p_statement(s, level, cdef_flag = 0, visibility = 'private'): ...@@ -1209,13 +1209,21 @@ def p_statement(s, level, cdef_flag = 0, visibility = 'private'):
if level not in ('module', 'module_pxd'): if level not in ('module', 'module_pxd'):
s.error("ctypedef statement not allowed here") s.error("ctypedef statement not allowed here")
return p_ctypedef_statement(s, level, visibility) return p_ctypedef_statement(s, level, visibility)
overridable = 0
if s.sy == 'cdef': if s.sy == 'cdef':
cdef_flag = 1 cdef_flag = 1
s.next() s.next()
if s.sy == 'rdef':
cdef_flag = 1
overridable = 1
s.next()
if cdef_flag: if cdef_flag:
if level not in ('module', 'module_pxd', 'function', 'c_class', 'c_class_pxd'): if level not in ('module', 'module_pxd', 'function', 'c_class', 'c_class_pxd'):
s.error('cdef statement not allowed here') s.error('cdef statement not allowed here')
return p_cdef_statement(s, level, visibility) return p_cdef_statement(s, level, visibility, overridable = overridable)
# elif s.sy == 'rdef':
# s.next()
# return p_c_func_or_var_declaration(s, level, s.position(), visibility = visibility, overridable = True)
elif s.sy == 'def': elif s.sy == 'def':
if level not in ('module', 'class', 'c_class', 'property'): if level not in ('module', 'class', 'c_class', 'property'):
s.error('def statement not allowed here') s.error('def statement not allowed here')
...@@ -1234,8 +1242,6 @@ def p_statement(s, level, cdef_flag = 0, visibility = 'private'): ...@@ -1234,8 +1242,6 @@ def p_statement(s, level, cdef_flag = 0, visibility = 'private'):
if level in ('c_class', 'c_class_pxd'): if level in ('c_class', 'c_class_pxd'):
if s.sy == 'pass': if s.sy == 'pass':
return p_pass_statement(s, with_newline = 1) return p_pass_statement(s, with_newline = 1)
else:
s.error("Executable statement not allowed here")
if s.sy == 'if': if s.sy == 'if':
return p_if_statement(s) return p_if_statement(s)
elif s.sy == 'while': elif s.sy == 'while':
...@@ -1572,8 +1578,10 @@ def p_c_arg_decl(s, in_pyfunc, cmethod_flag = 0, kw_only = 0): ...@@ -1572,8 +1578,10 @@ def p_c_arg_decl(s, in_pyfunc, cmethod_flag = 0, kw_only = 0):
default = default, default = default,
kw_only = kw_only) kw_only = kw_only)
def p_cdef_statement(s, level, visibility = 'private'): def p_cdef_statement(s, level, visibility = 'private', overridable = False):
pos = s.position() pos = s.position()
if overridable and level not in ('c_class', 'c_class_pxd'):
error(pos, "Overridable cdef function not allowed here")
visibility = p_visibility(s, visibility) visibility = p_visibility(s, visibility)
if visibility == 'extern' and s.sy in ('from' ,':'): if visibility == 'extern' and s.sy in ('from' ,':'):
return p_cdef_extern_block(s, level, pos) return p_cdef_extern_block(s, level, pos)
...@@ -1595,7 +1603,7 @@ def p_cdef_statement(s, level, visibility = 'private'): ...@@ -1595,7 +1603,7 @@ def p_cdef_statement(s, level, visibility = 'private'):
s.expect_newline('Expected a newline') s.expect_newline('Expected a newline')
return node return node
else: else:
return p_c_func_or_var_declaration(s, level, pos, visibility) return p_c_func_or_var_declaration(s, level, pos, visibility, overridable)
def p_cdef_extern_block(s, level, pos): def p_cdef_extern_block(s, level, pos):
include_file = None include_file = None
...@@ -1700,13 +1708,13 @@ def p_visibility(s, prev_visibility): ...@@ -1700,13 +1708,13 @@ def p_visibility(s, prev_visibility):
return visibility return visibility
def p_c_modifiers(s): def p_c_modifiers(s):
if s.systring in ('inline', ): if s.sy == 'IDENT' and s.systring in ('inline',):
modifier = s.systring.upper() # uppercase is macro defined for various compilers modifier = s.systring
s.next() s.next()
return modifier + ' ' + p_c_modifiers(s) return [modifier] + p_c_modifiers(s)
return "" return []
def p_c_func_or_var_declaration(s, level, pos, visibility = 'private'): def p_c_func_or_var_declaration(s, level, pos, visibility = 'private', overridable = False):
cmethod_flag = level in ('c_class', 'c_class_pxd') cmethod_flag = level in ('c_class', 'c_class_pxd')
modifiers = p_c_modifiers(s) modifiers = p_c_modifiers(s)
base_type = p_c_base_type(s) base_type = p_c_base_type(s)
...@@ -1720,7 +1728,8 @@ def p_c_func_or_var_declaration(s, level, pos, visibility = 'private'): ...@@ -1720,7 +1728,8 @@ def p_c_func_or_var_declaration(s, level, pos, visibility = 'private'):
base_type = base_type, base_type = base_type,
declarator = declarator, declarator = declarator,
body = suite, body = suite,
modifiers = modifiers) modifiers = modifiers,
overridable = overridable)
else: else:
if level == 'module_pxd' and visibility <> 'extern': if level == 'module_pxd' and visibility <> 'extern':
error(pos, error(pos,
......
...@@ -346,8 +346,6 @@ class CIntType(CNumericType): ...@@ -346,8 +346,6 @@ class CIntType(CNumericType):
class CBIntType(CIntType): class CBIntType(CIntType):
# TODO: this should be a macro "(__ ? Py_True : Py_False)"
# and no error checking should be needed (just an incref).
to_py_function = "__Pyx_PyBool_FromLong" to_py_function = "__Pyx_PyBool_FromLong"
from_py_function = "__Pyx_PyObject_IsTrue" from_py_function = "__Pyx_PyObject_IsTrue"
exception_check = 0 exception_check = 0
......
...@@ -138,7 +138,7 @@ reserved_words = [ ...@@ -138,7 +138,7 @@ reserved_words = [
"raise", "import", "exec", "try", "except", "finally", "raise", "import", "exec", "try", "except", "finally",
"while", "if", "elif", "else", "for", "in", "assert", "while", "if", "elif", "else", "for", "in", "assert",
"and", "or", "not", "is", "in", "lambda", "from", "and", "or", "not", "is", "in", "lambda", "from",
"NULL", "cimport", "by", "with" "NULL", "cimport", "by", "with", "rdef"
] ]
function_contexts = [ # allowed arguments to the "with" option function_contexts = [ # allowed arguments to the "with" option
......
...@@ -30,6 +30,7 @@ class Entry: ...@@ -30,6 +30,7 @@ class Entry:
# or class attribute during # or class attribute during
# class construction # class construction
# is_special boolean Is a special class method # is_special boolean Is a special class method
# is_member boolean Is an assigned class member
# is_variable boolean Is a variable # is_variable boolean Is a variable
# is_cfunction boolean Is a C function # is_cfunction boolean Is a C function
# is_cmethod boolean Is a C method of an extension type # is_cmethod boolean Is a C method of an extension type
...@@ -72,6 +73,7 @@ class Entry: ...@@ -72,6 +73,7 @@ class Entry:
is_cglobal = 0 is_cglobal = 0
is_pyglobal = 0 is_pyglobal = 0
is_special = 0 is_special = 0
is_member = 0
is_variable = 0 is_variable = 0
is_cfunction = 0 is_cfunction = 0
is_cmethod = 0 is_cmethod = 0
...@@ -121,6 +123,7 @@ class Scope: ...@@ -121,6 +123,7 @@ class Scope:
# free_temp_entries [Entry] Temp variables currently unused # free_temp_entries [Entry] Temp variables currently unused
# temp_counter integer Counter for naming temp vars # temp_counter integer Counter for naming temp vars
# cname_to_entry {string : Entry} Temp cname to entry mapping # cname_to_entry {string : Entry} Temp cname to entry mapping
# int_to_entry {int : Entry} Temp cname to entry mapping
# pow_function_used boolean The C pow() function is used # pow_function_used boolean The C pow() function is used
# return_type PyrexType or None Return type of function owning scope # return_type PyrexType or None Return type of function owning scope
# is_py_class_scope boolean Is a Python class scope # is_py_class_scope boolean Is a Python class scope
...@@ -167,6 +170,7 @@ class Scope: ...@@ -167,6 +170,7 @@ class Scope:
self.cname_to_entry = {} self.cname_to_entry = {}
self.pow_function_used = 0 self.pow_function_used = 0
self.string_to_entry = {} self.string_to_entry = {}
self.num_to_entry = {}
self.pystring_entries = [] self.pystring_entries = []
def __str__(self): def __str__(self):
...@@ -392,6 +396,28 @@ class Scope: ...@@ -392,6 +396,28 @@ class Scope:
entry.pystring_cname = entry.cname + "p" entry.pystring_cname = entry.cname + "p"
self.pystring_entries.append(entry) self.pystring_entries.append(entry)
self.global_scope().all_pystring_entries.append(entry) self.global_scope().all_pystring_entries.append(entry)
def add_py_num(self, value):
# Add an entry for an int constant.
cname = "%s%s" % (Naming.interned_num_prefix, value)
cname = cname.replace('-', 'neg_').replace('.','_')
entry = Entry("", cname, c_long_type, init = value)
entry.used = 1
entry.is_interned = 1
self.const_entries.append(entry)
self.interned_nums.append(entry)
return entry
def get_py_num(self, value):
# Get entry for int constant. Returns an existing
# one if possible, otherwise creates a new one.
genv = self.global_scope()
entry = genv.num_to_entry.get(value)
if not entry:
entry = genv.add_py_num(value)
genv.num_to_entry[value] = entry
genv.pynum_entries.append(entry)
return entry
def new_const_cname(self): def new_const_cname(self):
# Create a new globally-unique name for a constant. # Create a new globally-unique name for a constant.
...@@ -606,8 +632,10 @@ class ModuleScope(Scope): ...@@ -606,8 +632,10 @@ class ModuleScope(Scope):
self.cimported_modules = [] self.cimported_modules = []
self.intern_map = {} self.intern_map = {}
self.interned_names = [] self.interned_names = []
self.interned_nums = []
self.all_pystring_entries = [] self.all_pystring_entries = []
self.types_imported = {} self.types_imported = {}
self.pynum_entries = []
def qualifying_scope(self): def qualifying_scope(self):
return self.parent_module return self.parent_module
...@@ -1052,45 +1080,58 @@ class CClassScope(ClassScope): ...@@ -1052,45 +1080,58 @@ class CClassScope(ClassScope):
def declare_var(self, name, type, pos, def declare_var(self, name, type, pos,
cname = None, visibility = 'private', is_cdef = 0): cname = None, visibility = 'private', is_cdef = 0):
# Add an entry for an attribute. if is_cdef:
if self.defined: # Add an entry for an attribute.
error(pos, if self.defined:
"C attributes cannot be added in implementation part of"
" extension type")
if get_special_method_signature(name):
error(pos,
"The name '%s' is reserved for a special method."
% name)
if not cname:
cname = name
entry = self.declare(name, cname, type, pos)
entry.visibility = visibility
entry.is_variable = 1
self.var_entries.append(entry)
if type.is_pyobject:
self.has_pyobject_attrs = 1
if visibility not in ('private', 'public', 'readonly'):
error(pos,
"Attribute of extension type cannot be declared %s" % visibility)
if visibility in ('public', 'readonly'):
if type.pymemberdef_typecode:
self.public_attr_entries.append(entry)
if name == "__weakref__":
error(pos, "Special attribute __weakref__ cannot be exposed to Python")
else:
error(pos, error(pos,
"C attribute of type '%s' cannot be accessed from Python" % type) "C attributes cannot be added in implementation part of"
if visibility == 'public' and type.is_extension_type: " extension type")
error(pos, if get_special_method_signature(name):
"Non-generic Python attribute cannot be exposed for writing from Python") error(pos,
return entry "The name '%s' is reserved for a special method."
% name)
if not cname:
cname = name
entry = self.declare(name, cname, type, pos)
entry.visibility = visibility
entry.is_variable = 1
self.var_entries.append(entry)
if type.is_pyobject:
self.has_pyobject_attrs = 1
if visibility not in ('private', 'public', 'readonly'):
error(pos,
"Attribute of extension type cannot be declared %s" % visibility)
if visibility in ('public', 'readonly'):
if type.pymemberdef_typecode:
self.public_attr_entries.append(entry)
if name == "__weakref__":
error(pos, "Special attribute __weakref__ cannot be exposed to Python")
else:
error(pos,
"C attribute of type '%s' cannot be accessed from Python" % type)
if visibility == 'public' and type.is_extension_type:
error(pos,
"Non-generic Python attribute cannot be exposed for writing from Python")
return entry
else:
# Add an entry for a class attribute.
entry = Scope.declare_var(self, name, type, pos,
cname, visibility, is_cdef)
entry.is_member = 1
entry.is_pyglobal = 1 # xxx: is_pyglobal changes behaviour in so many places that
# I keep it in for now. is_member should be enough
# later on
entry.namespace_cname = "(PyObject *)%s" % self.parent_type.typeptr_cname
if Options.intern_names:
entry.interned_cname = self.intern(name)
return entry
def declare_pyfunction(self, name, pos): def declare_pyfunction(self, name, pos):
# Add an entry for a method. # Add an entry for a method.
if name in ('__eq__', '__ne__', '__lt__', '__gt__', '__le__', '__ge__'): if name in ('__eq__', '__ne__', '__lt__', '__gt__', '__le__', '__ge__'):
error(pos, "Special method %s must be implemented via __richcmp__" error(pos, "Special method %s must be implemented via __richcmp__" % name)
% name) entry = self.declare_var(name, py_object_type, pos)
entry = self.declare(name, name, py_object_type, pos)
special_sig = get_special_method_signature(name) special_sig = get_special_method_signature(name)
if special_sig: if special_sig:
# Special methods get put in the method table with a particular # Special methods get put in the method table with a particular
...@@ -1168,8 +1209,29 @@ class CClassScope(ClassScope): ...@@ -1168,8 +1209,29 @@ class CClassScope(ClassScope):
entry = self.add_cfunction(base_entry.name, base_entry.type, None, entry = self.add_cfunction(base_entry.name, base_entry.type, None,
adapt(base_entry.cname), base_entry.visibility) adapt(base_entry.cname), base_entry.visibility)
entry.is_inherited = 1 entry.is_inherited = 1
def allocate_temp(self, type):
return Scope.allocate_temp(self.global_scope(), type)
def release_temp(self, cname):
return Scope.release_temp(self.global_scope(), cname)
def lookup(self, name):
if name == "classmethod":
# We don't want to use the builtin classmethod here 'cause it won't do the
# right thing in this scope (as the class memebers aren't still functions).
# Don't want to add a cfunction to this scope 'cause that would mess with
# the type definition, so we just return the right entry.
self.use_utility_code(classmethod_utility_code)
entry = Entry("classmethod",
"__Pyx_Method_ClassMethod",
CFuncType(py_object_type, [CFuncTypeArg("", py_object_type, None)], 0, 0))
entry.is_cfunction = 1
return entry
else:
return Scope.lookup(self, name)
class PropertyScope(Scope): class PropertyScope(Scope):
# Scope holding the __get__, __set__ and __del__ methods for # Scope holding the __get__, __set__ and __del__ methods for
# a property of an extension type. # a property of an extension type.
...@@ -1188,3 +1250,25 @@ class PropertyScope(Scope): ...@@ -1188,3 +1250,25 @@ class PropertyScope(Scope):
error(pos, "Only __get__, __set__ and __del__ methods allowed " error(pos, "Only __get__, __set__ and __del__ methods allowed "
"in a property declaration") "in a property declaration")
return None return None
# Should this go elsewhere (and then get imported)?
#------------------------------------------------------------------------------------
classmethod_utility_code = [
"""
#include "descrobject.h"
static PyObject* __Pyx_Method_ClassMethod(PyObject *method); /*proto*/
""","""
static PyObject* __Pyx_Method_ClassMethod(PyObject *method) {
/* It appears that PyMethodDescr_Type is not anywhere exposed in the Python/C API */
/* if (!PyObject_TypeCheck(method, &PyMethodDescr_Type)) { */
if (strcmp(method->ob_type->tp_name, "method_descriptor") != 0) {
PyErr_Format(PyExc_TypeError, "Extension type classmethod() can only be called on a method_descriptor.");
return NULL;
}
PyMethodDescrObject *descr = (PyMethodDescrObject *)method;
return PyDescr_NewClassMethod(descr->d_type, descr->d_method);
}
"""
]
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import Naming import Naming
import PyrexTypes import PyrexTypes
import sys
class Signature: class Signature:
# Method slot signature descriptor. # Method slot signature descriptor.
...@@ -163,7 +164,7 @@ class GCDependentSlot(SlotDescriptor): ...@@ -163,7 +164,7 @@ class GCDependentSlot(SlotDescriptor):
# the type participates in GC. # the type participates in GC.
def __init__(self, slot_name, no_gc_value, gc_value, dynamic = 0): def __init__(self, slot_name, no_gc_value, gc_value, dynamic = 0):
SlotDescriptor.__init__(self, slot_name, dynamic) SlotDescriptor.__init__(self, slot_name, dynamic = dynamic)
self.no_gc_value = no_gc_value self.no_gc_value = no_gc_value
self.gc_value = gc_value self.gc_value = gc_value
......
version = '0.9.6.6' version = '0.9.6.7'
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