(cl: ClassIR, attr: str, rtype: RType, emitter: Emitter)
| 1174 | |
| 1175 | |
| 1176 | def generate_setter(cl: ClassIR, attr: str, rtype: RType, emitter: Emitter) -> None: |
| 1177 | attr_field = emitter.attr(attr) |
| 1178 | emitter.emit_line("static int") |
| 1179 | emitter.emit_line( |
| 1180 | "{}({} *self, PyObject *value, void *closure)".format( |
| 1181 | setter_name(cl, attr, emitter.names), cl.struct_name(emitter.names) |
| 1182 | ) |
| 1183 | ) |
| 1184 | emitter.emit_line("{") |
| 1185 | |
| 1186 | deletable = cl.is_deletable(attr) |
| 1187 | if not deletable: |
| 1188 | emitter.emit_line("if (value == NULL) {") |
| 1189 | emitter.emit_line("PyErr_SetString(PyExc_AttributeError,") |
| 1190 | emitter.emit_line( |
| 1191 | f' "{repr(cl.name)} object attribute {repr(attr)} cannot be deleted");' |
| 1192 | ) |
| 1193 | emitter.emit_line("return -1;") |
| 1194 | emitter.emit_line("}") |
| 1195 | |
| 1196 | # HACK: Don't consider refcounted values as always defined, since it's possible to |
| 1197 | # access uninitialized values via 'gc.get_objects()'. Accessing non-refcounted |
| 1198 | # values is benign. |
| 1199 | always_defined = cl.is_always_defined(attr) and not rtype.is_refcounted |
| 1200 | |
| 1201 | if rtype.is_refcounted: |
| 1202 | attr_expr = f"self->{attr_field}" |
| 1203 | if not always_defined: |
| 1204 | emitter.emit_undefined_attr_check(rtype, attr_expr, "!=", "self", attr, cl) |
| 1205 | emitter.emit_dec_ref(f"self->{attr_field}", rtype) |
| 1206 | if not always_defined: |
| 1207 | emitter.emit_line("}") |
| 1208 | |
| 1209 | if deletable: |
| 1210 | emitter.emit_line("if (value != NULL) {") |
| 1211 | |
| 1212 | if rtype.is_unboxed: |
| 1213 | emitter.emit_unbox("value", "tmp", rtype, error=ReturnHandler("-1"), declare_dest=True) |
| 1214 | elif is_same_type(rtype, object_rprimitive): |
| 1215 | emitter.emit_line("PyObject *tmp = value;") |
| 1216 | else: |
| 1217 | emitter.emit_cast("value", "tmp", rtype, declare_dest=True) |
| 1218 | emitter.emit_lines("if (!tmp)", " return -1;") |
| 1219 | emitter.emit_inc_ref("tmp", rtype) |
| 1220 | emitter.emit_line(f"self->{attr_field} = tmp;") |
| 1221 | if rtype.error_overlap and not always_defined: |
| 1222 | emitter.emit_attr_bitmap_set("tmp", "self", rtype, cl, attr) |
| 1223 | |
| 1224 | if deletable: |
| 1225 | emitter.emit_line("} else {") |
| 1226 | emitter.set_undefined_value(f"self->{attr_field}", rtype) |
| 1227 | if rtype.error_overlap: |
| 1228 | emitter.emit_attr_bitmap_clear("self", rtype, cl, attr) |
| 1229 | emitter.emit_line("}") |
| 1230 | emitter.emit_line("return 0;") |
| 1231 | emitter.emit_line("}") |
| 1232 | |
| 1233 |
no test coverage detected
searching dependent graphs…