cython-devel
changeset 2158:50307880f9c1
almost complete refactoring of constant allocation to move it into the code generation phase
| author | Stefan Behnel <scoder@users.berlios.de> |
|---|---|
| date | Wed Mar 18 21:44:34 2009 +0100 (2 years ago) |
| parents | b968461f6584 |
| children | 02d666a252ee |
| files | Cython/Compiler/Code.py Cython/Compiler/ExprNodes.py Cython/Compiler/ModuleNode.py Cython/Compiler/Naming.py Cython/Compiler/Nodes.py Cython/Compiler/Symtab.py tests/errors/e_strcoerce.pyx |
line diff
1.1 --- a/Cython/Compiler/Code.py Sun Mar 15 19:34:39 2009 +0100
1.2 +++ b/Cython/Compiler/Code.py Wed Mar 18 21:44:34 2009 +0100
1.3 @@ -2,15 +2,16 @@
1.4 # Pyrex - Code output module
1.5 #
1.6
1.7 +import re
1.8 import codecs
1.9 import Naming
1.10 import Options
1.11 -from Cython.Utils import open_new_file, open_source_file
1.12 +import StringEncoding
1.13 +from Cython import Utils
1.14 from PyrexTypes import py_object_type, typecast
1.15 from TypeSlots import method_coexist
1.16 from Scanning import SourceDescriptor
1.17 from Cython.StringIOTree import StringIOTree
1.18 -import DebugFlags
1.19 try:
1.20 set
1.21 except NameError:
1.22 @@ -48,6 +49,8 @@
1.23 self.temps_used_type = {} # name -> (type, manage_ref)
1.24 self.temp_counter = 0
1.25
1.26 + # labels
1.27 +
1.28 def new_label(self, name=None):
1.29 n = self.label_counter
1.30 self.label_counter = n + 1
1.31 @@ -107,6 +110,8 @@
1.32 def label_used(self, lbl):
1.33 return lbl in self.labels_used
1.34
1.35 + # temp handling
1.36 +
1.37 def allocate_temp(self, type, manage_ref):
1.38 """
1.39 Allocates a temporary (which may create a new one or get a previously
1.40 @@ -196,6 +201,81 @@
1.41 if manage_ref
1.42 for cname in freelist]
1.43
1.44 +
1.45 +class IntConst(object):
1.46 + """Global info about a Python integer constant held by GlobalState.
1.47 + """
1.48 + # cname string
1.49 + # value int
1.50 + # is_long boolean
1.51 +
1.52 + def __init__(self, cname, value, is_long):
1.53 + self.cname = cname
1.54 + self.value = value
1.55 + self.is_long = is_long
1.56 +
1.57 +possible_identifier = re.compile(ur"(?![0-9])\w+$", re.U).match
1.58 +nice_identifier = re.compile('^[a-zA-Z0-0_]+$').match
1.59 +
1.60 +class StringConst(object):
1.61 + """Global info about a C string constant held by GlobalState.
1.62 + """
1.63 + # cname string
1.64 + # text EncodedString or BytesLiteral
1.65 + # py_strings {(identifier, encoding) : PyStringConst}
1.66 +
1.67 + def __init__(self, cname, text, byte_string):
1.68 + self.cname = cname
1.69 + self.text = text
1.70 + self.escaped_value = StringEncoding.escape_byte_string(byte_string)
1.71 + self.py_strings = None
1.72 +
1.73 + def get_py_string_const(self, encoding, identifier=None):
1.74 + py_strings = self.py_strings
1.75 + text = self.text
1.76 + if encoding is not None:
1.77 + encoding = encoding.upper()
1.78 +
1.79 + key = (bool(identifier), encoding)
1.80 + if py_strings is not None and key in py_strings:
1.81 + py_string = py_strings[key]
1.82 + else:
1.83 + if py_strings is None:
1.84 + self.py_strings = {}
1.85 + is_unicode = encoding is None
1.86 + intern = bool(identifier or (
1.87 + identifier is None and possible_identifier(text)))
1.88 + if intern:
1.89 + prefix = Naming.interned_str_prefix
1.90 + else:
1.91 + prefix = Naming.py_const_prefix
1.92 + pystring_cname = "%s%s%s_%s" % (
1.93 + prefix,
1.94 + is_unicode and 'u' or 'b',
1.95 + identifier and 'i' or '',
1.96 + self.cname[len(Naming.const_prefix):])
1.97 +
1.98 + py_string = PyStringConst(
1.99 + pystring_cname, is_unicode, bool(identifier), intern)
1.100 + self.py_strings[key] = py_string
1.101 +
1.102 + return py_string
1.103 +
1.104 +class PyStringConst(object):
1.105 + """Global info about a Python string constant held by GlobalState.
1.106 + """
1.107 + # cname string
1.108 + # unicode boolean
1.109 + # intern boolean
1.110 + # identifier boolean
1.111 +
1.112 + def __init__(self, cname, is_unicode, identifier=False, intern=False):
1.113 + self.cname = cname
1.114 + self.identifier = identifier
1.115 + self.unicode = is_unicode
1.116 + self.intern = intern
1.117 +
1.118 +
1.119 class GlobalState(object):
1.120 # filename_table {string : int} for finding filename table indexes
1.121 # filename_list [string] filenames in filename table order
1.122 @@ -212,6 +292,9 @@
1.123 # check if constants are already added).
1.124 # In time, hopefully the literals etc. will be
1.125 # supplied directly instead.
1.126 + #
1.127 + # const_cname_counter int global counter for constant identifiers
1.128 + #
1.129
1.130
1.131 # interned_strings
1.132 @@ -232,10 +315,13 @@
1.133 self.input_file_contents = {}
1.134 self.used_utility_code = set()
1.135 self.declared_cnames = {}
1.136 - self.pystring_table_needed = False
1.137 self.in_utility_code_generation = False
1.138 self.emit_linenums = emit_linenums
1.139
1.140 + self.const_cname_counter = 1
1.141 + self.string_const_index = {}
1.142 + self.int_const_index = {}
1.143 +
1.144 def initwriters(self, rootwriter):
1.145 self.utilprotowriter = rootwriter.new_writer()
1.146 self.utildefwriter = rootwriter.new_writer()
1.147 @@ -257,10 +343,6 @@
1.148 self.cleanupwriter.putln("")
1.149 self.cleanupwriter.putln("static void __Pyx_CleanupGlobals(void) {")
1.150
1.151 - self.pystring_table.putln("")
1.152 - self.pystring_table.putln("static __Pyx_StringTabEntry %s[] = {" %
1.153 - Naming.stringtab_cname)
1.154 -
1.155 #
1.156 # Global constants, interned objects, etc.
1.157 #
1.158 @@ -270,16 +352,7 @@
1.159 def close_global_decls(self):
1.160 # This is called when it is known that no more global declarations will
1.161 # declared (but can be called before or after insert_XXX).
1.162 - if self.pystring_table_needed:
1.163 - self.pystring_table.putln("{0, 0, 0, 0, 0, 0}")
1.164 - self.pystring_table.putln("};")
1.165 - import Nodes
1.166 - self.use_utility_code(Nodes.init_string_tab_utility_code)
1.167 - self.initwriter.putln(
1.168 - "if (__Pyx_InitStrings(%s) < 0) %s;" % (
1.169 - Naming.stringtab_cname,
1.170 - self.initwriter.error_goto(self.module_pos)))
1.171 -
1.172 + self.generate_const_declarations()
1.173 if Options.cache_builtins:
1.174 w = self.init_cached_builtins_writer
1.175 w.putln("return 0;")
1.176 @@ -300,8 +373,7 @@
1.177 w.exit_cfunc_scope()
1.178
1.179 def insert_initcode_into(self, code):
1.180 - if self.pystring_table_needed:
1.181 - code.insert(self.pystring_table)
1.182 + code.insert(self.pystring_table)
1.183 if Options.cache_builtins:
1.184 code.insert(self.init_cached_builtins_writer)
1.185 code.insert(self.initwriter)
1.186 @@ -312,6 +384,137 @@
1.187 def put_pyobject_decl(self, entry):
1.188 self.decls_writer.putln("static PyObject *%s;" % entry.cname)
1.189
1.190 + # constant handling at code generation time
1.191 +
1.192 + def get_int_const(self, str_value, longness=False):
1.193 + longness = bool(longness or Utils.long_literal(str_value))
1.194 + try:
1.195 + c = self.int_const_index[(str_value, longness)]
1.196 + except KeyError:
1.197 + c = self.new_int_const(str_value, longness)
1.198 + return c
1.199 +
1.200 + def get_string_const(self, text):
1.201 + # return a C string constant, creating a new one if necessary
1.202 + if text.is_unicode:
1.203 + byte_string = text.utf8encode()
1.204 + else:
1.205 + byte_string = text.byteencode()
1.206 + try:
1.207 + c = self.string_const_index[byte_string]
1.208 + except KeyError:
1.209 + c = self.new_string_const(text, byte_string)
1.210 + return c
1.211 +
1.212 + def get_py_string_const(self, text, identifier=None):
1.213 + # return a Python string constant, creating a new one if necessary
1.214 + c_string = self.get_string_const(text)
1.215 + py_string = c_string.get_py_string_const(text.encoding, identifier)
1.216 + return py_string
1.217 +
1.218 + def new_string_const(self, text, byte_string):
1.219 + cname = self.new_string_const_cname(text)
1.220 + c = StringConst(cname, text, byte_string)
1.221 + self.string_const_index[byte_string] = c
1.222 + return c
1.223 +
1.224 + def new_int_const(self, value, longness):
1.225 + cname = self.new_int_const_cname(value, longness)
1.226 + c = IntConst(cname, value, longness)
1.227 + self.int_const_index[(value, longness)] = c
1.228 + return c
1.229 +
1.230 + def new_string_const_cname(self, value, intern=None):
1.231 + # Create a new globally-unique nice name for a C string constant.
1.232 + if len(value) < 20 and nice_identifier(value):
1.233 + return "%s%s" % (Naming.const_prefix, value)
1.234 + else:
1.235 + return self.new_const_cname()
1.236 +
1.237 + def new_int_const_cname(self, value, longness):
1.238 + if longness:
1.239 + value += 'L'
1.240 + cname = "%s%s" % (Naming.interned_num_prefix, value)
1.241 + cname = cname.replace('-', 'neg_').replace('.','_')
1.242 + return cname
1.243 +
1.244 + def new_const_cname(self, prefix=''):
1.245 + n = self.const_cname_counter
1.246 + self.const_cname_counter += 1
1.247 + return "%s%s%d" % (Naming.const_prefix, prefix, n)
1.248 +
1.249 + def add_cached_builtin_decl(self, entry):
1.250 + if Options.cache_builtins:
1.251 + if self.should_declare(entry.cname, entry):
1.252 + interned_cname = self.get_py_string_const(entry.name, True).cname
1.253 + self.put_pyobject_decl(entry)
1.254 + self.init_cached_builtins_writer.putln('%s = __Pyx_GetName(%s, %s); if (!%s) %s' % (
1.255 + entry.cname,
1.256 + Naming.builtins_cname,
1.257 + interned_cname,
1.258 + entry.cname,
1.259 + self.init_cached_builtins_writer.error_goto(entry.pos)))
1.260 +
1.261 + def generate_const_declarations(self):
1.262 + self.generate_string_constants()
1.263 + self.generate_int_constants()
1.264 +
1.265 + def generate_string_constants(self):
1.266 + c_consts = [ (len(c.cname), c.cname, c)
1.267 + for c in self.string_const_index.itervalues() ]
1.268 + c_consts.sort()
1.269 + py_strings = []
1.270 + for _, cname, c in c_consts:
1.271 + self.decls_writer.putln('static char %s[] = "%s";' % (
1.272 + cname, c.escaped_value))
1.273 + if c.py_strings is not None:
1.274 + for py_string in c.py_strings.itervalues():
1.275 + py_strings.append((c.cname, len(py_string.cname), py_string))
1.276 +
1.277 + if py_strings:
1.278 + import Nodes
1.279 + self.use_utility_code(Nodes.init_string_tab_utility_code)
1.280 +
1.281 + py_strings.sort()
1.282 + self.pystring_table.putln("")
1.283 + self.pystring_table.putln("static __Pyx_StringTabEntry %s[] = {" %
1.284 + Naming.stringtab_cname)
1.285 + for c_cname, _, py_string in py_strings:
1.286 + self.decls_writer.putln(
1.287 + "static PyObject *%s;" % py_string.cname)
1.288 + self.pystring_table.putln(
1.289 + "{&%s, %s, sizeof(%s), %d, %d, %d}," % (
1.290 + py_string.cname,
1.291 + c_cname,
1.292 + c_cname,
1.293 + py_string.unicode,
1.294 + py_string.intern,
1.295 + py_string.identifier
1.296 + ))
1.297 + self.pystring_table.putln("{0, 0, 0, 0, 0, 0}")
1.298 + self.pystring_table.putln("};")
1.299 +
1.300 + self.initwriter.putln(
1.301 + "if (__Pyx_InitStrings(%s) < 0) %s;" % (
1.302 + Naming.stringtab_cname,
1.303 + self.initwriter.error_goto(self.module_pos)))
1.304 +
1.305 + def generate_int_constants(self):
1.306 + consts = [ (len(c.value), c.value, c.is_long, c)
1.307 + for c in self.int_const_index.itervalues() ]
1.308 + consts.sort()
1.309 + for _, value, longness, c in consts:
1.310 + cname = c.cname
1.311 + self.decls_writer.putln("static PyObject *%s;" % cname)
1.312 + if longness:
1.313 + function = '%s = PyLong_FromString((char *)"%s", 0, 0); %s;'
1.314 + else:
1.315 + function = "%s = PyInt_FromLong(%s); %s;"
1.316 + self.initwriter.putln(function % (
1.317 + cname,
1.318 + value,
1.319 + self.initwriter.error_goto_if_null(cname, self.module_pos)))
1.320 +
1.321 # The functions below are there in a transition phase only
1.322 # and will be deprecated. They are called from Nodes.BlockNode.
1.323 # The copy&paste duplication is intentional in order to be able
1.324 @@ -327,55 +530,6 @@
1.325 self.declared_cnames[cname] = entry
1.326 return True
1.327
1.328 - def add_const_definition(self, entry):
1.329 - if self.should_declare(entry.cname, entry):
1.330 - self.decls_writer.put_var_declaration(entry, static = 1)
1.331 -
1.332 - def add_interned_string_decl(self, entry):
1.333 - if self.should_declare(entry.cname, entry):
1.334 - self.decls_writer.put_var_declaration(entry, static = 1)
1.335 - self.add_py_string_decl(entry)
1.336 -
1.337 - def add_py_string_decl(self, entry):
1.338 - if self.should_declare(entry.pystring_cname, entry):
1.339 - self.decls_writer.putln("static PyObject *%s;" % entry.pystring_cname)
1.340 - self.pystring_table_needed = True
1.341 - self.pystring_table.putln("{&%s, %s, sizeof(%s), %d, %d, %d}," % (
1.342 - entry.pystring_cname,
1.343 - entry.cname,
1.344 - entry.cname,
1.345 - entry.type.is_unicode,
1.346 - entry.is_interned,
1.347 - entry.is_identifier
1.348 - ))
1.349 -
1.350 - def add_interned_num_decl(self, entry):
1.351 - if self.should_declare(entry.cname, entry):
1.352 - if entry.init[-1] == "L":
1.353 - self.initwriter.putln('%s = PyLong_FromString((char *)"%s", 0, 0); %s;' % (
1.354 - entry.cname,
1.355 - entry.init[:-1], # strip 'L' for Py3 compatibility
1.356 - self.initwriter.error_goto_if_null(entry.cname, self.module_pos)))
1.357 - else:
1.358 - self.initwriter.putln("%s = PyInt_FromLong(%s); %s;" % (
1.359 - entry.cname,
1.360 - entry.init,
1.361 - self.initwriter.error_goto_if_null(entry.cname, self.module_pos)))
1.362 -
1.363 - self.put_pyobject_decl(entry)
1.364 -
1.365 - def add_cached_builtin_decl(self, entry):
1.366 - if Options.cache_builtins:
1.367 - if self.should_declare(entry.cname, entry):
1.368 - self.put_pyobject_decl(entry)
1.369 - self.init_cached_builtins_writer.putln('%s = __Pyx_GetName(%s, %s); if (!%s) %s' % (
1.370 - entry.cname,
1.371 - Naming.builtins_cname,
1.372 - entry.interned_cname,
1.373 - entry.cname,
1.374 - self.init_cached_builtins_writer.error_goto(entry.pos)))
1.375 -
1.376 -
1.377 #
1.378 # File name state
1.379 #
1.380 @@ -475,6 +629,7 @@
1.381 setattr(self.funcstate, name, value)
1.382 return property(get, set)
1.383
1.384 +
1.385 class CCodeWriter(object):
1.386 """
1.387 Utility class to output C code.
1.388 @@ -596,6 +751,25 @@
1.389 def exit_cfunc_scope(self):
1.390 self.funcstate = None
1.391
1.392 + # constant handling
1.393 +
1.394 + def get_py_num(self, str_value, longness):
1.395 + return self.globalstate.get_int_const(str_value, longness).cname
1.396 +
1.397 + def get_string_const(self, text):
1.398 + return self.globalstate.get_string_const(text).cname
1.399 +
1.400 + def get_py_string_const(self, text, identifier=None):
1.401 + return self.globalstate.get_py_string_const(text, identifier).cname
1.402 +
1.403 + def intern(self, text):
1.404 + return self.get_py_string_const(text)
1.405 +
1.406 + def intern_identifier(self, text):
1.407 + return self.get_py_string_const(text, True)
1.408 +
1.409 + # code generation
1.410 +
1.411 def putln(self, code = ""):
1.412 if self.marker and self.bol:
1.413 self.emit_marker()
1.414 @@ -732,6 +906,18 @@
1.415 else:
1.416 self.putln("%s;" % decl)
1.417
1.418 + def put_h_guard(self, guard):
1.419 + self.putln("#ifndef %s" % guard)
1.420 + self.putln("#define %s" % guard)
1.421 +
1.422 + def unlikely(self, cond):
1.423 + if Options.gcc_branch_hints:
1.424 + return 'unlikely(%s)' % cond
1.425 + else:
1.426 + return cond
1.427 +
1.428 + # Python objects and reference counting
1.429 +
1.430 def entry_as_pyobject(self, entry):
1.431 type = entry.type
1.432 if (not entry.is_self_arg and not entry.type.is_complete()
1.433 @@ -876,20 +1062,12 @@
1.434 doc_code,
1.435 term))
1.436
1.437 + # error handling
1.438 +
1.439 def put_error_if_neg(self, pos, value):
1.440 # return self.putln("if (unlikely(%s < 0)) %s" % (value, self.error_goto(pos))) # TODO this path is almost _never_ taken, yet this macro makes is slower!
1.441 return self.putln("if (%s < 0) %s" % (value, self.error_goto(pos)))
1.442
1.443 - def put_h_guard(self, guard):
1.444 - self.putln("#ifndef %s" % guard)
1.445 - self.putln("#define %s" % guard)
1.446 -
1.447 - def unlikely(self, cond):
1.448 - if Options.gcc_branch_hints:
1.449 - return 'unlikely(%s)' % cond
1.450 - else:
1.451 - return cond
1.452 -
1.453 def set_error_info(self, pos):
1.454 if Options.c_line_in_traceback:
1.455 cinfo = " %s = %s;" % (Naming.clineno_cname, Naming.line_c_macro)
1.456 @@ -937,7 +1115,7 @@
1.457 # level int indentation level
1.458
1.459 def __init__(self, outfile_name):
1.460 - self.f = open_new_file(outfile_name)
1.461 + self.f = Utils.open_new_file(outfile_name)
1.462 self.level = 0
1.463
1.464 def putln(self, code):
2.1 --- a/Cython/Compiler/ExprNodes.py Sun Mar 15 19:34:39 2009 +0100
2.2 +++ b/Cython/Compiler/ExprNodes.py Wed Mar 18 21:44:34 2009 +0100
2.3 @@ -541,7 +541,7 @@
2.4 src_type = self.type
2.5 src_is_py_type = src_type.is_pyobject
2.6 dst_is_py_type = dst_type.is_pyobject
2.7 -
2.8 +
2.9 if dst_type.is_pyobject:
2.10 if not src.type.is_pyobject:
2.11 src = CoerceToPyTypeNode(src, env)
2.12 @@ -857,7 +857,6 @@
2.13 # Arrange for a Python version of the number to be pre-allocated
2.14 # when coercing to a Python type.
2.15 if dst_type.is_pyobject:
2.16 - self.entry = env.get_py_num(self.value, self.longness)
2.17 self.type = PyrexTypes.py_object_type
2.18 # We still need to perform normal coerce_to processing on the
2.19 # result, because we might be coercing to an extension type,
2.20 @@ -868,11 +867,14 @@
2.21 self.type = PyrexTypes.c_bint_type
2.22 return self
2.23
2.24 - def calculate_result_code(self):
2.25 - if self.type.is_pyobject:
2.26 - return self.entry.cname
2.27 - else:
2.28 - return str(self.value) + self.unsigned + self.longness
2.29 + def generate_evaluation_code(self, code):
2.30 + if self.type.is_pyobject:
2.31 + self.result_code = code.get_py_num(self.value, self.longness)
2.32 + else:
2.33 + self.result_code = str(self.value) + self.unsigned + self.longness
2.34 +
2.35 + def calculate_result_code(self):
2.36 + return self.result_code
2.37
2.38 def calculate_constant_result(self):
2.39 self.constant_result = int(self.value, 0)
2.40 @@ -903,16 +905,11 @@
2.41
2.42
2.43 class StringNode(ConstNode):
2.44 - # entry Symtab.Entry
2.45 -
2.46 type = PyrexTypes.c_char_ptr_type
2.47
2.48 def compile_time_value(self, denv):
2.49 return self.value
2.50 -
2.51 - def analyse_types(self, env):
2.52 - self.entry = env.add_string_const(self.value)
2.53 -
2.54 +
2.55 def analyse_as_type(self, env):
2.56 type = PyrexTypes.parse_basic_type(self.value)
2.57 if type is not None:
2.58 @@ -924,17 +921,17 @@
2.59 sizeof_node.analyse_types(env)
2.60 if isinstance(sizeof_node, SizeofTypeNode):
2.61 return sizeof_node.arg_type
2.62 -
2.63 +
2.64 def coerce_to(self, dst_type, env):
2.65 if dst_type == PyrexTypes.c_char_ptr_type:
2.66 self.type = PyrexTypes.c_char_ptr_type
2.67 return self
2.68 -
2.69 +
2.70 if dst_type.is_int:
2.71 - if not self.type.is_pyobject and len(self.entry.init) == 1:
2.72 + if not self.type.is_pyobject and len(self.value) == 1:
2.73 return CharNode(self.pos, value=self.value)
2.74 else:
2.75 - error(self.pos, "Only coerce single-character ascii strings can be used as ints.")
2.76 + error(self.pos, "Only single-character byte strings can be coerced into ints.")
2.77 return self
2.78 # Arrange for a Python version of the string to be pre-allocated
2.79 # when coercing to a Python type.
2.80 @@ -948,40 +945,38 @@
2.81 return ConstNode.coerce_to(node, dst_type, env)
2.82
2.83 def as_py_string_node(self, env):
2.84 - # Return a new StringNode with the same entry as this node
2.85 + # Return a new StringNode with the same value as this node
2.86 # but whose type is a Python type instead of a C type.
2.87 - entry = self.entry
2.88 - env.add_py_string(entry)
2.89 - return StringNode(self.pos, value = self.value, entry = entry, type = py_object_type)
2.90 -
2.91 - def calculate_result_code(self):
2.92 - if self.type.is_pyobject:
2.93 - return self.entry.pystring_cname
2.94 - else:
2.95 - return self.entry.cname
2.96 + return StringNode(self.pos, value = self.value, type = py_object_type)
2.97 +
2.98 + def generate_evaluation_code(self, code):
2.99 + if self.type.is_pyobject:
2.100 + self.result_code = code.get_py_string_const(self.value)
2.101 + else:
2.102 + self.result_code = code.get_string_const(self.value)
2.103 +
2.104 + def calculate_result_code(self):
2.105 + return self.result_code
2.106
2.107
2.108 class UnicodeNode(PyConstNode):
2.109 - # entry Symtab.Entry
2.110 -
2.111 type = unicode_type
2.112 -
2.113 - def analyse_types(self, env):
2.114 - self.entry = env.add_string_const(self.value)
2.115 - env.add_py_string(self.entry)
2.116 -
2.117 - def calculate_result_code(self):
2.118 - return self.entry.pystring_cname
2.119 -
2.120 - def _coerce_to(self, dst_type, env):
2.121 - if not dst_type.is_pyobject:
2.122 - node = StringNode(self.pos, entry = entry, type = py_object_type)
2.123 - return ConstNode.coerce_to(node, dst_type, env)
2.124 - else:
2.125 - return self
2.126 - # We still need to perform normal coerce_to processing on the
2.127 - # result, because we might be coercing to an extension type,
2.128 - # in which case a type test node will be needed.
2.129 +
2.130 + def coerce_to(self, dst_type, env):
2.131 + if dst_type.is_pyobject:
2.132 + return self
2.133 + else:
2.134 + error(self.pos, "Unicode objects do not support coercion to C types.")
2.135 + return self
2.136 +
2.137 + def generate_evaluation_code(self, code):
2.138 + if self.type.is_pyobject:
2.139 + self.result_code = code.get_py_string_const(self.value)
2.140 + else:
2.141 + self.result_code = code.get_string_const(self.value)
2.142 +
2.143 + def calculate_result_code(self):
2.144 + return self.result_code
2.145
2.146 def compile_time_value(self, env):
2.147 return self.value
2.148 @@ -992,11 +987,14 @@
2.149 # keyword arguments in a call, or for imported names
2.150 type = PyrexTypes.py_object_type
2.151
2.152 - def analyse_types(self, env):
2.153 - self.cname = env.intern_identifier(self.value)
2.154 -
2.155 - def calculate_result_code(self):
2.156 - return self.cname
2.157 + def generate_evaluation_code(self, code):
2.158 + if self.type.is_pyobject:
2.159 + self.result_code = code.get_py_string_const(self.value, True)
2.160 + else:
2.161 + self.result_code = code.get_string_const(self.value)
2.162 +
2.163 + def calculate_result_code(self):
2.164 + return self.result_code
2.165
2.166
2.167 class LongNode(AtomicNewTempExprNode):
2.168 @@ -1058,7 +1056,6 @@
2.169 # name string Python name of the variable
2.170 #
2.171 # entry Entry Symbol table entry
2.172 - # interned_cname string
2.173
2.174 is_name = True
2.175 is_cython_module = False
2.176 @@ -1200,10 +1197,6 @@
2.177 entry = self.entry
2.178 type = entry.type
2.179 self.type = type
2.180 - if entry.is_pyglobal or entry.is_builtin:
2.181 - assert type.is_pyobject, "Python global or builtin not a Python object"
2.182 - self.interned_cname = self.entry.interned_cname = \
2.183 - env.intern_identifier(self.entry.name)
2.184
2.185 def check_identifier_kind(self):
2.186 #print "NameNode.check_identifier_kind:", self.entry.name ###
2.187 @@ -1270,6 +1263,8 @@
2.188 if entry.is_builtin and Options.cache_builtins:
2.189 return # Lookup already cached
2.190 elif entry.is_pyglobal or entry.is_builtin:
2.191 + assert entry.type.is_pyobject, "Python global or builtin not a Python object"
2.192 + interned_cname = code.intern_identifier(self.entry.name)
2.193 if entry.is_builtin:
2.194 namespace = Naming.builtins_cname
2.195 else: # entry.is_pyglobal
2.196 @@ -1278,7 +1273,7 @@
2.197 '%s = __Pyx_GetName(%s, %s); %s' % (
2.198 self.result(),
2.199 namespace,
2.200 - self.interned_cname,
2.201 + interned_cname,
2.202 code.error_goto_if_null(self.result(), self.pos)))
2.203 code.put_gotref(self.py_result())
2.204
2.205 @@ -1305,6 +1300,8 @@
2.206 # is_pyglobal seems to be True for module level-globals only.
2.207 # We use this to access class->tp_dict if necessary.
2.208 if entry.is_pyglobal:
2.209 + assert entry.type.is_pyobject, "Python global or builtin not a Python object"
2.210 + interned_cname = code.intern_identifier(self.entry.name)
2.211 namespace = self.entry.scope.namespace_cname
2.212 if entry.is_member:
2.213 # if the entry is a member we have to cheat: SetAttr does not work
2.214 @@ -1312,7 +1309,7 @@
2.215 code.put_error_if_neg(self.pos,
2.216 'PyDict_SetItem(%s->tp_dict, %s, %s)' % (
2.217 namespace,
2.218 - self.interned_cname,
2.219 + interned_cname,
2.220 rhs.py_result()))
2.221 rhs.generate_disposal_code(code)
2.222 rhs.free_temps(code)
2.223 @@ -1323,7 +1320,7 @@
2.224 code.put_error_if_neg(self.pos,
2.225 'PyObject_SetAttr(%s, %s, %s)' % (
2.226 namespace,
2.227 - self.interned_cname,
2.228 + interned_cname,
2.229 rhs.py_result()))
2.230 if debug_disposal_code:
2.231 print("NameNode.generate_assignment_code:")
2.232 @@ -2630,7 +2627,6 @@
2.233 # member string C name of struct member
2.234 # is_called boolean Function call is being done on result
2.235 # entry Entry Symbol table entry of attribute
2.236 - # interned_attr_cname string C name of interned attribute name
2.237
2.238 is_attribute = 1
2.239 subexprs = ['obj']
2.240 @@ -2830,7 +2826,6 @@
2.241 if obj_type.is_pyobject:
2.242 self.type = py_object_type
2.243 self.is_py_attr = 1
2.244 - self.interned_attr_cname = env.intern_identifier(self.attribute)
2.245 else:
2.246 if not obj_type.is_error:
2.247 error(self.pos,
2.248 @@ -2879,12 +2874,13 @@
2.249 return "%s%s%s" % (obj_code, self.op, self.member)
2.250
2.251 def generate_result_code(self, code):
2.252 + interned_attr_cname = code.intern_identifier(self.attribute)
2.253 if self.is_py_attr:
2.254 code.putln(
2.255 '%s = PyObject_GetAttr(%s, %s); %s' % (
2.256 self.result(),
2.257 self.obj.py_result(),
2.258 - self.interned_attr_cname,
2.259 + interned_attr_cname,
2.260 code.error_goto_if_null(self.result(), self.pos)))
2.261 code.put_gotref(self.py_result())
2.262 else:
2.263 @@ -2896,12 +2892,13 @@
2.264 self.put_nonecheck(code)
2.265
2.266 def generate_assignment_code(self, rhs, code):
2.267 + interned_attr_cname = code.intern_identifier(self.attribute)
2.268 self.obj.generate_evaluation_code(code)
2.269 if self.is_py_attr:
2.270 code.put_error_if_neg(self.pos,
2.271 'PyObject_SetAttr(%s, %s, %s)' % (
2.272 self.obj.py_result(),
2.273 - self.interned_attr_cname,
2.274 + interned_attr_cname,
2.275 rhs.py_result()))
2.276 rhs.generate_disposal_code(code)
2.277 rhs.free_temps(code)
2.278 @@ -2928,12 +2925,13 @@
2.279 self.obj.free_temps(code)
2.280
2.281 def generate_deletion_code(self, code):
2.282 + interned_attr_cname = code.intern_identifier(self.attribute)
2.283 self.obj.generate_evaluation_code(code)
2.284 if self.is_py_attr:
2.285 code.put_error_if_neg(self.pos,
2.286 'PyObject_DelAttr(%s, %s)' % (
2.287 self.obj.py_result(),
2.288 - self.interned_attr_cname))
2.289 + interned_attr_cname))
2.290 else:
2.291 error(self.pos, "Cannot delete C attribute of extension type")
2.292 self.obj.generate_disposal_code(code)
2.293 @@ -3552,7 +3550,6 @@
2.294 # a name, tuple of bases and class dictionary.
2.295 #
2.296 # name EncodedString Name of the class
2.297 - # cname string Class name as a Python string
2.298 # bases ExprNode Base class tuple
2.299 # dict ExprNode Class dict (not owned by this node)
2.300 # doc ExprNode or None Doc string
2.301 @@ -3561,7 +3558,6 @@
2.302 subexprs = ['bases', 'doc']
2.303
2.304 def analyse_types(self, env):
2.305 - self.cname = env.intern_identifier(self.name)
2.306 self.bases.analyse_types(env)
2.307 if self.doc:
2.308 self.doc.analyse_types(env)
2.309 @@ -3574,6 +3570,7 @@
2.310 gil_message = "Constructing Python class"
2.311
2.312 def generate_result_code(self, code):
2.313 + cname = code.intern_identifier(self.name)
2.314 if self.doc:
2.315 code.put_error_if_neg(self.pos,
2.316 'PyDict_SetItemString(%s, "__doc__", %s)' % (
2.317 @@ -3584,7 +3581,7 @@
2.318 self.result(),
2.319 self.bases.py_result(),
2.320 self.dict.py_result(),
2.321 - self.cname,
2.322 + cname,
2.323 self.module_name,
2.324 code.error_goto_if_null(self.result(), self.pos)))
2.325 code.put_gotref(self.py_result())
3.1 --- a/Cython/Compiler/ModuleNode.py Sun Mar 15 19:34:39 2009 +0100
3.2 +++ b/Cython/Compiler/ModuleNode.py Wed Mar 18 21:44:34 2009 +0100
3.3 @@ -261,7 +261,7 @@
3.4 self.generate_py_string_decls(env, code)
3.5
3.6 code.globalstate.insert_global_var_declarations_into(code)
3.7 -
3.8 +
3.9 self.generate_cached_builtins_decls(env, code)
3.10 self.body.generate_function_definitions(env, code)
3.11 code.mark_pos(None)
3.12 @@ -550,13 +550,6 @@
3.13 code.putln('static const char * %s= %s;' % (Naming.cfilenm_cname, Naming.file_c_macro))
3.14 code.putln('static const char *%s;' % Naming.filename_cname)
3.15 code.putln('static const char **%s;' % Naming.filetable_cname)
3.16 - if env.doc:
3.17 - docstr = env.doc
3.18 - if not isinstance(docstr, str):
3.19 - docstr = docstr.utf8encode()
3.20 - code.putln('')
3.21 - code.putln('static char %s[] = "%s";' % (
3.22 - env.doc_cname, escape_byte_string(docstr)))
3.23
3.24 env.use_utility_code(streq_utility_code)
3.25
3.26 @@ -1491,12 +1484,16 @@
3.27 "static struct PyGetSetDef %s[] = {" %
3.28 env.getset_table_cname)
3.29 for entry in env.property_entries:
3.30 + if entry.doc:
3.31 + doc_code = "__Pyx_DOCSTR(%s)" % code.get_string_const(entry.doc)
3.32 + else:
3.33 + doc_code = "0"
3.34 code.putln(
3.35 '{(char *)"%s", %s, %s, %s, 0},' % (
3.36 entry.name,
3.37 entry.getter_cname or "0",
3.38 entry.setter_cname or "0",
3.39 - entry.doc_cname or "0"))
3.40 + doc_code))
3.41 code.putln(
3.42 "{0, 0, 0, 0, 0}")
3.43 code.putln(
3.44 @@ -1719,7 +1716,7 @@
3.45
3.46 def generate_pymoduledef_struct(self, env, code):
3.47 if env.doc:
3.48 - doc = "__Pyx_DOCSTR(%s)" % env.doc_cname
3.49 + doc = "__Pyx_DOCSTR(%s)" % code.get_string_const(env.doc)
3.50 else:
3.51 doc = "0"
3.52 code.putln("")
3.53 @@ -1741,7 +1738,7 @@
3.54 # Generate code to create the module object and
3.55 # install the builtins.
3.56 if env.doc:
3.57 - doc = env.doc_cname
3.58 + doc = "__Pyx_DOCSTR(%s)" % code.get_string_const(env.doc)
3.59 else:
3.60 doc = "0"
3.61 code.putln("#if PY_MAJOR_VERSION < 3")
4.1 --- a/Cython/Compiler/Naming.py Sun Mar 15 19:34:39 2009 +0100
4.2 +++ b/Cython/Compiler/Naming.py Wed Mar 18 21:44:34 2009 +0100
4.3 @@ -27,6 +27,7 @@
4.4 pymethdef_prefix = pyrex_prefix + "mdef_"
4.5 methtab_prefix = pyrex_prefix + "methods_"
4.6 memtab_prefix = pyrex_prefix + "members_"
4.7 +interned_str_prefix = pyrex_prefix + "n_"
4.8 interned_num_prefix = pyrex_prefix + "int_"
4.9 objstruct_prefix = pyrex_prefix + "obj_"
4.10 typeptr_prefix = pyrex_prefix + "ptype_"
5.1 --- a/Cython/Compiler/Nodes.py Sun Mar 15 19:34:39 2009 +0100
5.2 +++ b/Cython/Compiler/Nodes.py Wed Mar 18 21:44:34 2009 +0100
5.3 @@ -489,7 +489,7 @@
5.4 self.dimension.analyse_const_expression(env)
5.5 if not self.dimension.type.is_int:
5.6 error(self.dimension.pos, "Array dimension not integer")
5.7 - size = self.dimension.result()
5.8 + size = self.dimension.compile_time_value(env)
5.9 try:
5.10 size = int(size)
5.11 except ValueError:
5.12 @@ -581,7 +581,7 @@
5.13 "Exception value must be a Python exception or cdef function with no arguments.")
5.14 exc_val = self.exception_value
5.15 else:
5.16 - exc_val = self.exception_value.result()
5.17 + exc_val = self.exception_value.compile_time_value(env)
5.18 if not return_type.assignable_from(self.exception_value.type):
5.19 error(self.exception_value.pos,
5.20 "Exception value incompatible with function return type")
5.21 @@ -642,6 +642,17 @@
5.22 else:
5.23 return self.name_declarator, self.type
5.24
5.25 + def prepare_default_result_code(self, code):
5.26 + if self.default:
5.27 + if self.default.is_literal:
5.28 + # FIXME: IS IT OK TO CALL THIS HERE???
5.29 + self.default.generate_evaluation_code(code)
5.30 + self.default_result_code = self.default.result()
5.31 + if self.default.type != self.type and not self.type.is_int:
5.32 + self.default_result_code = self.type.cast_code(self.default_result_code)
5.33 + else:
5.34 + self.default_result_code = self.default_entry.cname
5.35 +
5.36 def annotate(self, code):
5.37 if self.default:
5.38 self.default.annotate(code)
5.39 @@ -934,7 +945,7 @@
5.40 if not self.value.type.is_int:
5.41 self.value = self.value.coerce_to(PyrexTypes.c_int_type, env)
5.42 self.value.analyse_const_expression(env)
5.43 - value = self.value.result()
5.44 + value = self.value.compile_time_value(env)
5.45 else:
5.46 value = self.name
5.47 entry = env.declare_const(self.name, enum_entry.type,
5.48 @@ -989,21 +1000,17 @@
5.49 arg.default = arg.default.coerce_to(arg.type, genv)
5.50 if arg.default.is_literal:
5.51 arg.default_entry = arg.default
5.52 - arg.default_result_code = arg.default.calculate_result_code()
5.53 - if arg.default.type != arg.type and not arg.type.is_int:
5.54 - arg.default_result_code = arg.type.cast_code(arg.default_result_code)
5.55 else:
5.56 arg.default.allocate_temps(genv)
5.57 arg.default_entry = genv.add_default_value(arg.type)
5.58 if arg.type.is_pyobject:
5.59 arg.default_entry.init = 0
5.60 arg.default_entry.used = 1
5.61 - arg.default_result_code = arg.default_entry.cname
5.62 else:
5.63 error(arg.pos,
5.64 "This argument cannot have a default value")
5.65 arg.default = None
5.66 -
5.67 +
5.68 def need_gil_acquisition(self, lenv):
5.69 return 0
5.70
5.71 @@ -1350,8 +1357,6 @@
5.72 self.entry.as_variable = self.py_func.entry
5.73 # Reset scope entry the above cfunction
5.74 env.entries[name] = self.entry
5.75 - self.py_func.interned_attr_cname = env.intern_identifier(
5.76 - self.py_func.entry.name)
5.77 if not env.is_module_scope or Options.lookup_module_cpdef:
5.78 self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
5.79 self.body = StatListNode(self.pos, stats=[self.override, self.body])
5.80 @@ -1433,7 +1438,9 @@
5.81 def generate_argument_declarations(self, env, code):
5.82 for arg in self.args:
5.83 if arg.default:
5.84 - code.putln('%s = %s;' % (arg.type.declaration_code(arg.cname), arg.default_result_code))
5.85 + arg.prepare_default_result_code(code)
5.86 + code.putln('%s = %s;' % (
5.87 + arg.type.declaration_code(arg.cname), arg.default_result_code))
5.88
5.89 def generate_keyword_list(self, code):
5.90 pass
5.91 @@ -1793,10 +1800,6 @@
5.92 arg.entry = self.declare_argument(env, arg)
5.93 arg.entry.used = 1
5.94 arg.entry.is_self_arg = arg.is_self_arg
5.95 - if not arg.is_self_arg:
5.96 - arg.name_entry = env.get_string_const(
5.97 - arg.name, identifier = True)
5.98 - env.add_py_string(arg.name_entry, identifier = True)
5.99 if arg.hdr_type:
5.100 if arg.is_self_arg or \
5.101 (arg.type.is_extension_type and not arg.hdr_type.is_extension_type):
5.102 @@ -1878,6 +1881,8 @@
5.103 code.putln("PyObject *%s = 0;" % arg.hdr_cname)
5.104 else:
5.105 code.put_var_declaration(arg.entry)
5.106 + if arg.default:
5.107 + arg.prepare_default_result_code(code)
5.108
5.109 def generate_keyword_list(self, code):
5.110 if self.signature_has_generic_args() and \
5.111 @@ -1887,7 +1892,8 @@
5.112 Naming.pykwdlist_cname)
5.113 for arg in self.args:
5.114 if arg.is_generic:
5.115 - code.put('&%s,' % arg.name_entry.pystring_cname)
5.116 + pystring_cname = code.intern_identifier(arg.name)
5.117 + code.put('&%s,' % pystring_cname)
5.118 code.putln("0};")
5.119
5.120 def generate_argument_parsing_code(self, env, code):
5.121 @@ -2073,10 +2079,11 @@
5.122 code.putln('} else {')
5.123 for i, arg in enumerate(kw_only_args):
5.124 if not arg.default:
5.125 + pystring_cname = code.intern_identifier(arg.name)
5.126 # required keyword-only argument missing
5.127 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' % (
5.128 self.name.utf8encode(),
5.129 - arg.name_entry.pystring_cname))
5.130 + pystring_cname))
5.131 code.putln(code.error_goto(self.pos))
5.132 break
5.133
5.134 @@ -2224,19 +2231,20 @@
5.135 code.putln('default:')
5.136 else:
5.137 code.putln('case %2d:' % i)
5.138 + pystring_cname = code.intern_identifier(arg.name)
5.139 if arg.default:
5.140 if arg.kw_only:
5.141 # handled separately below
5.142 continue
5.143 code.putln('if (kw_args > %d) {' % num_required_args)
5.144 code.putln('PyObject* value = PyDict_GetItem(%s, %s);' % (
5.145 - Naming.kwds_cname, arg.name_entry.pystring_cname))
5.146 + Naming.kwds_cname, pystring_cname))
5.147 code.putln('if (unlikely(value)) { values[%d] = value; kw_args--; }' % i)
5.148 code.putln('}')
5.149 else:
5.150 num_required_args -= 1
5.151 code.putln('values[%d] = PyDict_GetItem(%s, %s);' % (
5.152 - i, Naming.kwds_cname, arg.name_entry.pystring_cname))
5.153 + i, Naming.kwds_cname, pystring_cname))
5.154 code.putln('if (likely(values[%d])) kw_args--;' % i);
5.155 if i < min_positional_args:
5.156 if i == 0:
5.157 @@ -2256,7 +2264,7 @@
5.158 elif arg.kw_only:
5.159 code.putln('else {')
5.160 code.put('__Pyx_RaiseKeywordRequired("%s", %s); ' %(
5.161 - self.name.utf8encode(), arg.name_entry.pystring_cname))
5.162 + self.name.utf8encode(), pystring_cname))
5.163 code.putln(code.error_goto(self.pos))
5.164 code.putln('}')
5.165 if max_positional_args > 0:
5.166 @@ -2276,9 +2284,10 @@
5.167 code.putln('while (kw_args > 0) {')
5.168 code.putln('PyObject* value;')
5.169 for i, arg in optional_args:
5.170 + pystring_cname = code.intern_identifier(arg.name)
5.171 code.putln(
5.172 'value = PyDict_GetItem(%s, %s);' % (
5.173 - Naming.kwds_cname, arg.name_entry.pystring_cname))
5.174 + Naming.kwds_cname, pystring_cname))
5.175 code.putln(
5.176 'if (value) { values[%d] = value; if (!(--kw_args)) break; }' % i)
5.177 code.putln('break;')
5.178 @@ -2445,6 +2454,7 @@
5.179 self.body.analyse_expressions(env)
5.180
5.181 def generate_execution_code(self, code):
5.182 + interned_attr_cname = code.intern_identifier(self.py_func.entry.name)
5.183 # Check to see if we are an extension type
5.184 if self.py_func.is_module_scope:
5.185 self_arg = "((PyObject *)%s)" % Naming.module_cname
5.186 @@ -2459,10 +2469,12 @@
5.187 code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
5.188 err = code.error_goto_if_null(self.func_node.result(), self.pos)
5.189 # need to get attribute manually--scope would return cdef method
5.190 - code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (self.func_node.result(), self_arg, self.py_func.interned_attr_cname, err))
5.191 + code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (
5.192 + self.func_node.result(), self_arg, interned_attr_cname, err))
5.193 code.put_gotref(self.func_node.py_result())
5.194 is_builtin_function_or_method = 'PyCFunction_Check(%s)' % self.func_node.result()
5.195 - is_overridden = '(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)' % (self.func_node.result(), self.py_func.entry.func_cname)
5.196 + is_overridden = '(PyCFunction_GET_FUNCTION(%s) != (void *)&%s)' % (
5.197 + self.func_node.result(), self.py_func.entry.func_cname)
5.198 code.putln('if (!%s || %s) {' % (is_builtin_function_or_method, is_overridden))
5.199 self.body.generate_execution_code(code)
5.200 code.putln('}')
5.201 @@ -2732,10 +2744,6 @@
5.202 def analyse_declarations(self, env):
5.203 entry = env.declare_property(self.name, self.doc, self.pos)
5.204 if entry:
5.205 - if self.doc and Options.docstrings:
5.206 - doc_entry = env.get_string_const(
5.207 - self.doc, identifier = False)
5.208 - entry.doc_cname = doc_entry.cname
5.209 self.body.analyse_declarations(entry.scope)
5.210
5.211 def analyse_expressions(self, env):
5.212 @@ -4709,7 +4717,7 @@
5.213 else:
5.214 coerced_item = self.item.coerce_to(target.type, env)
5.215 self.interned_items.append(
5.216 - (env.intern_identifier(name), target, coerced_item))
5.217 + (name, target, coerced_item))
5.218 #target.release_target_temp(env) # was release_temp ?!?
5.219 self.module.release_temp(env)
5.220 self.item.release_temp(env)
5.221 @@ -4722,7 +4730,8 @@
5.222 Naming.import_star,
5.223 self.module.py_result(),
5.224 code.error_goto(self.pos)))
5.225 - for cname, target, coerced_item in self.interned_items:
5.226 + for name, target, coerced_item in self.interned_items:
5.227 + cname = code.intern_identifier(name)
5.228 code.putln(
5.229 '%s = PyObject_GetAttr(%s, %s); %s' % (
5.230 self.item.result(),
6.1 --- a/Cython/Compiler/Symtab.py Sun Mar 15 19:34:39 2009 +0100
6.2 +++ b/Cython/Compiler/Symtab.py Wed Mar 18 21:44:34 2009 +0100
6.3 @@ -248,9 +248,6 @@
6.4 def __str__(self):
6.5 return "<%s %s>" % (self.__class__.__name__, self.qualified_name)
6.6
6.7 - def intern_identifier(self, name):
6.8 - return self.global_scope().intern_identifier(name)
6.9 -
6.10 def qualifying_scope(self):
6.11 return self.parent_scope
6.12
6.13 @@ -521,98 +518,6 @@
6.14 if entry and entry.is_type:
6.15 return entry.type
6.16
6.17 - def add_string_const(self, value, identifier = False):
6.18 - # Add an entry for a string constant.
6.19 - if identifier:
6.20 - cname = self.new_string_const_cname(value)
6.21 - else:
6.22 - cname = self.new_const_cname()
6.23 - if value.is_unicode:
6.24 - c_type = PyrexTypes.c_utf8_char_array_type
6.25 - value = value.utf8encode()
6.26 - else:
6.27 - c_type = PyrexTypes.c_char_array_type
6.28 - value = value.byteencode()
6.29 - entry = Entry("", cname, c_type, init = value)
6.30 - entry.used = 1
6.31 - self.const_entries.append(entry)
6.32 - return entry
6.33 -
6.34 - def get_string_const(self, value, identifier = False):
6.35 - # Get entry for string constant. Returns an existing
6.36 - # one if possible, otherwise creates a new one.
6.37 - genv = self.global_scope()
6.38 - if identifier:
6.39 - string_map = genv.identifier_to_entry
6.40 - else:
6.41 - string_map = genv.string_to_entry
6.42 - entry = string_map.get(value)
6.43 - if not entry:
6.44 - entry = self.add_string_const(value, identifier)
6.45 - entry.is_identifier = identifier
6.46 - string_map[value] = entry
6.47 - return entry
6.48 -
6.49 - def add_py_string(self, entry, identifier = None):
6.50 - # If not already done, allocate a C name for a Python version of
6.51 - # a string literal, and add it to the list of Python strings to
6.52 - # be created at module init time. If the string resembles a
6.53 - # Python identifier, it will be interned.
6.54 - if entry.pystring_cname:
6.55 - return
6.56 - value = entry.init
6.57 - entry.pystring_cname = Naming.py_const_prefix + entry.cname[len(Naming.const_prefix):]
6.58 - self.pystring_entries.append(entry)
6.59 - self.global_scope().all_pystring_entries.append(entry)
6.60 - if identifier or (identifier is None and possible_identifier(value)):
6.61 - entry.is_interned = 1
6.62 - self.global_scope().new_interned_string_entries.append(entry)
6.63 -
6.64 - def add_py_num(self, value):
6.65 - # Add an entry for an int constant.
6.66 - cname = "%s%s" % (Naming.interned_num_prefix, value)
6.67 - cname = cname.replace('-', 'neg_').replace('.','_')
6.68 - entry = Entry("", cname, py_object_type, init = value)
6.69 - entry.used = 1
6.70 - entry.is_interned = 1
6.71 - self.const_entries.append(entry)
6.72 - self.interned_nums.append(entry)
6.73 - return entry
6.74 -
6.75 - def get_py_num(self, value, longness):
6.76 - # Get entry for int constant. Returns an existing
6.77 - # one if possible, otherwise creates a new one.
6.78 - if longness or Utils.long_literal(value):
6.79 - value += "L"
6.80 - genv = self.global_scope()
6.81 - entry = genv.num_to_entry.get(value)
6.82 - if not entry:
6.83 - entry = genv.add_py_num(value)
6.84 - genv.num_to_entry[value] = entry
6.85 - genv.pynum_entries.append(entry)
6.86 - return entry
6.87 -
6.88 - def get_py_obj(self, obj, c_prefix=''):
6.89 - # Get entry for a generic constant. Returns an existing
6.90 - # one if possible, otherwise creates a new one.
6.91 - genv = self.global_scope()
6.92 - entry = genv.obj_to_entry.get(obj)
6.93 - if not entry:
6.94 - entry = genv.add_py_num(obj, c_prefix)
6.95 - genv.obj_to_entry[obj] = entry
6.96 - return entry
6.97 -
6.98 - def new_string_const_cname(self, value):
6.99 - # Create a new globally-unique nice name for a string constant.
6.100 - if len(value) < 20 and nice_identifier(value):
6.101 - return "%s%s" % (Naming.const_prefix, value)
6.102 - else:
6.103 - return self.global_scope().new_const_cname()
6.104 -
6.105 - def new_const_cname(self):
6.106 - # Create a new globally-unique name for a constant.
6.107 - return self.global_scope().new_const_cname()
6.108 -
6.109 def allocate_temp(self, type):
6.110 # Allocate a temporary variable of the given type from the
6.111 # free list if available, otherwise create a new one.
6.112 @@ -870,11 +775,6 @@
6.113 entry.is_builtin = 1
6.114 return entry
6.115
6.116 - def intern_identifier(self, name):
6.117 - string_entry = self.get_string_const(name, identifier = True)
6.118 - self.add_py_string(string_entry, identifier = 1)
6.119 - return string_entry.pystring_cname
6.120 -
6.121 def find_module(self, module_name, pos):
6.122 # Find a module in the import namespace, interpreting
6.123 # relative imports relative to this module's parent.
6.124 @@ -1416,7 +1316,6 @@
6.125 # I keep it in for now. is_member should be enough
6.126 # later on
6.127 self.namespace_cname = "(PyObject *)%s" % self.parent_type.typeptr_cname
6.128 - entry.interned_cname = self.intern_identifier(name)
6.129 return entry
6.130
6.131
7.1 --- a/tests/errors/e_strcoerce.pyx Sun Mar 15 19:34:39 2009 +0100
7.2 +++ b/tests/errors/e_strcoerce.pyx Wed Mar 18 21:44:34 2009 +0100
7.3 @@ -2,7 +2,12 @@
7.4 cdef int c2 = "te" # fails
7.5 cdef int cx = "test" # fails
7.6
7.7 +cdef int x1 = "\xFF" # works
7.8 +cdef int x2 = u"\xFF" # fails
7.9 +
7.10 +
7.11 _ERRORS = u"""
7.12 -2:14: Only coerce single-character ascii strings can be used as ints.
7.13 -3:14: Only coerce single-character ascii strings can be used as ints.
7.14 +2:14: Only single-character byte strings can be coerced into ints.
7.15 +3:14: Only single-character byte strings can be coerced into ints.
7.16 +6:14: Unicode objects do not support coercion to C types.
7.17 """
