diff options
Diffstat (limited to 'debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Nodes.py')
| -rw-r--r-- | debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Nodes.py | 3249 |
1 files changed, 0 insertions, 3249 deletions
diff --git a/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Nodes.py b/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Nodes.py deleted file mode 100644 index fb974df0..00000000 --- a/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Nodes.py +++ /dev/null @@ -1,3249 +0,0 @@ -# -# Pyrex - Parse tree nodes -# - -import string, sys - -import Code -from Errors import error, one_time_warning, InternalError -import Naming -import PyrexTypes -from PyrexTypes import py_object_type, c_int_type, error_type, \ - CTypedefType, CFuncType -from Symtab import ModuleScope, LocalScope, \ - StructOrUnionScope, PyClassScope, CClassScope -from Pyrex.Utils import open_new_file, replace_suffix -import Options - -from DebugFlags import debug_disposal_code - -class Node: - # pos (string, int, int) Source file position - # is_name boolean Is a NameNode - # is_literal boolean Is a ConstNode - - is_name = 0 - is_literal = 0 - - def __init__(self, pos, **kw): - self.pos = pos - self.__dict__.update(kw) - - gil_message = "Operation" - - def gil_check(self, env): - if env.nogil: - self.gil_error() - - def gil_error(self, message = None): - error(self.pos, "%s not allowed without gil" % (message or self.gil_message)) - - # - # There are 3 phases of parse tree processing, applied in order to - # all the statements in a given scope-block: - # - # (1) analyse_declarations - # Make symbol table entries for all declarations at the current - # level, both explicit (def, cdef, etc.) and implicit (assignment - # to an otherwise undeclared name). - # - # (2) analyse_expressions - # Determine the result types of expressions and fill in the - # 'type' attribute of each ExprNode. Insert coercion nodes into the - # tree where needed to convert to and from Python objects. - # Allocate temporary locals for intermediate results. - # - # (3) generate_code - # Emit C code for all declarations, statements and expressions. - # Recursively applies the 3 processing phases to the bodies of - # functions. - # - - def analyse_declarations(self, env): - pass - - def analyse_expressions(self, env): - raise InternalError("analyse_expressions not implemented for %s" % \ - self.__class__.__name__) - - def generate_code(self, code): - raise InternalError("generate_code not implemented for %s" % \ - self.__class__.__name__) - - -class BlockNode: - # Mixin class for nodes representing a declaration block. - pass - -# def generate_const_definitions(self, env, code): -# if env.const_entries: -# code.putln("") -# for entry in env.const_entries: -# if not entry.is_interned: -# code.put_var_declaration(entry, static = 1) - -# def generate_interned_name_decls(self, env, code): -# # Flush accumulated interned names from the global scope -# # and generate declarations for them. -# genv = env.global_scope() -# intern_map = genv.intern_map -# names = genv.interned_names -# if names: -# code.putln("") -# for name in names: -# code.putln( -# "static PyObject *%s;" % intern_map[name]) -# del names[:] - -# def generate_py_string_decls(self, env, code): -# entries = env.pystring_entries -# if entries: -# code.putln("") -# for entry in entries: -# code.putln( -# "static PyObject *%s;" % entry.pystring_cname) - - -class StatListNode(Node): - # stats a list of StatNode - - def analyse_declarations(self, env): - #print "StatListNode.analyse_declarations" ### - for stat in self.stats: - stat.analyse_declarations(env) - - def analyse_expressions(self, env): - #print "StatListNode.analyse_expressions" ### - for stat in self.stats: - stat.analyse_expressions(env) - - def generate_function_definitions(self, env, code): - #print "StatListNode.generate_function_definitions" ### - for stat in self.stats: - stat.generate_function_definitions(env, code) - - def generate_execution_code(self, code): - #print "StatListNode.generate_execution_code" ### - for stat in self.stats: - code.mark_pos(stat.pos) - stat.generate_execution_code(code) - - -class StatNode(Node): - # - # Code generation for statements is split into the following subphases: - # - # (1) generate_function_definitions - # Emit C code for the definitions of any structs, - # unions, enums and functions defined in the current - # scope-block. - # - # (2) generate_execution_code - # Emit C code for executable statements. - # - - def generate_function_definitions(self, env, code): - pass - - def generate_execution_code(self, code): - raise InternalError("generate_execution_code not implemented for %s" % \ - self.__class__.__name__) - - -class CDefExternNode(StatNode): - # include_file string or None - # body StatNode - - def analyse_declarations(self, env): - if self.include_file: - env.add_include_file(self.include_file) - old_cinclude_flag = env.in_cinclude - env.in_cinclude = 1 - self.body.analyse_declarations(env) - env.in_cinclude = old_cinclude_flag - - def analyse_expressions(self, env): - pass - - def generate_execution_code(self, code): - pass - - -class CDeclaratorNode(Node): - # Part of a C declaration. - # - # Processing during analyse_declarations phase: - # - # analyse - # Returns (name, type) pair where name is the - # CNameDeclaratorNode of the name being declared - # and type is the type it is being declared as. - # - # calling_convention string Calling convention of CFuncDeclaratorNode - # for which this is a base - - calling_convention = "" - - -class CNameDeclaratorNode(CDeclaratorNode): - # name string The Pyrex name being declared - # cname string or None C name, if specified - - def analyse(self, base_type, env): - return self, base_type - - -class CPtrDeclaratorNode(CDeclaratorNode): - # base CDeclaratorNode - - def analyse(self, base_type, env): - if base_type.is_pyobject: - error(self.pos, - "Pointer base type cannot be a Python object") - ptr_type = PyrexTypes.c_ptr_type(base_type) - return self.base.analyse(ptr_type, env) - - -class CArrayDeclaratorNode(CDeclaratorNode): - # base CDeclaratorNode - # dimension ExprNode - - def analyse(self, base_type, env): - if self.dimension: - self.dimension.analyse_const_expression(env) - if not self.dimension.type.is_int: - error(self.dimension.pos, "Array dimension not integer") - size = self.dimension.result() - else: - size = None - if not base_type.is_complete(): - error(self.pos, - "Array element type '%s' is incomplete" % base_type) - if base_type.is_pyobject: - error(self.pos, - "Array element cannot be a Python object") - if base_type.is_cfunction: - error(self.pos, - "Array element cannot be a function") - array_type = PyrexTypes.c_array_type(base_type, size) - return self.base.analyse(array_type, env) - - -class CFuncDeclaratorNode(CDeclaratorNode): - # base CDeclaratorNode - # args [CArgDeclNode] - # has_varargs boolean - # exception_value ConstNode - # exception_check boolean True if PyErr_Occurred check needed - # nogil boolean Can be called without gil - # with_gil boolean Acquire gil around function body - - def analyse(self, return_type, env): - func_type_args = [] - for arg_node in self.args: - name_declarator, type = arg_node.analyse(env) - name = name_declarator.name - if name_declarator.cname: - error(self.pos, - "Function argument cannot have C name specification") - # Turn *[] argument into ** - if type.is_array: - type = PyrexTypes.c_ptr_type(type.base_type) - # Catch attempted C-style func(void) decl - if type.is_void: - error(arg_node.pos, "Function argument cannot be void") - func_type_args.append( - PyrexTypes.CFuncTypeArg(name, type, arg_node.pos)) - if arg_node.default: - error(arg_node.pos, "C function argument cannot have default value") - exc_val = None - exc_check = 0 - if return_type.is_pyobject \ - and (self.exception_value or self.exception_check): - error(self.pos, - "Exception clause not allowed for function returning Python object") - else: - if self.exception_value: - self.exception_value.analyse_const_expression(env) - exc_val = self.exception_value.result() - if not return_type.assignable_from(self.exception_value.type): - error(self.exception_value.pos, - "Exception value incompatible with function return type") - exc_check = self.exception_check - if return_type.is_array: - error(self.pos, - "Function cannot return an array") - if return_type.is_cfunction: - error(self.pos, - "Function cannot return a function") - func_type = PyrexTypes.CFuncType( - return_type, func_type_args, self.has_varargs, - exception_value = exc_val, exception_check = exc_check, - calling_convention = self.base.calling_convention, - nogil = self.nogil, with_gil = self.with_gil) - return self.base.analyse(func_type, env) - - -class CArgDeclNode(Node): - # Item in a function declaration argument list. - # - # base_type CBaseTypeNode - # declarator CDeclaratorNode - # #not_none boolean Tagged with 'not None' - # allow_none tristate True == 'or None', False == 'not None', None = unspecified - # default ExprNode or None - # default_entry Symtab.Entry Entry for the variable holding the default value - # is_self_arg boolean Is the "self" arg of an extension type method - # is_kw_only boolean Is a keyword-only argument - - is_self_arg = 0 - - def analyse(self, env): - #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ### - base_type = self.base_type.analyse(env) - return self.declarator.analyse(base_type, env) - - -class CBaseTypeNode(Node): - # Abstract base class for C base type nodes. - # - # Processing during analyse_declarations phase: - # - # analyse - # Returns the type. - - pass - - -class CSimpleBaseTypeNode(CBaseTypeNode): - # name string - # module_path [string] Qualifying name components - # is_basic_c_type boolean - # signed boolean - # longness integer - # is_self_arg boolean Is self argument of C method - - def analyse(self, env): - # Return type descriptor. - #print "CSimpleBaseTypeNode.analyse: is_self_arg =", self.is_self_arg ### - type = None - if self.is_basic_c_type: - type = PyrexTypes.simple_c_type(self.signed, self.longness, self.name) - if not type: - error(self.pos, "Unrecognised type modifier combination") - elif self.name == "object" and not self.module_path: - type = py_object_type - elif self.name is None: - if self.is_self_arg and env.is_c_class_scope: - #print "CSimpleBaseTypeNode.analyse: defaulting to parent type" ### - type = env.parent_type - else: - type = py_object_type - else: - scope = env.find_imported_module(self.module_path, self.pos) - if scope: - entry = scope.find(self.name, self.pos) - if entry and entry.is_type: - type = entry.type - else: - error(self.pos, "'%s' is not a type identifier" % self.name) - if type: - return type - else: - return PyrexTypes.error_type - - -class CComplexBaseTypeNode(CBaseTypeNode): - # base_type CBaseTypeNode - # declarator CDeclaratorNode - - def analyse(self, env): - base = self.base_type.analyse(env) - _, type = self.declarator.analyse(base, env) - return type - - -class CVarDefNode(StatNode): - # C variable definition or forward/extern function declaration. - # - # visibility 'private' or 'public' or 'extern' - # base_type CBaseTypeNode - # declarators [CDeclaratorNode] - # in_pxd boolean - # api boolean - - def analyse_declarations(self, env, dest_scope = None): - if not dest_scope: - dest_scope = env - base_type = self.base_type.analyse(env) - for declarator in self.declarators: - name_declarator, type = declarator.analyse(base_type, env) - if not type.is_complete(): - if not (self.visibility == 'extern' and type.is_array): - error(declarator.pos, - "Variable type '%s' is incomplete" % type) - if self.visibility == 'extern' and type.is_pyobject: - error(declarator.pos, - "Python object cannot be declared extern") - name = name_declarator.name - cname = name_declarator.cname - if type.is_cfunction: - entry = dest_scope.declare_cfunction(name, type, declarator.pos, - cname = cname, visibility = self.visibility, in_pxd = self.in_pxd, - api = self.api) - else: - if self.in_pxd and self.visibility <> 'extern': - error(self.pos, - "Only 'extern' C variable declaration allowed in .pxd file") - dest_scope.declare_var(name, type, declarator.pos, - cname = cname, visibility = self.visibility, is_cdef = 1) - - def analyse_expressions(self, env): - pass - - def generate_execution_code(self, code): - pass - - -class CStructOrUnionDefNode(StatNode): - # name string - # cname string or None - # module_path [string] - # kind "struct" or "union" - # typedef_flag boolean - # cplus_flag boolean - # visibility "public" or "private" - # in_pxd boolean - # attributes [CVarDefNode] or None - # entry Entry - # bases [([name, ...], name), ...] - - def analyse_declarations(self, env): - scope = None - base_scopes = [] - for base in self.bases: - base_entry = env.find_qualified_name(base, self.pos) - if base_entry: - if base_entry.is_type and base_entry.type.is_struct_or_union \ - and base_entry.type.scope.is_cplus: - base_scopes.append(base_entry.type.scope) - else: - error(self.pos, "Base type '%s' is not a C++ struct" % - ".".join(base[0] + [base[1]])) - if self.attributes is not None: - scope = StructOrUnionScope(base_scopes = base_scopes, is_cplus = self.cplus_flag) - if self.module_path: - home_scope = env.find_imported_module(self.module_path, self.pos) - if not home_scope: - return - else: - home_scope = env - def declare(): - self.entry = home_scope.declare_struct_or_union( - self.name, self.kind, scope, self.typedef_flag, self.pos, - self.cname, visibility = self.visibility) - if self.attributes is not None: - if self.in_pxd and not env.in_cinclude: - self.entry.defined_in_pxd = 1 - if not self.typedef_flag: - declare() - if self.attributes is not None: - for attr in self.attributes: - attr.analyse_declarations(env, scope) - if self.typedef_flag: - declare() - - def analyse_expressions(self, env): - pass - - def generate_execution_code(self, code): - pass - - -class CEnumDefNode(StatNode): - # name string or None - # cname string or None - # items [CEnumDefItemNode] - # typedef_flag boolean - # visibility "public" or "private" - # in_pxd boolean - # entry Entry - - def analyse_declarations(self, env): - self.entry = env.declare_enum(self.name, self.pos, - cname = self.cname, typedef_flag = self.typedef_flag, - visibility = self.visibility) - if self.items is not None: - if self.in_pxd and not env.in_cinclude: - self.entry.defined_in_pxd = 1 - for item in self.items: - item.analyse_declarations(env, self.entry) - - def analyse_expressions(self, env): - pass - - def generate_execution_code(self, code): - pass - - -class CEnumDefItemNode(StatNode): - # name string - # cname string or None - # value ExprNode or None - - def analyse_declarations(self, env, enum_entry): - value_node = self.value - if value_node: - value_node.analyse_const_expression(env) - type = value_node.type - if type.is_int or type.is_enum: - value = value_node.result() - else: - error(self.pos, - "Type '%s' is not a valid enum value" % type) - value = "<error>" - else: - value = self.name - entry = env.declare_const(self.name, enum_entry.type, - value, self.pos, cname = self.cname) - enum_entry.enum_values.append(entry) - - -class CTypeDefNode(StatNode): - # base_type CBaseTypeNode - # declarator CDeclaratorNode - # visibility "public" or "private" - # in_pxd boolean - - def analyse_declarations(self, env): - base = self.base_type.analyse(env) - name_declarator, type = self.declarator.analyse(base, env) - name = name_declarator.name - cname = name_declarator.cname - entry = env.declare_typedef(name, type, self.pos, - cname = cname, visibility = self.visibility) - if self.in_pxd and not env.in_cinclude: - entry.defined_in_pxd = 1 - - def analyse_expressions(self, env): - pass - - def generate_execution_code(self, code): - pass - - -class FuncDefNode(StatNode, BlockNode): - # Base class for function definition nodes. - # - # return_type PyrexType - # #filename string C name of filename string const - # entry Symtab.Entry - - def analyse_expressions(self, env): - pass - - def need_gil_acquisition(self, lenv): - return 0 - - def generate_function_definitions(self, env, code): - # Generate C code for header and body of function - genv = env.global_scope() - lenv = LocalScope(name = self.entry.name, outer_scope = genv) - lenv.return_type = self.return_type - type = self.entry.type - if type.is_cfunction: - lenv.nogil = type.nogil and not type.with_gil - code.init_labels() - self.declare_arguments(lenv) - self.body.analyse_declarations(lenv) - self.body.analyse_expressions(lenv) - # Code for nested function definitions would go here - # if we supported them, which we probably won't. - # ----- Function header - code.putln("") - self.generate_function_header(code, - with_pymethdef = env.is_py_class_scope) - # ----- Local variable declarations - self.generate_argument_declarations(lenv, code) - code.put_var_declarations(lenv.var_entries) - init = "" - if not self.return_type.is_void: - code.putln( - "%s%s;" % - (self.return_type.declaration_code( - Naming.retval_cname), - init)) - code.put_var_declarations(lenv.temp_entries) - self.generate_keyword_list(code) - # ----- Extern library function declarations - lenv.generate_library_function_declarations(code) - # ----- GIL acquisition - acquire_gil = self.need_gil_acquisition(lenv) - if acquire_gil: - lenv.global_scope().gil_used = 1 - code.putln("PyGILState_STATE _save = PyGILState_Ensure();") - # ----- Fetch arguments - self.generate_argument_parsing_code(code) - self.generate_argument_increfs(lenv, code) - # ----- Initialise local variables - for entry in lenv.var_entries: - if entry.type.is_pyobject and entry.init_to_none and entry.used: - code.put_init_var_to_py_none(entry) - # ----- Check and convert arguments - self.generate_argument_conversion_code(code) - self.generate_argument_type_tests(code) - # ----- Function body - self.body.generate_execution_code(code) - # ----- Default return value - code.putln("") - if self.return_type.is_pyobject: - #if self.return_type.is_extension_type: - # lhs = "(PyObject *)%s" % Naming.retval_cname - #else: - lhs = Naming.retval_cname - code.put_init_to_py_none(lhs, self.return_type) - else: - val = self.return_type.default_value - if val: - code.putln("%s = %s;" % (Naming.retval_cname, val)) - #code.putln("goto %s;" % code.return_label) - # ----- Error cleanup - if code.error_label in code.labels_used: - code.put_goto(code.return_label) - code.put_label(code.error_label) - code.put_var_xdecrefs(lenv.temp_entries) - default_retval = self.return_type.default_value - err_val = self.error_value() - exc_check = self.caller_will_check_exceptions() - if err_val or exc_check: - code.putln( - '__Pyx_AddTraceback("%s");' % - self.entry.qualified_name) - val = err_val or default_retval - if val: - code.putln( - "%s = %s;" % ( - Naming.retval_cname, - val)) - else: - code.use_utility_code(unraisable_exception_utility_code) - code.putln( - '__Pyx_WriteUnraisable("%s");' % - self.entry.qualified_name) - #if not self.return_type.is_void: - if default_retval: - code.putln( - "%s = %s;" % ( - Naming.retval_cname, - default_retval)) - #self.return_type.default_value)) - # ----- Return cleanup - code.put_label(code.return_label) - code.put_var_decrefs(lenv.var_entries, used_only = 1) - #code.put_var_decrefs(lenv.arg_entries) - self.generate_argument_decrefs(lenv, code) - self.put_stararg_decrefs(code) - if acquire_gil: - code.putln("PyGILState_Release(_save);") - if not self.return_type.is_void: - code.putln("return %s;" % Naming.retval_cname) - code.putln("}") - - def put_stararg_decrefs(self, code): - pass - - def declare_argument(self, env, arg, readonly = 0): - if arg.type.is_void: - error(arg.pos, "Invalid use of 'void'") - elif not arg.type.is_complete() and not arg.type.is_array: - error(arg.pos, - "Argument type '%s' is incomplete" % arg.type) - return env.declare_arg(arg.name, arg.type, arg.pos, - readonly = readonly) - - def generate_argument_increfs(self, env, code): - # Turn writable borrowed argument refs into owned refs. - # This is necessary, because if the argument is assigned to, - # it will be decrefed. - for entry in env.arg_entries: - if not entry.is_readonly: - code.put_var_incref(entry) - - def generate_argument_decrefs(self, env, code): - for entry in env.arg_entries: - if not entry.is_readonly: - code.put_var_decref(entry) - - def generate_execution_code(self, code): - pass - - -class CFuncDefNode(FuncDefNode): - # C function definition. - # - # visibility 'private' or 'public' or 'extern' - # base_type CBaseTypeNode - # declarator CDeclaratorNode - # body StatListNode - # api boolean - # - # with_gil boolean Acquire GIL around body - # type CFuncType - - def unqualified_name(self): - return self.entry.name - - def analyse_declarations(self, env): - base_type = self.base_type.analyse(env) - name_declarator, type = self.declarator.analyse(base_type, env) - if not type.is_cfunction: - error(self.pos, - "Suite attached to non-function declaration") - # Remember the actual type according to the function header - # written here, because the type in the symbol table entry - # may be different if we're overriding a C method inherited - # from the base type of an extension type. - self.type = type - name = name_declarator.name - cname = name_declarator.cname - self.entry = env.declare_cfunction( - name, type, self.pos, - cname = cname, visibility = self.visibility, - defining = self.body is not None, - api = self.api) - self.return_type = type.return_type - - def declare_arguments(self, env): - type = self.type - without_gil = type.nogil and not type.with_gil - for arg in type.args: - if not arg.name: - error(arg.pos, "Missing argument name") - self.declare_argument(env, arg, - readonly = without_gil and arg.type.is_pyobject) - - def need_gil_acquisition(self, lenv): - type = self.type - with_gil = type.with_gil - if type.nogil and not with_gil: -# for arg in type.args: -# if arg.type.is_pyobject: -# error(self.pos, -# "Function with Python argument cannot be declared nogil") - if type.return_type.is_pyobject: - error(self.pos, - "Function with Python return type cannot be declared nogil") - for entry in lenv.var_entries + lenv.temp_entries: - #print "CFuncDefNode.need_gil_acquisition:", entry.name, entry.cname, "readonly =", entry.is_readonly ### - if entry.type.is_pyobject and not entry.is_readonly: - error(self.pos, "Function declared nogil has Python locals or temporaries") - return with_gil - - def generate_function_header(self, code, with_pymethdef): - arg_decls = [] - type = self.type - visibility = self.entry.visibility - for arg in type.args: - arg_decls.append(arg.declaration_code()) - if type.has_varargs: - arg_decls.append("...") - if not arg_decls: - arg_decls = ["void"] - entity = type.function_header_code(self.entry.func_cname, - string.join(arg_decls, ",")) - if visibility == 'public': - dll_linkage = "DL_EXPORT" - else: - dll_linkage = None - header = self.return_type.declaration_code(entity, - dll_linkage = dll_linkage) - if visibility <> 'private': - storage_class = "%s " % Naming.extern_c_macro - else: - storage_class = "static " - code.putln("%s%s {" % ( - storage_class, - header)) - - def generate_argument_declarations(self, env, code): - # Arguments already declared in function header - pass - - def generate_keyword_list(self, code): - pass - - def generate_argument_parsing_code(self, code): - pass - - def generate_argument_conversion_code(self, code): - pass - - def generate_argument_type_tests(self, code): - pass - - def error_value(self): - if self.return_type.is_pyobject: - return "0" - else: - #return None - return self.entry.type.exception_value - - def caller_will_check_exceptions(self): - return self.entry.type.exception_check - - -class PyArgDeclNode(Node): - # Argument which must be a Python object (used - # for * and ** arguments). - # - # name string - # entry Symtab.Entry - - pass - - -class DefNode(FuncDefNode): - # A Python function definition. - # - # name string the Python name of the function - # args [CArgDeclNode] formal arguments - # star_arg PyArgDeclNode or None * argument - # starstar_arg PyArgDeclNode or None ** argument - # doc string or None - # body StatListNode - # - # The following subnode is constructed internally - # when the def statement is inside a Python class definition. - # - # assmt AssignmentNode Function construction/assignment - - assmt = None - num_kwonly_args = 0 - reqd_kw_flags_cname = "0" - has_star_or_kwonly_args = 0 - - def __init__(self, pos, **kwds): - FuncDefNode.__init__(self, pos, **kwds) - n = 0 - for arg in self.args: - if arg.kw_only: - n += 1 - self.num_kwonly_args = n - if self.star_arg or self.starstar_arg or n > 0: - self.has_star_or_kwonly_args = 1 - - def analyse_declarations(self, env): - for arg in self.args: - base_type = arg.base_type.analyse(env) - name_declarator, type = \ - arg.declarator.analyse(base_type, env) - arg.name = name_declarator.name - if name_declarator.cname: - error(self.pos, - "Python function argument cannot have C name specification") - arg.type = type.as_argument_type() - arg.hdr_type = None - arg.needs_conversion = 0 - arg.needs_type_test = 0 - arg.is_generic = 1 - if arg.allow_none is not None and not arg.type.is_extension_type: - error(self.pos, - "Only extension type arguments can have 'or None' or 'not None'") - self.declare_pyfunction(env) - self.analyse_signature(env) - self.return_type = self.entry.signature.return_type() -# if self.has_star_or_kwonly_args: -# env.use_utility_code(get_starargs_utility_code) - - def analyse_signature(self, env): - any_type_tests_needed = 0 - sig = self.entry.signature - nfixed = sig.num_fixed_args() - for i in range(nfixed): - if i < len(self.args): - arg = self.args[i] - arg.is_generic = 0 - if sig.is_self_arg(i): - arg.is_self_arg = 1 - arg.hdr_type = arg.type = env.parent_type - arg.needs_conversion = 0 - else: - arg.hdr_type = sig.fixed_arg_type(i) - if not arg.type.same_as(arg.hdr_type): - if arg.hdr_type.is_pyobject and arg.type.is_pyobject: - arg.needs_type_test = 1 - any_type_tests_needed = 1 - else: - arg.needs_conversion = 1 - if arg.needs_conversion: - arg.hdr_cname = Naming.arg_prefix + arg.name - else: - arg.hdr_cname = Naming.var_prefix + arg.name - else: - self.bad_signature() - return - if nfixed < len(self.args): - if not sig.has_generic_args: - self.bad_signature() - for arg in self.args: - if arg.is_generic and arg.type.is_extension_type: - arg.needs_type_test = 1 - any_type_tests_needed = 1 -# if any_type_tests_needed: -# env.use_utility_code(arg_type_test_utility_code) - - def bad_signature(self): - sig = self.entry.signature - expected_str = "%d" % sig.num_fixed_args() - if sig.has_generic_args: - expected_str = expected_str + " or more" - name = self.name - if name.startswith("__") and name.endswith("__"): - desc = "Special method" - else: - desc = "Method" - error(self.pos, - "%s %s has wrong number of arguments " - "(%d declared, %s expected)" % ( - desc, self.name, len(self.args), expected_str)) - - def declare_pyfunction(self, env): - #print "DefNode.declare_pyfunction:", self.name, "in", env ### - name = self.name - entry = env.declare_pyfunction(self.name, self.pos) - self.entry = entry - prefix = env.scope_prefix - entry.func_cname = \ - Naming.func_prefix + prefix + name - entry.pymethdef_cname = \ - Naming.pymethdef_prefix + prefix + name - if not entry.is_special: - entry.doc = self.doc - entry.doc_cname = \ - Naming.funcdoc_prefix + prefix + name - - def declare_arguments(self, env): - for arg in self.args: - if not arg.name: - error(arg.pos, "Missing argument name") - if arg.needs_conversion: - arg.entry = env.declare_var(arg.name, arg.type, arg.pos) - if arg.type.is_pyobject: - arg.entry.init = "0" - arg.entry.init_to_none = 0 - else: - arg.entry = self.declare_argument(env, arg) - arg.entry.used = 1 - arg.entry.is_self_arg = arg.is_self_arg - if arg.hdr_type: - if arg.is_self_arg or \ - (arg.type.is_extension_type and not arg.hdr_type.is_extension_type): - arg.entry.is_declared_generic = 1 - self.declare_python_arg(env, self.star_arg) - self.declare_python_arg(env, self.starstar_arg) - - def declare_python_arg(self, env, arg): - if arg: - entry = env.declare_var(arg.name, - PyrexTypes.py_object_type, arg.pos) - entry.used = 1 - entry.init = "0" - entry.init_to_none = 0 - entry.xdecref_cleanup = 1 - arg.entry = entry - - def analyse_expressions(self, env): - self.analyse_default_values(env) - if env.is_py_class_scope: - self.synthesize_assignment_node(env) - - def analyse_default_values(self, env): - for arg in self.args: - if arg.default: - if arg.is_generic: - arg.default.analyse_types(env) - arg.default = arg.default.coerce_to(arg.type, env) - arg.default.allocate_temps(env) - arg.default_entry = env.add_default_value(arg.type) - arg.default_entry.used = 1 - else: - error(arg.pos, - "This argument cannot have a default value") - arg.default = None - - def synthesize_assignment_node(self, env): - import ExprNodes - self.assmt = SingleAssignmentNode(self.pos, - lhs = ExprNodes.NameNode(self.pos, name = self.name), - rhs = ExprNodes.UnboundMethodNode(self.pos, - class_cname = env.class_obj_cname, - function = ExprNodes.PyCFunctionNode(self.pos, - pymethdef_cname = self.entry.pymethdef_cname))) - self.assmt.analyse_declarations(env) - self.assmt.analyse_expressions(env) - - def generate_function_header(self, code, with_pymethdef): - arg_code_list = [] - sig = self.entry.signature - if sig.has_dummy_arg: - arg_code_list.append( - "PyObject *%s" % Naming.self_cname) - for arg in self.args: - if not arg.is_generic: - if arg.is_self_arg: - arg_code_list.append("PyObject *%s" % arg.hdr_cname) - else: - arg_code_list.append( - arg.hdr_type.declaration_code(arg.hdr_cname)) - if sig.has_generic_args: - arg_code_list.append( - "PyObject *%s, PyObject *%s" - % (Naming.args_cname, Naming.kwds_cname)) - arg_code = ", ".join(arg_code_list) - dc = self.return_type.declaration_code(self.entry.func_cname) - header = "static %s(%s)" % (dc, arg_code) - code.putln("%s; /*proto*/" % header) - if self.entry.doc: - code.putln( - 'static char %s[] = "%s";' % ( - self.entry.doc_cname, - self.entry.doc)) - if with_pymethdef: - code.put( - "static PyMethodDef %s = " % - self.entry.pymethdef_cname) - code.put_pymethoddef(self.entry, ";") - code.putln("%s {" % header) - - 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) - - def generate_keyword_list(self, code): - if self.entry.signature.has_generic_args: - reqd_kw_flags = [] - has_reqd_kwds = False - code.put( - "static char *%s[] = {" % - Naming.kwdlist_cname) - for arg in self.args: - if arg.is_generic: - code.put( - '"%s",' % - arg.name) - if arg.kw_only and not arg.default: - has_reqd_kwds = 1 - flag = "1" - else: - flag = "0" - reqd_kw_flags.append(flag) - code.putln( - "0};") - if has_reqd_kwds: - flags_name = Naming.reqd_kwds_cname - self.reqd_kw_flags_cname = flags_name - code.putln( - "static char %s[] = {%s};" % ( - flags_name, - ",".join(reqd_kw_flags))) - - def generate_argument_parsing_code(self, code): - # Generate PyArg_ParseTuple call for generic - # arguments, if any. - has_kwonly_args = self.num_kwonly_args > 0 - has_star_or_kw_args = self.star_arg is not None \ - or self.starstar_arg is not None or has_kwonly_args - if not self.entry.signature.has_generic_args: - if has_star_or_kw_args: - error(self.pos, "This method cannot have * or keyword arguments") - else: - arg_addrs = [] - arg_formats = [] - default_seen = 0 - for arg in self.args: - arg_entry = arg.entry - if arg.is_generic: - if arg.default: - code.putln( - "%s = %s;" % ( - arg_entry.cname, - arg.default_entry.cname)) - if not default_seen: - arg_formats.append("|") - default_seen = 1 - elif default_seen and not arg.kw_only: - error(arg.pos, "Non-default argument following default argument") - arg_addrs.append("&" + arg_entry.cname) - format = arg_entry.type.parsetuple_format - if format: - arg_formats.append(format) - else: - error(arg.pos, - "Cannot convert Python object argument to type '%s'" - % arg.type) - error_return_code = "return %s;" % self.error_value() - argformat = '"%s"' % string.join(arg_formats, "") - if has_star_or_kw_args: - self.generate_stararg_getting_code(code) - pt_arglist = [Naming.args_cname, Naming.kwds_cname, argformat, - Naming.kwdlist_cname] + arg_addrs - pt_argstring = string.join(pt_arglist, ", ") - code.put( - 'if (!PyArg_ParseTupleAndKeywords(%s)) ' % - pt_argstring) - if has_star_or_kw_args: - code.putln("{") - code.put_xdecref(Naming.args_cname, py_object_type) - code.put_xdecref(Naming.kwds_cname, py_object_type) - self.generate_arg_xdecref(self.star_arg, code) - self.generate_arg_xdecref(self.starstar_arg, code) - code.putln(error_return_code) - code.putln("}") - else: - code.putln(error_return_code) - - def put_stararg_decrefs(self, code): - if self.has_star_or_kwonly_args: - code.put_xdecref(Naming.args_cname, py_object_type) - code.put_xdecref(Naming.kwds_cname, py_object_type) - - def generate_arg_xdecref(self, arg, code): - if arg: - code.put_var_xdecref(arg.entry) - - def arg_address(self, arg): - if arg: - return "&%s" % arg.entry.cname - else: - return 0 - - def generate_stararg_getting_code(self, code): - num_kwonly = self.num_kwonly_args - nargs = len(self.args) - num_kwonly - self.entry.signature.num_fixed_args() - star_arg_addr = self.arg_address(self.star_arg) - starstar_arg_addr = self.arg_address(self.starstar_arg) - code.use_utility_code(get_starargs_utility_code) - code.putln( - "if (__Pyx_GetStarArgs(&%s, &%s, %s, %s, %s, %s, %s) < 0) return %s;" % ( - Naming.args_cname, - Naming.kwds_cname, - Naming.kwdlist_cname, - nargs, - star_arg_addr, - starstar_arg_addr, - self.reqd_kw_flags_cname, - self.error_value())) - - def generate_argument_conversion_code(self, code): - # Generate code to convert arguments from - # signature type to declared type, if needed. - for arg in self.args: - if arg.needs_conversion: - self.generate_arg_conversion(arg, code) - - def generate_arg_conversion(self, arg, code): - # Generate conversion code for one argument. - old_type = arg.hdr_type - new_type = arg.type - if old_type.is_pyobject: - self.generate_arg_conversion_from_pyobject(arg, code) - elif new_type.is_pyobject: - self.generate_arg_conversion_to_pyobject(arg, code) - else: - if new_type.assignable_from(old_type): - code.putln( - "%s = %s;" % (arg.entry.cname, arg.hdr_cname)) - else: - error(arg.pos, - "Cannot convert argument from '%s' to '%s'" % - (old_type, new_type)) - - def generate_arg_conversion_from_pyobject(self, arg, code): - new_type = arg.type - func = new_type.from_py_function - if func: - code.putln("%s = %s(%s); if (PyErr_Occurred()) %s" % ( - arg.entry.cname, - func, - arg.hdr_cname, - code.error_goto(arg.pos))) - else: - error(arg.pos, - "Cannot convert Python object argument to type '%s'" - % new_type) - - def generate_arg_conversion_to_pyobject(self, arg, code): - old_type = arg.hdr_type - func = old_type.to_py_function - if func: - code.putln("%s = %s(%s); if (!%s) %s" % ( - arg.entry.cname, - func, - arg.hdr_cname, - arg.entry.cname, - code.error_goto(arg.pos))) - else: - error(arg.pos, - "Cannot convert argument of type '%s' to Python object" - % old_type) - - def generate_argument_type_tests(self, code): - # Generate type tests for args whose signature - # type is PyObject * and whose declared type is - # a subtype thereof. - for arg in self.args: - if arg.needs_type_test: - self.generate_arg_type_test(arg, code) - - def generate_arg_type_test(self, arg, code): - # Generate type test for one argument. - if arg.type.typeobj_is_available(): - typeptr_cname = arg.type.typeptr_cname - arg_code = "((PyObject *)%s)" % arg.entry.cname - code.use_utility_code(arg_type_test_utility_code) - code.putln( - 'if (!__Pyx_ArgTypeTest(%s, %s, %d, "%s")) %s' % ( - arg_code, - typeptr_cname, - #not arg.not_none, - arg.allow_none <> False, - arg.name, - code.error_goto(arg.pos))) - if arg.allow_none is None: - one_time_warning(arg.pos, 'or_none', - "'not None' will become the default in a future version of Pyrex. " - "Use 'or None' to allow passing None.") - else: - error(arg.pos, "Cannot test type of extern C class " - "without type object name specification") - - def generate_execution_code(self, code): - # Evaluate and store argument default values - for arg in self.args: - default = arg.default - if default: - default.generate_evaluation_code(code) - default.make_owned_reference(code) - code.putln( - "%s = %s;" % ( - arg.default_entry.cname, - default.result_as(arg.default_entry.type))) - default.generate_post_assignment_code(code) -# if default.is_temp and default.type.is_pyobject: -# code.putln( -# "%s = 0;" % -# default.result()) - # For Python class methods, create and store function object - if self.assmt: - self.assmt.generate_execution_code(code) - - def error_value(self): - return self.entry.signature.error_value - - def caller_will_check_exceptions(self): - return 1 - - -class PyClassDefNode(StatNode, BlockNode): - # A Python class definition. - # - # name string Name of the class - # doc string or None - # body StatNode Attribute definition code - # entry Symtab.Entry - # scope PyClassScope - # - # The following subnodes are constructed internally: - # - # dict DictNode Class dictionary - # classobj ClassNode Class object - # target NameNode Variable to assign class object to - - def __init__(self, pos, name, bases, doc, body): - StatNode.__init__(self, pos) - self.name = name - self.doc = doc - self.body = body - import ExprNodes - self.dict = ExprNodes.DictNode(pos, key_value_pairs = []) - if self.doc: - doc_node = ExprNodes.StringNode(pos, value = self.doc) - else: - doc_node = None - self.classobj = ExprNodes.ClassNode(pos, - name = ExprNodes.StringNode(pos, value = name), - bases = bases, dict = self.dict, doc = doc_node) - self.target = ExprNodes.NameNode(pos, name = name) - - def analyse_declarations(self, env): - self.target.analyse_target_declaration(env) - - def analyse_expressions(self, env): - self.dict.analyse_expressions(env) - self.classobj.analyse_expressions(env) - genv = env.global_scope() - cenv = PyClassScope(name = self.name, outer_scope = genv) - cenv.class_dict_cname = self.dict.result() - cenv.class_obj_cname = self.classobj.result() - self.scope = cenv - self.body.analyse_declarations(cenv) - self.body.analyse_expressions(cenv) - self.target.analyse_target_expression(env, self.classobj) - self.dict.release_temp(env) - #self.classobj.release_temp(env) - #self.target.release_target_temp(env) - - def generate_function_definitions(self, env, code): - #self.generate_py_string_decls(self.scope, code) - self.body.generate_function_definitions( - self.scope, code) - - def generate_execution_code(self, code): - self.dict.generate_evaluation_code(code) - self.classobj.generate_evaluation_code(code) - self.body.generate_execution_code(code) - self.target.generate_assignment_code(self.classobj, code) - self.dict.generate_disposal_code(code) - - -class CClassDefNode(StatNode): - # An extension type definition. - # - # visibility 'private' or 'public' or 'extern' - # typedef_flag boolean - # api boolean - # module_name string or None For import of extern type objects - # class_name string Unqualified name of class - # as_name string or None Name to declare as in this scope - # base_class_module string or None Module containing the base class - # base_class_name string or None Name of the base class - # options CClassOptions: - # objstruct_name string or None Specified C name of object struct - # typeobj_name string or None Specified C name of type object - # no_gc boolean Suppress GC support - # in_pxd boolean Is in a .pxd file - # doc string or None - # body StatNode or None - # entry Symtab.Entry - # base_type PyExtensionType or None - - entry = None - - def analyse_declarations(self, env): - #print "CClassDefNode.analyse_declarations:", self.class_name - #print "...visibility =", self.visibility - #print "...module_name =", self.module_name - if env.in_cinclude and not self.options.objstruct_cname: - error(self.pos, "Object struct name specification required for " - "C class defined in 'extern from' block") - self.base_type = None - has_body = self.body is not None - if self.base_class_name: - if self.base_class_module: - base_class_scope = env.find_module(self.base_class_module, self.pos) - else: - base_class_scope = env - if base_class_scope: - base_class_entry = base_class_scope.find(self.base_class_name, self.pos) - if base_class_entry: - if not base_class_entry.is_type: - error(self.pos, "'%s' is not a type name" % self.base_class_name) - elif not base_class_entry.type.is_extension_type: - error(self.pos, "'%s' is not an extension type" % self.base_class_name) - elif has_body and base_class_entry.visibility <> 'extern' and not base_class_entry.type.is_defined(): - error(self.pos, "Base class '%s' is incomplete" % self.base_class_name) - else: - self.base_type = base_class_entry.type - if self.module_name and self.visibility <> 'extern': - module_path = self.module_name.split(".") - home_scope = env.find_imported_module(module_path, self.pos) - if not home_scope: - return - else: - home_scope = env - self.entry = home_scope.declare_c_class( - name = self.class_name, - pos = self.pos, - defining = has_body and self.in_pxd, - implementing = has_body and not self.in_pxd, - module_name = self.module_name, - base_type = self.base_type, - visibility = self.visibility, - typedef_flag = self.typedef_flag, - api = self.api, - options = self.options) - if home_scope is not env and self.visibility == 'extern': - env.add_imported_entry(self.class_name, self.entry, pos) - scope = self.entry.type.scope - if self.doc: - scope.doc = self.doc - if has_body: - self.body.analyse_declarations(scope) - if self.in_pxd: - scope.defined = 1 - else: - scope.implemented = 1 - env.allocate_vtable_names(self.entry) - - def analyse_expressions(self, env): - if self.body: - self.body.analyse_expressions(env) - - def generate_function_definitions(self, env, code): - if self.entry and self.body: -# self.body.generate_function_definitions( -# self.entry.type.scope, code) - self.body.generate_function_definitions(env, code) - - def generate_execution_code(self, code): - # This is needed to generate evaluation code for - # default values of method arguments. - if self.body: - self.body.generate_execution_code(code) - - -class PropertyNode(StatNode): - # Definition of a property in an extension type. - # - # name string - # doc string or None Doc string - # body StatListNode - - def analyse_declarations(self, env): - #print "PropertyNode.analyse_declarations:", env ### - entry = env.declare_property(self.name, self.doc, self.pos) - if entry: - #if self.doc: - # doc_entry = env.get_string_const(self.doc) - # entry.doc_cname = doc_entry.cname - self.body.analyse_declarations(entry.scope) - - def analyse_expressions(self, env): - self.body.analyse_expressions(env) - - def generate_function_definitions(self, env, code): - self.body.generate_function_definitions(env, code) - - def generate_execution_code(self, code): - pass - - -class GlobalNode(StatNode): - # Global variable declaration. - # - # names [string] - - def analyse_declarations(self, env): - for name in self.names: - env.declare_global(name, self.pos) - - def analyse_expressions(self, env): - pass - - def generate_execution_code(self, code): - pass - - -class ExprStatNode(StatNode): - # Expression used as a statement. - # - # expr ExprNode - - def analyse_expressions(self, env): - self.expr.analyse_expressions(env) - self.expr.release_temp(env) - - def generate_execution_code(self, code): - self.expr.generate_evaluation_code(code) - if not self.expr.is_temp and self.expr.result(): - code.putln("%s;" % self.expr.result()) - self.expr.generate_disposal_code(code) - - -class AssignmentNode(StatNode): - # Abstract base class for assignment nodes. - # - # The analyse_expressions and generate_execution_code - # phases of assignments are split into two sub-phases - # each, to enable all the right hand sides of a - # parallel assignment to be evaluated before assigning - # to any of the left hand sides. - - def analyse_expressions(self, env): - self.analyse_types(env) - self.allocate_rhs_temps(env) - self.allocate_lhs_temps(env) - - def generate_execution_code(self, code): - self.generate_rhs_evaluation_code(code) - self.generate_assignment_code(code) - - -class SingleAssignmentNode(AssignmentNode): - # The simplest case: - # - # a = b - # - # lhs ExprNode Left hand side - # rhs ExprNode Right hand side - - def analyse_declarations(self, env): - self.lhs.analyse_target_declaration(env) - - def analyse_types(self, env, use_temp = 0): - self.rhs.analyse_types(env) - self.lhs.analyse_target_types(env) - self.lhs.gil_assignment_check(env) - self.rhs = self.rhs.coerce_to(self.lhs.type, env) - if use_temp: - self.rhs = self.rhs.coerce_to_temp(env) - - def allocate_rhs_temps(self, env): - self.rhs.allocate_temps(env) - - def allocate_lhs_temps(self, env): - self.lhs.allocate_target_temps(env, self.rhs) - - def generate_rhs_evaluation_code(self, code): - self.rhs.generate_evaluation_code(code) - - def generate_assignment_code(self, code): - self.lhs.generate_assignment_code(self.rhs, code) - - -class AugmentedAssignmentNode(SingleAssignmentNode): - # An in-place operation: - # - # a op= b - # - # lhs ExprNode Left hand side - # operator string - # rhs ExprNode Right hand side - - def analyse_types(self, env): - op = self.operator - self.rhs.analyse_types(env) - self.lhs.analyse_inplace_types(env) - type = self.lhs.type - if type.is_pyobject: - type = py_object_type - else: - if type.is_ptr and (op == '+=' or op == '-='): - type = c_int_type - elif op == "**=": - error(self.pos, "**= operator not supported for non-Python types") - return - self.rhs = self.rhs.coerce_to(type, env) - - def allocate_lhs_temps(self, env): - self.lhs.allocate_inplace_target_temps(env, self.rhs) - - def generate_assignment_code(self, code): - self.lhs.generate_inplace_assignment_code(self.operator, self.rhs, code) - - -class CascadedAssignmentNode(AssignmentNode): - # An assignment with multiple left hand sides: - # - # a = b = c - # - # lhs_list [ExprNode] Left hand sides - # rhs ExprNode Right hand sides - # - # Used internally: - # - # coerced_rhs_list [ExprNode] RHS coerced to type of each LHS - - def analyse_declarations(self, env): - for lhs in self.lhs_list: - lhs.analyse_target_declaration(env) - - def analyse_types(self, env, use_temp = 0): - self.rhs.analyse_types(env) - if use_temp: - self.rhs = self.rhs.coerce_to_temp(env) - else: - self.rhs = self.rhs.coerce_to_simple(env) - from ExprNodes import CloneNode - self.coerced_rhs_list = [] - for lhs in self.lhs_list: - lhs.analyse_target_types(env) - lhs.gil_assignment_check(env) - rhs = CloneNode(self.rhs) - rhs = rhs.coerce_to(lhs.type, env) - self.coerced_rhs_list.append(rhs) - - def allocate_rhs_temps(self, env): - self.rhs.allocate_temps(env) - - def allocate_lhs_temps(self, env): - for lhs, rhs in zip(self.lhs_list, self.coerced_rhs_list): - rhs.allocate_temps(env) - lhs.allocate_target_temps(env, rhs) - #lhs.release_target_temp(env) - #rhs.release_temp(env) - self.rhs.release_temp(env) - - def generate_rhs_evaluation_code(self, code): - self.rhs.generate_evaluation_code(code) - - def generate_assignment_code(self, code): - for i in range(len(self.lhs_list)): - lhs = self.lhs_list[i] - rhs = self.coerced_rhs_list[i] - rhs.generate_evaluation_code(code) - lhs.generate_assignment_code(rhs, code) - # Assignment has disposed of the cloned RHS - self.rhs.generate_disposal_code(code) - -class ParallelAssignmentNode(AssignmentNode): - # A combined packing/unpacking assignment: - # - # a, b, c = d, e, f - # - # This has been rearranged by the parser into - # - # a = d ; b = e ; c = f - # - # but we must evaluate all the right hand sides - # before assigning to any of the left hand sides. - # - # stats [AssignmentNode] The constituent assignments - - def analyse_declarations(self, env): - for stat in self.stats: - stat.analyse_declarations(env) - - def analyse_expressions(self, env): - for stat in self.stats: - stat.analyse_types(env, use_temp = 1) - stat.allocate_rhs_temps(env) - for stat in self.stats: - stat.allocate_lhs_temps(env) - - def generate_execution_code(self, code): - for stat in self.stats: - stat.generate_rhs_evaluation_code(code) - for stat in self.stats: - stat.generate_assignment_code(code) - - -class PrintStatNode(StatNode): - # print statement - # - # args [ExprNode] - # ends_with_comma boolean - - def analyse_expressions(self, env): - for i in range(len(self.args)): - arg = self.args[i] - arg.analyse_types(env) - arg = arg.coerce_to_pyobject(env) - arg.allocate_temps(env) - arg.release_temp(env) - self.args[i] = arg -# env.use_utility_code(printing_utility_code) - self.gil_check(env) - - gil_message = "Python print statement" - - def generate_execution_code(self, code): - for arg in self.args: - arg.generate_evaluation_code(code) - code.use_utility_code(printing_utility_code) - code.putln( - "if (__Pyx_PrintItem(%s) < 0) %s" % ( - arg.py_result(), - code.error_goto(self.pos))) - arg.generate_disposal_code(code) - if not self.ends_with_comma: - code.use_utility_code(printing_utility_code) - code.putln( - "if (__Pyx_PrintNewline() < 0) %s" % - code.error_goto(self.pos)) - - -class DelStatNode(StatNode): - # del statement - # - # args [ExprNode] - - def analyse_declarations(self, env): - for arg in self.args: - arg.analyse_target_declaration(env) - - def analyse_expressions(self, env): - for arg in self.args: - arg.analyse_target_expression(env, None) - type = arg.type - if not (type.is_pyobject - or (type.is_ptr and type.base_type.is_struct_or_union - and type.base_type.scope.is_cplus)): - error(arg.pos, "'del' can only be applied to Python object or pointer to C++ type") - if type.is_pyobject: - self.gil_check(env) - - gil_message = "Deleting Python object" - - def generate_execution_code(self, code): - for arg in self.args: - if arg.type.is_pyobject: - arg.generate_deletion_code(code) - else: - arg.generate_evaluation_code(code) - code.putln("delete %s;" % arg.result()) - arg.generate_disposal_code(code) - - -class PassStatNode(StatNode): - # pass statement - - def analyse_expressions(self, env): - pass - - def generate_execution_code(self, code): - pass - - -class BreakStatNode(StatNode): - - def analyse_expressions(self, env): - pass - - def generate_execution_code(self, code): - if not code.break_label: - error(self.pos, "break statement not inside loop") - else: - #code.putln( - # "goto %s;" % - # code.break_label) - code.put_goto(code.break_label) - - -class ContinueStatNode(StatNode): - - def analyse_expressions(self, env): - pass - - def generate_execution_code(self, code): - if code.in_try_finally: - error(self.pos, "continue statement inside try of try...finally") - elif not code.continue_label: - error(self.pos, "continue statement not inside loop") - else: - #code.putln( - # "goto %s;" % - # code.continue_label) - code.put_goto(code.continue_label) - - -class ReturnStatNode(StatNode): - # return statement - # - # value ExprNode or None - # return_type PyrexType - # temps_in_use [Entry] Temps in use at time of return - - def analyse_expressions(self, env): - return_type = env.return_type - self.return_type = return_type - self.temps_in_use = env.temps_in_use() - if not return_type: - error(self.pos, "Return not inside a function body") - return - if self.value: - self.value.analyse_types(env) - if return_type.is_void or return_type.is_returncode: - error(self.value.pos, - "Return with value in void function") - else: - self.value = self.value.coerce_to(env.return_type, env) - self.value.allocate_temps(env) - self.value.release_temp(env) - else: - if (not return_type.is_void - and not return_type.is_pyobject - and not return_type.is_returncode): - error(self.pos, "Return value required") - if return_type.is_pyobject: - self.gil_check(env) - - gil_message = "Returning Python object" - - def generate_execution_code(self, code): - if not self.return_type: - # error reported earlier - return - if self.value: - self.value.generate_evaluation_code(code) - self.value.make_owned_reference(code) - code.putln( - "%s = %s;" % ( - Naming.retval_cname, - self.value.result_as(self.return_type))) - self.value.generate_post_assignment_code(code) - else: - if self.return_type.is_pyobject: - code.put_init_to_py_none(Naming.retval_cname, self.return_type) - elif self.return_type.is_returncode: - code.putln( - "%s = %s;" % ( - Naming.retval_cname, - self.return_type.default_value)) - for entry in self.temps_in_use: - code.put_var_decref_clear(entry) - #code.putln( - # "goto %s;" % - # code.return_label) - code.put_goto(code.return_label) - - -class RaiseStatNode(StatNode): - # raise statement - # - # exc_type ExprNode or None - # exc_value ExprNode or None - # exc_tb ExprNode or None - - def analyse_expressions(self, env): - if self.exc_type: - self.exc_type.analyse_types(env) - self.exc_type = self.exc_type.coerce_to_pyobject(env) - self.exc_type.allocate_temps(env) - if self.exc_value: - self.exc_value.analyse_types(env) - self.exc_value = self.exc_value.coerce_to_pyobject(env) - self.exc_value.allocate_temps(env) - if self.exc_tb: - self.exc_tb.analyse_types(env) - self.exc_tb = self.exc_tb.coerce_to_pyobject(env) - self.exc_tb.allocate_temps(env) - if self.exc_type: - self.exc_type.release_temp(env) - if self.exc_value: - self.exc_value.release_temp(env) - if self.exc_tb: - self.exc_tb.release_temp(env) - self.gil_check(env) - - gil_message = "Raising exception" - - def generate_execution_code(self, code): - if self.exc_type: - self.exc_type.generate_evaluation_code(code) - type_code = self.exc_type.py_result() - else: - type_code = 0 - if self.exc_value: - self.exc_value.generate_evaluation_code(code) - value_code = self.exc_value.py_result() - else: - value_code = "0" - if self.exc_tb: - self.exc_tb.generate_evaluation_code(code) - tb_code = self.exc_tb.py_result() - else: - tb_code = "0" - code.use_utility_code(raise_utility_code) - code.putln( - "__Pyx_Raise(%s, %s, %s);" % ( - type_code, - value_code, - tb_code)) - if self.exc_type: - self.exc_type.generate_disposal_code(code) - if self.exc_value: - self.exc_value.generate_disposal_code(code) - if self.exc_tb: - self.exc_tb.generate_disposal_code(code) - code.putln( - code.error_goto(self.pos)) - - -class ReraiseStatNode(StatNode): - - def analyse_expressions(self, env): - env.reraise_used = 1 - self.gil_check(env) - - gil_message = "Raising exception" - - def generate_execution_code(self, code): - vars = code.exc_vars - if vars: - tvars = tuple(vars) - code.putln("PyErr_Restore(%s, %s, %s);" % tvars) - code.putln("%s = %s = %s = 0;" % tvars) - code.putln(code.error_goto(self.pos)) - else: - error(self.pos, "Reraise not inside except clause") - - -class AssertStatNode(StatNode): - # assert statement - # - # cond ExprNode - # value ExprNode or None - - def analyse_expressions(self, env): - self.cond = self.cond.analyse_boolean_expression(env) - if self.value: - self.value.analyse_types(env) - self.value = self.value.coerce_to_pyobject(env) - self.value.allocate_temps(env) - self.cond.release_temp(env) - if self.value: - self.value.release_temp(env) - self.gil_check(env) - - gil_message = "Raising exception" - - def generate_execution_code(self, code): - code.putln("#ifndef PYREX_WITHOUT_ASSERTIONS") - self.cond.generate_evaluation_code(code) - code.putln( - "if (!%s) {" % - self.cond.result()) - if self.value: - self.value.generate_evaluation_code(code) - if self.value: - code.putln( - "PyErr_SetObject(PyExc_AssertionError, %s);" % - self.value.py_result()) - else: - code.putln( - "PyErr_SetNone(PyExc_AssertionError);") - code.putln( - code.error_goto(self.pos)) - code.putln( - "}") - self.cond.generate_disposal_code(code) - # Disposal code for value not needed because exception always raised - #if self.value: - # self.value.generate_disposal_code(code) - code.putln("#endif") - -class IfStatNode(StatNode): - # if statement - # - # if_clauses [IfClauseNode] - # else_clause StatNode or None - - def analyse_declarations(self, env): - for if_clause in self.if_clauses: - if_clause.analyse_declarations(env) - if self.else_clause: - self.else_clause.analyse_declarations(env) - - def analyse_expressions(self, env): - for if_clause in self.if_clauses: - if_clause.analyse_expressions(env) - if self.else_clause: - self.else_clause.analyse_expressions(env) - - def generate_execution_code(self, code): - end_label = code.new_label() - for if_clause in self.if_clauses: - if_clause.generate_execution_code(code, end_label) - if self.else_clause: - code.putln("/*else*/ {") - self.else_clause.generate_execution_code(code) - code.putln("}") - code.put_label(end_label) - - -class IfClauseNode(Node): - # if or elif clause in an if statement - # - # condition ExprNode - # body StatNode - - def analyse_declarations(self, env): - self.condition.analyse_declarations(env) - self.body.analyse_declarations(env) - - def analyse_expressions(self, env): - self.condition = \ - self.condition.analyse_temp_boolean_expression(env) - self.condition.release_temp(env) - self.body.analyse_expressions(env) - - def generate_execution_code(self, code, end_label): - self.condition.generate_evaluation_code(code) - code.putln( - "if (%s) {" % - self.condition.result()) - self.body.generate_execution_code(code) - #code.putln( - # "goto %s;" % - # end_label) - code.put_goto(end_label) - code.putln("}") - - -class WhileStatNode(StatNode): - # while statement - # - # condition ExprNode - # body StatNode - # else_clause StatNode - - def analyse_declarations(self, env): - self.body.analyse_declarations(env) - if self.else_clause: - self.else_clause.analyse_declarations(env) - - def analyse_expressions(self, env): - self.condition = \ - self.condition.analyse_temp_boolean_expression(env) - self.condition.release_temp(env) - #env.recycle_pending_temps() # TEMPORARY - self.body.analyse_expressions(env) - if self.else_clause: - self.else_clause.analyse_expressions(env) - - def generate_execution_code(self, code): - old_loop_labels = code.new_loop_labels() - code.putln( - "while (1) {") - self.condition.generate_evaluation_code(code) - code.putln( - "if (!%s) break;" % - self.condition.result()) - self.body.generate_execution_code(code) - code.put_label(code.continue_label) - code.putln("}") - break_label = code.break_label - code.set_loop_labels(old_loop_labels) - if self.else_clause: - code.putln("/*else*/ {") - self.else_clause.generate_execution_code(code) - code.putln("}") - code.put_label(break_label) - - -class ForInStatNode(StatNode): - # for statement - # - # target ExprNode - # iterator IteratorNode - # body StatNode - # else_clause StatNode - # item NextNode used internally - - def analyse_declarations(self, env): - self.target.analyse_target_declaration(env) - self.body.analyse_declarations(env) - if self.else_clause: - self.else_clause.analyse_declarations(env) - - def analyse_expressions(self, env): - import ExprNodes - self.iterator.analyse_expressions(env) - self.target.analyse_target_types(env) - self.item = ExprNodes.NextNode(self.iterator, env) - self.item = self.item.coerce_to(self.target.type, env) - self.item.allocate_temps(env) - self.target.allocate_target_temps(env, self.item) - #self.item.release_temp(env) - #self.target.release_target_temp(env) - self.body.analyse_expressions(env) - if self.else_clause: - self.else_clause.analyse_expressions(env) - self.iterator.release_temp(env) - - def generate_execution_code(self, code): - old_loop_labels = code.new_loop_labels() - self.iterator.generate_evaluation_code(code) - code.putln( - "for (;;) {") - self.item.generate_evaluation_code(code) - self.target.generate_assignment_code(self.item, code) - self.body.generate_execution_code(code) - code.put_label(code.continue_label) - code.putln( - "}") - break_label = code.break_label - code.set_loop_labels(old_loop_labels) - if self.else_clause: - code.putln("/*else*/ {") - self.else_clause.generate_execution_code(code) - code.putln("}") - code.put_label(break_label) - self.iterator.generate_disposal_code(code) - - -class IntegerForStatNode(StatNode): - # for expr rel name rel expr - # - # bound1 ExprNode - # relation1 string - # target NameNode - # relation2 string - # bound2 ExprNode - # body StatNode - # else_clause StatNode or None - # - # Used internally: - # - # is_py_target bool - # loopvar_name string - # py_loopvar_node PyTempNode or None - - def analyse_declarations(self, env): - self.target.analyse_target_declaration(env) - self.body.analyse_declarations(env) - if self.else_clause: - self.else_clause.analyse_declarations(env) - - def analyse_expressions(self, env): - import ExprNodes - self.target.analyse_target_types(env) - self.bound1.analyse_types(env) - self.bound2.analyse_types(env) - self.bound1 = self.bound1.coerce_to_integer(env) - self.bound2 = self.bound2.coerce_to_integer(env) - if not (self.bound2.is_name or self.bound2.is_literal): - self.bound2 = self.bound2.coerce_to_temp(env) - target_type = self.target.type - if not (target_type.is_pyobject or target_type.is_int): - error(self.target.pos, - "Integer for-loop variable must be of type int or Python object") - #if not (target_type.is_pyobject - # or target_type.assignable_from(PyrexTypes.c_int_type)): - # error(self.target.pos, - # "Cannot assign integer to variable of type '%s'" % target_type) - if target_type.is_int: - self.is_py_target = 0 - self.loopvar_name = self.target.entry.cname - self.py_loopvar_node = None - else: - self.is_py_target = 1 - c_loopvar_node = ExprNodes.TempNode(self.pos, - PyrexTypes.c_long_type, env) - c_loopvar_node.allocate_temps(env) - self.loopvar_name = c_loopvar_node.result() - self.py_loopvar_node = \ - ExprNodes.CloneNode(c_loopvar_node).coerce_to_pyobject(env) - self.bound1.allocate_temps(env) - self.bound2.allocate_temps(env) - if self.is_py_target: - self.py_loopvar_node.allocate_temps(env) - self.target.allocate_target_temps(env, self.py_loopvar_node) - #self.target.release_target_temp(env) - #self.py_loopvar_node.release_temp(env) - self.body.analyse_expressions(env) - if self.is_py_target: - c_loopvar_node.release_temp(env) - if self.else_clause: - self.else_clause.analyse_expressions(env) - self.bound1.release_temp(env) - self.bound2.release_temp(env) - - def generate_execution_code(self, code): - old_loop_labels = code.new_loop_labels() - self.bound1.generate_evaluation_code(code) - self.bound2.generate_evaluation_code(code) - offset, incop = self.relation_table[self.relation1] - code.putln( - "for (%s = %s%s; %s %s %s; %s%s) {" % ( - self.loopvar_name, - self.bound1.result(), offset, - self.loopvar_name, self.relation2, self.bound2.result(), - incop, self.loopvar_name)) - if self.py_loopvar_node: - self.py_loopvar_node.generate_evaluation_code(code) - self.target.generate_assignment_code(self.py_loopvar_node, code) - self.body.generate_execution_code(code) - code.put_label(code.continue_label) - code.putln("}") - break_label = code.break_label - code.set_loop_labels(old_loop_labels) - if self.else_clause: - code.putln("/*else*/ {") - self.else_clause.generate_execution_code(code) - code.putln("}") - code.put_label(break_label) - self.bound1.generate_disposal_code(code) - self.bound2.generate_disposal_code(code) - - relation_table = { - # {relop : (initial offset, increment op)} - '<=': ("", "++"), - '<' : ("+1", "++"), - '>=': ("", "--"), - '>' : ("-1", "--") - } - - -class TryExceptStatNode(StatNode): - # try .. except statement - # - # body StatNode - # except_clauses [ExceptClauseNode] - # else_clause StatNode or None - # cleanup_list [Entry] temps to clean up on error - - def analyse_declarations(self, env): - self.body.analyse_declarations(env) - for except_clause in self.except_clauses: - except_clause.analyse_declarations(env) - if self.else_clause: - self.else_clause.analyse_declarations(env) - self.gil_check(env) - - def analyse_expressions(self, env): - self.body.analyse_expressions(env) - self.cleanup_list = env.free_temp_entries[:] - for except_clause in self.except_clauses: - except_clause.analyse_expressions(env) - if self.else_clause: - self.else_clause.analyse_expressions(env) - self.gil_check(env) - - gil_message = "Try-except statement" - - def generate_execution_code(self, code): - old_error_label = code.new_error_label() - our_error_label = code.error_label - end_label = code.new_label() - code.putln( - "/*try:*/ {") - self.body.generate_execution_code(code) - code.putln( - "}") - code.error_label = old_error_label - if self.else_clause: - code.putln( - "/*else:*/ {") - self.else_clause.generate_execution_code(code) - code.putln( - "}") - code.put_goto(end_label) - code.put_label(our_error_label) - code.put_var_xdecrefs_clear(self.cleanup_list) - default_clause_seen = 0 - for except_clause in self.except_clauses: - if not except_clause.pattern: - default_clause_seen = 1 - else: - if default_clause_seen: - error(except_clause.pos, "Default except clause not last") - except_clause.generate_handling_code(code, end_label) - if not default_clause_seen: - code.put_goto(code.error_label) - code.put_label(end_label) - - -class ExceptClauseNode(Node): - # Part of try ... except statement. - # - # pattern ExprNode - # exc_target ExprNode or None - # tb_target ExprNode or None - # body StatNode - # match_flag string result of exception match - # exc_value ExcValueNode used internally - # tb_value ExcValueNode used internally - # function_name string qualified name of enclosing function - # exc_vars (string * 3) local exception variables - # reraise_used boolean body contains reraise statement - - def analyse_declarations(self, env): - if self.exc_target: - self.exc_target.analyse_target_declaration(env) - if self.tb_target: - self.tb_target.analyse_target_declaration(env) - self.body.analyse_declarations(env) - - def analyse_expressions(self, env): - genv = env.global_scope() - self.function_name = env.qualified_name - if self.pattern: - self.pattern.analyse_expressions(env) - self.pattern = self.pattern.coerce_to_pyobject(env) - self.match_flag = env.allocate_temp(PyrexTypes.c_int_type) - self.pattern.release_temp(env) - env.release_temp(self.match_flag) - self.exc_vars = [env.allocate_temp(py_object_type) for i in xrange(3)] - self.exc_value = self.analyse_target(env, self.exc_target, 1) - self.tb_value = self.analyse_target(env, self.tb_target, 2) - old_reraise_used = env.reraise_used - env.reraise_used = False - self.body.analyse_expressions(env) - self.reraise_used = env.reraise_used - env.reraise_used = old_reraise_used - for var in self.exc_vars: - env.release_temp(var) - - def analyse_target(self, env, target, var_no): - if target: - import ExprNodes - value = ExprNodes.ExcValueNode(self.pos, env, self.exc_vars[var_no]) - value.allocate_temps(env) - target.analyse_target_expression(env, value) - return value - - def generate_handling_code(self, code, end_label): - code.mark_pos(self.pos) - if self.pattern: - self.pattern.generate_evaluation_code(code) - code.putln( - "%s = PyErr_ExceptionMatches(%s);" % ( - self.match_flag, - self.pattern.py_result())) - self.pattern.generate_disposal_code(code) - code.putln( - "if (%s) {" % - self.match_flag) - else: - code.putln( - "/*except:*/ {") - any_bindings = self.exc_target or self.tb_target - exc_vars_used = any_bindings or self.reraise_used - if exc_vars_used: - if any_bindings: - code.putln( - '%s; __Pyx_AddTraceback("%s");' % ( - code.error_setup(self.pos), - self.function_name)) - exc_args = "&%s, &%s, &%s" % tuple(self.exc_vars) - code.putln("PyErr_Fetch(%s);" % exc_args) - if any_bindings: - code.use_utility_code(normalize_exception_utility_code) - code.putln("if (__Pyx_NormalizeException(%s) < 0) %s" % (exc_args, - code.error_goto(self.pos))) - if self.exc_target: - self.exc_value.generate_evaluation_code(code) - self.exc_target.generate_assignment_code(self.exc_value, code) - if self.tb_target: - self.tb_value.generate_evaluation_code(code) - self.tb_target.generate_assignment_code(self.tb_value, code) - old_exc_vars = code.exc_vars - code.exc_vars = self.exc_vars - self.body.generate_execution_code(code) - code.exc_vars = old_exc_vars - if exc_vars_used: - for var in self.exc_vars: - code.putln("Py_XDECREF(%s); %s = 0;" % (var, var)) - code.put_goto(end_label) - code.putln( - "}") - - -class TryFinallyStatNode(StatNode): - # try ... finally statement - # - # body StatNode - # finally_clause StatNode - # - # cleanup_list [Entry] temps to clean up on error - # - # The plan is that we funnel all continue, break - # return and error gotos into the beginning of the - # finally block, setting a variable to remember which - # one we're doing. At the end of the finally block, we - # switch on the variable to figure out where to go. - # In addition, if we're doing an error, we save the - # exception on entry to the finally block and restore - # it on exit. - - preserve_exception = 1 - - disallow_continue_in_try_finally = 0 - # There doesn't seem to be any point in disallowing - # continue in the try block, since we have no problem - # handling it. - - def analyse_declarations(self, env): - self.body.analyse_declarations(env) - self.finally_clause.analyse_declarations(env) - - def analyse_expressions(self, env): - self.body.analyse_expressions(env) - self.cleanup_list = env.free_temp_entries[:] - self.finally_clause.analyse_expressions(env) - self.gil_check(env) - - gil_message = "Try-finally statement" - - def generate_execution_code(self, code): - old_error_label = code.error_label - old_labels = code.all_new_labels() - new_labels = code.get_all_labels() - new_error_label = code.error_label - catch_label = code.new_label() - code.putln( - "/*try:*/ {") - if self.disallow_continue_in_try_finally: - was_in_try_finally = code.in_try_finally - code.in_try_finally = 1 - self.body.generate_execution_code(code) - if self.disallow_continue_in_try_finally: - code.in_try_finally = was_in_try_finally - code.putln( - "}") - code.putln( - "/*finally:*/ {") - cases_used = [] - error_label_used = 0 - for i, new_label in enumerate(new_labels): - if new_label in code.labels_used: - cases_used.append(i) - if new_label == new_error_label: - error_label_used = 1 - error_label_case = i - if cases_used: - code.putln( - "int __pyx_why;") - if error_label_used and self.preserve_exception: - code.putln( - "PyObject *%s, *%s, *%s;" % Naming.exc_vars) - code.putln( - "int %s;" % Naming.exc_lineno_name) - code.use_label(catch_label) - code.putln( - "__pyx_why = 0; goto %s;" % catch_label) - for i in cases_used: - new_label = new_labels[i] - #if new_label and new_label <> "<try>": - if new_label == new_error_label and self.preserve_exception: - self.put_error_catcher(code, - new_error_label, i+1, catch_label) - else: - code.putln( - "%s: __pyx_why = %s; goto %s;" % ( - new_label, - i+1, - catch_label)) - code.put_label(catch_label) - code.set_all_labels(old_labels) - if error_label_used: - code.new_error_label() - finally_error_label = code.error_label - self.finally_clause.generate_execution_code(code) - if error_label_used: - if finally_error_label in code.labels_used and self.preserve_exception: - over_label = code.new_label() - code.put_goto(over_label); - code.put_label(finally_error_label) - code.putln("if (__pyx_why == %d) {" % (error_label_case + 1)) - for var in Naming.exc_vars: - code.putln("Py_XDECREF(%s);" % var) - code.putln("}") - code.put_goto(old_error_label) - code.put_label(over_label) - code.error_label = old_error_label - if cases_used: - code.putln( - "switch (__pyx_why) {") - for i in cases_used: - old_label = old_labels[i] - if old_label == old_error_label and self.preserve_exception: - self.put_error_uncatcher(code, i+1, old_error_label) - else: - code.use_label(old_label) - code.putln( - "case %s: goto %s;" % ( - i+1, - old_label)) - code.putln( - "}") - code.putln( - "}") - - def put_error_catcher(self, code, error_label, i, catch_label): - code.putln( - "%s: {" % - error_label) - code.putln( - "__pyx_why = %s;" % - i) - code.put_var_xdecrefs_clear(self.cleanup_list) - code.putln( - "PyErr_Fetch(&%s, &%s, &%s);" % - Naming.exc_vars) - code.putln( - "%s = %s;" % ( - Naming.exc_lineno_name, Naming.lineno_cname)) - #code.putln( - # "goto %s;" % - # catch_label) - code.put_goto(catch_label) - code.putln( - "}") - - def put_error_uncatcher(self, code, i, error_label): - code.putln( - "case %s: {" % - i) - code.putln( - "PyErr_Restore(%s, %s, %s);" % - Naming.exc_vars) - code.putln( - "%s = %s;" % ( - Naming.lineno_cname, Naming.exc_lineno_name)) - for var in Naming.exc_vars: - code.putln( - "%s = 0;" % - var) - code.put_goto(error_label) - code.putln( - "}") - - -class GILStatNode(TryFinallyStatNode): - # 'with gil' or 'with nogil' statement - # - # state string 'gil' or 'nogil' - - preserve_exception = 0 - - def __init__(self, pos, state, body): - self.state = state - TryFinallyStatNode.__init__(self, pos, - body = body, - finally_clause = GILExitNode(pos, state = state)) - - def analyse_expressions(self, env): - env.global_scope().gil_used = 1 - was_nogil = env.nogil - env.nogil = 1 - TryFinallyStatNode.analyse_expressions(self, env) - env.nogil = was_nogil - - def gil_check(self, env): - pass - - def generate_execution_code(self, code): - code.putln("/*with %s:*/ {" % self.state) - if self.state == 'gil': - code.putln("PyGILState_STATE _save = PyGILState_Ensure();") - else: - code.putln("PyThreadState *_save;") - code.putln("Py_UNBLOCK_THREADS") - TryFinallyStatNode.generate_execution_code(self, code) - code.putln("}") - - -class GILExitNode(StatNode): - # Used as the 'finally' block in a GILStatNode - # - # state string 'gil' or 'nogil' - - def analyse_expressions(self, env): - pass - - def generate_execution_code(self, code): - if self.state == 'gil': - code.putln("PyGILState_Release();") - else: - code.putln("Py_BLOCK_THREADS") - - -class CImportStatNode(StatNode): - # cimport statement - # - # module_name string Qualified name of module being imported - # as_name string or None Name specified in "as" clause, if any - - def analyse_declarations(self, env): - module_scope = env.find_module(self.module_name, self.pos) - if "." in self.module_name: - names = self.module_name.split(".") - top_name = names[0] - top_module_scope = env.context.find_submodule(top_name) - module_scope = top_module_scope - for name in names[1:]: - submodule_scope = module_scope.find_submodule(name) - module_scope.declare_module(name, submodule_scope, self.pos) - if not self.as_name: - env.add_imported_module(submodule_scope) - module_scope = submodule_scope - if self.as_name: - env.declare_module(self.as_name, module_scope, self.pos) - env.add_imported_module(module_scope) - else: - env.declare_module(top_name, top_module_scope, self.pos) - env.add_imported_module(top_module_scope) - else: - name = self.as_name or self.module_name - env.declare_module(name, module_scope, self.pos) - env.add_imported_module(module_scope) - - def analyse_expressions(self, env): - pass - - def generate_execution_code(self, code): - pass - - -class FromCImportStatNode(StatNode): - # from ... cimport statement - # - # module_name string Qualified name of module - # imported_names Parsing.ImportedName Names to be imported - - def analyse_declarations(self, env): - module_scope = env.find_module(self.module_name, self.pos) - env.add_imported_module(module_scope) - for imp in self.imported_names: - kind = imp.kind - #entry = module_scope.find(imp.name, imp.pos) - entry = module_scope.lookup(imp.name) - if entry: - if kind and not self.declaration_matches(entry, kind): - entry.redeclared(pos) - else: - if kind == 'struct' or kind == 'union': - entry = module_scope.declare_struct_or_union(imp.name, - kind = kind, scope = None, typedef_flag = 0, pos = imp.pos) - elif kind == 'class': - entry = module_scope.declare_c_class(imp.name, pos = imp.pos, - module_name = self.module_name) - else: - error(imp.pos, "Name '%s' not declared in module '%s'" - % (imp.name, self.module_name)) - if entry: - local_name = imp.as_name or imp.name - env.add_imported_entry(local_name, entry, imp.pos) - - def declaration_matches(self, entry, kind): - if not entry.is_type: - return 0 - type = entry.type - if kind == 'class': - if not type.is_extension_type: - return 0 - else: - if not type.is_struct_or_union: - return 0 - if kind <> type.kind: - return 0 - return 1 - - def analyse_expressions(self, env): - pass - - def generate_execution_code(self, code): - pass - - -class FromImportStatNode(StatNode): - # from ... import statement - # - # module ImportNode - # items [(string, NameNode)] - # #interned_items [(string, NameNode)] - # item PyTempNode used internally - - def analyse_declarations(self, env): - for _, target in self.items: - target.analyse_target_declaration(env) - - def analyse_expressions(self, env): - import ExprNodes - self.module.analyse_expressions(env) - self.item = ExprNodes.PyTempNode(self.pos, env) - self.item.allocate_temp(env) - #self.interned_items = [] - for name, target in self.items: - #self.interned_items.append((env.intern(name), target)) - target.analyse_target_expression(env, None) - self.module.release_temp(env) - self.item.release_temp(env) - - def generate_execution_code(self, code): - self.module.generate_evaluation_code(code) - #for cname, target in self.interned_items: - for name, target in self.items: - cname = code.intern(name) - code.putln( - '%s = PyObject_GetAttr(%s, %s); if (!%s) %s' % ( - self.item.result(), - self.module.py_result(), - cname, - self.item.result(), - code.error_goto(self.pos))) - target.generate_assignment_code(self.item, code) - self.module.generate_disposal_code(code) - -#------------------------------------------------------------------------------------ -# -# Runtime support code -# -#------------------------------------------------------------------------------------ - -#utility_function_predeclarations = \ -#""" -#typedef struct {PyObject **p; char *s;} __Pyx_InternTabEntry; /*proto*/ -#typedef struct {PyObject **p; char *s; long n;} __Pyx_StringTabEntry; /*proto*/ -#""" - -utility_function_predeclarations = \ -""" -typedef struct {PyObject **p; int i; char *s; long n;} __Pyx_StringTabEntry; /*proto*/ -""" - -#get_name_predeclaration = \ -#"static PyObject *__Pyx_GetName(PyObject *dict, char *name); /*proto*/" - -#get_name_interned_predeclaration = \ -#"static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/" - -#------------------------------------------------------------------------------------ - -printing_utility_code = [ -""" -static int __Pyx_PrintItem(PyObject *); /*proto*/ -static int __Pyx_PrintNewline(void); /*proto*/ -""",r""" -static PyObject *__Pyx_GetStdout(void) { - PyObject *f = PySys_GetObject("stdout"); - if (!f) { - PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout"); - } - return f; -} - -static int __Pyx_PrintItem(PyObject *v) { - PyObject *f; - - if (!(f = __Pyx_GetStdout())) - return -1; - if (PyFile_SoftSpace(f, 1)) { - if (PyFile_WriteString(" ", f) < 0) - return -1; - } - if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0) - return -1; - if (PyString_Check(v)) { - char *s = PyString_AsString(v); - Py_ssize_t len = PyString_Size(v); - if (len > 0 && - isspace(Py_CHARMASK(s[len-1])) && - s[len-1] != ' ') - PyFile_SoftSpace(f, 0); - } - return 0; -} - -static int __Pyx_PrintNewline(void) { - PyObject *f; - - if (!(f = __Pyx_GetStdout())) - return -1; - if (PyFile_WriteString("\n", f) < 0) - return -1; - PyFile_SoftSpace(f, 0); - return 0; -} -"""] - -#------------------------------------------------------------------------------------ - -# The following function is based on do_raise() from ceval.c. - -raise_utility_code = [ -""" -static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb); /*proto*/ -""",""" -static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) { - if (value == Py_None) - value = NULL; - if (tb == Py_None) - tb = NULL; - Py_XINCREF(type); - Py_XINCREF(value); - Py_XINCREF(tb); - if (tb && !PyTraceBack_Check(tb)) { - PyErr_SetString(PyExc_TypeError, - "raise: arg 3 must be a traceback or None"); - goto raise_error; - } - #if PY_VERSION_HEX < 0x02050000 - if (!PyClass_Check(type)) - #else - if (!PyType_Check(type)) - #endif - { - /* Raising an instance. The value should be a dummy. */ - if (value) { - PyErr_SetString(PyExc_TypeError, - "instance exception may not have a separate value"); - goto raise_error; - } - /* Normalize to raise <class>, <instance> */ - value = type; - #if PY_VERSION_HEX < 0x02050000 - if (PyInstance_Check(type)) { - type = (PyObject*) ((PyInstanceObject*)type)->in_class; - Py_INCREF(type); - } - else { - PyErr_SetString(PyExc_TypeError, - "raise: exception must be an old-style class or instance"); - goto raise_error; - } - #else - type = (PyObject*) type->ob_type; - Py_INCREF(type); - if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) { - PyErr_SetString(PyExc_TypeError, - "raise: exception class must be a subclass of BaseException"); - goto raise_error; - } - #endif - } - PyErr_Restore(type, value, tb); - return; -raise_error: - Py_XDECREF(value); - Py_XDECREF(type); - Py_XDECREF(tb); - return; -} -"""] - -#------------------------------------------------------------------------------------ - -#reraise_utility_code = [ -#""" -#static void __Pyx_ReRaise(void); /*proto*/ -#""",""" -#static void __Pyx_ReRaise(void) { -# PyThreadState *tstate = PyThreadState_Get(); -# PyObject *type = tstate->exc_type; -# PyObject *value = tstate->exc_value; -# PyObject *tb = tstate->exc_traceback; -# Py_XINCREF(type); -# Py_XINCREF(value); -# Py_XINCREF(tb); -# PyErr_Restore(type, value, tb); -#} -#"""] - -#------------------------------------------------------------------------------------ - -arg_type_test_utility_code = [ -""" -static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, char *name); /*proto*/ -""",""" -static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, char *name) { - if (!type) { - PyErr_Format(PyExc_SystemError, "Missing type object"); - return 0; - } - if ((none_allowed && obj == Py_None) || PyObject_TypeCheck(obj, type)) - return 1; - PyErr_Format(PyExc_TypeError, - "Argument '%s' has incorrect type (expected %s, got %s)", - name, type->tp_name, obj->ob_type->tp_name); - return 0; -} -"""] - -#------------------------------------------------------------------------------------ -# -# __Pyx_GetStarArgs splits the args tuple and kwds dict into two parts -# each, one part suitable for passing to PyArg_ParseTupleAndKeywords, -# and the other containing any extra arguments. On success, replaces -# the borrowed references *args and *kwds with references to a new -# tuple and dict, and passes back new references in *args2 and *kwds2. -# Does not touch any of its arguments on failure. -# -# Any of *kwds, args2 and kwds2 may be 0 (but not args or kwds). If -# *kwds == 0, it is not changed. If kwds2 == 0 and *kwds != 0, a new -# reference to the same dictionary is passed back in *kwds. -# -# If rqd_kwds is not 0, it is an array of booleans corresponding to the -# names in kwd_list, indicating required keyword arguments. If any of -# these are not present in kwds, an exception is raised. -# - -get_starargs_utility_code = [ -""" -static int __Pyx_GetStarArgs(PyObject **args, PyObject **kwds, char *kwd_list[], \ - Py_ssize_t nargs, PyObject **args2, PyObject **kwds2, char rqd_kwds[]); /*proto*/ -""",""" -static int __Pyx_GetStarArgs( - PyObject **args, - PyObject **kwds, - char *kwd_list[], - Py_ssize_t nargs, - PyObject **args2, - PyObject **kwds2, - char rqd_kwds[]) -{ - PyObject *x = 0, *args1 = 0, *kwds1 = 0; - int i; - char **p; - - if (args2) - *args2 = 0; - if (kwds2) - *kwds2 = 0; - - if (args2) { - args1 = PyTuple_GetSlice(*args, 0, nargs); - if (!args1) - goto bad; - *args2 = PyTuple_GetSlice(*args, nargs, PyTuple_GET_SIZE(*args)); - if (!*args2) - goto bad; - } - else if (PyTuple_GET_SIZE(*args) > nargs) { - int m = nargs; - int n = PyTuple_GET_SIZE(*args); - PyErr_Format(PyExc_TypeError, - "function takes at most %d positional arguments (%d given)", - m, n); - goto bad; - } - else { - args1 = *args; - Py_INCREF(args1); - } - - if (rqd_kwds && !*kwds) - for (i = 0, p = kwd_list; *p; i++, p++) - if (rqd_kwds[i]) - goto missing_kwarg; - - if (kwds2) { - if (*kwds) { - kwds1 = PyDict_New(); - if (!kwds1) - goto bad; - *kwds2 = PyDict_Copy(*kwds); - if (!*kwds2) - goto bad; - for (i = 0, p = kwd_list; *p; i++, p++) { - x = PyDict_GetItemString(*kwds, *p); - if (x) { - if (PyDict_SetItemString(kwds1, *p, x) < 0) - goto bad; - if (PyDict_DelItemString(*kwds2, *p) < 0) - goto bad; - } - else if (rqd_kwds && rqd_kwds[i]) - goto missing_kwarg; - } - } - else { - *kwds2 = PyDict_New(); - if (!*kwds2) - goto bad; - } - } - else { - kwds1 = *kwds; - Py_XINCREF(kwds1); - if (rqd_kwds && *kwds) - for (i = 0, p = kwd_list; *p; i++, p++) - if (rqd_kwds[i] && !PyDict_GetItemString(*kwds, *p)) - goto missing_kwarg; - } - - *args = args1; - *kwds = kwds1; - return 0; -missing_kwarg: - PyErr_Format(PyExc_TypeError, - "required keyword argument '%s' is missing", *p); -bad: - Py_XDECREF(args1); - Py_XDECREF(kwds1); - if (args2) { - Py_XDECREF(*args2); - } - if (kwds2) { - Py_XDECREF(*kwds2); - } - return -1; -} -"""] - -#------------------------------------------------------------------------------------ - -unraisable_exception_utility_code = [ -""" -static void __Pyx_WriteUnraisable(char *name); /*proto*/ -""",""" -static void __Pyx_WriteUnraisable(char *name) { - PyObject *old_exc, *old_val, *old_tb; - PyObject *ctx; - PyGILState_STATE state = PyGILState_Ensure(); - PyErr_Fetch(&old_exc, &old_val, &old_tb); - ctx = PyString_FromString(name); - PyErr_Restore(old_exc, old_val, old_tb); - if (!ctx) - ctx = Py_None; - PyErr_WriteUnraisable(ctx); - PyGILState_Release(state); -} -"""] - -#------------------------------------------------------------------------------------ - -traceback_utility_code = [ -""" -static void __Pyx_AddTraceback(char *funcname); /*proto*/ -""",""" -#include "compile.h" -#include "frameobject.h" -#include "traceback.h" - -static void __Pyx_AddTraceback(char *funcname) { - PyObject *py_srcfile = 0; - PyObject *py_funcname = 0; - PyObject *py_globals = 0; - PyObject *empty_tuple = 0; - PyObject *empty_string = 0; - PyCodeObject *py_code = 0; - PyFrameObject *py_frame = 0; - - py_srcfile = PyString_FromString(%(FILENAME)s); - if (!py_srcfile) goto bad; - py_funcname = PyString_FromString(funcname); - if (!py_funcname) goto bad; - py_globals = PyModule_GetDict(%(GLOBALS)s); - if (!py_globals) goto bad; - empty_tuple = PyTuple_New(0); - if (!empty_tuple) goto bad; - empty_string = PyString_FromString(""); - if (!empty_string) goto bad; - py_code = PyCode_New( - 0, /*int argcount,*/ - 0, /*int nlocals,*/ - 0, /*int stacksize,*/ - 0, /*int flags,*/ - empty_string, /*PyObject *code,*/ - empty_tuple, /*PyObject *consts,*/ - empty_tuple, /*PyObject *names,*/ - empty_tuple, /*PyObject *varnames,*/ - empty_tuple, /*PyObject *freevars,*/ - empty_tuple, /*PyObject *cellvars,*/ - py_srcfile, /*PyObject *filename,*/ - py_funcname, /*PyObject *name,*/ - %(LINENO)s, /*int firstlineno,*/ - empty_string /*PyObject *lnotab*/ - ); - if (!py_code) goto bad; - py_frame = PyFrame_New( - PyThreadState_Get(), /*PyThreadState *tstate,*/ - py_code, /*PyCodeObject *code,*/ - py_globals, /*PyObject *globals,*/ - 0 /*PyObject *locals*/ - ); - if (!py_frame) goto bad; - py_frame->f_lineno = %(LINENO)s; - PyTraceBack_Here(py_frame); -bad: - Py_XDECREF(py_srcfile); - Py_XDECREF(py_funcname); - Py_XDECREF(empty_tuple); - Py_XDECREF(empty_string); - Py_XDECREF(py_code); - Py_XDECREF(py_frame); -} -""" % { - 'FILENAME': Naming.filename_cname, - 'LINENO': Naming.lineno_cname, - 'GLOBALS': Naming.module_cname -}] - -#------------------------------------------------------------------------------------ - -set_vtable_utility_code = [ -""" -static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/ -""",""" -static int __Pyx_SetVtable(PyObject *dict, void *vtable) { - PyObject *pycobj = 0; - int result; - - pycobj = PyCObject_FromVoidPtr(vtable, 0); - if (!pycobj) - goto bad; - if (PyDict_SetItemString(dict, "__pyx_vtable__", pycobj) < 0) - goto bad; - result = 0; - goto done; - -bad: - result = -1; -done: - Py_XDECREF(pycobj); - return result; -} -"""] - -#------------------------------------------------------------------------------------ - -get_vtable_utility_code = [ -""" -static int __Pyx_GetVtable(PyObject *dict, void *vtabptr); /*proto*/ -""",r""" -static int __Pyx_GetVtable(PyObject *dict, void *vtabptr) { - int result; - PyObject *pycobj; - - pycobj = PyMapping_GetItemString(dict, "__pyx_vtable__"); - if (!pycobj) - goto bad; - *(void **)vtabptr = PyCObject_AsVoidPtr(pycobj); - if (!*(void **)vtabptr) - goto bad; - result = 0; - goto done; - -bad: - result = -1; -done: - Py_XDECREF(pycobj); - return result; -} -"""] - -#------------------------------------------------------------------------------------ - -#init_intern_tab_utility_code = [ -#""" -#static int __Pyx_InternStrings(__Pyx_InternTabEntry *t); /*proto*/ -#""",""" -#static int __Pyx_InternStrings(__Pyx_InternTabEntry *t) { -# while (t->p) { -# *t->p = PyString_InternFromString(t->s); -# if (!*t->p) -# return -1; -# ++t; -# } -# return 0; -#} -#"""] - -#init_intern_tab_utility_code = [ -#""" -#static int __Pyx_InternStrings(PyObject **t[]); /*proto*/ -#""",""" -#static int __Pyx_InternStrings(PyObject **t[]) { -# while (*t) { -# PyString_InternInPlace(*t); -# if (!**t) -# return -1; -# ++t; -# } -# return 0; -#} -#"""] - -#------------------------------------------------------------------------------------ - -init_string_tab_utility_code = [ -""" -static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/ -""",""" -static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { - while (t->p) { - *t->p = PyString_FromStringAndSize(t->s, t->n - 1); - if (!*t->p) - return -1; - if (t->i) - PyString_InternInPlace(t->p); - ++t; - } - return 0; -} -"""] - -#------------------------------------------------------------------------------------ - -#get_exception_utility_code = [ -#""" -#static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/ -#""",""" -#static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) { -# PyThreadState *tstate = PyThreadState_Get(); -# PyObject *old_type, *old_value, *old_tb; -# PyErr_Fetch(type, value, tb); -# PyErr_NormalizeException(type, value, tb); -# if (PyErr_Occurred()) -# goto bad; -# if (!*tb) { -# printf("no traceback\n"); -# *tb = Py_None; -# Py_INCREF(*tb); -# } -##if 1 -# Py_INCREF(*type); -# Py_INCREF(*value); -# Py_INCREF(*tb); -# old_type = tstate->exc_type; -# old_value = tstate->exc_value; -# old_tb = tstate->exc_traceback; -# tstate->exc_type = *type; -# tstate->exc_value = *value; -# tstate->exc_traceback = *tb; -# Py_XDECREF(old_type); -# Py_XDECREF(old_value); -# Py_XDECREF(old_tb); -##endif -# return 0; -#bad: -# Py_XDECREF(*type); -# Py_XDECREF(*value); -# Py_XDECREF(*tb); -# return -1; -#} -#"""] - -#------------------------------------------------------------------------------------ - -#get_exception_utility_code = [ -#""" -#static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/ -#""",""" -#static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) { -# PyErr_Fetch(type, value, tb); -# PyErr_NormalizeException(type, value, tb); -# if (PyErr_Occurred()) -# goto bad; -# if (!*tb) { -# *tb = Py_None; -# Py_INCREF(*tb); -# } -# return 0; -#bad: -# Py_XDECREF(*type); -# Py_XDECREF(*value); -# Py_XDECREF(*tb); -# return -1; -#} -#"""] - -#------------------------------------------------------------------------------------ - -normalize_exception_utility_code = [ -""" -static int __Pyx_NormalizeException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/ -""",""" -static int __Pyx_NormalizeException(PyObject **type, PyObject **value, PyObject **tb) { - PyErr_NormalizeException(type, value, tb); - if (PyErr_Occurred()) - goto bad; - if (!*tb) { - *tb = Py_None; - Py_INCREF(*tb); - } - return 0; -bad: - Py_XDECREF(*type); - Py_XDECREF(*value); - Py_XDECREF(*tb); - return -1; -} -"""] - -#------------------------------------------------------------------------------------ |
