Commit d65fd747 authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

Merge.

Had to move some changes made in ModuleNode.py over to Code.py manually.
parents 18ba3a48 9262420f
...@@ -29,8 +29,6 @@ class IntroduceBufferAuxiliaryVars(CythonTransform): ...@@ -29,8 +29,6 @@ class IntroduceBufferAuxiliaryVars(CythonTransform):
self.max_ndim = 0 self.max_ndim = 0
result = super(IntroduceBufferAuxiliaryVars, self).__call__(node) result = super(IntroduceBufferAuxiliaryVars, self).__call__(node)
if self.buffers_exists: if self.buffers_exists:
if "endian.h" not in node.scope.include_files:
node.scope.include_files.append("endian.h")
use_py2_buffer_functions(node.scope) use_py2_buffer_functions(node.scope)
use_empty_bufstruct_code(node.scope, self.max_ndim) use_empty_bufstruct_code(node.scope, self.max_ndim)
return result return result
...@@ -590,18 +588,20 @@ static INLINE const char* __Pyx_ConsumeWhitespace(const char* ts) { ...@@ -590,18 +588,20 @@ static INLINE const char* __Pyx_ConsumeWhitespace(const char* ts) {
} }
static INLINE const char* __Pyx_BufferTypestringCheckEndian(const char* ts) { static INLINE const char* __Pyx_BufferTypestringCheckEndian(const char* ts) {
int num = 1;
int little_endian = ((char*)&num)[0];
int ok = 1; int ok = 1;
switch (*ts) { switch (*ts) {
case '@': case '@':
case '=': case '=':
++ts; break; ++ts; break;
case '<': case '<':
if (__BYTE_ORDER == __LITTLE_ENDIAN) ++ts; if (little_endian) ++ts;
else ok = 0; else ok = 0;
break; break;
case '>': case '>':
case '!': case '!':
if (__BYTE_ORDER == __BIG_ENDIAN) ++ts; if (!little_endian) ++ts;
else ok = 0; else ok = 0;
break; break;
} }
......
...@@ -189,7 +189,7 @@ class GlobalState(object): ...@@ -189,7 +189,7 @@ class GlobalState(object):
# This is called when it is known that no more global declarations will # This is called when it is known that no more global declarations will
# declared (but can be called before or after insert_XXX). # declared (but can be called before or after insert_XXX).
if self.pystring_table_needed: if self.pystring_table_needed:
self.pystring_table.putln("{0, 0, 0, 0, 0}").putln("};") self.pystring_table.putln("{0, 0, 0, 0, 0, 0}").putln("};")
import Nodes import Nodes
self.use_utility_code(Nodes.init_string_tab_utility_code) self.use_utility_code(Nodes.init_string_tab_utility_code)
self.initwriter.putln( self.initwriter.putln(
...@@ -254,17 +254,23 @@ class GlobalState(object): ...@@ -254,17 +254,23 @@ class GlobalState(object):
def add_interned_num_decl(self, entry): def add_interned_num_decl(self, entry):
if self.should_declare(entry.cname, entry): if self.should_declare(entry.cname, entry):
self.initwriter.putln("%s = PyInt_FromLong(%s); %s;" % ( if entry.init[-1] == "L":
entry.cname, self.initwriter.putln('%s = PyLong_FromString("%s", 0, 0); %s;' % (
entry.init, entry.cname,
self.initwriter.error_goto_if_null(entry.cname, self.module_pos))) # todo: fix pos entry.init,
self.initwriter.error_goto_if_null(entry.cname, self.module_pos)))
else:
self.initwriter.putln("%s = PyInt_FromLong(%s); %s;" % (
entry.cname,
entry.init,
self.initwriter.error_goto_if_null(entry.cname, self.module_pos)))
self.put_pyobject_decl(entry) self.put_pyobject_decl(entry)
def add_cached_builtin_decl(self, entry): def add_cached_builtin_decl(self, entry):
if self.should_declare(entry.cname, entry): if self.should_declare(entry.cname, entry):
self.put_pyobject_decl(entry) self.put_pyobject_decl(entry)
# #
# File name state # File name state
# #
......
...@@ -628,7 +628,7 @@ class BoolNode(ConstNode): ...@@ -628,7 +628,7 @@ class BoolNode(ConstNode):
return self.value return self.value
def calculate_result_code(self): def calculate_result_code(self):
return int(self.value) return str(int(self.value))
class NullNode(ConstNode): class NullNode(ConstNode):
type = PyrexTypes.c_null_ptr_type type = PyrexTypes.c_null_ptr_type
...@@ -646,13 +646,19 @@ class CharNode(ConstNode): ...@@ -646,13 +646,19 @@ class CharNode(ConstNode):
class IntNode(ConstNode): class IntNode(ConstNode):
# unsigned "" or "U"
# longness "" or "L" or "LL"
unsigned = ""
longness = ""
type = PyrexTypes.c_long_type type = PyrexTypes.c_long_type
def coerce_to(self, dst_type, env): def coerce_to(self, dst_type, env):
# Arrange for a Python version of the string to be pre-allocated # Arrange for a Python version of the string to be pre-allocated
# when coercing to a Python type. # when coercing to a Python type.
if dst_type.is_pyobject: if dst_type.is_pyobject:
self.entry = env.get_py_num(self.value) self.entry = env.get_py_num(self.value, self.longness)
self.type = PyrexTypes.py_object_type self.type = PyrexTypes.py_object_type
# We still need to perform normal coerce_to processing on the # We still need to perform normal coerce_to processing on the
# result, because we might be coercing to an extension type, # result, because we might be coercing to an extension type,
...@@ -663,7 +669,7 @@ class IntNode(ConstNode): ...@@ -663,7 +669,7 @@ class IntNode(ConstNode):
if self.type.is_pyobject: if self.type.is_pyobject:
return self.entry.cname return self.entry.cname
else: else:
return str(self.value) return str(self.value) + self.unsigned + self.longness
def compile_time_value(self, denv): def compile_time_value(self, denv):
return int(self.value, 0) return int(self.value, 0)
...@@ -1674,6 +1680,7 @@ class SimpleCallNode(CallNode): ...@@ -1674,6 +1680,7 @@ class SimpleCallNode(CallNode):
# self ExprNode or None used internally # self ExprNode or None used internally
# coerced_self ExprNode or None used internally # coerced_self ExprNode or None used internally
# wrapper_call bool used internally # wrapper_call bool used internally
# has_optional_args bool used internally
subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple'] subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
...@@ -1681,6 +1688,7 @@ class SimpleCallNode(CallNode): ...@@ -1681,6 +1688,7 @@ class SimpleCallNode(CallNode):
coerced_self = None coerced_self = None
arg_tuple = None arg_tuple = None
wrapper_call = False wrapper_call = False
has_optional_args = False
def compile_time_value(self, denv): def compile_time_value(self, denv):
function = self.function.compile_time_value(denv) function = self.function.compile_time_value(denv)
...@@ -1767,6 +1775,11 @@ class SimpleCallNode(CallNode): ...@@ -1767,6 +1775,11 @@ class SimpleCallNode(CallNode):
self.type = PyrexTypes.error_type self.type = PyrexTypes.error_type
self.result_code = "<error>" self.result_code = "<error>"
return return
if func_type.optional_arg_count and expected_nargs != actual_nargs:
self.has_optional_args = 1
self.is_temp = 1
self.opt_arg_struct = env.allocate_temp(func_type.op_arg_struct.base_type)
env.release_temp(self.opt_arg_struct)
# Coerce arguments # Coerce arguments
for i in range(min(max_nargs, actual_nargs)): for i in range(min(max_nargs, actual_nargs)):
formal_type = func_type.args[i].type formal_type = func_type.args[i].type
...@@ -1812,15 +1825,7 @@ class SimpleCallNode(CallNode): ...@@ -1812,15 +1825,7 @@ class SimpleCallNode(CallNode):
if expected_nargs == actual_nargs: if expected_nargs == actual_nargs:
optional_args = 'NULL' optional_args = 'NULL'
else: else:
optional_arg_code = [str(actual_nargs - expected_nargs)] optional_args = "&%s" % self.opt_arg_struct
for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
arg_code = actual_arg.result_as(formal_arg.type)
optional_arg_code.append(arg_code)
# for formal_arg in formal_args[actual_nargs:max_nargs]:
# optional_arg_code.append(formal_arg.type.cast_code('0'))
optional_arg_struct = '{%s}' % ','.join(optional_arg_code)
optional_args = PyrexTypes.c_void_ptr_type.cast_code(
'&' + func_type.op_arg_struct.base_type.cast_code(optional_arg_struct))
arg_list_code.append(optional_args) arg_list_code.append(optional_args)
for actual_arg in self.args[len(formal_args):]: for actual_arg in self.args[len(formal_args):]:
...@@ -1843,6 +1848,19 @@ class SimpleCallNode(CallNode): ...@@ -1843,6 +1848,19 @@ class SimpleCallNode(CallNode):
arg_code, arg_code,
code.error_goto_if_null(self.result_code, self.pos))) code.error_goto_if_null(self.result_code, self.pos)))
elif func_type.is_cfunction: elif func_type.is_cfunction:
if self.has_optional_args:
actual_nargs = len(self.args)
expected_nargs = len(func_type.args) - func_type.optional_arg_count
code.putln("%s.%s = %s;" % (
self.opt_arg_struct,
Naming.pyrex_prefix + "n",
len(self.args) - expected_nargs))
args = zip(func_type.args, self.args)
for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
code.putln("%s.%s = %s;" % (
self.opt_arg_struct,
formal_arg.name,
actual_arg.result_as(formal_arg.type)))
exc_checks = [] exc_checks = []
if self.type.is_pyobject: if self.type.is_pyobject:
exc_checks.append("!%s" % self.result_code) exc_checks.append("!%s" % self.result_code)
...@@ -1877,12 +1895,12 @@ class SimpleCallNode(CallNode): ...@@ -1877,12 +1895,12 @@ class SimpleCallNode(CallNode):
rhs, rhs,
raise_py_exception, raise_py_exception,
code.error_goto(self.pos))) code.error_goto(self.pos)))
return else:
code.putln( if exc_checks:
"%s%s; %s" % ( goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
lhs, else:
rhs, goto_error = ""
code.error_goto_if(" && ".join(exc_checks), self.pos))) code.putln("%s%s; %s" % (lhs, rhs, goto_error))
class GeneralCallNode(CallNode): class GeneralCallNode(CallNode):
# General Python function call, including keyword, # General Python function call, including keyword,
...@@ -2945,6 +2963,7 @@ class TypecastNode(ExprNode): ...@@ -2945,6 +2963,7 @@ class TypecastNode(ExprNode):
self.operand = self.operand.coerce_to_pyobject(env) self.operand = self.operand.coerce_to_pyobject(env)
else: else:
warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type)) warning(self.pos, "No conversion from %s to %s, python object pointer used." % (self.operand.type, self.type))
self.operand = self.operand.coerce_to_simple(env)
elif from_py and not to_py: elif from_py and not to_py:
if self.type.from_py_function: if self.type.from_py_function:
self.operand = self.operand.coerce_to(self.type, env) self.operand = self.operand.coerce_to(self.type, env)
......
...@@ -27,7 +27,8 @@ def make_lexicon(): ...@@ -27,7 +27,8 @@ def make_lexicon():
name = letter + Rep(letter | digit) name = letter + Rep(letter | digit)
intconst = decimal | (Str("0x") + Rep1(hexdigit)) intconst = decimal | (Str("0x") + Rep1(hexdigit))
longconst = intconst + Str("L") intsuffix = (Opt(Any("Uu")) + Opt(Any("Ll")) + Opt(Any("Ll"))) | (Opt(Any("Ll")) + Opt(Any("Ll")) + Opt(Any("Uu")))
intliteral = intconst + intsuffix
fltconst = (decimal_fract + Opt(exponent)) | (decimal + exponent) fltconst = (decimal_fract + Opt(exponent)) | (decimal + exponent)
imagconst = (intconst | fltconst) + Any("jJ") imagconst = (intconst | fltconst) + Any("jJ")
...@@ -79,8 +80,7 @@ def make_lexicon(): ...@@ -79,8 +80,7 @@ def make_lexicon():
return Lexicon([ return Lexicon([
(name, 'IDENT'), (name, 'IDENT'),
(intconst, 'INT'), (intliteral, 'INT'),
(longconst, 'LONG'),
(fltconst, 'FLOAT'), (fltconst, 'FLOAT'),
(imagconst, 'IMAG'), (imagconst, 'IMAG'),
(deco, 'DECORATOR'), (deco, 'DECORATOR'),
......
...@@ -842,8 +842,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -842,8 +842,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
#if need_self_cast: #if need_self_cast:
# self.generate_self_cast(scope, code) # self.generate_self_cast(scope, code)
if type.vtabslot_cname: if type.vtabslot_cname:
if base_type: vtab_base_type = type
struct_type_cast = "(struct %s*)" % base_type.vtabstruct_cname while vtab_base_type.base_type and vtab_base_type.base_type.vtabstruct_cname:
vtab_base_type = vtab_base_type.base_type
if vtab_base_type is not type:
struct_type_cast = "(struct %s*)" % vtab_base_type.vtabstruct_cname
else: else:
struct_type_cast = "" struct_type_cast = ""
code.putln("p->%s = %s%s;" % ( code.putln("p->%s = %s%s;" % (
......
...@@ -350,8 +350,13 @@ class CNameDeclaratorNode(CDeclaratorNode): ...@@ -350,8 +350,13 @@ class CNameDeclaratorNode(CDeclaratorNode):
def analyse(self, base_type, env, nonempty = 0): def analyse(self, base_type, env, nonempty = 0):
if nonempty and self.name == '': if nonempty and self.name == '':
# Must have mistaken the name for the type. raise RuntimeError
self.name = base_type.name # May have mistaken the name for the type.
if base_type.is_ptr or base_type.is_array or base_type.is_buffer:
error(self.pos, "Missing argument name.")
elif base_type.is_void:
error(self.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
self.name = base_type.declaration_code("", for_display=1, pyrex=1)
base_type = py_object_type base_type = py_object_type
self.type = base_type self.type = base_type
return self, base_type return self, base_type
...@@ -412,7 +417,7 @@ class CFuncDeclaratorNode(CDeclaratorNode): ...@@ -412,7 +417,7 @@ class CFuncDeclaratorNode(CDeclaratorNode):
def analyse(self, return_type, env, nonempty = 0): def analyse(self, return_type, env, nonempty = 0):
func_type_args = [] func_type_args = []
for arg_node in self.args: for arg_node in self.args:
name_declarator, type = arg_node.analyse(env, nonempty = nonempty) name_declarator, type = arg_node.analyse(env)
name = name_declarator.name name = name_declarator.name
if name_declarator.cname: if name_declarator.cname:
error(self.pos, error(self.pos,
...@@ -612,13 +617,28 @@ class CVarDefNode(StatNode): ...@@ -612,13 +617,28 @@ class CVarDefNode(StatNode):
# declarators [CDeclaratorNode] # declarators [CDeclaratorNode]
# in_pxd boolean # in_pxd boolean
# api boolean # api boolean
# need_properties [entry]
child_attrs = ["base_type", "declarators"] child_attrs = ["base_type", "declarators"]
need_properties = ()
def analyse_declarations(self, env, dest_scope = None): def analyse_declarations(self, env, dest_scope = None):
if not dest_scope: if not dest_scope:
dest_scope = env dest_scope = env
self.dest_scope = dest_scope
base_type = self.base_type.analyse(env) base_type = self.base_type.analyse(env)
if (dest_scope.is_c_class_scope
and self.visibility == 'public'
and base_type.is_pyobject
and (base_type.is_builtin_type or base_type.is_extension_type)):
self.need_properties = []
need_property = True
visibility = 'private'
else:
need_property = False
visibility = self.visibility
for declarator in self.declarators: for declarator in self.declarators:
name_declarator, type = declarator.analyse(base_type, env) name_declarator, type = declarator.analyse(base_type, env)
if not type.is_complete(): if not type.is_complete():
...@@ -641,8 +661,11 @@ class CVarDefNode(StatNode): ...@@ -641,8 +661,11 @@ class CVarDefNode(StatNode):
if self.in_pxd and self.visibility != 'extern': if self.in_pxd and self.visibility != 'extern':
error(self.pos, error(self.pos,
"Only 'extern' C variable declaration allowed in .pxd file") "Only 'extern' C variable declaration allowed in .pxd file")
dest_scope.declare_var(name, type, declarator.pos, entry = dest_scope.declare_var(name, type, declarator.pos,
cname = cname, visibility = self.visibility, is_cdef = 1) cname = cname, visibility = visibility, is_cdef = 1)
if need_property:
self.need_properties.append(entry)
entry.needs_property = 1
class CStructOrUnionDefNode(StatNode): class CStructOrUnionDefNode(StatNode):
...@@ -951,7 +974,7 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -951,7 +974,7 @@ class FuncDefNode(StatNode, BlockNode):
self.put_stararg_decrefs(code) self.put_stararg_decrefs(code)
if acquire_gil: if acquire_gil:
code.putln("PyGILState_Release(_save);") code.putln("PyGILState_Release(_save);")
code.putln("/* TODO: decref scope object */") # code.putln("/* TODO: decref scope object */")
# ----- Return # ----- Return
if not self.return_type.is_void: if not self.return_type.is_void:
code.putln("return %s;" % Naming.retval_cname) code.putln("return %s;" % Naming.retval_cname)
...@@ -1532,6 +1555,10 @@ class DefNode(FuncDefNode): ...@@ -1532,6 +1555,10 @@ class DefNode(FuncDefNode):
def generate_argument_parsing_code(self, env, code): def generate_argument_parsing_code(self, env, code):
# Generate PyArg_ParseTuple call for generic # Generate PyArg_ParseTuple call for generic
# arguments, if any. # arguments, if any.
if self.entry.signature.has_dummy_arg:
# get rid of unused argument warning
code.putln("%s = %s;" % (Naming.self_cname, Naming.self_cname))
old_error_label = code.new_error_label() old_error_label = code.new_error_label()
our_error_label = code.error_label our_error_label = code.error_label
end_label = code.new_label() end_label = code.new_label()
...@@ -2084,6 +2111,15 @@ class CClassDefNode(ClassDefNode): ...@@ -2084,6 +2111,15 @@ class CClassDefNode(ClassDefNode):
if self.doc and Options.docstrings: if self.doc and Options.docstrings:
scope.doc = embed_position(self.pos, self.doc) scope.doc = embed_position(self.pos, self.doc)
if has_body and not self.in_pxd:
# transforms not yet run on pxd files
from ParseTreeTransforms import AnalyseDeclarationsTransform
transform = AnalyseDeclarationsTransform(None)
for entry in scope.var_entries:
if hasattr(entry, 'needs_property'):
property = transform.create_Property(entry)
self.body.stats.append(property)
if has_body: if has_body:
self.body.analyse_declarations(scope) self.body.analyse_declarations(scope)
......
...@@ -342,6 +342,14 @@ class DecoratorTransform(CythonTransform): ...@@ -342,6 +342,14 @@ class DecoratorTransform(CythonTransform):
class AnalyseDeclarationsTransform(CythonTransform): class AnalyseDeclarationsTransform(CythonTransform):
basic_property = TreeFragment(u"""
property NAME:
def __get__(self):
return ATTR
def __set__(self, value):
ATTR = value
""", level='c_class')
def __call__(self, root): def __call__(self, root):
self.env_stack = [root.scope] self.env_stack = [root.scope]
return super(AnalyseDeclarationsTransform, self).__call__(root) return super(AnalyseDeclarationsTransform, self).__call__(root)
...@@ -366,7 +374,28 @@ class AnalyseDeclarationsTransform(CythonTransform): ...@@ -366,7 +374,28 @@ class AnalyseDeclarationsTransform(CythonTransform):
# on these nodes in a seperate recursive process from the # on these nodes in a seperate recursive process from the
# enclosing function or module, so we can simply drop them. # enclosing function or module, so we can simply drop them.
def visit_CVarDefNode(self, node): def visit_CVarDefNode(self, node):
return None if node.need_properties:
# cdef public attributes may need type testing on
# assignment, so we create a property accesss
# mechanism for them.
stats = []
for entry in node.need_properties:
property = self.create_Property(entry)
property.analyse_declarations(node.dest_scope)
self.visit(property)
stats.append(property)
return StatListNode(pos=node.pos, stats=stats)
else:
return None
def create_Property(self, entry):
property = self.basic_property.substitute({
u"ATTR": AttributeNode(pos=entry.pos,
obj=NameNode(pos=entry.pos, name="self"),
attribute=entry.name),
}, pos=entry.pos).stats[0]
property.name = entry.name
return property
class AnalyseExpressionsTransform(CythonTransform): class AnalyseExpressionsTransform(CythonTransform):
def visit_ModuleNode(self, node): def visit_ModuleNode(self, node):
......
...@@ -466,11 +466,18 @@ def p_atom(s): ...@@ -466,11 +466,18 @@ def p_atom(s):
elif sy == 'INT': elif sy == 'INT':
value = s.systring value = s.systring
s.next() s.next()
return ExprNodes.IntNode(pos, value = value) unsigned = ""
elif sy == 'LONG': longness = ""
value = s.systring while value[-1] in "UuLl":
s.next() if value[-1] in "Ll":
return ExprNodes.LongNode(pos, value = value) longness += "L"
else:
unsigned += "U"
value = value[:-1]
return ExprNodes.IntNode(pos,
value = value,
unsigned = unsigned,
longness = longness)
elif sy == 'FLOAT': elif sy == 'FLOAT':
value = s.systring value = s.systring
s.next() s.next()
...@@ -516,7 +523,7 @@ def p_name(s, name): ...@@ -516,7 +523,7 @@ def p_name(s, name):
elif isinstance(value, int): elif isinstance(value, int):
return ExprNodes.IntNode(pos, value = rep) return ExprNodes.IntNode(pos, value = rep)
elif isinstance(value, long): elif isinstance(value, long):
return ExprNodes.LongNode(pos, value = rep) return ExprNodes.IntNode(pos, value = rep, longness = "L")
elif isinstance(value, float): elif isinstance(value, float):
return ExprNodes.FloatNode(pos, value = rep) return ExprNodes.FloatNode(pos, value = rep)
elif isinstance(value, unicode): elif isinstance(value, unicode):
...@@ -2292,6 +2299,15 @@ def p_doc_string(s): ...@@ -2292,6 +2299,15 @@ def p_doc_string(s):
return result return result
else: else:
return None return None
def p_code(s, level=None):
s.add_type_name("object")
s.add_type_name("Py_buffer")
body = p_statement_list(s, Ctx(level = level), first_statement = 1)
if s.sy != 'EOF':
s.error("Syntax error in statement [%s,%s]" % (
repr(s.sy), repr(s.systring)))
return body
def p_module(s, pxd, full_module_name): def p_module(s, pxd, full_module_name):
s.add_type_name("object") s.add_type_name("object")
......
...@@ -262,7 +262,7 @@ class Scope: ...@@ -262,7 +262,7 @@ class Scope:
# Return the module-level scope containing this scope. # Return the module-level scope containing this scope.
return self.outer_scope.builtin_scope() return self.outer_scope.builtin_scope()
def declare(self, name, cname, type, pos): def declare(self, name, cname, type, pos, visibility):
# Create new entry, and add to dictionary if # Create new entry, and add to dictionary if
# name is not None. Reports a warning if already # name is not None. Reports a warning if already
# declared. # declared.
...@@ -271,13 +271,17 @@ class Scope: ...@@ -271,13 +271,17 @@ class Scope:
warning(pos, "'%s' is a reserved name in C." % cname, -1) warning(pos, "'%s' is a reserved name in C." % cname, -1)
dict = self.entries dict = self.entries
if name and dict.has_key(name): if name and dict.has_key(name):
warning(pos, "'%s' redeclared " % name, 0) if visibility == 'extern':
warning(pos, "'%s' redeclared " % name, 0)
else:
error(pos, "'%s' redeclared " % name)
entry = Entry(name, cname, type, pos = pos) entry = Entry(name, cname, type, pos = pos)
entry.in_cinclude = self.in_cinclude entry.in_cinclude = self.in_cinclude
if name: if name:
entry.qualified_name = self.qualify_name(name) entry.qualified_name = self.qualify_name(name)
dict[name] = entry dict[name] = entry
entry.scope = self entry.scope = self
entry.visibility = visibility
return entry return entry
def qualify_name(self, name): def qualify_name(self, name):
...@@ -290,7 +294,7 @@ class Scope: ...@@ -290,7 +294,7 @@ class Scope:
cname = name cname = name
else: else:
cname = self.mangle(Naming.enum_prefix, name) cname = self.mangle(Naming.enum_prefix, name)
entry = self.declare(name, cname, type, pos) entry = self.declare(name, cname, type, pos, 'private')
entry.is_const = 1 entry.is_const = 1
entry.value = value entry.value = value
return entry return entry
...@@ -300,8 +304,7 @@ class Scope: ...@@ -300,8 +304,7 @@ class Scope:
# Add an entry for a type definition. # Add an entry for a type definition.
if not cname: if not cname:
cname = name cname = name
entry = self.declare(name, cname, type, pos) entry = self.declare(name, cname, type, pos, visibility)
entry.visibility = visibility
entry.is_type = 1 entry.is_type = 1
if defining: if defining:
self.type_entries.append(entry) self.type_entries.append(entry)
...@@ -385,9 +388,8 @@ class Scope: ...@@ -385,9 +388,8 @@ class Scope:
cname = name cname = name
else: else:
cname = self.mangle(Naming.var_prefix, name) cname = self.mangle(Naming.var_prefix, name)
entry = self.declare(name, cname, type, pos) entry = self.declare(name, cname, type, pos, visibility)
entry.is_variable = 1 entry.is_variable = 1
entry.visibility = visibility
self.control_flow.set_state((), (name, 'initalized'), False) self.control_flow.set_state((), (name, 'initalized'), False)
return entry return entry
...@@ -400,7 +402,7 @@ class Scope: ...@@ -400,7 +402,7 @@ class Scope:
if entry and not entry.type.is_cfunction: if entry and not entry.type.is_cfunction:
# This is legal Python, but for now will produce invalid C. # This is legal Python, but for now will produce invalid C.
error(pos, "'%s' already declared" % name) error(pos, "'%s' already declared" % name)
entry = self.declare_var(name, py_object_type, pos) entry = self.declare_var(name, py_object_type, pos, visibility='extern')
entry.signature = pyfunction_signature entry.signature = pyfunction_signature
self.pyfunc_entries.append(entry) self.pyfunc_entries.append(entry)
return entry return entry
...@@ -416,8 +418,11 @@ class Scope: ...@@ -416,8 +418,11 @@ class Scope:
if visibility != 'private' and visibility != entry.visibility: if visibility != 'private' and visibility != entry.visibility:
warning(pos, "Function '%s' previously declared as '%s'" % (name, entry.visibility), 1) warning(pos, "Function '%s' previously declared as '%s'" % (name, entry.visibility), 1)
if not entry.type.same_as(type): if not entry.type.same_as(type):
warning(pos, "Function signature does not match previous declaration", 1) if visibility == 'extern' and entry.visibility == 'extern':
entry.type = type warning(pos, "Function signature does not match previous declaration", 1)
entry.type = type
else:
error(pos, "Function signature does not match previous declaration")
else: else:
if not cname: if not cname:
if api or visibility != 'private': if api or visibility != 'private':
...@@ -436,9 +441,8 @@ class Scope: ...@@ -436,9 +441,8 @@ class Scope:
def add_cfunction(self, name, type, pos, cname, visibility): def add_cfunction(self, name, type, pos, cname, visibility):
# Add a C function entry without giving it a func_cname. # Add a C function entry without giving it a func_cname.
entry = self.declare(name, cname, type, pos) entry = self.declare(name, cname, type, pos, visibility)
entry.is_cfunction = 1 entry.is_cfunction = 1
entry.visibility = visibility
self.cfunc_entries.append(entry) self.cfunc_entries.append(entry)
return entry return entry
...@@ -549,9 +553,11 @@ class Scope: ...@@ -549,9 +553,11 @@ class Scope:
self.interned_nums.append(entry) self.interned_nums.append(entry)
return entry return entry
def get_py_num(self, value): def get_py_num(self, value, longness):
# Get entry for int constant. Returns an existing # Get entry for int constant. Returns an existing
# one if possible, otherwise creates a new one. # one if possible, otherwise creates a new one.
if longness or Utils.long_literal(value):
value += "L"
genv = self.global_scope() genv = self.global_scope()
entry = genv.num_to_entry.get(value) entry = genv.num_to_entry.get(value)
if not entry: if not entry:
...@@ -644,7 +650,7 @@ class PreImportScope(Scope): ...@@ -644,7 +650,7 @@ class PreImportScope(Scope):
Scope.__init__(self, Options.pre_import, None, None) Scope.__init__(self, Options.pre_import, None, None)
def declare_builtin(self, name, pos): def declare_builtin(self, name, pos):
entry = self.declare(name, name, py_object_type, pos) entry = self.declare(name, name, py_object_type, pos, 'private')
entry.is_variable = True entry.is_variable = True
entry.is_pyglobal = True entry.is_pyglobal = True
return entry return entry
...@@ -814,7 +820,7 @@ class ModuleScope(Scope): ...@@ -814,7 +820,7 @@ class ModuleScope(Scope):
for entry in self.cached_builtins: for entry in self.cached_builtins:
if entry.name == name: if entry.name == name:
return entry return entry
entry = self.declare(None, None, py_object_type, pos) entry = self.declare(None, None, py_object_type, pos, 'private')
if Options.cache_builtins: if Options.cache_builtins:
entry.is_builtin = 1 entry.is_builtin = 1
entry.is_const = 1 entry.is_const = 1
...@@ -1114,7 +1120,7 @@ class LocalScope(Scope): ...@@ -1114,7 +1120,7 @@ class LocalScope(Scope):
def declare_arg(self, name, type, pos): def declare_arg(self, name, type, pos):
# Add an entry for an argument of a function. # Add an entry for an argument of a function.
cname = self.mangle(Naming.var_prefix, name) cname = self.mangle(Naming.var_prefix, name)
entry = self.declare(name, cname, type, pos) entry = self.declare(name, cname, type, pos, 'private')
entry.is_variable = 1 entry.is_variable = 1
if type.is_pyobject: if type.is_pyobject:
entry.init = "0" entry.init = "0"
...@@ -1187,7 +1193,7 @@ class StructOrUnionScope(Scope): ...@@ -1187,7 +1193,7 @@ class StructOrUnionScope(Scope):
cname = name cname = name
if type.is_cfunction: if type.is_cfunction:
type = PyrexTypes.CPtrType(type) type = PyrexTypes.CPtrType(type)
entry = self.declare(name, cname, type, pos) entry = self.declare(name, cname, type, pos, visibility)
entry.is_variable = 1 entry.is_variable = 1
self.var_entries.append(entry) self.var_entries.append(entry)
if type.is_pyobject and not allow_pyobject: if type.is_pyobject and not allow_pyobject:
...@@ -1319,8 +1325,7 @@ class CClassScope(ClassScope): ...@@ -1319,8 +1325,7 @@ class CClassScope(ClassScope):
% name) % name)
if not cname: if not cname:
cname = name cname = name
entry = self.declare(name, cname, type, pos) entry = self.declare(name, cname, type, pos, visibility)
entry.visibility = visibility
entry.is_variable = 1 entry.is_variable = 1
self.var_entries.append(entry) self.var_entries.append(entry)
if type.is_pyobject: if type.is_pyobject:
...@@ -1361,7 +1366,7 @@ class CClassScope(ClassScope): ...@@ -1361,7 +1366,7 @@ class CClassScope(ClassScope):
warning(pos, "__new__ method of extension type will change semantics " warning(pos, "__new__ method of extension type will change semantics "
"in a future version of Pyrex and Cython. Use __cinit__ instead.") "in a future version of Pyrex and Cython. Use __cinit__ instead.")
name = Utils.EncodedString("__cinit__") name = Utils.EncodedString("__cinit__")
entry = self.declare_var(name, py_object_type, pos) entry = self.declare_var(name, py_object_type, pos, visibility='extern')
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
...@@ -1436,7 +1441,9 @@ class CClassScope(ClassScope): ...@@ -1436,7 +1441,9 @@ class CClassScope(ClassScope):
return entry return entry
def declare_property(self, name, doc, pos): def declare_property(self, name, doc, pos):
entry = self.declare(name, name, py_object_type, pos) entry = self.lookup_here(name)
if entry is None:
entry = self.declare(name, name, py_object_type, pos, 'private')
entry.is_property = 1 entry.is_property = 1
entry.doc = doc entry.doc = doc
entry.scope = PropertyScope(name, entry.scope = PropertyScope(name,
...@@ -1454,7 +1461,7 @@ class CClassScope(ClassScope): ...@@ -1454,7 +1461,7 @@ class CClassScope(ClassScope):
for base_entry in \ for base_entry in \
base_scope.inherited_var_entries + base_scope.var_entries: base_scope.inherited_var_entries + base_scope.var_entries:
entry = self.declare(base_entry.name, adapt(base_entry.cname), entry = self.declare(base_entry.name, adapt(base_entry.cname),
base_entry.type, None) base_entry.type, None, 'private')
entry.is_variable = 1 entry.is_variable = 1
self.inherited_var_entries.append(entry) self.inherited_var_entries.append(entry)
for base_entry in base_scope.cfunc_entries: for base_entry in base_scope.cfunc_entries:
...@@ -1479,7 +1486,7 @@ class PropertyScope(Scope): ...@@ -1479,7 +1486,7 @@ class PropertyScope(Scope):
# Add an entry for a method. # Add an entry for a method.
signature = get_property_accessor_signature(name) signature = get_property_accessor_signature(name)
if signature: if signature:
entry = self.declare(name, name, py_object_type, pos) entry = self.declare(name, name, py_object_type, pos, 'private')
entry.is_special = 1 entry.is_special = 1
entry.signature = signature entry.signature = signature
return entry return entry
......
...@@ -28,7 +28,7 @@ class StringParseContext(Main.Context): ...@@ -28,7 +28,7 @@ class StringParseContext(Main.Context):
raise AssertionError("Not yet supporting any cimports/includes from string code snippets") raise AssertionError("Not yet supporting any cimports/includes from string code snippets")
return ModuleScope(module_name, parent_module = None, context = self) return ModuleScope(module_name, parent_module = None, context = self)
def parse_from_strings(name, code, pxds={}): def parse_from_strings(name, code, pxds={}, level=None):
""" """
Utility method to parse a (unicode) string of code. This is mostly Utility method to parse a (unicode) string of code. This is mostly
used for internal Cython compiler purposes (creating code snippets used for internal Cython compiler purposes (creating code snippets
...@@ -56,7 +56,10 @@ def parse_from_strings(name, code, pxds={}): ...@@ -56,7 +56,10 @@ def parse_from_strings(name, code, pxds={}):
scanner = PyrexScanner(buf, code_source, source_encoding = encoding, scanner = PyrexScanner(buf, code_source, source_encoding = encoding,
scope = scope, context = context) scope = scope, context = context)
tree = Parsing.p_module(scanner, 0, module_name) if level is None:
tree = Parsing.p_module(scanner, 0, module_name)
else:
tree = Parsing.p_code(scanner, level=level)
return tree return tree
class TreeCopier(VisitorTransform): class TreeCopier(VisitorTransform):
...@@ -171,7 +174,7 @@ def strip_common_indent(lines): ...@@ -171,7 +174,7 @@ def strip_common_indent(lines):
return lines return lines
class TreeFragment(object): class TreeFragment(object):
def __init__(self, code, name="(tree fragment)", pxds={}, temps=[], pipeline=[]): def __init__(self, code, name="(tree fragment)", pxds={}, temps=[], pipeline=[], level=None):
if isinstance(code, unicode): if isinstance(code, unicode):
def fmt(x): return u"\n".join(strip_common_indent(x.split(u"\n"))) def fmt(x): return u"\n".join(strip_common_indent(x.split(u"\n")))
...@@ -180,9 +183,9 @@ class TreeFragment(object): ...@@ -180,9 +183,9 @@ class TreeFragment(object):
for key, value in pxds.iteritems(): for key, value in pxds.iteritems():
fmt_pxds[key] = fmt(value) fmt_pxds[key] = fmt(value)
t = parse_from_strings(name, fmt_code, fmt_pxds) mod = t = parse_from_strings(name, fmt_code, fmt_pxds, level=level)
mod = t if level is None:
t = t.body # Make sure a StatListNode is at the top t = t.body # Make sure a StatListNode is at the top
if not isinstance(t, StatListNode): if not isinstance(t, StatListNode):
t = StatListNode(pos=mod.pos, stats=[t]) t = StatListNode(pos=mod.pos, stats=[t])
for transform in pipeline: for transform in pipeline:
......
...@@ -115,3 +115,15 @@ def escape_byte_string(s): ...@@ -115,3 +115,15 @@ def escape_byte_string(s):
else: else:
append(c) append(c)
return ''.join(l) return ''.join(l)
def long_literal(value):
if isinstance(value, basestring):
if len(value) < 2:
value = int(value)
elif value[0] == 0:
value = int(value, 8)
elif value[1] in 'xX':
value = int(value[2:], 16)
else:
value = int(value)
return not -2**31 <= value < 2**31
...@@ -7,7 +7,6 @@ from Cython.Distutils import build_ext ...@@ -7,7 +7,6 @@ from Cython.Distutils import build_ext
ext_modules=[ ext_modules=[
Extension("primes", ["primes.pyx"]), Extension("primes", ["primes.pyx"]),
Extension("spam", ["spam.pyx"]), Extension("spam", ["spam.pyx"]),
# Extension("optargs", ["optargs.pyx"], language = "c++"),
] ]
for file in glob.glob("*.pyx"): for file in glob.glob("*.pyx"):
......
PYTHON?=python PYTHON?=python
all: local
local:
${PYTHON} setup.py build_ext --inplace
clean: clean:
@echo Cleaning Source @echo Cleaning Source
@rm -fr build
@rm -f *.pyc */*.pyc */*/*.pyc @rm -f *.pyc */*.pyc */*/*.pyc
@rm -f *~ */*~ */*/*~ @rm -f *~ */*~ */*/*~
@rm -f core */core @rm -f core */core
@rm -f Cython/Plex/Scanners.{so,pyd}
@(cd Demos; $(MAKE) clean) @(cd Demos; $(MAKE) clean)
testclean: testclean:
......
@REM Start cython from windows commandline as "cython", not "cython.py".
@REM This is especially useful for windows power shell, as no extra window
@REM is used.
@echo OFF
python -c "from Cython.Compiler.Main import main; main(command_line = 1)" %*
...@@ -296,7 +296,18 @@ def collect_unittests(path, module_prefix, suite, selectors): ...@@ -296,7 +296,18 @@ def collect_unittests(path, module_prefix, suite, selectors):
loader = unittest.TestLoader() loader = unittest.TestLoader()
skipped_dirs = []
for dirpath, dirnames, filenames in os.walk(path): for dirpath, dirnames, filenames in os.walk(path):
if dirpath != path and "__init__.py" not in filenames:
skipped_dirs.append(dirpath + os.path.sep)
continue
skip = False
for dir in skipped_dirs:
if dirpath.startswith(dir):
skip = True
if skip:
continue
parentname = os.path.split(dirpath)[-1] parentname = os.path.split(dirpath)[-1]
if package_matches(parentname): if package_matches(parentname):
for f in filenames: for f in filenames:
...@@ -332,7 +343,7 @@ def collect_doctests(path, module_prefix, suite, selectors): ...@@ -332,7 +343,7 @@ def collect_doctests(path, module_prefix, suite, selectors):
module = getattr(module, x) module = getattr(module, x)
if hasattr(module, "__doc__") or hasattr(module, "__test__"): if hasattr(module, "__doc__") or hasattr(module, "__test__"):
try: try:
suite.addTests(doctest.DocTestSuite(module)) suite.addTest(doctest.DocTestSuite(module))
except ValueError: # no tests except ValueError: # no tests
pass pass
......
...@@ -14,8 +14,8 @@ if sys.version_info < (2,4): ...@@ -14,8 +14,8 @@ if sys.version_info < (2,4):
cython_dir = os.path.join(get_python_lib(prefix=''), 'Cython') cython_dir = os.path.join(get_python_lib(prefix=''), 'Cython')
compiler_dir = os.path.join(cython_dir, 'Compiler') compiler_dir = os.path.join(cython_dir, 'Compiler')
setup_args['data_files'] = [ setup_args['data_files'] = [
{compiler_dir : ['Cython/Compiler/Lexicon.pickle'], (compiler_dir, ['Cython/Compiler/Lexicon.pickle']),
cython_dir : ['Cython/Includes/*.pxd']}] (cython_dir, ['Cython/Includes/*.pxd'])]
else: else:
setup_args['package_data'] = {'Cython.Compiler' : ['Lexicon.pickle'], setup_args['package_data'] = {'Cython.Compiler' : ['Lexicon.pickle'],
'Cython' : ['Includes/*.pxd']} 'Cython' : ['Includes/*.pxd']}
......
def f(obj, int i, float f, char *s1, char s2[]): def f(obj, int i, float f, char *s1, char s2[]):
pass pass
\ No newline at end of file cdef g(obj, int i, float f, char *s1, char s2[]):
pass
cdef do_g(object (*func)(object, int, float, char*, char*)):
return func(1, 2, 3.14159, "a", "b")
do_g(&g)
...@@ -4,4 +4,4 @@ cdef class Sub2(Crunchy): ...@@ -4,4 +4,4 @@ cdef class Sub2(Crunchy):
cdef char character cdef char character
cdef class Sub1(Sub2): cdef class Sub1(Sub2):
cdef char character pass
cdef class Spam:
cdef public Spam e
_ERRORS = u"""
/Local/Projects/D/Pyrex/Source/Tests/Errors1/e_extmember.pyx:2:18: Non-generic Python attribute cannot be exposed for writing from Python
"""
__doc__ = u"""
>>> e = ExtClass()
>>> e.get()
5
"""
cdef class ExtClass:
cdef int _attribute = 2
def get(self):
return self._attribute
_attribute = 5 # FIXME: this is not currently handled!!!
_ERRORS = u"""
8:13: Cannot assign default value to cdef class attributes
"""
...@@ -86,7 +86,6 @@ _ERRORS = u""" ...@@ -86,7 +86,6 @@ _ERRORS = u"""
15: 5: Calling gil-requiring function without gil 15: 5: Calling gil-requiring function without gil
24: 9: Calling gil-requiring function without gil 24: 9: Calling gil-requiring function without gil
26:12: Assignment of Python object not allowed without gil 26:12: Assignment of Python object not allowed without gil
27: 8: Constructing Python long int not allowed without gil
28: 8: Constructing complex number not allowed without gil 28: 8: Constructing complex number not allowed without gil
29:12: Accessing Python global or builtin not allowed without gil 29:12: Accessing Python global or builtin not allowed without gil
30: 8: Backquote expression not allowed without gil 30: 8: Backquote expression not allowed without gil
......
"""
>>> call_test()
False
True
False
True
True
True
True
"""
cdef test(bint value):
print value
def call_test():
test(False)
test(True)
test(0)
test(234)
test(-1)
x = True
test(x)
x = 3242
test(x)
__doc__ = u"""
>>> test_c(u'abc')
fileabc
typeabc
>>> print test_file_py(u'abc')
abc
>>> print range(u'abc')
rangeabc
"""
def test_file_py(file):
return file
cdef test_file_c(file):
return u'file' + file
def range(arg):
return u'range' + arg
cdef type(arg):
return u'type' + arg
def test_c(arg):
print test_file_c(arg)
print type(arg)
...@@ -2,6 +2,11 @@ __doc__ = u""" ...@@ -2,6 +2,11 @@ __doc__ = u"""
>>> call2() >>> call2()
>>> call3() >>> call3()
>>> call4() >>> call4()
>>> test_foo()
2
3
7
26
""" """
# the calls: # the calls:
...@@ -19,3 +24,13 @@ def call4(): ...@@ -19,3 +24,13 @@ def call4():
cdef b(a, b, c=1, d=2): cdef b(a, b, c=1, d=2):
pass pass
cdef int foo(int a, int b=1, int c=1):
return a+b*c
def test_foo():
print foo(1)
print foo(1, 2)
print foo(1, 2, 3)
print foo(1, foo(2, 3), foo(4))
__doc__ = """
>>> s = Spam()
>>> s.e = s
>>> s.e = 1
Traceback (most recent call last):
TypeError: Cannot convert int to extmember.Spam
>>> s.e is s
True
>>> s.e = None
"""
cdef class Spam:
cdef public Spam e
__doc__ = """
>>> c_longs()
(1, 1L, -1L, 18446744073709551615L)
>>> py_longs()
(1, 1L, 100000000000000000000000000000000L, -100000000000000000000000000000000L)
"""
def c_longs():
cdef long a = 1L
cdef unsigned long ua = 1UL
cdef long long aa = 0xFFFFFFFFFFFFFFFFLL
cdef unsigned long long uaa = 0xFFFFFFFFFFFFFFFFULL
return a, ua, aa, uaa
def py_longs():
return 1, 1L, 100000000000000000000000000000000, -100000000000000000000000000000000
...@@ -34,9 +34,9 @@ def h(i): ...@@ -34,9 +34,9 @@ def h(i):
return 5 ** i return 5 ** i
def constant_py(): def constant_py():
result = 2L ** 10 result = (<object>2) ** 10
return result return result
def constant_long(): def constant_long():
result = 2L ** 36 result = (<object>2L) ** 36
return result return result
...@@ -29,4 +29,4 @@ cdef class Sub2(list): ...@@ -29,4 +29,4 @@ cdef class Sub2(list):
cdef char character cdef char character
cdef class Sub1(Sub2): cdef class Sub1(Sub2):
cdef char character pass
__doc__ = u"""
>>> zoo = Zoo()
>>> for cl in (Zoo, Bam, Bar, Foo, Base, Base0): assert isinstance(zoo, cl)
>>> fooit(zoo)
42
>>> bam = Bam()
>>> for cl in (Bam, Bar, Foo, Base, Base0): assert isinstance(bam, cl)
>>> fooit(bam)
42
>>> bar = Bar()
>>> for cl in (Bar, Foo, Base, Base0): assert isinstance(bar, cl)
>>> fooit(bar)
42
>>> foo = Foo()
>>> for cl in (Foo, Base, Base0): assert isinstance(foo, cl)
>>> fooit(foo)
42
>>> base = Base()
>>> for cl in (Base, Base0): assert isinstance(base, cl)
>>> fooit(base)
Traceback (most recent call last):
TypeError: Argument 'foo' has incorrect type (expected subclasses.Foo, got subclasses.Base)
>>> base0 = Base0()
>>> for cl in (Base0,): assert isinstance(base0, cl)
>>> fooit(base0)
Traceback (most recent call last):
TypeError: Argument 'foo' has incorrect type (expected subclasses.Foo, got subclasses.Base0)
"""
cdef class Base0:
pass
cdef class Base(Base0):
pass
cdef class Foo(Base):
cdef fooit(self):
return 42
cdef class Bar(Foo):
pass
cdef class Bam(Bar):
pass
cdef class Zoo(Bam):
pass
def fooit(Foo foo):
return foo.fooit()
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