Emit cast to a tuple type. The arguments are similar to emit_cast.
(
self,
src: str,
dest: str,
typ: RTuple,
declare_dest: bool,
error: ErrorHandler,
src_type: RType | None,
)
| 938 | self.emit_label(good_label) |
| 939 | |
| 940 | def emit_tuple_cast( |
| 941 | self, |
| 942 | src: str, |
| 943 | dest: str, |
| 944 | typ: RTuple, |
| 945 | declare_dest: bool, |
| 946 | error: ErrorHandler, |
| 947 | src_type: RType | None, |
| 948 | ) -> None: |
| 949 | """Emit cast to a tuple type. |
| 950 | |
| 951 | The arguments are similar to emit_cast. |
| 952 | """ |
| 953 | if declare_dest: |
| 954 | self.emit_line(f"PyObject *{dest};") |
| 955 | # This reuse of the variable is super dodgy. We don't even |
| 956 | # care about the values except to check whether they are |
| 957 | # invalid. |
| 958 | out_label = self.new_label() |
| 959 | self.emit_lines( |
| 960 | "if (unlikely(!(PyTuple_Check({r}) && PyTuple_GET_SIZE({r}) == {size}))) {{".format( |
| 961 | r=src, size=len(typ.types) |
| 962 | ), |
| 963 | f"{dest} = NULL;", |
| 964 | f"goto {out_label};", |
| 965 | "}", |
| 966 | ) |
| 967 | for i, item in enumerate(typ.types): |
| 968 | # Since we did the checks above this should never fail |
| 969 | self.emit_cast( |
| 970 | f"PyTuple_GET_ITEM({src}, {i})", |
| 971 | dest, |
| 972 | item, |
| 973 | declare_dest=False, |
| 974 | raise_exception=False, |
| 975 | optional=False, |
| 976 | ) |
| 977 | self.emit_line(f"if ({dest} == NULL) goto {out_label};") |
| 978 | |
| 979 | self.emit_line(f"{dest} = {src};") |
| 980 | self.emit_label(out_label) |
| 981 | |
| 982 | def emit_arg_check(self, src: str, dest: str, typ: RType, check: str, optional: bool) -> None: |
| 983 | if optional: |
no test coverage detected