cython-devel

changeset 1217:7e25b2f3f235

Coercion of dict to struct.
author Robert Bradshaw <robertwb@math.washington.edu>
date Tue Oct 07 20:18:12 2008 -0700 (3 years ago)
parents 89a0907f44d1
children 51eb93696d35
files Cython/Compiler/ExprNodes.py
line diff
1.1 --- a/Cython/Compiler/ExprNodes.py Tue Oct 07 19:15:18 2008 -0700 1.2 +++ b/Cython/Compiler/ExprNodes.py Tue Oct 07 20:18:12 2008 -0700 1.3 @@ -2880,6 +2880,8 @@ 1.4 # Dictionary constructor. 1.5 # 1.6 # key_value_pairs [DictItemNode] 1.7 + # 1.8 + # obj_conversion_errors [PyrexError] used internally 1.9 1.10 subexprs = ['key_value_pairs'] 1.11 1.12 @@ -2892,11 +2894,52 @@ 1.13 self.compile_time_value_error(e) 1.14 1.15 def analyse_types(self, env): 1.16 + hold_errors() 1.17 for item in self.key_value_pairs: 1.18 item.analyse_types(env) 1.19 + self.gil_check(env) 1.20 + self.obj_conversion_errors = held_errors() 1.21 + release_errors(ignore=True) 1.22 self.type = dict_type 1.23 - self.gil_check(env) 1.24 - self.is_temp = 1 1.25 + self.is_temp = 1 1.26 + 1.27 + def coerce_to(self, dst_type, env): 1.28 + if dst_type.is_pyobject: 1.29 + self.release_errors() 1.30 + if not self.type.subtype_of(dst_type): 1.31 + error(self.pos, "Cannot interpret dict as type '%s'" % dst_type) 1.32 + elif dst_type.is_struct_or_union: 1.33 + self.type = dst_type 1.34 + if not dst_type.is_struct and len(self.key_value_pairs) != 1: 1.35 + error(self.pos, "Exactly one field must be specified to convert to union '%s'" % dst_type) 1.36 + elif dst_type.is_struct and len(self.key_value_pairs) < len(dst_type.scope.var_entries): 1.37 + warning(self.pos, "Not all members given for struct '%s'" % dst_type, 1) 1.38 + for item in self.key_value_pairs: 1.39 + if isinstance(item.key, CoerceToPyTypeNode): 1.40 + item.key = item.key.arg 1.41 + if isinstance(item.key, (StringNode, IdentifierStringNode)): 1.42 + item.key = NameNode(pos=item.key.pos, name=item.key.value) 1.43 + if not isinstance(item.key, NameNode): 1.44 + print item.key 1.45 + error(item.key.pos, "Struct field must be a name") 1.46 + else: 1.47 + member = dst_type.scope.lookup_here(item.key.name) 1.48 + if not member: 1.49 + error(item.key.pos, "struct '%s' has no field '%s'" % (dst_type, item.key.name)) 1.50 + else: 1.51 + value = item.value 1.52 + if isinstance(value, CoerceToPyTypeNode): 1.53 + value = value.arg 1.54 + item.value = value.coerce_to(member.type, env) 1.55 + else: 1.56 + self.type = error_type 1.57 + error(self.pos, "Cannot interpret dict as type '%s'" % dst_type) 1.58 + return self 1.59 + 1.60 + def release_errors(self): 1.61 + for err in self.obj_conversion_errors: 1.62 + report_error(err) 1.63 + self.obj_conversion_errors = [] 1.64 1.65 gil_message = "Constructing Python dict" 1.66 1.67 @@ -2913,17 +2956,25 @@ 1.68 def generate_evaluation_code(self, code): 1.69 # Custom method used here because key-value 1.70 # pairs are evaluated and used one at a time. 1.71 - code.putln( 1.72 - "%s = PyDict_New(); %s" % ( 1.73 - self.result(), 1.74 - code.error_goto_if_null(self.result(), self.pos))) 1.75 + if self.type.is_pyobject: 1.76 + self.release_errors() 1.77 + code.putln( 1.78 + "%s = PyDict_New(); %s" % ( 1.79 + self.result(), 1.80 + code.error_goto_if_null(self.result(), self.pos))) 1.81 for item in self.key_value_pairs: 1.82 item.generate_evaluation_code(code) 1.83 - code.put_error_if_neg(self.pos, 1.84 - "PyDict_SetItem(%s, %s, %s)" % ( 1.85 - self.result(), 1.86 - item.key.py_result(), 1.87 - item.value.py_result())) 1.88 + if self.type.is_pyobject: 1.89 + code.put_error_if_neg(self.pos, 1.90 + "PyDict_SetItem(%s, %s, %s)" % ( 1.91 + self.result(), 1.92 + item.key.py_result(), 1.93 + item.value.py_result())) 1.94 + else: 1.95 + code.putln("%s.%s = %s;" % ( 1.96 + self.result(), 1.97 + item.key.name, 1.98 + item.value.result())) 1.99 item.generate_disposal_code(code) 1.100 1.101 def annotate(self, code):