(
builder: IRBuilder,
expr: Expression,
target: Lvalue | None,
body: GenFunc,
is_async: bool,
line: int,
)
| 1093 | |
| 1094 | |
| 1095 | def transform_with( |
| 1096 | builder: IRBuilder, |
| 1097 | expr: Expression, |
| 1098 | target: Lvalue | None, |
| 1099 | body: GenFunc, |
| 1100 | is_async: bool, |
| 1101 | line: int, |
| 1102 | ) -> None: |
| 1103 | # This is basically a straight transcription of the Python code in PEP 343. |
| 1104 | # I don't actually understand why a bunch of it is the way it is. |
| 1105 | # We could probably optimize the case where the manager is compiled by us, |
| 1106 | # but that is not our common case at all, so. |
| 1107 | |
| 1108 | al = "a" if is_async else "" |
| 1109 | |
| 1110 | mgr_v = builder.accept(expr) |
| 1111 | is_native = isinstance(mgr_v.type, RInstance) |
| 1112 | if is_native: |
| 1113 | value = builder.add(MethodCall(mgr_v, f"__{al}enter__", args=[], line=line)) |
| 1114 | exit_ = None |
| 1115 | else: |
| 1116 | typ = builder.primitive_op(type_op, [mgr_v], line) |
| 1117 | exit_ = builder.maybe_spill(builder.py_get_attr(typ, f"__{al}exit__", line)) |
| 1118 | value = builder.py_call(builder.py_get_attr(typ, f"__{al}enter__", line), [mgr_v], line) |
| 1119 | |
| 1120 | mgr = builder.maybe_spill(mgr_v) |
| 1121 | exc = builder.maybe_spill_assignable(builder.true()) |
| 1122 | if is_async: |
| 1123 | value = emit_await(builder, value, line) |
| 1124 | |
| 1125 | def maybe_natively_call_exit(exc_info: bool) -> Value: |
| 1126 | if exc_info: |
| 1127 | args = get_sys_exc_info(builder) |
| 1128 | else: |
| 1129 | none = builder.none_object() |
| 1130 | args = [none, none, none] |
| 1131 | |
| 1132 | if is_native: |
| 1133 | assert isinstance(mgr_v.type, RInstance), mgr_v.type |
| 1134 | exit_val = builder.gen_method_call( |
| 1135 | builder.read(mgr, line), |
| 1136 | f"__{al}exit__", |
| 1137 | arg_values=args, |
| 1138 | line=line, |
| 1139 | result_type=none_rprimitive, |
| 1140 | ) |
| 1141 | else: |
| 1142 | assert exit_ is not None |
| 1143 | exit_val = builder.py_call( |
| 1144 | builder.read(exit_, line), [builder.read(mgr, line)] + args, line |
| 1145 | ) |
| 1146 | |
| 1147 | if is_async: |
| 1148 | return emit_await(builder, exit_val, line) |
| 1149 | else: |
| 1150 | return exit_val |
| 1151 | |
| 1152 | def try_body() -> None: |
no test coverage detected
searching dependent graphs…