From: Dag Sverre Seljebotn Date: Sun, 3 Aug 2008 18:35:30 +0000 (+0200) Subject: Merge. X-Git-Tag: 0.9.8.1~49^2~29 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=d65fd74750c352e4fd49fa99ff88b4d04a1a34b9;p=cython.git Merge. Had to move some changes made in ModuleNode.py over to Code.py manually. --- d65fd74750c352e4fd49fa99ff88b4d04a1a34b9 diff --cc Cython/Compiler/Buffer.py index 2bac70dc,59e63165..994d48b4 --- a/Cython/Compiler/Buffer.py +++ b/Cython/Compiler/Buffer.py @@@ -29,10 -29,9 +29,8 @@@ class IntroduceBufferAuxiliaryVars(Cyth self.max_ndim = 0 result = super(IntroduceBufferAuxiliaryVars, self).__call__(node) if self.buffers_exists: - if "endian.h" not in node.scope.include_files: - node.scope.include_files.append("endian.h") use_py2_buffer_functions(node.scope) use_empty_bufstruct_code(node.scope, self.max_ndim) - node.scope.use_utility_code(access_utility_code) return result diff --cc Cython/Compiler/Code.py index 1dcfe42d,79aa5c2e..f41f4fb4 --- a/Cython/Compiler/Code.py +++ b/Cython/Compiler/Code.py @@@ -131,227 -118,11 +131,233 @@@ class FunctionState(object) self.temps_free[type] = freelist freelist.append(name) +class GlobalState(object): + # filename_table {string : int} for finding filename table indexes + # filename_list [string] filenames in filename table order + # input_file_contents dict contents (=list of lines) of any file that was used as input + # to create this output C code. This is + # used to annotate the comments. + # + # used_utility_code set(string|int) Ids of used utility code (to avoid reinsertion) + # utilprotowriter CCodeWriter + # utildefwriter CCodeWriter + # + # declared_cnames {string:Entry} used in a transition phase to merge pxd-declared + # constants etc. into the pyx-declared ones (i.e, + # check if constants are already added). + # In time, hopefully the literals etc. will be + # supplied directly instead. + + + # interned_strings + # consts + # py_string_decls + # interned_nums + # cached_builtins + + def __init__(self, rootwriter): + self.filename_table = {} + self.filename_list = [] + self.input_file_contents = {} + self.used_utility_code = set() + self.declared_cnames = {} + self.pystring_table_needed = False + + def initwriters(self, rootwriter): + self.utilprotowriter = rootwriter.new_writer() + self.utildefwriter = rootwriter.new_writer() + self.decls_writer = rootwriter.new_writer() + self.pystring_table = rootwriter.new_writer() + self.initwriter = rootwriter.new_writer() + + self.initwriter.enter_cfunc_scope() + self.initwriter.putln("").putln("static int __Pyx_InitGlobals(void) {") + + (self.pystring_table + .putln("") + .putln("static __Pyx_StringTabEntry %s[] = {" % + Naming.stringtab_cname) + ) + + # + # Global constants, interned objects, etc. + # + def insert_global_var_declarations_into(self, code): + code.insert(self.decls_writer) + + def close_global_decls(self): + # This is called when it is known that no more global declarations will + # declared (but can be called before or after insert_XXX). + if self.pystring_table_needed: - self.pystring_table.putln("{0, 0, 0, 0, 0}").putln("};") ++ self.pystring_table.putln("{0, 0, 0, 0, 0, 0}").putln("};") + import Nodes + self.use_utility_code(Nodes.init_string_tab_utility_code) + self.initwriter.putln( + "if (__Pyx_InitStrings(%s) < 0) %s;" % ( + Naming.stringtab_cname, + self.initwriter.error_goto(self.module_pos))) + + (self.initwriter + .putln("return 0;") + .put_label(self.initwriter.error_label) + .putln("return -1;") + .putln("}") + ) + self.initwriter.exit_cfunc_scope() + + def insert_py_string_table_into(self, code): + if self.pystring_table_needed: + code.insert(self.pystring_table) + + def insert_initglobals_into(self, code): + code.insert(self.initwriter) + + def put_pyobject_decl(self, entry): + self.decls_writer.putln("static PyObject *%s;" % entry.cname) + + # The functions below are there in a transition phase only + # and will be deprecated. They are called from Nodes.BlockNode. + # The copy&paste duplication is intentional in order to be able + # to see quickly how BlockNode worked, until this is replaced. + + def should_declare(self, cname, entry): + if cname in self.declared_cnames: + other = self.declared_cnames[cname] + assert entry.type == other.type + assert entry.init == other.init + return False + else: + self.declared_cnames[cname] = entry + return True + + def add_const_definition(self, entry): + if self.should_declare(entry.cname, entry): + self.decls_writer.put_var_declaration(entry, static = 1) + + def add_interned_string_decl(self, entry): + if self.should_declare(entry.cname, entry): + self.decls_writer.put_var_declaration(entry, static = 1) + self.add_py_string_decl(entry) + + def add_py_string_decl(self, entry): + if self.should_declare(entry.pystring_cname, entry): + self.decls_writer.putln("static PyObject *%s;" % entry.pystring_cname) + self.pystring_table_needed = True + self.pystring_table.putln("{&%s, %s, sizeof(%s), %d, %d, %d}," % ( + entry.pystring_cname, + entry.cname, + entry.cname, + entry.type.is_unicode, + entry.is_interned, + entry.is_identifier + )) + + def add_interned_num_decl(self, entry): + if self.should_declare(entry.cname, entry): - self.initwriter.putln("%s = PyInt_FromLong(%s); %s;" % ( - entry.cname, - entry.init, - self.initwriter.error_goto_if_null(entry.cname, self.module_pos))) # todo: fix pos ++ if entry.init[-1] == "L": ++ self.initwriter.putln('%s = PyLong_FromString("%s", 0, 0); %s;' % ( ++ entry.cname, ++ entry.init, ++ self.initwriter.error_goto_if_null(entry.cname, self.module_pos))) ++ else: ++ self.initwriter.putln("%s = PyInt_FromLong(%s); %s;" % ( ++ entry.cname, ++ entry.init, ++ self.initwriter.error_goto_if_null(entry.cname, self.module_pos))) ++ + self.put_pyobject_decl(entry) + + def add_cached_builtin_decl(self, entry): + if self.should_declare(entry.cname, entry): + self.put_pyobject_decl(entry) + - + # + # File name state + # + + def lookup_filename(self, filename): + try: + index = self.filename_table[filename] + except KeyError: + index = len(self.filename_list) + self.filename_list.append(filename) + self.filename_table[filename] = index + return index + + def commented_file_contents(self, source_desc): + try: + return self.input_file_contents[source_desc] + except KeyError: + F = [u' * ' + line.rstrip().replace( + u'*/', u'*[inserted by cython to avoid comment closer]/' + ).encode('ASCII', 'replace') # + Py2 auto-decode to unicode + for line in source_desc.get_lines()] + if len(F) == 0: F.append(u'') + self.input_file_contents[source_desc] = F + return F + + # + # Utility code state + # + + def use_utility_code(self, codetup, name=None): + """ + Adds the given utility code to the C file if needed. + + codetup should unpack into one prototype code part and one + definition code part, both strings inserted directly in C. + + If name is provided, it is used as an identifier to avoid inserting + code twice. Otherwise, id(codetup) is used as such an identifier. + """ + if name is None: name = id(codetup) + if self.check_utility_code_needed_and_register(name): + proto, _def = codetup + self.utilprotowriter.put(proto) + self.utildefwriter.put(_def) + + def has_utility_code(self, name): + return name in self.used_utility_code + + def use_generated_code(self, func, name, *args, **kw): + """ + Requests that the utility code that func can generate is used in the C + file. func is called like this: + + func(proto, definition, name, *args, **kw) + + where proto and definition are two CCodeWriter instances; the + former should have the prototype written to it and the other the definition. + + The call might happen at some later point (if compiling multiple modules + into a cache for instance), and will only happen once per utility code. + + name is used to identify the utility code, so that it isn't regenerated + when the same code is requested again. + """ + if self.check_utility_code_needed_and_register(name): + func(self.utilprotowriter, self.utildefwriter, + name, *args, **kw) + + def check_utility_code_needed_and_register(self, name): + if name in self.used_utility_code: + return False + else: + self.used_utility_code.add(name) + return True + + def put_utility_code_protos(self, writer): + writer.insert(self.utilprotowriter) + + def put_utility_code_defs(self, writer): + writer.insert(self.utildefwriter) + + def funccontext_property(name): def get(self): - return getattr(self.func, name) + return getattr(self.funcstate, name) def set(self, value): - setattr(self.func, name, value) + setattr(self.funcstate, name, value) return property(get, set) class CCodeWriter(object):