Commit 24c64823 authored by Stefan Behnel's avatar Stefan Behnel

merged in latest cython-devel

parents a8bdadbe 07226b17
......@@ -5389,7 +5389,7 @@ class BoolBinopNode(ExprNode):
def infer_type(self, env):
type1 = self.operand1.infer_type(env)
type2 = self.operand2.infer_type(env)
return PyrexTypes.spanning_type(type1, type2)
return PyrexTypes.independent_spanning_type(type1, type2)
def calculate_constant_result(self):
if self.operator == 'and':
......@@ -5418,7 +5418,7 @@ class BoolBinopNode(ExprNode):
def analyse_types(self, env):
self.operand1.analyse_types(env)
self.operand2.analyse_types(env)
self.type = PyrexTypes.spanning_type(self.operand1.type, self.operand2.type)
self.type = PyrexTypes.independent_spanning_type(self.operand1.type, self.operand2.type)
self.operand1 = self.operand1.coerce_to(self.type, env)
self.operand2 = self.operand2.coerce_to(self.type, env)
......@@ -5492,8 +5492,8 @@ class CondExprNode(ExprNode):
return self.true_val.type_dependencies(env) + self.false_val.type_dependencies(env)
def infer_type(self, env):
return self.compute_result_type(self.true_val.infer_type(env),
self.false_val.infer_type(env))
return PyrexTypes.independent_spanning_type(self.true_val.infer_type(env),
self.false_val.infer_type(env))
def calculate_constant_result(self):
if self.test.constant_result:
......@@ -5506,7 +5506,7 @@ class CondExprNode(ExprNode):
self.test = self.test.coerce_to_boolean(env)
self.true_val.analyse_types(env)
self.false_val.analyse_types(env)
self.type = self.compute_result_type(self.true_val.type, self.false_val.type)
self.type = PyrexTypes.independent_spanning_type(self.true_val.type, self.false_val.type)
if self.true_val.type.is_pyobject or self.false_val.type.is_pyobject:
self.true_val = self.true_val.coerce_to(self.type, env)
self.false_val = self.false_val.coerce_to(self.type, env)
......@@ -5514,24 +5514,6 @@ class CondExprNode(ExprNode):
if self.type == PyrexTypes.error_type:
self.type_error()
def compute_result_type(self, type1, type2):
if type1 == type2:
return type1
elif type1.is_numeric and type2.is_numeric:
return PyrexTypes.widest_numeric_type(type1, type2)
elif type1.is_extension_type and type1.subtype_of_resolved_type(type2):
return type2
elif type2.is_extension_type and type2.subtype_of_resolved_type(type1):
return type1
elif type1.is_pyobject or type2.is_pyobject:
return py_object_type
elif type1.assignable_from(type2):
return type1
elif type2.assignable_from(type1):
return type2
else:
return PyrexTypes.error_type
def type_error(self):
if not (self.true_val.type.is_error or self.false_val.type.is_error):
error(self.pos, "Incompatable types in conditional expression (%s; %s)" %
......
......@@ -1693,6 +1693,8 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
return node
_handle_simple_method_list_pop = _handle_simple_method_object_pop
PyList_Append_func_type = PyrexTypes.CFuncType(
PyrexTypes.c_int_type, [
PyrexTypes.CFuncTypeArg("list", PyrexTypes.py_object_type, None),
......@@ -2423,7 +2425,7 @@ impl = """
static CYTHON_INLINE Py_UNICODE __Pyx_PyUnicode_GetItemInt(PyObject* unicode, Py_ssize_t index, int check_bounds) {
if (check_bounds) {
if (unlikely(index >= PyUnicode_GET_SIZE(unicode)) |
unlikely(index < -PyUnicode_GET_SIZE(unicode))) {
((index < 0) & unlikely(index < -PyUnicode_GET_SIZE(unicode)))) {
PyErr_Format(PyExc_IndexError, "string index out of range");
return (Py_UNICODE)-1;
}
......@@ -2444,7 +2446,7 @@ impl = """
static CYTHON_INLINE char __Pyx_PyBytes_GetItemInt(PyObject* bytes, Py_ssize_t index, int check_bounds) {
if (check_bounds) {
if (unlikely(index >= PyBytes_GET_SIZE(bytes)) |
unlikely(index < -PyBytes_GET_SIZE(bytes))) {
((index < 0) & unlikely(index < -PyBytes_GET_SIZE(bytes)))) {
PyErr_Format(PyExc_IndexError, "string index out of range");
return -1;
}
......@@ -2524,6 +2526,24 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
self._calculate_const(node)
return node
def visit_BoolBinopNode(self, node):
self._calculate_const(node)
if node.constant_result is ExprNodes.not_a_constant:
return node
if not node.operand1.is_literal or not node.operand2.is_literal:
# We calculate other constants to make them available to
# the compiler, but we only aggregate constant nodes
# recursively, so non-const nodes are straight out.
return node
if node.constant_result == node.operand1.constant_result and node.operand1.is_literal:
return node.operand1
elif node.constant_result == node.operand2.constant_result and node.operand2.is_literal:
return node.operand2
else:
# FIXME: we could do more ...
return node
def visit_BinopNode(self, node):
self._calculate_const(node)
if node.constant_result is ExprNodes.not_a_constant:
......@@ -2566,7 +2586,10 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
new_node = target_class(pos=node.pos, type = widest_type)
new_node.constant_result = node.constant_result
new_node.value = str(node.constant_result)
if isinstance(node, ExprNodes.BoolNode):
new_node.value = node.constant_result
else:
new_node.value = str(node.constant_result)
#new_node = new_node.coerce_to(node.type, self.current_scope)
return new_node
......
......@@ -2413,31 +2413,52 @@ def widest_numeric_type(type1, type2):
widest_type = type2
return widest_type
def spanning_type(type1, type2):
# Return a type assignable from both type1 and type2.
if type1 is py_object_type or type2 is py_object_type:
def independent_spanning_type(type1, type2):
# Return a type assignable independently from both type1 and
# type2, but do not require any interoperability between the two.
# For example, in "True * 2", it is safe to assume an integer
# result type (so spanning_type() will do the right thing),
# whereas "x = True or 2" must evaluate to a type that can hold
# both a boolean value and an integer, so this function works
# better.
if type1 == type2:
return type1
elif (type1 is c_bint_type or type2 is c_bint_type) and (type1.is_numeric and type2.is_numeric):
# special case: if one of the results is a bint and the other
# is another C integer, we must prevent returning a numeric
# type so that we do not loose the ability to coerce to a
# Python bool if we have to.
return py_object_type
elif type1 == type2:
span_type = _spanning_type(type1, type2)
if span_type is None:
return PyrexTypes.error_type
return span_type
def spanning_type(type1, type2):
# Return a type assignable from both type1 and type2, or
# py_object_type if no better type is found. Assumes that the
# code that calls this will try a coercion afterwards, which will
# fail if the types cannot actually coerce to a py_object_type.
if type1 == type2:
return type1
elif type1.is_numeric and type2.is_numeric:
elif type1 is py_object_type or type2 is py_object_type:
return py_object_type
span_type = _spanning_type(type1, type2)
if span_type is None:
return py_object_type
return span_type
def _spanning_type(type1, type2):
if type1.is_numeric and type2.is_numeric:
return widest_numeric_type(type1, type2)
elif type1.is_builtin_type and type1.name == 'float' and type2.is_numeric:
return widest_numeric_type(c_double_type, type2)
elif type2.is_builtin_type and type2.name == 'float' and type1.is_numeric:
return widest_numeric_type(type1, c_double_type)
elif type1.is_pyobject ^ type2.is_pyobject:
return py_object_type
elif type1.is_extension_type and type2.is_extension_type:
if type1.typeobj_is_imported() or type2.typeobj_is_imported():
return py_object_type
while True:
if type1.subtype_of(type2):
return type2
elif type2.subtype_of(type1):
return type1
type1, type2 = type1.base_type, type2.base_type
if type1 is None or type2 is None:
return py_object_type
return widest_extension_type(type1, type2)
elif type1.is_pyobject or type2.is_pyobject:
return py_object_type
elif type1.assignable_from(type2):
if type1.is_extension_type and type1.typeobj_is_imported():
# external types are unsafe, so we use PyObject instead
......@@ -2449,8 +2470,20 @@ def spanning_type(type1, type2):
return py_object_type
return type2
else:
return None
def widest_extension_type(type1, type2):
if type1.typeobj_is_imported() or type2.typeobj_is_imported():
return py_object_type
while True:
if type1.subtype_of(type2):
return type2
elif type2.subtype_of(type1):
return type1
type1, type2 = type1.base_type, type2.base_type
if type1 is None or type2 is None:
return py_object_type
def simple_c_type(signed, longness, name):
# Find type descriptor for simple type given name and modifiers.
# Returns None if arguments don't make sense.
......
# http://www.opengroup.org/onlinepubs/009695399/basedefs/fcntl.h.html
cdef extern from "fcntl.h" nogil:
enum: F_DUPFD
enum: F_GETFD
enum: F_SETFD
enum: F_GETFL
enum: F_SETFL
enum: F_GETLK
enum: F_SETLK
enum: F_SETLKW
enum: F_GETOWN
enum: F_SETOWN
enum: FD_CLOEXEC
enum: F_RDLCK
enum: F_UNLCK
enum: F_WRLCK
enum: SEEK_SET
enum: SEEK_CUR
enum: SEEK_END
enum: O_CREAT
enum: O_EXCL
enum: O_NOCTTY
enum: O_TRUNC
enum: O_APPEND
enum: O_DSYNC
enum: O_NONBLOCK
enum: O_RSYNC
enum: O_SYNC
enum: O_ACCMODE # O_RDONLY|O_WRONLY|O_RDWR
enum: O_RDONLY
enum: O_WRONLY
enum: O_RDWR
enum: S_IFMT
enum: S_IFBLK
enum: S_IFCHR
enum: S_IFIFO
enum: S_IFREG
enum: S_IFDIR
enum: S_IFLNK
enum: S_IFSOCK
ctypedef int mode_t
ctypedef signed pid_t
ctypedef signed off_t
struct flock:
short l_type
short l_whence
off_t l_start
off_t l_len
pid_t l_pid
int creat(char *, mode_t)
int fcntl(int, int, ...)
int open(char *, int, ...)
#int open (char *, int, mode_t)
# http://www.opengroup.org/onlinepubs/009695399/basedefs/unistd.h.html
cdef extern from "unistd.h" nogil:
#:NULL
enum: R_OK
enum: W_OK
enum: X_OK
enum: F_OK
# confstr()
#_CS_PATH
#_CS_POSIX_*
enum: SEEK_SET
enum: SEEK_CUR
enum: SEEK_END
enum: F_LOCK
enum: F_TEST
enum: F_TLOCK
enum: F_ULOCK
# pathconf()
# _PC_*
# sysconf()
# _SC_*
enum: STDIN_FILENO #0
enum: STDOUT_FILENO #1
enum: STDERR_FILENO #2
#:ctypedef unsigned size_t
#:ctypedef signed ssize_t
ctypedef int uid_t
ctypedef int gid_t
ctypedef signed off_t
ctypedef signed pid_t
ctypedef unsigned useconds_t
ctypedef signed intptr_t
int access(char *, int)
unsigned alarm(unsigned)
int chdir(char *)
int chown(char *, uid_t, gid_t)
int close(int)
size_t confstr(int, char *, size_t)
char *crypt(char *, char *)
char *ctermid(char *)
int dup(int)
int dup2(int, int)
void encrypt(char[64], int)
int execl(char *, char *, ...)
int execle(char *, char *, ...)
int execlp(char *, char *, ...)
int execv(char *, char *[])
int execve(char *, char *[], char *[])
int execvp(char *, char *[])
void _exit(int)
int fchown(int, uid_t, gid_t)
int fchdir(int)
int fdatasync(int)
pid_t fork()
long fpathconf(int, int)
int fsync(int)
int ftruncate(int, off_t)
char *getcwd(char *, size_t)
gid_t getegid()
uid_t geteuid()
gid_t getgid()
int getgroups(int, gid_t [])
long gethostid()
int gethostname(char *, size_t)
char *getlogin()
int getlogin_r(char *, size_t)
int getopt(int, char * [], char *)
pid_t getpgid(pid_t)
pid_t getpgrp()
pid_t getpid()
pid_t getppid()
pid_t getsid(pid_t)
uid_t getuid()
char *getwd(char *)
int isatty(int)
int lchown(char *, uid_t, gid_t)
int link(char *, char *)
int lockf(int, int, off_t)
off_t lseek(int, off_t, int)
int nice(int)
long pathconf(char *, int)
int pause()
int pipe(int [2])
ssize_t pread(int, void *, size_t, off_t)
ssize_t pwrite(int, void *, size_t, off_t)
ssize_t read(int, void *, size_t)
ssize_t readlink(char *, char *, size_t)
int rmdir(char *)
int setegid(gid_t)
int seteuid(uid_t)
int setgid(gid_t)
int setpgid(pid_t, pid_t)
pid_t setpgrp()
int setregid(gid_t, gid_t)
int setreuid(uid_t, uid_t)
pid_t setsid()
int setuid(uid_t)
unsigned sleep(unsigned)
void swab(void *, void *, ssize_t)
int symlink(char *, char *)
void sync()
long sysconf(int)
pid_t tcgetpgrp(int)
int tcsetpgrp(int, pid_t)
int truncate(char *, off_t)
char *ttyname(int)
int ttyname_r(int, char *, size_t)
useconds_t ualarm(useconds_t, useconds_t)
int unlink(char *)
int usleep(useconds_t)
pid_t vfork()
ssize_t write(int, void *, size_t)
char *optarg
int optind
int opterr
int optopt
......@@ -35,7 +35,8 @@ TEST_RUN_DIRS = ['run', 'wrappers', 'pyregr']
# which should be excluded if the module is not present.
EXT_DEP_MODULES = {
'numpy' : re.compile('.*\.numpy_.*').match,
'pstats' : re.compile('.*\.pstats_.*').match
'pstats' : re.compile('.*\.pstats_.*').match,
'posix' : re.compile('.*\.posix_.*').match,
}
def get_numpy_include_dirs():
......
......@@ -10,6 +10,6 @@ cfunc_call_tuple_args_T408
cascaded_list_unpacking_T467
compile.cpp_operators
# Pyrex regression tests that don't current work:
# CPython regression tests that don't current work:
pyregr.test_threadsignals
pyregr.test_module
......@@ -7,7 +7,7 @@ cimport libc.limits
cimport libc.locale
cimport libc.signal
cimport libc.stddef
cimport libc.stdint
#cimport libc.stdint # XXX MSVC
cimport libc.stdio
cimport libc.stdlib
cimport libc.string
......@@ -18,7 +18,7 @@ from libc cimport limits
from libc cimport locale
from libc cimport signal
from libc cimport stddef
from libc cimport stdint
#from libc cimport stdint # XXX MSVC
from libc cimport stdio
from libc cimport stdlib
from libc cimport string
......@@ -29,7 +29,7 @@ from libc.limits cimport *
from libc.locale cimport *
from libc.signal cimport *
from libc.stddef cimport *
from libc.stdint cimport *
#from libc.stdint cimport * # XXX MSVC
from libc.stdio cimport *
from libc.stdlib cimport *
from libc.string cimport *
......
cimport posix
cimport posix.unistd
from posix cimport unistd
from posix.unistd cimport *
cimport posix.fcntl
from posix cimport fcntl
from posix.fcntl cimport *
......@@ -52,3 +52,10 @@ def and2_no_result(a,b):
'b *'
"""
a and b
def and2_literal():
"""
>>> and2_literal()
5
"""
return True and 5
cimport cython
@cython.test_fail_if_path_exists('//BoolBinopNode')
def or_literal_bint():
"""
>>> True or 5
True
>>> or_literal_bint()
True
"""
return True or 5
@cython.test_fail_if_path_exists('//BoolBinopNode')
def and_literal_bint():
"""
>>> 5 and True
True
>>> and_literal_bint()
True
"""
return 5 and True
@cython.test_fail_if_path_exists('//BoolBinopNode')
def False_and_True_or_0():
"""
>>> False and True or 0
0
>>> False_and_True_or_0()
0
"""
return False and True or 0
@cython.test_fail_if_path_exists('//BoolBinopNode')
def True_and_True_or_0():
"""
>>> True and True or 0
True
>>> True_and_True_or_0()
True
"""
return True and True or 0
def x_and_True_or_False(x):
"""
>>> x_and_True_or_False(0)
False
>>> x_and_True_or_False(1)
True
>>> x_and_True_or_False('abc')
True
>>> x_and_True_or_False([])
False
"""
return x and True or False
def x_and_True_or_0(x):
"""
>>> 0 and True or 0
0
>>> x_and_True_or_0(0)
0
>>> 1 and True or 0
True
>>> x_and_True_or_0(1)
True
>>> x_and_True_or_0('abc')
True
>>> x_and_True_or_0([])
0
"""
return x and True or 0
def x_and_True_or_1(x):
"""
>>> 0 and True or 1
1
>>> x_and_True_or_1(0)
1
>>> 1 and True or 1
True
>>> x_and_True_or_1(1)
True
>>> x_and_True_or_1('abc')
True
>>> x_and_True_or_1([])
1
"""
return x and True or 1
def x_and_1_or_False(x):
"""
>>> 0 and 1 or False
False
>>> x_and_1_or_False(0)
False
>>> 1 and 1 or False
1
>>> x_and_1_or_False(1)
1
>>> x_and_1_or_False('abc')
1
>>> x_and_1_or_False([])
False
"""
return x and 1 or False
cdef class Test:
"""
>>> t = Test(True)
>>> t.some_ro_bool
True
>>> t.some_public_bool
True
"""
cdef public bint some_public_bool
cdef readonly bint some_ro_bool
def __init__(self, bint boolval):
self.some_ro_bool = boolval
self.some_public_bool = boolval
import cython
cdef extern from "complex_int_T446_fix.h":
pass
def test_arith(int complex a, int complex b):
"""
>>> test_arith(4, 2)
......
#if defined _MSC_VER && defined __cplusplus
#define CYTHON_CCOMPLEX 0
#endif
......@@ -32,6 +32,30 @@ def simple_pop(L):
"""
return L.pop()
@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode/AttributeNode')
def simple_pop_typed(list L):
"""
>>> L = list(range(10))
>>> simple_pop_typed(L)
9
>>> simple_pop_typed(L)
8
>>> L
[0, 1, 2, 3, 4, 5, 6, 7]
>>> while L:
... _ = simple_pop_typed(L)
>>> L
[]
>>> simple_pop_typed(L)
Traceback (most recent call last):
...
IndexError: pop from empty list
"""
return L.pop()
@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode/AttributeNode')
def index_pop(L, int i):
......@@ -68,6 +92,40 @@ def index_pop(L, int i):
"""
return L.pop(i)
@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode/AttributeNode')
def index_pop_typed(list L, int i):
"""
>>> L = list(range(10))
>>> index_pop_typed(L, 2)
2
>>> index_pop_typed(L, -2)
8
>>> L
[0, 1, 3, 4, 5, 6, 7, 9]
>>> index_pop_typed(L, 100)
Traceback (most recent call last):
...
IndexError: pop index out of range
>>> index_pop_typed(L, -100)
Traceback (most recent call last):
...
IndexError: pop index out of range
>>> while L:
... _ = index_pop_typed(L, 0)
>>> L
[]
>>> index_pop_typed(L, 0)
Traceback (most recent call last):
...
IndexError: pop from empty list
"""
return L.pop(i)
@cython.test_fail_if_path_exists('//PythonCapiCallNode')
def crazy_pop(L):
"""
......
......@@ -51,3 +51,10 @@ def or2_no_result(a,b):
'a *'
"""
a or b
def or2_literal():
"""
>>> or2_literal()
5
"""
return False or 5
from libc.stdio cimport *
from posix.unistd cimport *
from posix.fcntl cimport *
cdef int noisy_function() except -1:
cdef int ret = 0
ret = printf(b"0123456789\n", 0)
assert ret == 11
ret = fflush(stdout)
assert ret == 0
ret = fprintf(stdout, b"0123456789\n", 0)
assert ret == 11
ret = fflush(stdout)
assert ret == 0
ret = write(STDOUT_FILENO, b"0123456789\n", 11)
assert ret == 11
return 0
def test_silent_stdout():
"""
>>> test_silent_stdout()
"""
cdef int ret
cdef int stdout_save, dev_null
stdout_save = dup(STDOUT_FILENO)
assert stdout_save != -1
dev_null = open(b"/dev/null", O_WRONLY, 0)
assert dev_null != -1
ret = dup2(dev_null, STDOUT_FILENO)
assert ret == STDOUT_FILENO
ret = close(dev_null)
assert ret == 0
try:
noisy_function()
finally:
ret = dup2(stdout_save, STDOUT_FILENO)
assert ret == STDOUT_FILENO
ret = close(stdout_save)
assert ret == 0
cdef class silent_fd:
cdef int fd_save, fd
def __cinit__(self, int fd=-1):
self.fd_save = -1
self.fd = STDOUT_FILENO
if fd != -1:
self.fd = fd
def __enter__(self):
cdef int ret = 0, dev_null = -1
assert self.fd_save == -1
dev_null = open(b"/dev/null", O_WRONLY, 0)
assert dev_null != -1
try:
self.fd_save = dup(self.fd)
assert self.fd_save != -1
try:
ret = dup2(dev_null, self.fd)
assert ret != -1
except:
ret = close(self.fd_save)
self.fd_save = -1
finally:
ret = close(dev_null)
def __exit__(self, t, v, tb):
cdef int ret = 0
if self.fd_save != -1:
ret = dup2(self.fd_save, self.fd)
assert ret == self.fd
ret = close(self.fd_save)
assert ret == 0
self.fd_save = -1
return None
def test_silent_stdout_ctxmanager():
"""
>> test_silent_stdout_ctxmanager()
"""
with silent_fd():
noisy_function()
try:
with silent_fd():
noisy_function()
raise RuntimeError
except RuntimeError:
pass
with silent_fd(STDOUT_FILENO):
noisy_function()
......@@ -46,12 +46,13 @@ Traceback (most recent call last):
OverflowError: ...
"""
# XXX This should generate a warning !!!
cdef extern from *:
ctypedef long ssize_t
ctypedef long ssize_t # XXX This should generate a warning !!!
ssize_t PY_SSIZE_T_MAX
ssize_t PY_SSIZE_T_MIN
SSIZE_T_MAX = <ssize_t>((<size_t>-1)>>1)
SSIZE_T_MIN = (-SSIZE_T_MAX-1)
SSIZE_T_MAX = PY_SSIZE_T_MAX
SSIZE_T_MIN = PY_SSIZE_T_MIN
def test(ssize_t i):
return i
......
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