Commit 63e41169 authored by Stefan Behnel's avatar Stefan Behnel

merge of 0.9.6.4

parents 8d6047a6 2bff23cb
......@@ -6,6 +6,7 @@ import Naming
import Options
from Cython.Utils import open_new_file
from PyrexTypes import py_object_type, typecast
from TypeSlots import method_coexist
class CCodeWriter:
# f file output file
......@@ -288,12 +289,17 @@ class CCodeWriter:
doc_code = entry.doc_cname
else:
doc_code = 0
self.putln(
'{"%s", (PyCFunction)%s, METH_VARARGS|METH_KEYWORDS, %s}%s' % (
entry.name,
entry.func_cname,
doc_code,
term))
method_flags = entry.signature.method_flags()
if method_flags:
if entry.is_special:
method_flags += [method_coexist]
self.putln(
'{"%s", (PyCFunction)%s, %s, %s}%s' % (
entry.name,
entry.func_cname,
"|".join(method_flags),
doc_code,
term))
def put_error_if_neg(self, pos, value):
# return self.putln("if (unlikely(%s < 0)) %s" % (value, self.error_goto(pos))) # TODO this path is almost _never_ taken, yet this macro makes is slower!
......
......@@ -699,6 +699,8 @@ class NameNode(AtomicExprNode):
#print "NameNode.analyse_target_declaration:", self.name ###
#print "...declaring as py_object_type" ###
self.entry = env.declare_var(self.name, py_object_type, self.pos)
if self.entry.is_declared_generic:
self.result_ctype = py_object_type
def analyse_types(self, env):
self.entry = env.lookup(self.name)
......
......@@ -173,6 +173,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln(" #define PY_SSIZE_T_MIN INT_MIN")
code.putln(" #define PyInt_FromSsize_t(z) PyInt_FromLong(z)")
code.putln(" #define PyInt_AsSsize_t(o) PyInt_AsLong(o)")
code.putln(" #define PyNumber_Index(o) PyNumber_Int(o)")
code.putln(" #define PyIndex_Check(o) PyNumber_Check(o)")
code.putln("#endif")
self.generate_extern_c_macro_definition(code)
code.putln("%s double pow(double, double);" % Naming.extern_c_macro)
......
......@@ -8,6 +8,7 @@ import Code
from Errors import error, warning, InternalError
import Naming
import PyrexTypes
import TypeSlots
from PyrexTypes import py_object_type, error_type, CTypedefType
from Symtab import ModuleScope, LocalScope, \
StructOrUnionScope, PyClassScope, CClassScope
......@@ -819,6 +820,18 @@ class DefNode(FuncDefNode):
def analyse_signature(self, env):
any_type_tests_needed = 0
# Use the simpler calling signature for zero- and one-argument functions.
if not self.entry.is_special and not self.star_arg and not self.starstar_arg:
if self.entry.signature is TypeSlots.pyfunction_signature:
if len(self.args) == 0:
self.entry.signature = TypeSlots.pyfunction_noargs
elif len(self.args) == 1 and self.args[0].default is None:
self.entry.signature = TypeSlots.pyfunction_onearg
elif self.entry.signature is TypeSlots.pymethod_signature:
if len(self.args) == 1:
self.entry.signature = TypeSlots.unaryfunc
elif len(self.args) == 2 and self.args[1].default is None:
self.entry.signature = TypeSlots.ibinaryfunc
sig = self.entry.signature
nfixed = sig.num_fixed_args()
for i in range(nfixed):
......@@ -851,6 +864,12 @@ class DefNode(FuncDefNode):
if arg.is_generic and arg.type.is_extension_type:
arg.needs_type_test = 1
any_type_tests_needed = 1
elif arg.type is PyrexTypes.c_py_ssize_t_type:
# Want to use __index__ rather than __int__ method
# that PyArg_ParseTupleAndKeywords calls
arg.needs_conversion = 1
arg.hdr_type = PyrexTypes.py_object_type
arg.hdr_cname = Naming.arg_prefix + arg.name
if any_type_tests_needed:
env.use_utility_code(arg_type_test_utility_code)
......@@ -957,6 +976,8 @@ class DefNode(FuncDefNode):
else:
arg_code_list.append(
arg.hdr_type.declaration_code(arg.hdr_cname))
if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
arg_code_list.append("PyObject *unused")
if sig.has_generic_args:
arg_code_list.append(
"PyObject *%s, PyObject *%s"
......@@ -980,7 +1001,10 @@ class DefNode(FuncDefNode):
def generate_argument_declarations(self, env, code):
for arg in self.args:
if arg.is_generic: # or arg.needs_conversion:
code.put_var_declaration(arg.entry)
if arg.needs_conversion:
code.putln("PyObject *%s = 0;" % arg.hdr_cname)
else:
code.put_var_declaration(arg.entry)
def generate_keyword_list(self, code):
if self.entry.signature.has_generic_args:
......@@ -994,7 +1018,7 @@ class DefNode(FuncDefNode):
arg.name)
code.putln(
"0};")
def generate_argument_parsing_code(self, code):
# Generate PyArg_ParseTuple call for generic
# arguments, if any.
......@@ -1015,8 +1039,12 @@ class DefNode(FuncDefNode):
default_seen = 1
elif default_seen:
error(arg.pos, "Non-default argument following default argument")
arg_addrs.append("&" + arg_entry.cname)
format = arg_entry.type.parsetuple_format
if arg.needs_conversion:
arg_addrs.append("&" + arg.hdr_cname)
format = arg.hdr_type.parsetuple_format
else:
arg_addrs.append("&" + arg_entry.cname)
format = arg_entry.type.parsetuple_format
if format:
arg_formats.append(format)
else:
......@@ -1088,7 +1116,9 @@ class DefNode(FuncDefNode):
old_type = arg.hdr_type
new_type = arg.type
if old_type.is_pyobject:
code.putln("if (likely(%s)) {" % arg.hdr_cname)
self.generate_arg_conversion_from_pyobject(arg, code)
code.putln("}")
elif new_type.is_pyobject:
self.generate_arg_conversion_to_pyobject(arg, code)
else:
......@@ -2602,6 +2632,8 @@ typedef struct {const char *s; const void **p;} __Pyx_CApiTabEntry; /*proto*/
typedef struct {PyObject **p; char *s;} __Pyx_InternTabEntry; /*proto*/
typedef struct {PyObject **p; char *s; long n; int is_unicode;} __Pyx_StringTabEntry; /*proto*/
#define __pyx_PyIndex_AsSsize_t(b) PyInt_AsSsize_t(PyNumber_Index(b))
#define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False))
static INLINE int __Pyx_PyObject_IsTrue(PyObject* x) {
if (x == Py_True) return 1;
......
......@@ -352,7 +352,7 @@ class CBIntType(CIntType):
class CPySSizeTType(CIntType):
to_py_function = "PyInt_FromSsize_t"
from_py_function = "PyInt_AsSsize_t"
from_py_function = "__pyx_PyIndex_AsSsize_t"
class CUIntType(CIntType):
......
......@@ -7,6 +7,7 @@ from Errors import error, InternalError, warning
import Options
import Naming
from PyrexTypes import *
import TypeSlots
from TypeSlots import \
pyfunction_signature, pymethod_signature, \
get_special_method_signature, get_property_accessor_signature
......@@ -28,6 +29,7 @@ class Entry:
# is_pyglobal boolean Is a Python module-level variable
# or class attribute during
# class construction
# is_special boolean Is a special class method
# is_variable boolean Is a variable
# is_cfunction boolean Is a C function
# is_cmethod boolean Is a C method of an extension type
......@@ -68,6 +70,7 @@ class Entry:
is_builtin = 0
is_cglobal = 0
is_pyglobal = 0
is_special = 0
is_variable = 0
is_cfunction = 0
is_cmethod = 0
......@@ -198,6 +201,9 @@ class Scope:
# Create new entry, and add to dictionary if
# name is not None. Reports a warning if already
# declared.
if not self.in_cinclude and cname and re.match("^_[_A-Z]+$", cname):
# See http://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html#Reserved-Names
warning(pos, "'%s' is a reserved name in C." % cname, -1)
dict = self.entries
if name and dict.has_key(name):
warning(pos, "'%s' redeclared " % name, 0)
......@@ -1076,14 +1082,21 @@ class CClassScope(ClassScope):
def declare_pyfunction(self, name, pos):
# Add an entry for a method.
if name in ('__eq__', '__ne__', '__lt__', '__gt__', '__le__', '__ge__'):
error(pos, "Special method %s must be implemented via __richcmp__"
% name)
entry = self.declare(name, name, py_object_type, pos)
special_sig = get_special_method_signature(name)
if special_sig:
# Special methods get put in the method table with a particular
# signature declared in advance.
entry.signature = special_sig
# Special methods don't get put in the method table
entry.is_special = 1
else:
entry.signature = pymethod_signature
self.pyfunc_entries.append(entry)
entry.is_special = 0
self.pyfunc_entries.append(entry)
return entry
def declare_cfunction(self, name, type, pos,
......
......@@ -82,6 +82,18 @@ class Signature:
def return_type(self):
return self.format_map[self.ret_format]
def method_flags(self):
if self.ret_format == "O":
full_args = "O" + self.fixed_arg_format if self.has_dummy_arg else self.fixed_arg_format
if full_args in ["O", "T"]:
if self.has_generic_args:
return [method_varargs, method_keywords]
else:
return [method_noargs]
elif full_args in ["OO", "TO"] and not self.has_generic_args:
return [method_onearg]
return None
class SlotDescriptor:
......@@ -342,6 +354,15 @@ def get_property_accessor_signature(name):
pyfunction_signature = Signature("-*", "O")
pymethod_signature = Signature("T*", "O")
#------------------------------------------------------------------------------------------
#
# Signatures for simple Python functions.
#
#------------------------------------------------------------------------------------------
pyfunction_noargs = Signature("-", "O")
pyfunction_onearg = Signature("-O", "O")
#------------------------------------------------------------------------------------------
#
# Signatures for the various kinds of function that
......@@ -590,3 +611,12 @@ MethodSlot(delattrofunc, "", "__delattr__")
MethodSlot(descrgetfunc, "", "__get__")
MethodSlot(descrsetfunc, "", "__set__")
MethodSlot(descrdelfunc, "", "__delete__")
# Method flags for python-exposed methods.
method_noargs = "METH_NOARGS"
method_onearg = "METH_O"
method_varargs = "METH_VARARGS"
method_keywords = "METH_KEYWORDS"
method_coexist = "METH_COEXIST"
version = '0.9.6'
version = '0.9.6.4'
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