# 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.
- def __init__(self):
+
+ # 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 = {}
+
+ def initwriters(self, rootwriter):
+ self.utilprotowriter = rootwriter.new_writer()
+ self.utildefwriter = rootwriter.new_writer()
+ self.decls_writer = rootwriter.new_writer()
+
+ #
+ # Global constants, interned objects, etc.
+ #
+ def insert_global_var_declarations_into(self, code):
+ code.insert(self.decls_writer)
+
+ # 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)
+ if self.should_declare(entry.pystring_cname, entry):
+ self.decls_writer.putln("static PyObject *%s;" % entry.pystring_cname)
+
+ 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)
+
+ def add_interned_num_decl(self, entry):
+ if self.should_declare(entry.cname, entry):
+ self.decls_writer.putln("static PyObject *%s;" % entry.cname)
+
+ def add_cached_builtin_decl(self, entry):
+ if self.should_declare(entry.cname, entry):
+ self.decls_writer.putln("static PyObject *%s;" % entry.cname)
+
+ #
+ # File name state
+ #
def lookup_filename(self, filename):
try:
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.
self.bol = 1
if create_from is None:
# Root CCodeWriter
- self.globalstate = GlobalState()
- # These needs to be constructed after all state is set, as
- # the construction copies over the state
- self.globalstate.utilprotowriter = self.new_writer()
- self.globalstate.utildefwriter = self.new_writer()
+ self.globalstate = GlobalState(self)
+ self.globalstate.initwriters(self)
+ # ^^^ need seperate step because this will reference self.globalstate
else:
# Use same global state
self.globalstate = create_from.globalstate
return
assert isinstance(source_desc, SourceDescriptor)
contents = self.globalstate.commented_file_contents(source_desc)
-
lines = contents[max(0,line-3):line] # line numbers start at 1
lines[-1] += u' # <<<<<<<<<<<<<<'
lines += contents[line:line+2]
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)
+ code.globalstate.add_const_definition(entry)
def generate_interned_string_decls(self, env, code):
entries = env.global_scope().new_interned_string_entries
if entries:
- code.putln("")
for entry in entries:
- code.put_var_declaration(entry, static = 1)
- code.putln("")
- for entry in entries:
- code.putln(
- "static PyObject *%s;" % entry.pystring_cname)
+ code.globalstate.add_interned_string_decl(entry)
del entries[:]
def generate_py_string_decls(self, env, code):
return # earlier error
entries = env.pystring_entries
if entries:
- code.putln("")
for entry in entries:
if not entry.is_interned:
- code.putln(
- "static PyObject *%s;" % entry.pystring_cname)
+ code.globalstate.add_py_string_decl(entry)
def generate_interned_num_decls(self, env, code):
# Flush accumulated interned nums from the global scope
genv = env.global_scope()
entries = genv.interned_nums
if entries:
- code.putln("")
for entry in entries:
- code.putln(
- "static PyObject *%s;" % entry.cname)
+ code.globalstate.add_interned_num_decl(entry)
del entries[:]
def generate_cached_builtins_decls(self, env, code):
entries = env.global_scope().undeclared_cached_builtins
- if len(entries) > 0:
- code.putln("")
for entry in entries:
- code.putln("static PyObject *%s;" % entry.cname)
+ code.globalstate.add_cached_builtin_decl(entry)
del entries[:]
"True": ["Py_True", py_object_type],
}
+const_counter = 1 # As a temporary solution for compiling code in pxds
+
class ModuleScope(Scope):
# module_name string Python name of the module
# module_cname string C name of Python module object
# method_table_cname string C name of method table
# doc string Module doc string
# doc_cname string C name of module doc string
- # const_counter integer Counter for naming constants
+ # const_counter integer Counter for naming constants (PS: MOVED TO GLOBAL)
# utility_code_list [((string, string), string)] Queuing utility codes for forwarding to Code.py
# default_entries [Entry] Function argument default entries
# python_include_files [string] Standard Python headers to be included
self.method_table_cname = Naming.methtable_cname
self.doc = ""
self.doc_cname = Naming.moddoc_cname
- self.const_counter = 1
self.utility_code_list = []
self.default_entries = []
self.module_entries = {}
return entry
def new_const_cname(self):
+ global const_counter
# Create a new globally-unique name for a constant.
prefix=''
- n = self.const_counter
- self.const_counter = n + 1
+ n = const_counter
+ const_counter = n + 1
return "%s%s%d" % (Naming.const_prefix, prefix, n)
def use_utility_code(self, new_code, name=None):