10
10
import sys
11
11
import uuid
12
12
from 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
+ )
14
21
from datetime import datetime
15
22
from decimal import Decimal
16
23
from fractions import Fraction
89
96
Fn ,
90
97
FnArity ,
91
98
FunctionContext ,
99
+ FunctionContextType ,
92
100
HostCall ,
93
101
HostField ,
94
102
If ,
@@ -447,16 +455,23 @@ def is_async_ctx(self) -> bool:
447
455
448
456
It is possible that the current function is defined inside other functions,
449
457
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
+ )
451
463
452
464
@contextlib .contextmanager
453
- def new_func_ctx (self , context_type : FunctionContext ):
465
+ def new_func_ctx (
466
+ self , context_type : FunctionContextType
467
+ ) -> Iterator [FunctionContext ]:
454
468
"""Context manager which can be used to set a function or method context for
455
469
child nodes to examine. A new function context is pushed onto the stack each
456
470
time the Analyzer finds a new function or method definition, so there may be
457
471
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
460
475
self ._func_ctx .pop ()
461
476
462
477
@property
@@ -1186,7 +1201,7 @@ def __deftype_method_param_bindings(
1186
1201
return has_vargs , fixed_arity , param_nodes
1187
1202
1188
1203
1189
- def __deftype_classmethod (
1204
+ def __deftype_classmethod ( # pylint: disable=too-many-locals
1190
1205
form : Union [llist .PersistentList , ISeq ],
1191
1206
ctx : AnalyzerContext ,
1192
1207
method_name : str ,
@@ -1222,24 +1237,23 @@ def __deftype_classmethod(
1222
1237
has_vargs , fixed_arity , param_nodes = __deftype_method_param_bindings (
1223
1238
params , ctx , SpecialForm .DEFTYPE
1224
1239
)
1225
- with ctx .new_func_ctx (FunctionContext .CLASSMETHOD ), ctx .expr_pos ():
1240
+ with ctx .new_func_ctx (FunctionContextType .CLASSMETHOD ), ctx .expr_pos ():
1226
1241
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
+ )
1227
1249
method = DefTypeClassMethod (
1228
1250
form = form ,
1229
1251
name = method_name ,
1230
1252
params = vec .vector (param_nodes ),
1231
1253
fixed_arity = fixed_arity ,
1232
1254
is_variadic = has_vargs ,
1233
1255
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 ,
1243
1257
class_local = cls_binding ,
1244
1258
env = ctx .get_node_env (),
1245
1259
)
@@ -1286,8 +1300,15 @@ def __deftype_or_reify_method( # pylint: disable=too-many-arguments,too-many-lo
1286
1300
1287
1301
loop_id = genname (method_name )
1288
1302
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 ():
1290
1304
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
+ )
1291
1312
method = DefTypeMethodArity (
1292
1313
form = form ,
1293
1314
name = method_name ,
@@ -1296,15 +1317,7 @@ def __deftype_or_reify_method( # pylint: disable=too-many-arguments,too-many-lo
1296
1317
fixed_arity = fixed_arity ,
1297
1318
is_variadic = has_vargs ,
1298
1319
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 ,
1308
1321
loop_id = loop_id ,
1309
1322
env = ctx .get_node_env (),
1310
1323
)
@@ -1356,22 +1369,21 @@ def __deftype_or_reify_property(
1356
1369
1357
1370
assert not has_vargs , f"{ special_form } properties may not have arguments"
1358
1371
1359
- with ctx .new_func_ctx (FunctionContext .PROPERTY ), ctx .expr_pos ():
1372
+ with ctx .new_func_ctx (FunctionContextType .PROPERTY ), ctx .expr_pos ():
1360
1373
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 (
1367
1375
form = form .rest ,
1368
1376
statements = vec .vector (stmts ),
1369
1377
ret = ret ,
1370
1378
is_body = True ,
1371
- # Use the argument vector or first body statement, whichever
1372
- # exists, for metadata.
1373
1379
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 ,
1375
1387
env = ctx .get_node_env (),
1376
1388
)
1377
1389
prop .visit (partial (_assert_no_recur , ctx ))
@@ -1393,24 +1405,23 @@ def __deftype_staticmethod(
1393
1405
has_vargs , fixed_arity , param_nodes = __deftype_method_param_bindings (
1394
1406
args , ctx , SpecialForm .DEFTYPE
1395
1407
)
1396
- with ctx .new_func_ctx (FunctionContext .STATICMETHOD ), ctx .expr_pos ():
1408
+ with ctx .new_func_ctx (FunctionContextType .STATICMETHOD ), ctx .expr_pos ():
1397
1409
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
+ )
1398
1417
method = DefTypeStaticMethod (
1399
1418
form = form ,
1400
1419
name = method_name ,
1401
1420
params = vec .vector (param_nodes ),
1402
1421
fixed_arity = fixed_arity ,
1403
1422
is_variadic = has_vargs ,
1404
1423
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 ,
1414
1425
env = ctx .get_node_env (),
1415
1426
)
1416
1427
method .visit (partial (_assert_no_recur , ctx ))
@@ -2092,31 +2103,28 @@ def __fn_method_ast( # pylint: disable=too-many-locals
2092
2103
with ctx .new_recur_point (fn_loop_id , param_nodes ):
2093
2104
with (
2094
2105
ctx .new_func_ctx (
2095
- FunctionContext .ASYNC_FUNCTION
2106
+ FunctionContextType .ASYNC_FUNCTION
2096
2107
if is_async
2097
- else FunctionContext .FUNCTION
2108
+ else FunctionContextType .FUNCTION
2098
2109
),
2099
2110
ctx .expr_pos (),
2100
2111
):
2101
2112
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
+ )
2102
2120
method = FnArity (
2103
2121
form = form ,
2104
2122
loop_id = fn_loop_id ,
2105
2123
params = vec .vector (param_nodes ),
2106
2124
tag = return_tag ,
2107
2125
is_variadic = has_vargs ,
2108
2126
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 ,
2120
2128
env = ctx .get_node_env (),
2121
2129
)
2122
2130
method .visit (partial (_assert_recur_is_tail , ctx ))
@@ -3420,6 +3428,9 @@ def _yield_ast(form: ISeq, ctx: AnalyzerContext) -> Yield:
3420
3428
"yield forms must contain 1 or 2 elements, as in: (yield [expr])" , form = form
3421
3429
)
3422
3430
3431
+ # Indicate that the current function is a generator
3432
+ ctx .func_ctx .is_generator = True
3433
+
3423
3434
if nelems == 2 :
3424
3435
with ctx .expr_pos ():
3425
3436
expr = _analyze_form (runtime .nth (form , 1 ), ctx )
0 commit comments