1010import sys
1111import uuid
1212from collections import defaultdict
13- from collections .abc import Collection , Iterable , Mapping , MutableMapping , MutableSet
13+ from collections .abc import (
14+ Collection ,
15+ Iterable ,
16+ Iterator ,
17+ Mapping ,
18+ MutableMapping ,
19+ MutableSet ,
20+ )
1421from datetime import datetime
1522from decimal import Decimal
1623from fractions import Fraction
8996 Fn ,
9097 FnArity ,
9198 FunctionContext ,
99+ FunctionContextType ,
92100 HostCall ,
93101 HostField ,
94102 If ,
@@ -447,16 +455,23 @@ def is_async_ctx(self) -> bool:
447455
448456 It is possible that the current function is defined inside other functions,
449457 so this does not imply anything about the nesting level of the current node."""
450- return self .func_ctx == FunctionContext .ASYNC_FUNCTION
458+ func_ctx = self .func_ctx
459+ return (
460+ func_ctx is not None
461+ and func_ctx .function_type == FunctionContextType .ASYNC_FUNCTION
462+ )
451463
452464 @contextlib .contextmanager
453- def new_func_ctx (self , context_type : FunctionContext ):
465+ def new_func_ctx (
466+ self , context_type : FunctionContextType
467+ ) -> Iterator [FunctionContext ]:
454468 """Context manager which can be used to set a function or method context for
455469 child nodes to examine. A new function context is pushed onto the stack each
456470 time the Analyzer finds a new function or method definition, so there may be
457471 many nested function contexts."""
458- self ._func_ctx .append (context_type )
459- yield
472+ func_ctx = FunctionContext (context_type )
473+ self ._func_ctx .append (func_ctx )
474+ yield func_ctx
460475 self ._func_ctx .pop ()
461476
462477 @property
@@ -1186,7 +1201,7 @@ def __deftype_method_param_bindings(
11861201 return has_vargs , fixed_arity , param_nodes
11871202
11881203
1189- def __deftype_classmethod (
1204+ def __deftype_classmethod ( # pylint: disable=too-many-locals
11901205 form : Union [llist .PersistentList , ISeq ],
11911206 ctx : AnalyzerContext ,
11921207 method_name : str ,
@@ -1222,24 +1237,23 @@ def __deftype_classmethod(
12221237 has_vargs , fixed_arity , param_nodes = __deftype_method_param_bindings (
12231238 params , ctx , SpecialForm .DEFTYPE
12241239 )
1225- with ctx .new_func_ctx (FunctionContext .CLASSMETHOD ), ctx .expr_pos ():
1240+ with ctx .new_func_ctx (FunctionContextType .CLASSMETHOD ), ctx .expr_pos ():
12261241 stmts , ret = _body_ast (runtime .nthrest (form , 2 ), ctx )
1242+ body = Do (
1243+ form = form .rest ,
1244+ statements = vec .vector (stmts ),
1245+ ret = ret ,
1246+ is_body = True ,
1247+ env = ctx .get_node_env (),
1248+ )
12271249 method = DefTypeClassMethod (
12281250 form = form ,
12291251 name = method_name ,
12301252 params = vec .vector (param_nodes ),
12311253 fixed_arity = fixed_arity ,
12321254 is_variadic = has_vargs ,
12331255 kwarg_support = kwarg_support ,
1234- body = Do (
1235- form = form .rest ,
1236- statements = vec .vector (stmts ),
1237- ret = ret ,
1238- is_body = True ,
1239- # Use the argument vector or first body statement, whichever
1240- # exists, for metadata.
1241- env = ctx .get_node_env (),
1242- ),
1256+ body = body ,
12431257 class_local = cls_binding ,
12441258 env = ctx .get_node_env (),
12451259 )
@@ -1286,8 +1300,15 @@ def __deftype_or_reify_method( # pylint: disable=too-many-arguments,too-many-lo
12861300
12871301 loop_id = genname (method_name )
12881302 with ctx .new_recur_point (loop_id , param_nodes ):
1289- with ctx .new_func_ctx (FunctionContext .METHOD ), ctx .expr_pos ():
1303+ with ctx .new_func_ctx (FunctionContextType .METHOD ), ctx .expr_pos ():
12901304 stmts , ret = _body_ast (runtime .nthrest (form , 2 ), ctx )
1305+ body = Do (
1306+ form = form .rest ,
1307+ statements = vec .vector (stmts ),
1308+ ret = ret ,
1309+ is_body = True ,
1310+ env = ctx .get_node_env (),
1311+ )
12911312 method = DefTypeMethodArity (
12921313 form = form ,
12931314 name = method_name ,
@@ -1296,15 +1317,7 @@ def __deftype_or_reify_method( # pylint: disable=too-many-arguments,too-many-lo
12961317 fixed_arity = fixed_arity ,
12971318 is_variadic = has_vargs ,
12981319 kwarg_support = kwarg_support ,
1299- body = Do (
1300- form = form .rest ,
1301- statements = vec .vector (stmts ),
1302- ret = ret ,
1303- is_body = True ,
1304- # Use the argument vector or first body statement, whichever
1305- # exists, for metadata.
1306- env = ctx .get_node_env (),
1307- ),
1320+ body = body ,
13081321 loop_id = loop_id ,
13091322 env = ctx .get_node_env (),
13101323 )
@@ -1356,22 +1369,21 @@ def __deftype_or_reify_property(
13561369
13571370 assert not has_vargs , f"{ special_form } properties may not have arguments"
13581371
1359- with ctx .new_func_ctx (FunctionContext .PROPERTY ), ctx .expr_pos ():
1372+ with ctx .new_func_ctx (FunctionContextType .PROPERTY ), ctx .expr_pos ():
13601373 stmts , ret = _body_ast (runtime .nthrest (form , 2 ), ctx )
1361- prop = DefTypeProperty (
1362- form = form ,
1363- name = method_name ,
1364- this_local = this_binding ,
1365- params = vec .vector (param_nodes ),
1366- body = Do (
1374+ body = Do (
13671375 form = form .rest ,
13681376 statements = vec .vector (stmts ),
13691377 ret = ret ,
13701378 is_body = True ,
1371- # Use the argument vector or first body statement, whichever
1372- # exists, for metadata.
13731379 env = ctx .get_node_env (),
1374- ),
1380+ )
1381+ prop = DefTypeProperty (
1382+ form = form ,
1383+ name = method_name ,
1384+ this_local = this_binding ,
1385+ params = vec .vector (param_nodes ),
1386+ body = body ,
13751387 env = ctx .get_node_env (),
13761388 )
13771389 prop .visit (partial (_assert_no_recur , ctx ))
@@ -1393,24 +1405,23 @@ def __deftype_staticmethod(
13931405 has_vargs , fixed_arity , param_nodes = __deftype_method_param_bindings (
13941406 args , ctx , SpecialForm .DEFTYPE
13951407 )
1396- with ctx .new_func_ctx (FunctionContext .STATICMETHOD ), ctx .expr_pos ():
1408+ with ctx .new_func_ctx (FunctionContextType .STATICMETHOD ), ctx .expr_pos ():
13971409 stmts , ret = _body_ast (runtime .nthrest (form , 2 ), ctx )
1410+ body = Do (
1411+ form = form .rest ,
1412+ statements = vec .vector (stmts ),
1413+ ret = ret ,
1414+ is_body = True ,
1415+ env = ctx .get_node_env (),
1416+ )
13981417 method = DefTypeStaticMethod (
13991418 form = form ,
14001419 name = method_name ,
14011420 params = vec .vector (param_nodes ),
14021421 fixed_arity = fixed_arity ,
14031422 is_variadic = has_vargs ,
14041423 kwarg_support = kwarg_support ,
1405- body = Do (
1406- form = form .rest ,
1407- statements = vec .vector (stmts ),
1408- ret = ret ,
1409- is_body = True ,
1410- # Use the argument vector or first body statement, whichever
1411- # exists, for metadata.
1412- env = ctx .get_node_env (),
1413- ),
1424+ body = body ,
14141425 env = ctx .get_node_env (),
14151426 )
14161427 method .visit (partial (_assert_no_recur , ctx ))
@@ -2092,31 +2103,28 @@ def __fn_method_ast( # pylint: disable=too-many-locals
20922103 with ctx .new_recur_point (fn_loop_id , param_nodes ):
20932104 with (
20942105 ctx .new_func_ctx (
2095- FunctionContext .ASYNC_FUNCTION
2106+ FunctionContextType .ASYNC_FUNCTION
20962107 if is_async
2097- else FunctionContext .FUNCTION
2108+ else FunctionContextType .FUNCTION
20982109 ),
20992110 ctx .expr_pos (),
21002111 ):
21012112 stmts , ret = _body_ast (form .rest , ctx )
2113+ body = Do (
2114+ form = form .rest ,
2115+ statements = vec .vector (stmts ),
2116+ ret = ret ,
2117+ is_body = True ,
2118+ env = ctx .get_node_env (),
2119+ )
21022120 method = FnArity (
21032121 form = form ,
21042122 loop_id = fn_loop_id ,
21052123 params = vec .vector (param_nodes ),
21062124 tag = return_tag ,
21072125 is_variadic = has_vargs ,
21082126 fixed_arity = len (param_nodes ) - int (has_vargs ),
2109- body = Do (
2110- form = form .rest ,
2111- statements = vec .vector (stmts ),
2112- ret = ret ,
2113- is_body = True ,
2114- # Use the argument vector or first body statement, whichever
2115- # exists, for metadata.
2116- env = ctx .get_node_env (),
2117- ),
2118- # Use the argument vector for fetching line/col since the
2119- # form itself is a sequence with no meaningful metadata.
2127+ body = body ,
21202128 env = ctx .get_node_env (),
21212129 )
21222130 method .visit (partial (_assert_recur_is_tail , ctx ))
@@ -3420,6 +3428,9 @@ def _yield_ast(form: ISeq, ctx: AnalyzerContext) -> Yield:
34203428 "yield forms must contain 1 or 2 elements, as in: (yield [expr])" , form = form
34213429 )
34223430
3431+ # Indicate that the current function is a generator
3432+ ctx .func_ctx .is_generator = True
3433+
34233434 if nelems == 2 :
34243435 with ctx .expr_pos ():
34253436 expr = _analyze_form (runtime .nth (form , 1 ), ctx )
0 commit comments