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):
