rapydscript-ng 0.8.3 → 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/bin/build.ts +29 -0
- package/package.json +1 -1
- package/release/baselib-plain-pretty.js +85 -61
- package/release/baselib-plain-ugly.js +3 -3
- package/release/compiler.js +2543 -2432
- package/release/signatures.json +26 -26
- package/src/ast.pyj +170 -58
- package/src/baselib-builtins.pyj +35 -14
- package/src/baselib-containers.pyj +70 -40
- package/src/baselib-internal.pyj +20 -8
- package/src/baselib-itertools.pyj +6 -2
- package/src/baselib-str.pyj +74 -28
- package/src/errors.pyj +4 -1
- package/src/lib/aes.pyj +664 -35
- package/src/lib/elementmaker.pyj +105 -13
- package/src/lib/encodings.pyj +31 -7
- package/src/lib/gettext.pyj +6 -3
- package/src/lib/math.pyj +38 -22
- package/src/lib/pythonize.pyj +5 -3
- package/src/lib/random.pyj +13 -5
- package/src/lib/re.pyj +81 -18
- package/src/lib/traceback.pyj +42 -10
- package/src/lib/uuid.pyj +2 -1
- package/src/output/classes.pyj +70 -26
- package/src/output/codegen.pyj +92 -20
- package/src/output/comments.pyj +11 -4
- package/src/output/exceptions.pyj +17 -4
- package/src/output/functions.pyj +34 -13
- package/src/output/literals.pyj +7 -2
- package/src/output/loops.pyj +50 -16
- package/src/output/modules.pyj +41 -12
- package/src/output/operators.pyj +154 -31
- package/src/output/statements.pyj +38 -10
- package/src/output/stream.pyj +43 -12
- package/src/output/utils.pyj +10 -3
- package/src/parse.pyj +740 -259
- package/src/string_interpolation.pyj +4 -1
- package/src/tokenizer.pyj +300 -55
- package/src/unicode_aliases.pyj +4 -2
- package/src/utils.pyj +19 -5
- package/test/functions.pyj +8 -0
- package/test/generic.pyj +9 -0
- package/test/lsp.pyj +16 -0
- package/tools/compiler.mjs +0 -6
- package/tools/fmt.mjs +41 -2
- package/tools/lint-worker.mjs +7 -1
- package/tools/lint.mjs +12 -5
- package/tools/lsp.mjs +11 -1
package/src/parse.pyj
CHANGED
|
@@ -1,33 +1,110 @@
|
|
|
1
1
|
# vim:fileencoding=utf-8
|
|
2
2
|
# License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
|
-
# globals: readfile, writefile, stat_file, sha1sum, ast_from_json,
|
|
3
|
+
# globals: readfile, writefile, stat_file, sha1sum, ast_from_json,
|
|
4
|
+
# globals: ast_to_json, make_lazy_ast_module, decode_cache, encode_cache
|
|
4
5
|
from __python__ import hash_literals
|
|
5
6
|
|
|
6
7
|
from ast import (
|
|
7
|
-
AST_ArgsDef,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
8
|
+
AST_ArgsDef,
|
|
9
|
+
AST_Array,
|
|
10
|
+
AST_Assign,
|
|
11
|
+
AST_Binary,
|
|
12
|
+
AST_BlockStatement,
|
|
13
|
+
AST_Break,
|
|
14
|
+
AST_Call,
|
|
15
|
+
AST_CallArg,
|
|
16
|
+
AST_CallArgs,
|
|
17
|
+
AST_Catch,
|
|
18
|
+
AST_Class,
|
|
19
|
+
AST_ClassCall,
|
|
20
|
+
AST_Conditional,
|
|
21
|
+
AST_Constant,
|
|
22
|
+
AST_Continue,
|
|
23
|
+
AST_DWLoop,
|
|
24
|
+
AST_Debugger,
|
|
25
|
+
AST_Decorator,
|
|
26
|
+
AST_Definitions,
|
|
27
|
+
AST_DictComprehension,
|
|
28
|
+
AST_Directive,
|
|
29
|
+
AST_Do,
|
|
30
|
+
AST_Dot,
|
|
31
|
+
AST_Else,
|
|
32
|
+
AST_EmptyStatement,
|
|
33
|
+
AST_Except,
|
|
34
|
+
AST_ExpressiveObject,
|
|
35
|
+
AST_False,
|
|
36
|
+
AST_Finally,
|
|
37
|
+
AST_ForIn,
|
|
38
|
+
AST_ForJS,
|
|
39
|
+
AST_Function,
|
|
40
|
+
AST_GeneratorComprehension,
|
|
41
|
+
AST_Hole,
|
|
42
|
+
AST_If,
|
|
43
|
+
AST_Import,
|
|
44
|
+
AST_ImportedVar,
|
|
45
|
+
AST_Imports,
|
|
46
|
+
AST_ListComprehension,
|
|
47
|
+
AST_Method,
|
|
48
|
+
AST_New,
|
|
49
|
+
AST_Null,
|
|
50
|
+
AST_Number,
|
|
51
|
+
AST_Object,
|
|
52
|
+
AST_ObjectKeyVal,
|
|
53
|
+
AST_PropAccess,
|
|
54
|
+
AST_RegExp,
|
|
55
|
+
AST_Return,
|
|
56
|
+
AST_Scope,
|
|
57
|
+
AST_Set,
|
|
58
|
+
AST_SetComprehension,
|
|
59
|
+
AST_SetItem,
|
|
60
|
+
AST_Seq,
|
|
61
|
+
AST_SimpleStatement,
|
|
62
|
+
AST_Splice,
|
|
63
|
+
AST_String,
|
|
64
|
+
AST_Sub,
|
|
65
|
+
AST_ItemAccess,
|
|
66
|
+
AST_SymbolAlias,
|
|
67
|
+
AST_SymbolCatch,
|
|
68
|
+
AST_SymbolDefun,
|
|
69
|
+
AST_SymbolFunarg,
|
|
70
|
+
AST_SymbolLambda,
|
|
71
|
+
AST_SymbolNonlocal,
|
|
72
|
+
AST_SymbolRef,
|
|
73
|
+
AST_SymbolVar,
|
|
74
|
+
AST_This,
|
|
75
|
+
AST_Throw,
|
|
76
|
+
AST_Toplevel,
|
|
77
|
+
AST_True,
|
|
78
|
+
AST_Try,
|
|
79
|
+
AST_UnaryPrefix,
|
|
80
|
+
AST_Undefined,
|
|
81
|
+
AST_Var,
|
|
82
|
+
AST_VarDef,
|
|
83
|
+
AST_Verbatim,
|
|
84
|
+
AST_While,
|
|
85
|
+
AST_With,
|
|
86
|
+
AST_WithClause,
|
|
87
|
+
AST_Yield,
|
|
88
|
+
AST_Await,
|
|
89
|
+
AST_Assert,
|
|
90
|
+
AST_Existential,
|
|
91
|
+
is_node_type,
|
|
92
|
+
TreeWalker
|
|
23
93
|
)
|
|
24
94
|
from errors import SyntaxError, ImportError
|
|
25
95
|
from tokenizer import tokenizer, is_token, RESERVED_WORDS
|
|
26
|
-
from utils import
|
|
96
|
+
from utils import (
|
|
97
|
+
make_predicate, array_to_hash, defaults, has_prop, cache_file_name
|
|
98
|
+
)
|
|
27
99
|
|
|
28
100
|
|
|
29
101
|
COMPILER_VERSION = '__COMPILER_VERSION__'
|
|
30
|
-
PYTHON_FLAGS = {
|
|
102
|
+
PYTHON_FLAGS = {
|
|
103
|
+
'dict_literals': True,
|
|
104
|
+
'overload_getitem': True,
|
|
105
|
+
'bound_methods': True,
|
|
106
|
+
'hash_literals': True,
|
|
107
|
+
}
|
|
31
108
|
CACHE_VERSION = 1
|
|
32
109
|
|
|
33
110
|
|
|
@@ -50,28 +127,19 @@ NATIVE_CLASSES = {
|
|
|
50
127
|
'SyntaxError': {},
|
|
51
128
|
'TypeError': {},
|
|
52
129
|
'URIError': {},
|
|
53
|
-
'Object': {
|
|
54
|
-
'
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
},
|
|
62
|
-
'
|
|
63
|
-
'static': static_predicate('fromCharCode')
|
|
64
|
-
},
|
|
65
|
-
'Array': {
|
|
66
|
-
'static': static_predicate('isArray from of')
|
|
67
|
-
},
|
|
130
|
+
'Object': {'static': static_predicate(
|
|
131
|
+
'getOwnPropertyNames getOwnPropertyDescriptor'
|
|
132
|
+
' getOwnPropertyDescriptors'
|
|
133
|
+
' getOwnPropertySymbols keys entries values create defineProperty'
|
|
134
|
+
' defineProperties getPrototypeOf setPrototypeOf assign'
|
|
135
|
+
' seal isSealed is preventExtensions isExtensible'
|
|
136
|
+
' freeze isFrozen'
|
|
137
|
+
)},
|
|
138
|
+
'String': {'static': static_predicate('fromCharCode')},
|
|
139
|
+
'Array': {'static': static_predicate('isArray from of')},
|
|
68
140
|
'Function': {},
|
|
69
|
-
'Date': {
|
|
70
|
-
|
|
71
|
-
},
|
|
72
|
-
'ArrayBuffer': {
|
|
73
|
-
'static': static_predicate('isView transfer')
|
|
74
|
-
},
|
|
141
|
+
'Date': {'static': static_predicate('UTC now parse')},
|
|
142
|
+
'ArrayBuffer': {'static': static_predicate('isView transfer')},
|
|
75
143
|
'DataView': {},
|
|
76
144
|
'Float32Array': {},
|
|
77
145
|
'Float64Array': {},
|
|
@@ -87,9 +155,7 @@ NATIVE_CLASSES = {
|
|
|
87
155
|
'Proxy': {},
|
|
88
156
|
'Set': {},
|
|
89
157
|
'WeakSet': {},
|
|
90
|
-
'Promise': {
|
|
91
|
-
'static': static_predicate('all race reject resolve')
|
|
92
|
-
},
|
|
158
|
+
'Promise': {'static': static_predicate('all race reject resolve')},
|
|
93
159
|
'WebSocket': {},
|
|
94
160
|
'XMLHttpRequest': {},
|
|
95
161
|
'TextEncoder': {},
|
|
@@ -141,7 +207,9 @@ PRECEDENCE = (def (a, ret):
|
|
|
141
207
|
|
|
142
208
|
STATEMENTS_WITH_LABELS = array_to_hash(['for', 'do', 'while', 'switch'])
|
|
143
209
|
|
|
144
|
-
ATOMIC_START_TOKEN = array_to_hash([
|
|
210
|
+
ATOMIC_START_TOKEN = array_to_hash([
|
|
211
|
+
'atom', 'num', 'string', 'regexp', 'name', 'js'
|
|
212
|
+
])
|
|
145
213
|
|
|
146
214
|
compile_time_decorators = ['staticmethod', 'external', 'property']
|
|
147
215
|
|
|
@@ -164,7 +232,10 @@ def has_setter_decorator(decorators, name):
|
|
|
164
232
|
remove = v'[]'
|
|
165
233
|
for v'var i = 0; i < decorators.length; i++':
|
|
166
234
|
s = decorators[i]
|
|
167
|
-
if is_node_type(s, AST_Dot) and is_node_type(
|
|
235
|
+
if is_node_type(s, AST_Dot) and is_node_type(
|
|
236
|
+
s.expression,
|
|
237
|
+
AST_SymbolRef
|
|
238
|
+
) and s.expression.name is name and s.property is 'setter':
|
|
168
239
|
remove.push(i)
|
|
169
240
|
if remove.length:
|
|
170
241
|
remove.reverse()
|
|
@@ -175,7 +246,11 @@ def has_setter_decorator(decorators, name):
|
|
|
175
246
|
|
|
176
247
|
|
|
177
248
|
# -----[ Parser ]-----
|
|
178
|
-
def create_parser_ctx(
|
|
249
|
+
def create_parser_ctx(
|
|
250
|
+
S, import_dirs, module_id, baselib_items,
|
|
251
|
+
imported_module_ids, imported_modules,
|
|
252
|
+
importing_modules, options
|
|
253
|
+
):
|
|
179
254
|
def next():
|
|
180
255
|
S.prev = S.token
|
|
181
256
|
if S.peeked.length:
|
|
@@ -197,10 +272,17 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
197
272
|
return S.prev
|
|
198
273
|
|
|
199
274
|
def croak(msg, line, col, pos, is_eof):
|
|
200
|
-
# note: undefined means nothing was passed in,
|
|
275
|
+
# note: undefined means nothing was passed in,
|
|
276
|
+
# None/null means a null value was passed in
|
|
201
277
|
ctx = S.input.context()
|
|
202
|
-
raise new SyntaxError(
|
|
203
|
-
|
|
278
|
+
raise new SyntaxError(
|
|
279
|
+
msg,
|
|
280
|
+
ctx.filename,
|
|
281
|
+
(line if line is not undefined else ctx.tokline),
|
|
282
|
+
(col if col is not undefined else ctx.tokcol),
|
|
283
|
+
(pos if pos is not undefined else ctx.tokpos),
|
|
284
|
+
is_eof
|
|
285
|
+
)
|
|
204
286
|
|
|
205
287
|
def token_error(token, msg):
|
|
206
288
|
is_eof = token.type is 'eof'
|
|
@@ -209,9 +291,13 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
209
291
|
def unexpected(token):
|
|
210
292
|
if token is undefined:
|
|
211
293
|
token = S.token
|
|
212
|
-
token_error(
|
|
294
|
+
token_error(
|
|
295
|
+
token,
|
|
296
|
+
'Unexpected token: ' + token.type + ' «' + token.value + '»'
|
|
297
|
+
)
|
|
213
298
|
|
|
214
|
-
# --- Error recovery (only active when
|
|
299
|
+
# --- Error recovery (only active when
|
|
300
|
+
# options.recover_errors is True) --------
|
|
215
301
|
# These helpers let the LSP obtain a usable AST from a file that contains
|
|
216
302
|
# syntax errors. They are never invoked on the normal compile path, so they
|
|
217
303
|
# cannot introduce a performance or behavior regression there.
|
|
@@ -229,7 +315,8 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
229
315
|
# Resynchronize after a syntax error: always consume at least one token
|
|
230
316
|
# (guaranteeing forward progress) then stop at the start of the next
|
|
231
317
|
# logical line, a block dedent, or eof. next() may itself raise a
|
|
232
|
-
# tokenizer level SyntaxError (e.g. an unterminated string on the
|
|
318
|
+
# tokenizer level SyntaxError (e.g. an unterminated string on the
|
|
319
|
+
# skipped
|
|
233
320
|
# line); such errors are recorded and skipping continues. The tokenizer
|
|
234
321
|
# advances its position for every such error (and never raises for an
|
|
235
322
|
# unexpected character in recover mode), so this loop always terminates.
|
|
@@ -249,8 +336,12 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
249
336
|
def expect_token(type, val):
|
|
250
337
|
if is_(type, val):
|
|
251
338
|
return next()
|
|
252
|
-
token_error(
|
|
253
|
-
|
|
339
|
+
token_error(
|
|
340
|
+
S.token,
|
|
341
|
+
'Unexpected token ' + S.token.type +
|
|
342
|
+
' «' + S.token.value + '»' +
|
|
343
|
+
', expected ' + type + ' «' + val + '»'
|
|
344
|
+
)
|
|
254
345
|
|
|
255
346
|
def expect(punc):
|
|
256
347
|
return expect_token('punc', punc)
|
|
@@ -277,11 +368,17 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
277
368
|
# Get the named functions and classes
|
|
278
369
|
if Array.isArray(body):
|
|
279
370
|
for obj in body:
|
|
280
|
-
if is_node_type(
|
|
371
|
+
if is_node_type(
|
|
372
|
+
obj,
|
|
373
|
+
AST_Function
|
|
374
|
+
) or is_node_type(obj, AST_Class):
|
|
281
375
|
if obj.name:
|
|
282
376
|
ans.push(obj.name.name)
|
|
283
377
|
else:
|
|
284
|
-
token_error(
|
|
378
|
+
token_error(
|
|
379
|
+
obj.start,
|
|
380
|
+
'Top-level functions must have names'
|
|
381
|
+
)
|
|
285
382
|
else:
|
|
286
383
|
# skip inner scopes
|
|
287
384
|
if is_node_type(obj, AST_Scope):
|
|
@@ -291,8 +388,13 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
291
388
|
if opt:
|
|
292
389
|
ans = ans.concat(scan_for_top_level_callables(opt))
|
|
293
390
|
|
|
294
|
-
if is_node_type(
|
|
295
|
-
|
|
391
|
+
if is_node_type(
|
|
392
|
+
opt,
|
|
393
|
+
AST_Assign
|
|
394
|
+
) and not (is_node_type(opt.right, AST_Scope)):
|
|
395
|
+
ans = ans.concat(
|
|
396
|
+
scan_for_top_level_callables(opt.right)
|
|
397
|
+
)
|
|
296
398
|
|
|
297
399
|
elif body.body:
|
|
298
400
|
# recursive descent into wrapper statements that contain body blocks
|
|
@@ -311,7 +413,8 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
311
413
|
|
|
312
414
|
def scan_for_local_vars(body):
|
|
313
415
|
"""
|
|
314
|
-
Pick out all variables being assigned to from within this scope,
|
|
416
|
+
Pick out all variables being assigned to from within this scope,
|
|
417
|
+
we'll mark them as local
|
|
315
418
|
|
|
316
419
|
body body to be scanned
|
|
317
420
|
"""
|
|
@@ -373,7 +476,10 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
373
476
|
if opt:
|
|
374
477
|
extend(scan_for_local_vars(opt))
|
|
375
478
|
|
|
376
|
-
if is_node_type(
|
|
479
|
+
if is_node_type(
|
|
480
|
+
opt,
|
|
481
|
+
AST_Assign
|
|
482
|
+
) and not (is_node_type(opt.right, AST_Scope)):
|
|
377
483
|
extend(scan_for_local_vars(opt.right))
|
|
378
484
|
|
|
379
485
|
# pick up iterators from loops
|
|
@@ -399,7 +505,10 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
399
505
|
is_compound_assign = False
|
|
400
506
|
for lhs in body.traverse_chain()[0]:
|
|
401
507
|
add_assign_lhs(lhs)
|
|
402
|
-
if is_node_type(
|
|
508
|
+
if is_node_type(
|
|
509
|
+
lhs,
|
|
510
|
+
AST_Seq
|
|
511
|
+
) or is_node_type(lhs, AST_Array):
|
|
403
512
|
is_compound_assign = True
|
|
404
513
|
break
|
|
405
514
|
if is_compound_assign:
|
|
@@ -454,19 +563,28 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
454
563
|
|
|
455
564
|
@embed_tokens
|
|
456
565
|
async def statement():
|
|
457
|
-
# From Kovid: The next three lines were a hack to try to support
|
|
566
|
+
# From Kovid: The next three lines were a hack to try to support
|
|
567
|
+
# statements
|
|
458
568
|
# starting with a regexp literal. However, it did not work, for example:
|
|
459
569
|
# echo 'f=1\n/asd/.test()' | rs -> parse error
|
|
460
|
-
# So we just accept that this cannot be supported in RS, and avoid
|
|
570
|
+
# So we just accept that this cannot be supported in RS, and avoid
|
|
571
|
+
# hacks that mess
|
|
461
572
|
# with the internal state of S. In any case,
|
|
462
573
|
# statements starting with a literal are very rare.
|
|
463
574
|
if S.token.type is 'operator' and S.token.value.substr(0, 1) is '/':
|
|
464
|
-
token_error(
|
|
575
|
+
token_error(
|
|
576
|
+
S.token,
|
|
577
|
+
'RapydScript does not support statements starting with'
|
|
578
|
+
' regexp literals'
|
|
579
|
+
)
|
|
465
580
|
|
|
466
581
|
S.statement_starting_token = S.token
|
|
467
582
|
tmp_ = S.token.type
|
|
468
583
|
p = prev()
|
|
469
|
-
if p and not S.token.nlb and ATOMIC_START_TOKEN[p.type] and not is_(
|
|
584
|
+
if p and not S.token.nlb and ATOMIC_START_TOKEN[p.type] and not is_(
|
|
585
|
+
'punc',
|
|
586
|
+
':'
|
|
587
|
+
):
|
|
470
588
|
unexpected()
|
|
471
589
|
if tmp_ is 'string':
|
|
472
590
|
return await simple_statement()
|
|
@@ -476,7 +594,8 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
476
594
|
return new AST_Directive({
|
|
477
595
|
'value': tmp_
|
|
478
596
|
})
|
|
479
|
-
elif tmp_ is 'num' or tmp_ is 'regexp' or tmp_ is 'operator'
|
|
597
|
+
elif (tmp_ is 'num' or tmp_ is 'regexp' or tmp_ is 'operator'
|
|
598
|
+
or tmp_ is 'atom' or tmp_ is 'js'):
|
|
480
599
|
return await simple_statement()
|
|
481
600
|
elif tmp_ is 'punc':
|
|
482
601
|
tmp_ = S.token.value
|
|
@@ -491,11 +610,16 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
491
610
|
return await simple_statement()
|
|
492
611
|
elif tmp_ is ';':
|
|
493
612
|
next()
|
|
494
|
-
return new AST_EmptyStatement({
|
|
613
|
+
return new AST_EmptyStatement({
|
|
614
|
+
'stype': ';', 'start': prev(), 'end': prev()
|
|
615
|
+
})
|
|
495
616
|
else:
|
|
496
617
|
unexpected()
|
|
497
618
|
elif tmp_ is 'name':
|
|
498
|
-
if (is_token(peek(), 'punc', ':')) token_error(
|
|
619
|
+
if (is_token(peek(), 'punc', ':')) token_error(
|
|
620
|
+
peek(),
|
|
621
|
+
'invalid syntax, colon not allowed here'
|
|
622
|
+
)
|
|
499
623
|
return await simple_statement()
|
|
500
624
|
elif tmp_ is 'keyword':
|
|
501
625
|
tmp_ = S.token.value
|
|
@@ -514,7 +638,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
514
638
|
expect_token('keyword', 'while')
|
|
515
639
|
tmp = await expression(True)
|
|
516
640
|
if is_node_type(tmp, AST_Assign):
|
|
517
|
-
croak(
|
|
641
|
+
croak(
|
|
642
|
+
'Assignments in do loop conditions are not allowed'
|
|
643
|
+
)
|
|
518
644
|
semicolon()
|
|
519
645
|
return tmp
|
|
520
646
|
)()
|
|
@@ -525,7 +651,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
525
651
|
elif tmp_ is 'while':
|
|
526
652
|
while_cond = await expression(True)
|
|
527
653
|
if is_node_type(while_cond, AST_Assign):
|
|
528
|
-
croak(
|
|
654
|
+
croak(
|
|
655
|
+
'Assignments in while loop conditions are not allowed'
|
|
656
|
+
)
|
|
529
657
|
if not is_('punc', ':'):
|
|
530
658
|
croak('Expected a colon after the while statement')
|
|
531
659
|
while_body = await in_loop(statement)
|
|
@@ -581,12 +709,17 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
581
709
|
if is_('punc', ','):
|
|
582
710
|
next()
|
|
583
711
|
msg = await expression(False)
|
|
584
|
-
return new AST_Assert({
|
|
712
|
+
return new AST_Assert({
|
|
713
|
+
'start': start, 'condition': cond,
|
|
714
|
+
'message': msg, 'end': prev()
|
|
715
|
+
})
|
|
585
716
|
elif tmp_ is 'if':
|
|
586
717
|
return await if_()
|
|
587
718
|
elif tmp_ is 'pass':
|
|
588
719
|
semicolon()
|
|
589
|
-
return new AST_EmptyStatement({
|
|
720
|
+
return new AST_EmptyStatement({
|
|
721
|
+
'stype': 'pass', 'start': prev(), 'end': prev()
|
|
722
|
+
})
|
|
590
723
|
elif tmp_ is 'return':
|
|
591
724
|
if S.in_function is 0:
|
|
592
725
|
croak("'return' outside of function")
|
|
@@ -644,7 +777,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
644
777
|
if is_('keyword', 'as'):
|
|
645
778
|
next()
|
|
646
779
|
alias = as_symbol(AST_SymbolAlias)
|
|
647
|
-
clauses.push(new AST_WithClause({
|
|
780
|
+
clauses.push(new AST_WithClause({
|
|
781
|
+
'expression': expr, 'alias': alias
|
|
782
|
+
}))
|
|
648
783
|
if is_('punc', ','):
|
|
649
784
|
next()
|
|
650
785
|
continue
|
|
@@ -695,8 +830,12 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
695
830
|
init = await expression(True, True)
|
|
696
831
|
# standardize AST_Seq into array now for consistency
|
|
697
832
|
if is_node_type(init, AST_Seq):
|
|
698
|
-
if is_node_type(
|
|
699
|
-
|
|
833
|
+
if is_node_type(
|
|
834
|
+
init.car,
|
|
835
|
+
AST_SymbolRef
|
|
836
|
+
) and is_node_type(init.cdr, AST_SymbolRef):
|
|
837
|
+
# Optimization to prevent runtime call to ρσ_flatten
|
|
838
|
+
# when init is simply (a, b)
|
|
700
839
|
tmp = init.to_array()
|
|
701
840
|
else:
|
|
702
841
|
tmp = [init]
|
|
@@ -708,7 +847,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
708
847
|
|
|
709
848
|
if is_('operator', 'in'):
|
|
710
849
|
if is_node_type(init, AST_Var) and init.definitions.length > 1:
|
|
711
|
-
croak(
|
|
850
|
+
croak(
|
|
851
|
+
'Only one variable declaration allowed in for..in loop'
|
|
852
|
+
)
|
|
712
853
|
next()
|
|
713
854
|
return await for_in(init, list_comp)
|
|
714
855
|
|
|
@@ -763,13 +904,15 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
763
904
|
|
|
764
905
|
elif is_node_type(expr, AST_Dot):
|
|
765
906
|
referenced_path = []
|
|
766
|
-
# this one is for detecting classes inside modules and
|
|
907
|
+
# this one is for detecting classes inside modules and
|
|
908
|
+
# eventually nested classes
|
|
767
909
|
while is_node_type(expr, AST_Dot):
|
|
768
910
|
referenced_path.unshift(expr.property)
|
|
769
911
|
expr = expr.expression
|
|
770
912
|
if is_node_type(expr, AST_SymbolRef):
|
|
771
913
|
referenced_path.unshift(expr.name)
|
|
772
|
-
# now 'referenced_path' should contain the full path
|
|
914
|
+
# now 'referenced_path' should contain the full path
|
|
915
|
+
# of potential class
|
|
773
916
|
if len(referenced_path) > 1:
|
|
774
917
|
class_name = referenced_path.join('.')
|
|
775
918
|
for s in range(S.classes.length - 1, -1, -1):
|
|
@@ -779,17 +922,29 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
779
922
|
|
|
780
923
|
def import_error(message):
|
|
781
924
|
ctx = S.input.context()
|
|
782
|
-
raise new ImportError(
|
|
925
|
+
raise new ImportError(
|
|
926
|
+
message,
|
|
927
|
+
ctx.filename,
|
|
928
|
+
ctx.tokline,
|
|
929
|
+
ctx.tokcol,
|
|
930
|
+
ctx.tokpos
|
|
931
|
+
)
|
|
783
932
|
|
|
784
933
|
async def do_import(key):
|
|
785
934
|
if has_prop(imported_modules, key):
|
|
786
935
|
return
|
|
787
|
-
# Circular import check must come BEFORE loading_promises so we
|
|
936
|
+
# Circular import check must come BEFORE loading_promises so we
|
|
937
|
+
# detect cycles
|
|
788
938
|
# even when the same module is being loaded by a parallel chain.
|
|
789
939
|
if has_prop(importing_modules, key) and importing_modules[key]:
|
|
790
|
-
import_error(
|
|
791
|
-
|
|
792
|
-
|
|
940
|
+
import_error(
|
|
941
|
+
'Detected a recursive import of: ' + key +
|
|
942
|
+
' while importing: ' + module_id
|
|
943
|
+
)
|
|
944
|
+
# If a parallel chain is already loading this module, wait for it
|
|
945
|
+
# instead of
|
|
946
|
+
# starting a duplicate load. loading_promises is shared across
|
|
947
|
+
# the entire
|
|
793
948
|
# compilation via options.loading_promises.
|
|
794
949
|
loading_promises = options.loading_promises
|
|
795
950
|
if has_prop(loading_promises, key):
|
|
@@ -798,8 +953,10 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
798
953
|
|
|
799
954
|
# Register this load BEFORE the first await so that any parallel caller
|
|
800
955
|
# that reaches this point sees the in-progress entry and waits.
|
|
801
|
-
# Use a single-element list to capture the resolve function from
|
|
802
|
-
#
|
|
956
|
+
# Use a single-element list to capture the resolve function from
|
|
957
|
+
# the Promise
|
|
958
|
+
# executor without needing nonlocal (mutating a container,
|
|
959
|
+
# not rebinding).
|
|
803
960
|
_rfn = v'[null]'
|
|
804
961
|
|
|
805
962
|
def _capture_resolve(resolve):
|
|
@@ -813,20 +970,37 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
813
970
|
await do_import(package_module_id)
|
|
814
971
|
|
|
815
972
|
if options.for_linting:
|
|
816
|
-
imported_modules[key] = {
|
|
817
|
-
|
|
973
|
+
imported_modules[key] = {
|
|
974
|
+
'is_cached': True,
|
|
975
|
+
'classes': {},
|
|
976
|
+
'module_id': key,
|
|
977
|
+
'exports': [],
|
|
978
|
+
'nonlocalvars': [],
|
|
979
|
+
'baselib': {},
|
|
980
|
+
'outputs': {},
|
|
981
|
+
'discard_asserts': options.discard_asserts,
|
|
982
|
+
}
|
|
818
983
|
return
|
|
819
984
|
|
|
820
|
-
# stat_file returns {mtimeMs, content?}. For real filesystems
|
|
821
|
-
#
|
|
985
|
+
# stat_file returns {mtimeMs, content?}. For real filesystems
|
|
986
|
+
# mtimeMs is a
|
|
987
|
+
# number and content is absent; for virtual filesystems
|
|
988
|
+
# content holds the
|
|
822
989
|
# already-read source to avoid a double read.
|
|
823
990
|
async def safe_stat(base_path): # noqa
|
|
824
|
-
for i, path in enumerate([
|
|
991
|
+
for i, path in enumerate([
|
|
992
|
+
base_path + '.pyj', base_path + '/__init__.pyj'
|
|
993
|
+
]):
|
|
825
994
|
try:
|
|
826
995
|
st = await stat_file(path)
|
|
827
|
-
return [
|
|
996
|
+
return [
|
|
997
|
+
st.mtimeMs,
|
|
998
|
+
path,
|
|
999
|
+
st.content if has_prop(st, 'content') else None,
|
|
1000
|
+
]
|
|
828
1001
|
except as e:
|
|
829
|
-
if e.code is 'ENOENT' or e.code is 'EPERM'
|
|
1002
|
+
if (e.code is 'ENOENT' or e.code is 'EPERM'
|
|
1003
|
+
or e.code is 'EACCESS'):
|
|
830
1004
|
if i is 1:
|
|
831
1005
|
return None, None, None
|
|
832
1006
|
if i is 1:
|
|
@@ -837,15 +1011,24 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
837
1011
|
|
|
838
1012
|
for location in import_dirs:
|
|
839
1013
|
if location:
|
|
840
|
-
file_mtime, filename, prefetched_src = await safe_stat(
|
|
1014
|
+
file_mtime, filename, prefetched_src = await safe_stat(
|
|
1015
|
+
location + '/' + modpath
|
|
1016
|
+
)
|
|
841
1017
|
if filename is not None:
|
|
842
1018
|
break
|
|
843
1019
|
if filename is None:
|
|
844
|
-
import_error(
|
|
845
|
-
|
|
846
|
-
|
|
1020
|
+
import_error(
|
|
1021
|
+
"Failed Import: '" + key +
|
|
1022
|
+
"' module doesn't exist in any of the import"
|
|
1023
|
+
' directories: ' + import_dirs.join(':')
|
|
1024
|
+
)
|
|
1025
|
+
|
|
1026
|
+
# Read the cache file. I/O starts here; any CPU work done
|
|
1027
|
+
# before the
|
|
847
1028
|
# await can overlap with the disk read.
|
|
848
|
-
cache_read = readfile(
|
|
1029
|
+
cache_read = readfile(
|
|
1030
|
+
cache_file_name(filename, options.module_cache_dir)
|
|
1031
|
+
)
|
|
849
1032
|
|
|
850
1033
|
cached = None
|
|
851
1034
|
ast_json_str = None
|
|
@@ -858,21 +1041,31 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
858
1041
|
cached = None
|
|
859
1042
|
|
|
860
1043
|
srchash = src_code = None
|
|
861
|
-
cache_ok =
|
|
862
|
-
|
|
863
|
-
|
|
1044
|
+
cache_ok = (
|
|
1045
|
+
cached and cached.v is CACHE_VERSION
|
|
1046
|
+
and cached.compiler_version is COMPILER_VERSION
|
|
1047
|
+
)
|
|
1048
|
+
if (cache_ok and file_mtime is not None
|
|
1049
|
+
and cached.mtime is not None
|
|
1050
|
+
and cached.mtime is file_mtime):
|
|
1051
|
+
# Fast path: mtime matches — source file is unchanged,
|
|
1052
|
+
# skip reading and hashing it
|
|
864
1053
|
srchash = cached.signature
|
|
865
1054
|
else:
|
|
866
|
-
# Need source content to validate with sha1sum (or to
|
|
1055
|
+
# Need source content to validate with sha1sum (or to
|
|
1056
|
+
# re-parse on miss)
|
|
867
1057
|
src_code = prefetched_src or await readfile(filename, 'utf-8')
|
|
868
1058
|
srchash = sha1sum(src_code)
|
|
869
1059
|
if not cache_ok or cached.signature is not srchash:
|
|
870
1060
|
cached = None
|
|
871
1061
|
|
|
872
1062
|
if cached is not None:
|
|
873
|
-
# Load all deps in parallel — cached module deps have been
|
|
874
|
-
#
|
|
875
|
-
#
|
|
1063
|
+
# Load all deps in parallel — cached module deps have been
|
|
1064
|
+
# pre-validated as
|
|
1065
|
+
# non-circular so Promise.all is safe. The loading_promises
|
|
1066
|
+
# dict ensures
|
|
1067
|
+
# that if two parallel chains try to load the same dep,
|
|
1068
|
+
# only one actually
|
|
876
1069
|
# does the work; the other waits.
|
|
877
1070
|
pending = v'[]'
|
|
878
1071
|
for ikey in cached.imported_module_ids:
|
|
@@ -880,11 +1073,17 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
880
1073
|
pending.push(do_import(ikey))
|
|
881
1074
|
if pending.length > 0:
|
|
882
1075
|
await Promise.all(pending)
|
|
883
|
-
# Reconstruct classes dict from the simplified cache
|
|
1076
|
+
# Reconstruct classes dict from the simplified cache
|
|
1077
|
+
# (no full AST nodes).
|
|
884
1078
|
classes = {}
|
|
885
1079
|
for cname in Object.keys(cached.classes or {}):
|
|
886
1080
|
ci = cached.classes[cname]
|
|
887
|
-
classes[cname] = {
|
|
1081
|
+
classes[cname] = {
|
|
1082
|
+
'name': {'name': cname},
|
|
1083
|
+
'static': ci.static or {},
|
|
1084
|
+
'bound': ci.bound or [],
|
|
1085
|
+
'classvars': ci.classvars or {},
|
|
1086
|
+
}
|
|
888
1087
|
meta = {
|
|
889
1088
|
'module_id': key,
|
|
890
1089
|
'filename': filename,
|
|
@@ -901,21 +1100,25 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
901
1100
|
module = make_lazy_ast_module(ast_json_str, meta)
|
|
902
1101
|
imported_modules[key] = module
|
|
903
1102
|
else:
|
|
904
|
-
await parse(
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
1103
|
+
await parse(
|
|
1104
|
+
src_code,
|
|
1105
|
+
{
|
|
1106
|
+
'filename': filename,
|
|
1107
|
+
'toplevel': None,
|
|
1108
|
+
'basedir': options.basedir,
|
|
1109
|
+
'libdir': options.libdir,
|
|
1110
|
+
'import_dirs': options.import_dirs,
|
|
1111
|
+
'module_id': key,
|
|
1112
|
+
'imported_modules': imported_modules,
|
|
1113
|
+
'importing_modules': importing_modules,
|
|
1114
|
+
'discard_asserts': options.discard_asserts,
|
|
1115
|
+
'module_cache_dir': options.module_cache_dir,
|
|
1116
|
+
'_src_hash': srchash,
|
|
1117
|
+
'_file_mtime': file_mtime,
|
|
1118
|
+
'loading_promises': loading_promises,
|
|
1119
|
+
}
|
|
1120
|
+
)
|
|
1121
|
+
# This function will add the module to imported_modules itself
|
|
919
1122
|
finally:
|
|
920
1123
|
del loading_promises[key]
|
|
921
1124
|
if _rfn[0]:
|
|
@@ -951,7 +1154,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
951
1154
|
else:
|
|
952
1155
|
continue
|
|
953
1156
|
break
|
|
954
|
-
return new AST_EmptyStatement({
|
|
1157
|
+
return new AST_EmptyStatement({
|
|
1158
|
+
'stype': 'scoped_flags', 'start': prev(), 'end': prev()
|
|
1159
|
+
})
|
|
955
1160
|
|
|
956
1161
|
async def import_(from_import):
|
|
957
1162
|
ans = new AST_Imports({'imports': []})
|
|
@@ -1001,8 +1206,14 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1001
1206
|
exports[symdef.name] = True
|
|
1002
1207
|
while True:
|
|
1003
1208
|
aname = as_symbol(AST_ImportedVar)
|
|
1004
|
-
if not options.for_linting and not has_prop(
|
|
1005
|
-
|
|
1209
|
+
if not options.for_linting and not has_prop(
|
|
1210
|
+
exports,
|
|
1211
|
+
aname.name
|
|
1212
|
+
):
|
|
1213
|
+
import_error(
|
|
1214
|
+
'The symbol "' + aname.name +
|
|
1215
|
+
'" is not exported from the module: ' + key
|
|
1216
|
+
)
|
|
1006
1217
|
if is_('keyword', 'as'):
|
|
1007
1218
|
next()
|
|
1008
1219
|
aname.alias = as_symbol(AST_SymbolAlias)
|
|
@@ -1022,12 +1233,20 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1022
1233
|
obj = classes[argvar.name]
|
|
1023
1234
|
if obj:
|
|
1024
1235
|
key = argvar.alias.name if argvar.alias else argvar.name
|
|
1025
|
-
S.classes[-1][key] = {
|
|
1236
|
+
S.classes[-1][key] = {
|
|
1237
|
+
'static': obj.static,
|
|
1238
|
+
'bound': obj.bound,
|
|
1239
|
+
'classvars': obj.classvars,
|
|
1240
|
+
}
|
|
1026
1241
|
else:
|
|
1027
1242
|
for cname in Object.keys(classes):
|
|
1028
1243
|
obj = classes[cname]
|
|
1029
1244
|
key = imp.alias.name if imp.alias else imp.key
|
|
1030
|
-
S.classes[-1][key + '.' + obj.name.name] = {
|
|
1245
|
+
S.classes[-1][key + '.' + obj.name.name] = {
|
|
1246
|
+
'static': obj.static,
|
|
1247
|
+
'bound': obj.bound,
|
|
1248
|
+
'classvars': obj.classvars,
|
|
1249
|
+
}
|
|
1031
1250
|
|
|
1032
1251
|
return ans
|
|
1033
1252
|
|
|
@@ -1077,7 +1296,8 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1077
1296
|
return d
|
|
1078
1297
|
)()
|
|
1079
1298
|
cls_body = await (async def (loop, labels):
|
|
1080
|
-
# navigate to correct location in the module tree and
|
|
1299
|
+
# navigate to correct location in the module tree and
|
|
1300
|
+
# append the class
|
|
1081
1301
|
S.in_class.push(name.name)
|
|
1082
1302
|
S.classes[S.classes.length - 1][name.name] = class_details
|
|
1083
1303
|
S.classes.push({})
|
|
@@ -1117,7 +1337,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1117
1337
|
if stmt.is_getter or stmt.is_setter:
|
|
1118
1338
|
descriptor = definition.dynamic_properties[stmt.name.name]
|
|
1119
1339
|
if not descriptor:
|
|
1120
|
-
descriptor = definition.dynamic_properties[
|
|
1340
|
+
descriptor = definition.dynamic_properties[
|
|
1341
|
+
stmt.name.name
|
|
1342
|
+
] = {}
|
|
1121
1343
|
descriptor['getter' if stmt.is_getter else 'setter'] = stmt
|
|
1122
1344
|
elif stmt.name.name is '__init__':
|
|
1123
1345
|
definition.init = stmt
|
|
@@ -1134,14 +1356,25 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1134
1356
|
return
|
|
1135
1357
|
if is_node_type(node, AST_Function):
|
|
1136
1358
|
return
|
|
1137
|
-
if is_node_type(node, AST_Assign) and is_node_type(
|
|
1359
|
+
if is_node_type(node, AST_Assign) and is_node_type(
|
|
1360
|
+
node.left,
|
|
1361
|
+
AST_SymbolRef
|
|
1362
|
+
):
|
|
1138
1363
|
varname = node.left.name
|
|
1139
1364
|
if FORBIDDEN_CLASS_VARS.indexOf(varname) is not -1:
|
|
1140
|
-
token_error(
|
|
1365
|
+
token_error(
|
|
1366
|
+
node.left.start,
|
|
1367
|
+
varname + ' is not allowed as a class variable name'
|
|
1368
|
+
)
|
|
1141
1369
|
class_var_names[varname] = True
|
|
1142
1370
|
definition.classvars[varname] = True
|
|
1143
|
-
elif is_node_type(node, AST_SymbolRef) and has_prop(
|
|
1144
|
-
|
|
1371
|
+
elif is_node_type(node, AST_SymbolRef) and has_prop(
|
|
1372
|
+
class_var_names,
|
|
1373
|
+
node.name
|
|
1374
|
+
):
|
|
1375
|
+
node.thedef = new AST_SymbolDefun({
|
|
1376
|
+
'name': name.name + '.prototype.' + node.name
|
|
1377
|
+
})
|
|
1145
1378
|
if descend:
|
|
1146
1379
|
descend.call(node)
|
|
1147
1380
|
this._visit = visit_node
|
|
@@ -1154,7 +1387,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1154
1387
|
return definition
|
|
1155
1388
|
|
|
1156
1389
|
async def function_(in_class, is_expression, is_async=False):
|
|
1157
|
-
name = as_symbol(
|
|
1390
|
+
name = as_symbol(
|
|
1391
|
+
AST_SymbolDefun if in_class else AST_SymbolLambda
|
|
1392
|
+
) if is_('name') else None
|
|
1158
1393
|
if in_class and not name:
|
|
1159
1394
|
croak('Cannot use anonymous function as class methods')
|
|
1160
1395
|
is_anonymous = not name
|
|
@@ -1166,10 +1401,16 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1166
1401
|
property_setter = has_setter_decorator(S.decorators, name.name)
|
|
1167
1402
|
if staticloc:
|
|
1168
1403
|
if property_getter or property_setter:
|
|
1169
|
-
croak(
|
|
1170
|
-
|
|
1404
|
+
croak(
|
|
1405
|
+
'A method cannot be both static and a'
|
|
1406
|
+
' property getter/setter'
|
|
1407
|
+
)
|
|
1408
|
+
S.classes[S.classes.length - 2][in_class].static[
|
|
1409
|
+
name.name
|
|
1410
|
+
] = True
|
|
1171
1411
|
staticmethod = True
|
|
1172
|
-
elif name.name is not '__init__'
|
|
1412
|
+
elif (name.name is not '__init__'
|
|
1413
|
+
and S.scoped_flags.get('bound_methods')):
|
|
1173
1414
|
S.classes[S.classes.length - 2][in_class].bound.push(name.name)
|
|
1174
1415
|
|
|
1175
1416
|
expect('(')
|
|
@@ -1196,7 +1437,11 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1196
1437
|
if has_prop(seen_names, current_arg_name):
|
|
1197
1438
|
token_error(prev(), "Can't repeat parameter names")
|
|
1198
1439
|
if current_arg_name is 'arguments':
|
|
1199
|
-
token_error(
|
|
1440
|
+
token_error(
|
|
1441
|
+
prev(),
|
|
1442
|
+
"Can't use the name arguments as a parameter"
|
|
1443
|
+
' name, it is reserved by JavaScript'
|
|
1444
|
+
)
|
|
1200
1445
|
seen_names[current_arg_name] = True
|
|
1201
1446
|
# save these in order to move back if we have an annotation
|
|
1202
1447
|
name_token = S.token
|
|
@@ -1226,8 +1471,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1226
1471
|
return sym
|
|
1227
1472
|
else:
|
|
1228
1473
|
if not is_('name'):
|
|
1229
|
-
# there is no name, which is an error we should
|
|
1230
|
-
# same line as the definition, so
|
|
1474
|
+
# there is no name, which is an error we should
|
|
1475
|
+
# report on the same line as the definition, so
|
|
1476
|
+
# move to that is we're not already there.
|
|
1231
1477
|
if S.input.context().tokline is not def_line:
|
|
1232
1478
|
croak('Name expected', def_line)
|
|
1233
1479
|
else:
|
|
@@ -1252,29 +1498,52 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1252
1498
|
# **kwargs
|
|
1253
1499
|
next()
|
|
1254
1500
|
if kwargs_sym:
|
|
1255
|
-
token_error(
|
|
1501
|
+
token_error(
|
|
1502
|
+
name_token,
|
|
1503
|
+
"Can't define multiple **kwargs"
|
|
1504
|
+
' in function definition'
|
|
1505
|
+
)
|
|
1256
1506
|
kwargs_sym = await get_arg()
|
|
1257
1507
|
elif is_('operator', '*'):
|
|
1258
1508
|
# *args
|
|
1259
1509
|
next()
|
|
1260
1510
|
if starargs_sym:
|
|
1261
|
-
token_error(
|
|
1511
|
+
token_error(
|
|
1512
|
+
name_token,
|
|
1513
|
+
"Can't define multiple *args in function definition"
|
|
1514
|
+
)
|
|
1262
1515
|
if kwargs_sym:
|
|
1263
|
-
token_error(
|
|
1516
|
+
token_error(
|
|
1517
|
+
name_token,
|
|
1518
|
+
"Can't define *args after **kwargs"
|
|
1519
|
+
' in function definition'
|
|
1520
|
+
)
|
|
1264
1521
|
starargs_sym = await get_arg()
|
|
1265
1522
|
else:
|
|
1266
1523
|
if starargs_sym or kwargs_sym:
|
|
1267
|
-
token_error(
|
|
1524
|
+
token_error(
|
|
1525
|
+
name_token,
|
|
1526
|
+
"Can't define a formal parameter after"
|
|
1527
|
+
' *args or **kwargs'
|
|
1528
|
+
)
|
|
1268
1529
|
a.push(await get_arg())
|
|
1269
1530
|
if is_('operator', '='):
|
|
1270
1531
|
if kwargs_sym:
|
|
1271
|
-
token_error(
|
|
1532
|
+
token_error(
|
|
1533
|
+
name_token,
|
|
1534
|
+
"Can't define an optional formal parameter"
|
|
1535
|
+
' after **kwargs'
|
|
1536
|
+
)
|
|
1272
1537
|
next()
|
|
1273
1538
|
defaults[current_arg_name] = await expression(False)
|
|
1274
1539
|
has_defaults = True
|
|
1275
1540
|
else:
|
|
1276
1541
|
if has_defaults:
|
|
1277
|
-
token_error(
|
|
1542
|
+
token_error(
|
|
1543
|
+
name_token,
|
|
1544
|
+
"Can't define required formal parameters"
|
|
1545
|
+
' after optional formal parameters'
|
|
1546
|
+
)
|
|
1278
1547
|
next()
|
|
1279
1548
|
# check if we have a return type annotation
|
|
1280
1549
|
if is_('punc', '->'):
|
|
@@ -1288,7 +1557,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1288
1557
|
'kwargs': kwargs_sym,
|
|
1289
1558
|
'defaults': defaults,
|
|
1290
1559
|
'has_defaults': has_defaults,
|
|
1291
|
-
'is_simple_func':
|
|
1560
|
+
'is_simple_func': (
|
|
1561
|
+
not starargs_sym and not kwargs_sym and not has_defaults
|
|
1562
|
+
),
|
|
1292
1563
|
})
|
|
1293
1564
|
)()
|
|
1294
1565
|
|
|
@@ -1339,14 +1610,23 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1339
1610
|
definition.is_getter = property_getter
|
|
1340
1611
|
definition.is_setter = property_setter
|
|
1341
1612
|
if definition.argnames.args.length < 1 and not definition.static:
|
|
1342
|
-
croak(
|
|
1613
|
+
croak(
|
|
1614
|
+
'Methods of a class must have at least one argument,'
|
|
1615
|
+
' traditionally named self'
|
|
1616
|
+
)
|
|
1343
1617
|
if definition.name and definition.name.name is '__init__':
|
|
1344
1618
|
if definition.is_generator:
|
|
1345
|
-
croak(
|
|
1619
|
+
croak(
|
|
1620
|
+
'The __init__ method of a class cannot be a'
|
|
1621
|
+
' generator (yield not allowed)'
|
|
1622
|
+
)
|
|
1346
1623
|
if definition.is_async:
|
|
1347
1624
|
croak('The __init__ method of a class cannot be async')
|
|
1348
1625
|
if property_getter or property_setter:
|
|
1349
|
-
croak(
|
|
1626
|
+
croak(
|
|
1627
|
+
'The __init__ method of a class cannot be a'
|
|
1628
|
+
' property getter/setter'
|
|
1629
|
+
)
|
|
1350
1630
|
if definition.is_async and definition.is_generator:
|
|
1351
1631
|
croak('A function cannot be both async and a generator')
|
|
1352
1632
|
if definition.is_generator:
|
|
@@ -1357,13 +1637,19 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1357
1637
|
for i in range(assignments.length):
|
|
1358
1638
|
for j in range(definition.argnames.args.length + 1):
|
|
1359
1639
|
if j is definition.argnames.args.length:
|
|
1360
|
-
definition.localvars.push(
|
|
1361
|
-
|
|
1640
|
+
definition.localvars.push(
|
|
1641
|
+
new_symbol(AST_SymbolVar, assignments[i])
|
|
1642
|
+
)
|
|
1643
|
+
elif (j < definition.argnames.args.length
|
|
1644
|
+
and assignments[i] is definition.argnames.args[j].name):
|
|
1362
1645
|
break
|
|
1363
1646
|
|
|
1364
1647
|
nonlocals = scan_for_nonlocal_defs(definition.body)
|
|
1365
1648
|
nonlocals = {name for name in nonlocals}
|
|
1366
|
-
definition.localvars = definition.localvars.filter(
|
|
1649
|
+
definition.localvars = definition.localvars.filter(
|
|
1650
|
+
def (v):
|
|
1651
|
+
return not nonlocals.has(v.name)
|
|
1652
|
+
)
|
|
1367
1653
|
return definition
|
|
1368
1654
|
|
|
1369
1655
|
async def if_():
|
|
@@ -1419,7 +1705,8 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1419
1705
|
a.push(stmt)
|
|
1420
1706
|
else:
|
|
1421
1707
|
current_whitespace = S.token.leading_whitespace
|
|
1422
|
-
if current_whitespace.length is 0
|
|
1708
|
+
if (current_whitespace.length is 0
|
|
1709
|
+
or prev_whitespace is current_whitespace):
|
|
1423
1710
|
croak('Expected an indented block')
|
|
1424
1711
|
while not is_('punc', '}'):
|
|
1425
1712
|
if is_('eof'):
|
|
@@ -1499,7 +1786,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1499
1786
|
|
|
1500
1787
|
return new AST_Try({
|
|
1501
1788
|
'body': body,
|
|
1502
|
-
'bcatch': (
|
|
1789
|
+
'bcatch': (
|
|
1790
|
+
new AST_Catch({'body': bcatch}) if bcatch.length else None
|
|
1791
|
+
),
|
|
1503
1792
|
'bfinally': bfinally,
|
|
1504
1793
|
'belse': belse
|
|
1505
1794
|
})
|
|
@@ -1612,7 +1901,10 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1612
1901
|
'end': tok,
|
|
1613
1902
|
'value': tok.value,
|
|
1614
1903
|
})
|
|
1615
|
-
token_error(
|
|
1904
|
+
token_error(
|
|
1905
|
+
tok,
|
|
1906
|
+
'Expecting an atomic token (number/string/bool/regexp/js/None)'
|
|
1907
|
+
)
|
|
1616
1908
|
|
|
1617
1909
|
def as_atom_node():
|
|
1618
1910
|
ret = token_as_atom_node()
|
|
@@ -1627,15 +1919,20 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1627
1919
|
if is_('punc'):
|
|
1628
1920
|
tmp_ = start.value
|
|
1629
1921
|
if tmp_ is '(':
|
|
1922
|
+
prev_parens = S.in_parenthesized_expr
|
|
1630
1923
|
S.in_parenthesized_expr = True
|
|
1631
1924
|
next()
|
|
1632
1925
|
if is_('punc', ')'):
|
|
1633
1926
|
next()
|
|
1927
|
+
S.in_parenthesized_expr = prev_parens
|
|
1634
1928
|
return new AST_Array({'elements': []})
|
|
1635
1929
|
ex = await expression(True)
|
|
1636
1930
|
if is_('keyword', 'for'):
|
|
1637
|
-
ret = await read_comprehension(
|
|
1638
|
-
|
|
1931
|
+
ret = await read_comprehension(
|
|
1932
|
+
new AST_GeneratorComprehension({'statement': ex}),
|
|
1933
|
+
')'
|
|
1934
|
+
)
|
|
1935
|
+
S.in_parenthesized_expr = prev_parens
|
|
1639
1936
|
return ret
|
|
1640
1937
|
ex.start = start
|
|
1641
1938
|
ex.end = S.token
|
|
@@ -1645,7 +1942,7 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1645
1942
|
expect(')')
|
|
1646
1943
|
if is_node_type(ex, AST_UnaryPrefix):
|
|
1647
1944
|
ex.parenthesized = True
|
|
1648
|
-
S.in_parenthesized_expr =
|
|
1945
|
+
S.in_parenthesized_expr = prev_parens
|
|
1649
1946
|
return await subscripts(ex, allow_calls)
|
|
1650
1947
|
elif tmp_ is '[':
|
|
1651
1948
|
return await subscripts(await array_(), allow_calls)
|
|
@@ -1700,7 +1997,10 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1700
1997
|
saw_starargs = False
|
|
1701
1998
|
while not is_('punc', closing):
|
|
1702
1999
|
if saw_starargs:
|
|
1703
|
-
token_error(
|
|
2000
|
+
token_error(
|
|
2001
|
+
prev(),
|
|
2002
|
+
'*args must be the last argument in a function call'
|
|
2003
|
+
)
|
|
1704
2004
|
|
|
1705
2005
|
if first:
|
|
1706
2006
|
first = False
|
|
@@ -1730,7 +2030,10 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1730
2030
|
kwargs.push([arg.left, arg.right])
|
|
1731
2031
|
else:
|
|
1732
2032
|
pargs.push(arg)
|
|
1733
|
-
return new AST_CallArgs({
|
|
2033
|
+
return new AST_CallArgs({
|
|
2034
|
+
'args': pargs, 'kwargs': kwargs,
|
|
2035
|
+
'kwarg_items': v'[]', 'starargs': saw_starargs
|
|
2036
|
+
})
|
|
1734
2037
|
return a
|
|
1735
2038
|
|
|
1736
2039
|
async def func_call_list(empty):
|
|
@@ -1740,13 +2043,19 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1740
2043
|
kwarg_items = v'[]'
|
|
1741
2044
|
starargs = False
|
|
1742
2045
|
if empty:
|
|
1743
|
-
return new AST_CallArgs({
|
|
2046
|
+
return new AST_CallArgs({
|
|
2047
|
+
'args': a, 'kwargs': kwargs,
|
|
2048
|
+
'kwarg_items': kwarg_items, 'starargs': starargs
|
|
2049
|
+
})
|
|
1744
2050
|
single_comprehension = False
|
|
1745
2051
|
while not is_('punc', ')') and not is_('eof'):
|
|
1746
2052
|
if not first:
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
2053
|
+
if S.token.nlb and not is_('punc', ','):
|
|
2054
|
+
pass
|
|
2055
|
+
else:
|
|
2056
|
+
expect(',')
|
|
2057
|
+
if is_('punc', ')'):
|
|
2058
|
+
break
|
|
1750
2059
|
if is_('operator', '*'):
|
|
1751
2060
|
next()
|
|
1752
2061
|
arg = await expression(False)
|
|
@@ -1763,16 +2072,27 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1763
2072
|
else:
|
|
1764
2073
|
if is_('keyword', 'for'):
|
|
1765
2074
|
if not first:
|
|
1766
|
-
croak(
|
|
1767
|
-
|
|
1768
|
-
|
|
2075
|
+
croak(
|
|
2076
|
+
'Generator expression must be'
|
|
2077
|
+
' parenthesized if not sole argument'
|
|
2078
|
+
)
|
|
2079
|
+
comp = await read_comprehension(
|
|
2080
|
+
new AST_GeneratorComprehension({'statement': arg}),
|
|
2081
|
+
')'
|
|
2082
|
+
)
|
|
2083
|
+
a.push(new AST_CallArg({
|
|
2084
|
+
'value': comp, 'is_array': False
|
|
2085
|
+
}))
|
|
1769
2086
|
single_comprehension = True
|
|
1770
2087
|
break
|
|
1771
2088
|
a.push(new AST_CallArg({'value': arg, 'is_array': False}))
|
|
1772
2089
|
first = False
|
|
1773
2090
|
if not single_comprehension:
|
|
1774
2091
|
next()
|
|
1775
|
-
return new AST_CallArgs({
|
|
2092
|
+
return new AST_CallArgs({
|
|
2093
|
+
'args': a, 'kwargs': kwargs,
|
|
2094
|
+
'kwarg_items': kwarg_items, 'starargs': starargs
|
|
2095
|
+
})
|
|
1776
2096
|
|
|
1777
2097
|
@embed_tokens
|
|
1778
2098
|
async def array_():
|
|
@@ -1782,7 +2102,10 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1782
2102
|
expr.push(await expression(False))
|
|
1783
2103
|
if is_('keyword', 'for'):
|
|
1784
2104
|
# list comprehension
|
|
1785
|
-
return await read_comprehension(
|
|
2105
|
+
return await read_comprehension(
|
|
2106
|
+
new AST_ListComprehension({'statement': expr[0]}),
|
|
2107
|
+
']'
|
|
2108
|
+
)
|
|
1786
2109
|
|
|
1787
2110
|
if not is_('punc', ']'):
|
|
1788
2111
|
expect(',')
|
|
@@ -1818,7 +2141,10 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1818
2141
|
ctx.expecting_object_literal_key = orig
|
|
1819
2142
|
if is_('keyword', 'for'):
|
|
1820
2143
|
# is_pydict is irrelevant here
|
|
1821
|
-
return await read_comprehension(
|
|
2144
|
+
return await read_comprehension(
|
|
2145
|
+
new AST_SetComprehension({'statement': left}),
|
|
2146
|
+
'}'
|
|
2147
|
+
)
|
|
1822
2148
|
if a.length is 0 and (is_('punc', ',') or is_('punc', '}')):
|
|
1823
2149
|
end = prev()
|
|
1824
2150
|
return await set_(start, end, left)
|
|
@@ -1836,11 +2162,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1836
2162
|
return await dict_comprehension(a, is_pydict, is_jshash)
|
|
1837
2163
|
|
|
1838
2164
|
next()
|
|
1839
|
-
return new (
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
'is_jshash': is_jshash,
|
|
1843
|
-
})
|
|
2165
|
+
return new (
|
|
2166
|
+
AST_ExpressiveObject if has_non_const_keys else AST_Object
|
|
2167
|
+
)({'properties': a, 'is_pydict': is_pydict, 'is_jshash': is_jshash,})
|
|
1844
2168
|
|
|
1845
2169
|
async def set_(start, end, expr):
|
|
1846
2170
|
ostart = start
|
|
@@ -1852,7 +2176,9 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1852
2176
|
# allow trailing comma
|
|
1853
2177
|
break
|
|
1854
2178
|
set_val = await expression(False)
|
|
1855
|
-
a.push(new AST_SetItem({
|
|
2179
|
+
a.push(new AST_SetItem({
|
|
2180
|
+
'start': start, 'value': set_val, 'end': prev()
|
|
2181
|
+
}))
|
|
1856
2182
|
next()
|
|
1857
2183
|
return new AST_Set({'items': a, 'start': ostart, 'end': prev()})
|
|
1858
2184
|
|
|
@@ -1860,7 +2186,8 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1860
2186
|
if is_node_type(obj, AST_GeneratorComprehension):
|
|
1861
2187
|
baselib_items['yield'] = True
|
|
1862
2188
|
S.in_comprehension = True
|
|
1863
|
-
|
|
2189
|
+
# in case we are already in a parenthesized expression
|
|
2190
|
+
S.in_parenthesized_expr = False
|
|
1864
2191
|
expect_token('keyword', 'for')
|
|
1865
2192
|
forloop = await for_(True)
|
|
1866
2193
|
obj.init = forloop.init
|
|
@@ -1881,11 +2208,17 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1881
2208
|
else:
|
|
1882
2209
|
left = await expression(False)
|
|
1883
2210
|
if not is_('punc', ':'):
|
|
1884
|
-
return await read_comprehension(
|
|
2211
|
+
return await read_comprehension(
|
|
2212
|
+
new AST_SetComprehension({'statement': left}),
|
|
2213
|
+
'}'
|
|
2214
|
+
)
|
|
1885
2215
|
expect(':')
|
|
1886
2216
|
right = await expression(False)
|
|
1887
2217
|
return await read_comprehension(
|
|
1888
|
-
new AST_DictComprehension({
|
|
2218
|
+
new AST_DictComprehension({
|
|
2219
|
+
'statement': left, 'value_statement': right,
|
|
2220
|
+
'is_pydict': is_pydict, 'is_jshash': is_jshash
|
|
2221
|
+
}),
|
|
1889
2222
|
'}'
|
|
1890
2223
|
)
|
|
1891
2224
|
|
|
@@ -1893,7 +2226,8 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1893
2226
|
tmp = S.token
|
|
1894
2227
|
next()
|
|
1895
2228
|
tmp_ = tmp.type
|
|
1896
|
-
if tmp_ is 'name' or tmp_ is 'operator'
|
|
2229
|
+
if (tmp_ is 'name' or tmp_ is 'operator'
|
|
2230
|
+
or tmp_ is 'keyword' or tmp_ is 'atom'):
|
|
1897
2231
|
return tmp.value
|
|
1898
2232
|
else:
|
|
1899
2233
|
unexpected()
|
|
@@ -1928,7 +2262,10 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1928
2262
|
return sym
|
|
1929
2263
|
|
|
1930
2264
|
def is_static_method(cls, method):
|
|
1931
|
-
if has_prop(
|
|
2265
|
+
if has_prop(
|
|
2266
|
+
COMMON_STATIC,
|
|
2267
|
+
method
|
|
2268
|
+
) or (cls.static and has_prop(cls.static, method)):
|
|
1932
2269
|
return True
|
|
1933
2270
|
else:
|
|
1934
2271
|
return False
|
|
@@ -1992,44 +2329,79 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
1992
2329
|
_ca.push(new AST_CallArg({'value': expr, 'is_array': False}))
|
|
1993
2330
|
for _sb in slice_bounds:
|
|
1994
2331
|
_ca.push(new AST_CallArg({'value': _sb, 'is_array': False}))
|
|
1995
|
-
return await subscripts(
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
'
|
|
2332
|
+
return await subscripts(
|
|
2333
|
+
new AST_Call({
|
|
2334
|
+
'start': start,
|
|
2335
|
+
'expression': new AST_SymbolRef({
|
|
2336
|
+
'name': (
|
|
2337
|
+
'ρσ_delslice'
|
|
2338
|
+
if S.in_delete else 'ρσ_eslice'
|
|
2339
|
+
)
|
|
2340
|
+
}),
|
|
2341
|
+
'args': new AST_CallArgs({
|
|
2342
|
+
'args': _ca, 'kwargs': v'[]',
|
|
2343
|
+
'kwarg_items': v'[]', 'starargs': False
|
|
2344
|
+
}),
|
|
2345
|
+
'end': prev()
|
|
1999
2346
|
}),
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
}), allow_calls)
|
|
2347
|
+
allow_calls
|
|
2348
|
+
)
|
|
2003
2349
|
else:
|
|
2004
2350
|
# regular slice (arr[start:end])
|
|
2005
|
-
slice_bounds = [
|
|
2351
|
+
slice_bounds = [
|
|
2352
|
+
new AST_Number({'value': 0}) if i is None else i
|
|
2353
|
+
for i in slice_bounds
|
|
2354
|
+
]
|
|
2006
2355
|
if S.in_delete:
|
|
2007
2356
|
_ca2 = v'[]'
|
|
2008
|
-
_ca2.push(new AST_CallArg({
|
|
2009
|
-
|
|
2357
|
+
_ca2.push(new AST_CallArg({
|
|
2358
|
+
'value': expr, 'is_array': False
|
|
2359
|
+
}))
|
|
2360
|
+
_ca2.push(new AST_CallArg({
|
|
2361
|
+
'value': new AST_Number({'value': 1}),
|
|
2362
|
+
'is_array': False
|
|
2363
|
+
}))
|
|
2010
2364
|
for _sb in slice_bounds:
|
|
2011
|
-
_ca2.push(new AST_CallArg({
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2365
|
+
_ca2.push(new AST_CallArg({
|
|
2366
|
+
'value': _sb, 'is_array': False
|
|
2367
|
+
}))
|
|
2368
|
+
return await subscripts(
|
|
2369
|
+
new AST_Call({
|
|
2370
|
+
'start': start,
|
|
2371
|
+
'expression': new AST_SymbolRef({
|
|
2372
|
+
'name': 'ρσ_delslice'
|
|
2373
|
+
}),
|
|
2374
|
+
'args': new AST_CallArgs({
|
|
2375
|
+
'args': _ca2, 'kwargs': v'[]',
|
|
2376
|
+
'kwarg_items': v'[]', 'starargs': False
|
|
2377
|
+
}),
|
|
2378
|
+
'end': prev()
|
|
2379
|
+
}),
|
|
2380
|
+
allow_calls
|
|
2381
|
+
)
|
|
2018
2382
|
|
|
2019
2383
|
_ca3 = v'[]'
|
|
2020
2384
|
for _sb in slice_bounds:
|
|
2021
|
-
_ca3.push(new AST_CallArg({
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2385
|
+
_ca3.push(new AST_CallArg({
|
|
2386
|
+
'value': _sb, 'is_array': False
|
|
2387
|
+
}))
|
|
2388
|
+
return await subscripts(
|
|
2389
|
+
new AST_Call({
|
|
2025
2390
|
'start': start,
|
|
2026
|
-
'expression':
|
|
2027
|
-
|
|
2391
|
+
'expression': new AST_Dot({
|
|
2392
|
+
'start': start,
|
|
2393
|
+
'expression': expr,
|
|
2394
|
+
'property': 'slice',
|
|
2395
|
+
'end': prev()
|
|
2396
|
+
}),
|
|
2397
|
+
'args': new AST_CallArgs({
|
|
2398
|
+
'args': _ca3, 'kwargs': v'[]',
|
|
2399
|
+
'kwarg_items': v'[]', 'starargs': False
|
|
2400
|
+
}),
|
|
2028
2401
|
'end': prev()
|
|
2029
2402
|
}),
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
}), allow_calls)
|
|
2403
|
+
allow_calls
|
|
2404
|
+
)
|
|
2033
2405
|
else:
|
|
2034
2406
|
# regular index (arr[index])
|
|
2035
2407
|
if is_py_sub:
|
|
@@ -2061,6 +2433,7 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
2061
2433
|
|
|
2062
2434
|
async def call_(expr):
|
|
2063
2435
|
start = expr.start
|
|
2436
|
+
prev_parens = S.in_parenthesized_expr
|
|
2064
2437
|
S.in_parenthesized_expr = True
|
|
2065
2438
|
next()
|
|
2066
2439
|
if not expr.parens and get_class_in_scope(expr):
|
|
@@ -2072,7 +2445,7 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
2072
2445
|
'args': call_args,
|
|
2073
2446
|
'end': prev()
|
|
2074
2447
|
}), True)
|
|
2075
|
-
S.in_parenthesized_expr =
|
|
2448
|
+
S.in_parenthesized_expr = prev_parens
|
|
2076
2449
|
return ret
|
|
2077
2450
|
else:
|
|
2078
2451
|
if is_node_type(expr, AST_Dot):
|
|
@@ -2091,7 +2464,7 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
2091
2464
|
'args': classcall_args,
|
|
2092
2465
|
'end': prev()
|
|
2093
2466
|
}), True)
|
|
2094
|
-
S.in_parenthesized_expr =
|
|
2467
|
+
S.in_parenthesized_expr = prev_parens
|
|
2095
2468
|
return ret
|
|
2096
2469
|
elif is_node_type(expr, AST_SymbolRef):
|
|
2097
2470
|
tmp_ = expr.name
|
|
@@ -2103,12 +2476,15 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
2103
2476
|
'expression': jstype_args.args[0].value,
|
|
2104
2477
|
'end': prev()
|
|
2105
2478
|
})
|
|
2106
|
-
S.in_parenthesized_expr =
|
|
2479
|
+
S.in_parenthesized_expr = prev_parens
|
|
2107
2480
|
return ret
|
|
2108
2481
|
elif tmp_ is 'isinstance':
|
|
2109
2482
|
args = await func_call_list()
|
|
2110
2483
|
if args.args.length is not 2:
|
|
2111
|
-
croak(
|
|
2484
|
+
croak(
|
|
2485
|
+
'isinstance() must be called with exactly'
|
|
2486
|
+
' two arguments'
|
|
2487
|
+
)
|
|
2112
2488
|
ret = new AST_Binary({
|
|
2113
2489
|
'start': start,
|
|
2114
2490
|
'left': args.args[0].value,
|
|
@@ -2116,7 +2492,7 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
2116
2492
|
'right': args.args[1].value,
|
|
2117
2493
|
'end': prev()
|
|
2118
2494
|
})
|
|
2119
|
-
S.in_parenthesized_expr =
|
|
2495
|
+
S.in_parenthesized_expr = prev_parens
|
|
2120
2496
|
return ret
|
|
2121
2497
|
|
|
2122
2498
|
# fall-through to basic function call
|
|
@@ -2127,7 +2503,7 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
2127
2503
|
'args': basic_args,
|
|
2128
2504
|
'end': prev()
|
|
2129
2505
|
}), True)
|
|
2130
|
-
S.in_parenthesized_expr =
|
|
2506
|
+
S.in_parenthesized_expr = prev_parens
|
|
2131
2507
|
return ret
|
|
2132
2508
|
|
|
2133
2509
|
async def get_attr(expr, allow_calls):
|
|
@@ -2147,11 +2523,14 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
2147
2523
|
}), allow_calls)
|
|
2148
2524
|
|
|
2149
2525
|
async def existential(expr, allow_calls):
|
|
2150
|
-
ans = new AST_Existential({
|
|
2526
|
+
ans = new AST_Existential({
|
|
2527
|
+
'start': expr.start, 'end': S.token, 'expression': expr
|
|
2528
|
+
})
|
|
2151
2529
|
next()
|
|
2152
2530
|
ttype = S.token.type
|
|
2153
2531
|
val = S.token.value
|
|
2154
|
-
if S.token.nlb or ttype is 'keyword'
|
|
2532
|
+
if (S.token.nlb or ttype is 'keyword'
|
|
2533
|
+
or ttype is 'operator' or ttype is 'eof'):
|
|
2155
2534
|
ans.after = None
|
|
2156
2535
|
return ans
|
|
2157
2536
|
if ttype is 'punc':
|
|
@@ -2197,14 +2576,21 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
2197
2576
|
expr = await expression()
|
|
2198
2577
|
S.parsing_decorator = False
|
|
2199
2578
|
S.decorators.push(expr)
|
|
2200
|
-
return new AST_EmptyStatement({
|
|
2579
|
+
return new AST_EmptyStatement({
|
|
2580
|
+
'stype': '@', 'start': prev(), 'end': prev()
|
|
2581
|
+
})
|
|
2201
2582
|
if is_('operator') and UNARY_PREFIX[start.value]:
|
|
2202
2583
|
next()
|
|
2203
2584
|
is_parenthesized = is_('punc', '(')
|
|
2204
2585
|
S.in_delete = start.value is 'delete'
|
|
2205
2586
|
expr = await maybe_unary(allow_calls)
|
|
2206
2587
|
S.in_delete = False
|
|
2207
|
-
ex = make_unary(
|
|
2588
|
+
ex = make_unary(
|
|
2589
|
+
AST_UnaryPrefix,
|
|
2590
|
+
start.value,
|
|
2591
|
+
expr,
|
|
2592
|
+
is_parenthesized
|
|
2593
|
+
)
|
|
2208
2594
|
ex.start = start
|
|
2209
2595
|
ex.end = prev()
|
|
2210
2596
|
return ex
|
|
@@ -2248,7 +2634,12 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
2248
2634
|
async def maybe_conditional(no_in):
|
|
2249
2635
|
start = S.token
|
|
2250
2636
|
expr = await expr_ops(no_in)
|
|
2251
|
-
if (is_('keyword', 'if') and (
|
|
2637
|
+
if (is_('keyword', 'if') and (
|
|
2638
|
+
S.in_parenthesized_expr or (
|
|
2639
|
+
S.statement_starting_token is not S.token
|
|
2640
|
+
and not S.in_comprehension
|
|
2641
|
+
and not S.token.nlb
|
|
2642
|
+
))):
|
|
2252
2643
|
next()
|
|
2253
2644
|
ne = await expression(False)
|
|
2254
2645
|
expect_token('keyword', 'else')
|
|
@@ -2264,10 +2655,18 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
2264
2655
|
return expr
|
|
2265
2656
|
|
|
2266
2657
|
def create_assign(data):
|
|
2267
|
-
if data.right and is_node_type(
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2658
|
+
if data.right and is_node_type(
|
|
2659
|
+
data.right,
|
|
2660
|
+
AST_Seq
|
|
2661
|
+
) and (
|
|
2662
|
+
is_node_type(data.right.car, AST_Assign)
|
|
2663
|
+
or is_node_type(data.right.cdr, AST_Assign)
|
|
2664
|
+
) and data.operator is not '=':
|
|
2665
|
+
token_error(
|
|
2666
|
+
data.start,
|
|
2667
|
+
'Invalid assignment operator for chained'
|
|
2668
|
+
' assignment: ' + data.operator
|
|
2669
|
+
)
|
|
2271
2670
|
ans = AST_Assign(data)
|
|
2272
2671
|
if S.in_class.length and S.in_class[-1]:
|
|
2273
2672
|
class_name = S.in_class[-1]
|
|
@@ -2287,7 +2686,10 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
2287
2686
|
val = S.token.value
|
|
2288
2687
|
if is_('operator') and ASSIGNMENT[val]:
|
|
2289
2688
|
if only_plain_assignment and val is not '=':
|
|
2290
|
-
croak(
|
|
2689
|
+
croak(
|
|
2690
|
+
'Invalid assignment operator for chained assignment: '
|
|
2691
|
+
+ val
|
|
2692
|
+
)
|
|
2291
2693
|
next()
|
|
2292
2694
|
assign_right = await maybe_assign(no_in, True)
|
|
2293
2695
|
return create_assign({
|
|
@@ -2317,20 +2719,26 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
2317
2719
|
})
|
|
2318
2720
|
if commas:
|
|
2319
2721
|
left = v'[ expr ]'
|
|
2320
|
-
while is_(
|
|
2321
|
-
|
|
2722
|
+
while is_(
|
|
2723
|
+
'punc', ','
|
|
2724
|
+
) and (not peek().nlb or S.in_parenthesized_expr) or (
|
|
2725
|
+
S.in_parenthesized_expr and S.token.nlb
|
|
2726
|
+
and not is_('punc', ')')
|
|
2727
|
+
):
|
|
2728
|
+
if is_('punc', ','):
|
|
2729
|
+
next()
|
|
2322
2730
|
if is_node_type(expr, AST_Assign):
|
|
2323
2731
|
left[-1] = left[-1].left
|
|
2324
2732
|
seq_cdr = await expression(True, no_in)
|
|
2325
2733
|
return create_assign({
|
|
2326
2734
|
'start': start,
|
|
2327
|
-
'left': (
|
|
2328
|
-
|
|
2329
|
-
|
|
2735
|
+
'left': (
|
|
2736
|
+
left[0] if left.length is 1
|
|
2737
|
+
else new AST_Array({'elements': left})
|
|
2738
|
+
),
|
|
2330
2739
|
'operator': expr.operator,
|
|
2331
2740
|
'right': new AST_Seq({
|
|
2332
|
-
'car': expr.right,
|
|
2333
|
-
'cdr': seq_cdr
|
|
2741
|
+
'car': expr.right, 'cdr': seq_cdr
|
|
2334
2742
|
}),
|
|
2335
2743
|
'end': peek()
|
|
2336
2744
|
})
|
|
@@ -2378,10 +2786,15 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
2378
2786
|
raise
|
|
2379
2787
|
else:
|
|
2380
2788
|
element = await statement()
|
|
2381
|
-
if first_token and is_node_type(
|
|
2789
|
+
if first_token and is_node_type(
|
|
2790
|
+
element,
|
|
2791
|
+
AST_Directive
|
|
2792
|
+
) and element.value.indexOf('#!') is 0:
|
|
2382
2793
|
shebang = element.value
|
|
2383
2794
|
else:
|
|
2384
|
-
|
|
2795
|
+
# do not process strings as docstrings if we are
|
|
2796
|
+
# concatenating toplevels
|
|
2797
|
+
ds = not toplevel and is_docstring(element)
|
|
2385
2798
|
if ds:
|
|
2386
2799
|
docstrings.push(ds)
|
|
2387
2800
|
else:
|
|
@@ -2404,17 +2817,21 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
2404
2817
|
|
|
2405
2818
|
if options.recover_errors:
|
|
2406
2819
|
# Combine parser-level recovered errors with any collected by the
|
|
2407
|
-
# tokenizer (e.g. skipped unexpected characters) for the
|
|
2820
|
+
# tokenizer (e.g. skipped unexpected characters) for the
|
|
2821
|
+
# LSP to report.
|
|
2408
2822
|
recovered = S.recovered_errors
|
|
2409
2823
|
try:
|
|
2410
2824
|
tok_ctx = S.input.context()
|
|
2411
|
-
if tok_ctx and tok_ctx.recovered_errors
|
|
2825
|
+
if (tok_ctx and tok_ctx.recovered_errors
|
|
2826
|
+
and tok_ctx.recovered_errors.length):
|
|
2412
2827
|
recovered = recovered.concat(tok_ctx.recovered_errors)
|
|
2413
2828
|
except:
|
|
2414
2829
|
pass
|
|
2415
2830
|
toplevel.recovered_errors = recovered
|
|
2416
2831
|
|
|
2417
|
-
toplevel.nonlocalvars = scan_for_nonlocal_defs(
|
|
2832
|
+
toplevel.nonlocalvars = scan_for_nonlocal_defs(
|
|
2833
|
+
toplevel.body
|
|
2834
|
+
).concat(S.globals)
|
|
2418
2835
|
toplevel.localvars = []
|
|
2419
2836
|
toplevel.exports = []
|
|
2420
2837
|
seen_exports = {}
|
|
@@ -2445,16 +2862,23 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
2445
2862
|
importing_modules[module_id] = False
|
|
2446
2863
|
toplevel.comments_after = S.token.comments_before or v'[]'
|
|
2447
2864
|
|
|
2448
|
-
if options._src_hash and options.filename
|
|
2865
|
+
if (options._src_hash and options.filename
|
|
2866
|
+
and module_id is not '__main__'):
|
|
2449
2867
|
try:
|
|
2450
|
-
# Simplified class info (no full AST nodes) for
|
|
2868
|
+
# Simplified class info (no full AST nodes) for
|
|
2869
|
+
# lazy-shell reconstruction.
|
|
2451
2870
|
classes_cache = {}
|
|
2452
2871
|
for cname in Object.keys(toplevel.classes or {}):
|
|
2453
2872
|
cls = toplevel.classes[cname]
|
|
2454
|
-
classes_cache[cname] = {
|
|
2873
|
+
classes_cache[cname] = {
|
|
2874
|
+
'static': cls.static or {},
|
|
2875
|
+
'bound': cls.bound or [],
|
|
2876
|
+
'classvars': cls.classvars or {},
|
|
2877
|
+
}
|
|
2455
2878
|
# Single pass: compute has_side_effects + tree-shaking index.
|
|
2456
2879
|
# The index lets the tree-shaker resolve the fixpoint iteration
|
|
2457
|
-
# (steps 4-5) without accessing mod.body — no AST
|
|
2880
|
+
# (steps 4-5) without accessing mod.body — no AST
|
|
2881
|
+
# deserialization
|
|
2458
2882
|
# until step 6 (pruning), which needs actual nodes anyway.
|
|
2459
2883
|
has_se = False
|
|
2460
2884
|
idx_exec_refs_set = {}
|
|
@@ -2468,26 +2892,50 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
2468
2892
|
node.walk(new TreeWalker(_rv))
|
|
2469
2893
|
|
|
2470
2894
|
for idx_stmt in toplevel.body:
|
|
2471
|
-
if is_node_type(
|
|
2895
|
+
if is_node_type(
|
|
2896
|
+
idx_stmt,
|
|
2897
|
+
AST_Function
|
|
2898
|
+
) or is_node_type(idx_stmt, AST_Class):
|
|
2472
2899
|
if idx_stmt.name:
|
|
2473
2900
|
idx_pinned = False
|
|
2474
2901
|
if idx_stmt.decorators:
|
|
2475
2902
|
for idx_dec in idx_stmt.decorators:
|
|
2476
|
-
if idx_dec.expression and is_node_type(
|
|
2903
|
+
if idx_dec.expression and is_node_type(
|
|
2904
|
+
idx_dec.expression,
|
|
2905
|
+
AST_SymbolRef
|
|
2906
|
+
) and idx_dec.expression.name == 'no_prune':
|
|
2477
2907
|
idx_pinned = True
|
|
2478
2908
|
break
|
|
2479
2909
|
idx_def_refs = {}
|
|
2480
2910
|
_collect_refs_into(idx_stmt, idx_def_refs)
|
|
2481
|
-
idx_top_defs[idx_stmt.name.name] = {
|
|
2911
|
+
idx_top_defs[idx_stmt.name.name] = {
|
|
2912
|
+
'pinned': idx_pinned,
|
|
2913
|
+
'refs': Object.keys(idx_def_refs),
|
|
2914
|
+
}
|
|
2482
2915
|
elif is_node_type(idx_stmt, AST_Imports):
|
|
2483
2916
|
for idx_imp in idx_stmt.imports:
|
|
2484
2917
|
if idx_imp.argnames and idx_imp.argnames.length:
|
|
2485
2918
|
for idx_arg in idx_imp.argnames:
|
|
2486
|
-
idx_local =
|
|
2487
|
-
|
|
2919
|
+
idx_local = (
|
|
2920
|
+
idx_arg.alias.name
|
|
2921
|
+
if idx_arg.alias else idx_arg.name
|
|
2922
|
+
)
|
|
2923
|
+
idx_import_bindings[idx_local] = {
|
|
2924
|
+
'source': idx_imp.key,
|
|
2925
|
+
'imported_name': idx_arg.name,
|
|
2926
|
+
'is_namespace': False,
|
|
2927
|
+
}
|
|
2488
2928
|
else:
|
|
2489
|
-
idx_local =
|
|
2490
|
-
|
|
2929
|
+
idx_local = (
|
|
2930
|
+
idx_imp.alias.name
|
|
2931
|
+
if idx_imp.alias
|
|
2932
|
+
else idx_imp.key.split('.')[0]
|
|
2933
|
+
)
|
|
2934
|
+
idx_import_bindings[idx_local] = {
|
|
2935
|
+
'source': idx_imp.key,
|
|
2936
|
+
'imported_name': None,
|
|
2937
|
+
'is_namespace': True,
|
|
2938
|
+
}
|
|
2491
2939
|
else:
|
|
2492
2940
|
if not has_se:
|
|
2493
2941
|
se_found = v'[false]'
|
|
@@ -2516,12 +2964,22 @@ def create_parser_ctx(S, import_dirs, module_id, baselib_items, imported_module_
|
|
|
2516
2964
|
'top_defs': idx_top_defs,
|
|
2517
2965
|
},
|
|
2518
2966
|
}
|
|
2519
|
-
if options._file_mtime is not None
|
|
2967
|
+
if (options._file_mtime is not None
|
|
2968
|
+
and options._file_mtime is not undefined):
|
|
2520
2969
|
cache_meta['mtime'] = options._file_mtime
|
|
2521
|
-
# Binary format: metadata JSON followed by newline
|
|
2522
|
-
|
|
2970
|
+
# Binary format: metadata JSON followed by newline
|
|
2971
|
+
# and binary AST pool.
|
|
2972
|
+
await writefile(
|
|
2973
|
+
cache_file_name(options.filename, options.module_cache_dir),
|
|
2974
|
+
encode_cache(JSON.stringify(cache_meta), toplevel)
|
|
2975
|
+
)
|
|
2523
2976
|
except as e:
|
|
2524
|
-
console.error(
|
|
2977
|
+
console.error(
|
|
2978
|
+
'Failed to write AST cache file:',
|
|
2979
|
+
options.filename,
|
|
2980
|
+
'with error:',
|
|
2981
|
+
e
|
|
2982
|
+
)
|
|
2525
2983
|
|
|
2526
2984
|
return toplevel
|
|
2527
2985
|
|
|
@@ -2533,13 +2991,18 @@ async def parse(text, options):
|
|
|
2533
2991
|
'filename': None, # name of the file being parsed
|
|
2534
2992
|
'module_id': '__main__', # The id of the module being parsed
|
|
2535
2993
|
'toplevel': None,
|
|
2536
|
-
|
|
2994
|
+
# If True certain actions are not performed, such as importing modules
|
|
2995
|
+
'for_linting': False,
|
|
2537
2996
|
'import_dirs': v'[]',
|
|
2538
|
-
|
|
2997
|
+
# Map of class names to AST_Class that are available in the
|
|
2998
|
+
# global namespace (used by the REPL)
|
|
2999
|
+
'classes': undefined,
|
|
2539
3000
|
'scoped_flags': {}, # Global scoped flags (used by the REPL)
|
|
2540
3001
|
'discard_asserts': False,
|
|
2541
3002
|
'module_cache_dir': '',
|
|
2542
|
-
|
|
3003
|
+
# When True, continue parsing past syntax errors (used by the
|
|
3004
|
+
# LSP). See run_parser/block_.
|
|
3005
|
+
'recover_errors': False,
|
|
2543
3006
|
})
|
|
2544
3007
|
import_dirs = [x for x in options.import_dirs]
|
|
2545
3008
|
for location in v'[options.libdir, options.basedir]':
|
|
@@ -2550,16 +3013,21 @@ async def parse(text, options):
|
|
|
2550
3013
|
imported_module_ids = []
|
|
2551
3014
|
imported_modules = options.imported_modules or {}
|
|
2552
3015
|
importing_modules = options.importing_modules or {}
|
|
2553
|
-
# loading_promises tracks modules currently being loaded across the
|
|
2554
|
-
#
|
|
3016
|
+
# loading_promises tracks modules currently being loaded across the
|
|
3017
|
+
# entire compilation.
|
|
3018
|
+
# It is shared by passing it through options so parallel sub-parse()
|
|
3019
|
+
# calls all see it.
|
|
2555
3020
|
if not options.loading_promises:
|
|
2556
3021
|
options.loading_promises = {}
|
|
2557
3022
|
importing_modules[module_id] = True
|
|
2558
3023
|
|
|
2559
3024
|
# The internal state of the parser
|
|
2560
3025
|
S = {
|
|
2561
|
-
'input': tokenizer(
|
|
2562
|
-
|
|
3026
|
+
'input': tokenizer(
|
|
3027
|
+
text, options.filename, options.recover_errors
|
|
3028
|
+
) if jstype(text) is 'string' else text,
|
|
3029
|
+
# syntax errors swallowed during recovery (recover_errors mode only)
|
|
3030
|
+
'recovered_errors': v'[]',
|
|
2563
3031
|
'token': None,
|
|
2564
3032
|
'prev': None,
|
|
2565
3033
|
'peeked': [],
|
|
@@ -2595,9 +3063,22 @@ async def parse(text, options):
|
|
|
2595
3063
|
if options.classes:
|
|
2596
3064
|
for cname in options.classes:
|
|
2597
3065
|
obj = options.classes[cname]
|
|
2598
|
-
S.classes[0][cname] = {
|
|
3066
|
+
S.classes[0][cname] = {
|
|
3067
|
+
'static': obj.static,
|
|
3068
|
+
'bound': obj.bound,
|
|
3069
|
+
'classvars': obj.classvars,
|
|
3070
|
+
}
|
|
2599
3071
|
|
|
2600
3072
|
if jstype(text) is 'string' and not options._src_hash:
|
|
2601
3073
|
options._src_hash = sha1sum(text)
|
|
2602
3074
|
|
|
2603
|
-
return await create_parser_ctx(
|
|
3075
|
+
return await create_parser_ctx(
|
|
3076
|
+
S,
|
|
3077
|
+
import_dirs,
|
|
3078
|
+
module_id,
|
|
3079
|
+
baselib_items,
|
|
3080
|
+
imported_module_ids,
|
|
3081
|
+
imported_modules,
|
|
3082
|
+
importing_modules,
|
|
3083
|
+
options
|
|
3084
|
+
)()
|