MCPcopy Index your code
hub / github.com/python/mypy / get_attr_expr

Method get_attr_expr

mypyc/codegen/emitfunc.py:356–395  ·  view source on GitHub ↗

Generate attribute accessor for normal (non-property) access. This either has a form like obj->attr_name for attributes defined in non-trait classes, and *(obj + attr_offset) for attributes defined by traits. We also insert all necessary C casts here.

(self, obj: str, op: GetAttr | SetAttr, decl_cl: ClassIR)

Source from the content-addressed store, hash-verified

354 )
355
356 def get_attr_expr(self, obj: str, op: GetAttr | SetAttr, decl_cl: ClassIR) -> str:
357 """Generate attribute accessor for normal (non-property) access.
358
359 This either has a form like obj->attr_name for attributes defined in non-trait
360 classes, and *(obj + attr_offset) for attributes defined by traits. We also
361 insert all necessary C casts here.
362 """
363 # The struct cast below needs the defining group's __native.h
364 # included by the consuming .c file. Record both the receiver
365 # and declaring classes as cross-group deps.
366 self.emitter.register_group_dep(op.class_type.class_ir)
367 self.emitter.register_group_dep(decl_cl)
368 cast = f"({op.class_type.struct_name(self.emitter.names)} *)"
369 if decl_cl.is_trait and op.class_type.class_ir.is_trait:
370 # For pure trait access find the offset first, offsets
371 # are ordered by attribute position in the cl.attributes dict.
372 # TODO: pre-calculate the mapping to make this faster.
373 trait_attr_index = list(decl_cl.attributes).index(op.attr)
374 # TODO: reuse these names somehow?
375 offset = self.emitter.temp_name()
376 self.declarations.emit_line(f"size_t {offset};")
377 self.emitter.emit_line(
378 "{} = {};".format(
379 offset,
380 "CPy_FindAttrOffset({}, {}, {})".format(
381 self.emitter.type_struct_name(decl_cl),
382 f"({cast}{obj})->vtable",
383 trait_attr_index,
384 ),
385 )
386 )
387 attr_cast = f"({self.ctype(op.class_type.attr_type(op.attr))} *)"
388 return f"*{attr_cast}((char *){obj} + {offset})"
389 else:
390 # Cast to something non-trait. Note: for this to work, all struct
391 # members for non-trait classes must obey monotonic linear growth.
392 if op.class_type.class_ir.is_trait:
393 assert not decl_cl.is_trait
394 cast = f"({decl_cl.struct_name(self.emitter.names)} *)"
395 return f"({cast}{obj})->{self.emitter.attr(op.attr)}"
396
397 def visit_get_attr(self, op: GetAttr) -> None:
398 if op.allow_error_value:

Callers 3

visit_get_attrMethod · 0.95
visit_set_attrMethod · 0.95

Calls 11

ctypeMethod · 0.95
listClass · 0.85
register_group_depMethod · 0.80
indexMethod · 0.80
type_struct_nameMethod · 0.80
attrMethod · 0.80
struct_nameMethod · 0.45
temp_nameMethod · 0.45
emit_lineMethod · 0.45
formatMethod · 0.45
attr_typeMethod · 0.45

Tested by

no test coverage detected