Generate and return the FuncIR for a given FuncDef. If the given FuncItem is a nested function, then we generate a callable class representing the function and use that instead of the actual function. if the given FuncItem contains a nested function, then we generate an environment
(
builder: IRBuilder,
fitem: FuncItem,
name: str,
sig: FuncSignature,
cdef: ClassDef | None = None,
make_ext_method: bool = False,
)
| 165 | |
| 166 | |
| 167 | def gen_func_item( |
| 168 | builder: IRBuilder, |
| 169 | fitem: FuncItem, |
| 170 | name: str, |
| 171 | sig: FuncSignature, |
| 172 | cdef: ClassDef | None = None, |
| 173 | make_ext_method: bool = False, |
| 174 | ) -> tuple[FuncIR, Value | None]: |
| 175 | """Generate and return the FuncIR for a given FuncDef. |
| 176 | |
| 177 | If the given FuncItem is a nested function, then we generate a |
| 178 | callable class representing the function and use that instead of |
| 179 | the actual function. if the given FuncItem contains a nested |
| 180 | function, then we generate an environment class so that inner |
| 181 | nested functions can access the environment of the given FuncDef. |
| 182 | |
| 183 | Consider the following nested function: |
| 184 | |
| 185 | def a() -> None: |
| 186 | def b() -> None: |
| 187 | def c() -> None: |
| 188 | return None |
| 189 | return None |
| 190 | return None |
| 191 | |
| 192 | The classes generated would look something like the following. |
| 193 | |
| 194 | has pointer to +-------+ |
| 195 | +--------------------------> | a_env | |
| 196 | | +-------+ |
| 197 | | ^ |
| 198 | | | has pointer to |
| 199 | +-------+ associated with +-------+ |
| 200 | | b_obj | -------------------> | b_env | |
| 201 | +-------+ +-------+ |
| 202 | ^ |
| 203 | | |
| 204 | +-------+ has pointer to | |
| 205 | | c_obj | --------------------------+ |
| 206 | +-------+ |
| 207 | """ |
| 208 | |
| 209 | # TODO: do something about abstract methods. |
| 210 | |
| 211 | func_reg: Value | None = None |
| 212 | |
| 213 | # We treat lambdas as always being nested because we always generate |
| 214 | # a class for lambdas, no matter where they are. (It would probably also |
| 215 | # work to special case toplevel lambdas and generate a non-class function.) |
| 216 | is_nested = fitem in builder.nested_fitems or isinstance(fitem, LambdaExpr) |
| 217 | contains_nested = fitem in builder.encapsulating_funcs.keys() |
| 218 | is_decorated = fitem in builder.fdefs_to_decorators |
| 219 | is_singledispatch = fitem in builder.singledispatch_impls |
| 220 | in_non_ext = False |
| 221 | add_nested_funcs_to_env = has_nested_func_self_reference(builder, fitem) |
| 222 | class_name = None |
| 223 | if cdef: |
| 224 | ir = builder.mapper.type_to_ir[cdef.info] |
no test coverage detected
searching dependent graphs…