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 """