Generate IR for an arbitrary call of form e.m(...). This can also deal with calls to module-level functions.
(builder: IRBuilder, expr: CallExpr, callee: MemberExpr)
| 420 | |
| 421 | |
| 422 | def translate_method_call(builder: IRBuilder, expr: CallExpr, callee: MemberExpr) -> Value: |
| 423 | """Generate IR for an arbitrary call of form e.m(...). |
| 424 | |
| 425 | This can also deal with calls to module-level functions. |
| 426 | """ |
| 427 | if builder.is_native_ref_expr(callee): |
| 428 | # Call to module-level native function or such |
| 429 | return translate_call(builder, expr, callee) |
| 430 | elif ( |
| 431 | isinstance(callee.expr, RefExpr) |
| 432 | and isinstance(callee.expr.node, TypeInfo) |
| 433 | and callee.expr.node in builder.mapper.type_to_ir |
| 434 | and builder.mapper.type_to_ir[callee.expr.node].has_method(callee.name) |
| 435 | and all(kind in (ARG_POS, ARG_NAMED) for kind in expr.arg_kinds) |
| 436 | ): |
| 437 | # Call a method via the *class* |
| 438 | assert isinstance(callee.expr.node, TypeInfo), callee.expr.node |
| 439 | ir = builder.mapper.type_to_ir[callee.expr.node] |
| 440 | return call_classmethod(builder, ir, expr, callee) |
| 441 | elif builder.is_module_member_expr(callee): |
| 442 | # Fall back to a PyCall for non-native module calls |
| 443 | function = builder.accept(callee) |
| 444 | args = [builder.accept(arg) for arg in expr.args] |
| 445 | return builder.py_call( |
| 446 | function, args, expr.line, arg_kinds=expr.arg_kinds, arg_names=expr.arg_names |
| 447 | ) |
| 448 | else: |
| 449 | if isinstance(callee.expr, RefExpr): |
| 450 | node = callee.expr.node |
| 451 | if isinstance(node, Var) and node.is_cls: |
| 452 | typ = get_proper_type(node.type) |
| 453 | if isinstance(typ, TypeType) and isinstance(typ.item, Instance): |
| 454 | class_ir = builder.mapper.type_to_ir.get(typ.item.type) |
| 455 | if class_ir and class_ir.is_ext_class and class_ir.has_no_subclasses(): |
| 456 | # Call a native classmethod via cls that can be statically bound, |
| 457 | # since the class has no subclasses. |
| 458 | return call_classmethod(builder, class_ir, expr, callee) |
| 459 | |
| 460 | receiver_typ = builder.node_type(callee.expr) |
| 461 | |
| 462 | # If there is a specializer for this method name/type, try calling it. |
| 463 | # We would return the first successful one. |
| 464 | val = apply_method_specialization(builder, expr, callee, receiver_typ) |
| 465 | if val is not None: |
| 466 | return val |
| 467 | |
| 468 | obj = builder.accept(callee.expr) |
| 469 | args = [builder.accept(arg) for arg in expr.args] |
| 470 | return builder.gen_method_call( |
| 471 | obj, |
| 472 | callee.name, |
| 473 | args, |
| 474 | builder.node_type(expr), |
| 475 | expr.line, |
| 476 | expr.arg_kinds, |
| 477 | expr.arg_names, |
| 478 | ) |
| 479 |
no test coverage detected
searching dependent graphs…