rapydscript-ng 0.8.0 → 0.8.2
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 +14 -0
- package/README.md +8 -0
- package/bin/build.ts +117 -0
- package/build_wheels.py +133 -0
- package/editor-plugins/README.md +80 -0
- package/editor-plugins/nvim.lua +321 -0
- package/package.json +1 -1
- package/publish.py +27 -17
- package/release/compiler.js +8125 -8093
- package/release/signatures.json +27 -27
- package/release/stdlib_modules.json +1 -0
- package/src/ast.pyj +379 -279
- package/src/baselib-builtins.pyj +47 -26
- package/src/baselib-containers.pyj +105 -92
- package/src/baselib-errors.pyj +8 -1
- package/src/baselib-internal.pyj +35 -20
- package/src/baselib-itertools.pyj +13 -7
- package/src/baselib-str.pyj +55 -80
- package/src/compiler.pyj +4 -4
- package/src/errors.pyj +3 -4
- package/src/lib/aes.pyj +46 -32
- package/src/lib/elementmaker.pyj +11 -9
- package/src/lib/encodings.pyj +15 -5
- package/src/lib/gettext.pyj +9 -4
- package/src/lib/math.pyj +106 -45
- package/src/lib/operator.pyj +10 -10
- package/src/lib/pythonize.pyj +2 -1
- package/src/lib/random.pyj +28 -21
- package/src/lib/re.pyj +490 -17
- package/src/lib/traceback.pyj +7 -2
- package/src/lib/uuid.pyj +2 -2
- package/src/output/classes.pyj +28 -27
- package/src/output/codegen.pyj +80 -83
- package/src/output/comments.pyj +8 -8
- package/src/output/exceptions.pyj +20 -21
- package/src/output/functions.pyj +37 -26
- package/src/output/literals.pyj +14 -10
- package/src/output/loops.pyj +63 -59
- package/src/output/modules.pyj +52 -23
- package/src/output/operators.pyj +40 -29
- package/src/output/statements.pyj +20 -14
- package/src/output/stream.pyj +33 -34
- package/src/output/utils.pyj +12 -8
- package/src/parse.pyj +234 -233
- package/src/string_interpolation.pyj +5 -3
- package/src/tokenizer.pyj +176 -148
- package/src/utils.pyj +31 -14
- package/test/fmt.pyj +94 -4
- package/test/generic.pyj +9 -0
- package/test/lsp.pyj +35 -0
- package/test/str.pyj +8 -0
- package/tools/cli.mjs +25 -4
- package/tools/compile.mjs +7 -3
- package/tools/compiler.mjs +34 -2
- package/tools/fmt.mjs +269 -22
- package/tools/ini.mjs +112 -1
- package/tools/lsp.mjs +56 -6
- package/tools/repl.mjs +5 -2
- package/tools/self.mjs +15 -0
- package/tools/test.mjs +100 -0
- package/tools/web_repl_export.mjs +4 -0
- package/tree-sitter/package.json +1 -1
- package/tree-sitter/tree-sitter.json +1 -1
- package/editor-plugins/nvim/rapydscript/README.md +0 -184
- package/editor-plugins/nvim/rapydscript/bin/rapydscript.so +0 -0
- package/editor-plugins/nvim/rapydscript/ftdetect/rapydscript.lua +0 -10
- package/editor-plugins/nvim/rapydscript/lua/rapydscript/health.lua +0 -88
- package/editor-plugins/nvim/rapydscript/lua/rapydscript/init.lua +0 -279
- /package/tree-sitter/queries/{rapydscript/highlights.scm → highlights.scm} +0 -0
- /package/tree-sitter/queries/{rapydscript/indents.scm → indents.scm} +0 -0
- /package/tree-sitter/queries/{rapydscript/injections.scm → injections.scm} +0 -0
- /package/tree-sitter/queries/{rapydscript/locals.scm → locals.scm} +0 -0
package/src/ast.pyj
CHANGED
|
@@ -4,13 +4,14 @@ from __python__ import hash_literals
|
|
|
4
4
|
|
|
5
5
|
from utils import noop
|
|
6
6
|
|
|
7
|
+
|
|
7
8
|
def is_node_type(node, typ):
|
|
8
9
|
return v'node instanceof typ'
|
|
9
10
|
|
|
10
11
|
# Basic classes {{{
|
|
11
12
|
|
|
12
|
-
class AST:
|
|
13
13
|
|
|
14
|
+
class AST:
|
|
14
15
|
properties = {}
|
|
15
16
|
|
|
16
17
|
def __init__(self, initializer):
|
|
@@ -38,17 +39,18 @@ class AST_Token(AST):
|
|
|
38
39
|
'col': 'The column number at which the token occurs',
|
|
39
40
|
'pos': '',
|
|
40
41
|
'endpos': '',
|
|
41
|
-
'nlb':'True iff there was a newline before this token',
|
|
42
|
-
'comments_before':'True iff there were comments before this token',
|
|
43
|
-
'file':'The filename in which this token occurs',
|
|
42
|
+
'nlb': 'True iff there was a newline before this token',
|
|
43
|
+
'comments_before': 'True iff there were comments before this token',
|
|
44
|
+
'file': 'The filename in which this token occurs',
|
|
44
45
|
'leading_whitespace': 'The leading whitespace for the line on which this token occurs',
|
|
45
46
|
}
|
|
46
47
|
|
|
48
|
+
|
|
47
49
|
class AST_Node(AST):
|
|
48
|
-
|
|
50
|
+
'Base class of all AST nodes'
|
|
49
51
|
properties = {
|
|
50
|
-
'start':
|
|
51
|
-
'end':
|
|
52
|
+
'start': '[AST_Token] The first token of this node',
|
|
53
|
+
'end': '[AST_Token] The last token of this node'
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
def _walk(self, visitor):
|
|
@@ -59,12 +61,12 @@ class AST_Node(AST):
|
|
|
59
61
|
|
|
60
62
|
def _dump(self, depth=100, omit={'start', 'end'}, offset=0, include_name=True):
|
|
61
63
|
p = console.log
|
|
62
|
-
reset =
|
|
63
|
-
yellow =
|
|
64
|
-
blue =
|
|
65
|
-
green =
|
|
66
|
-
red =
|
|
67
|
-
magenta =
|
|
64
|
+
reset = '\x1b[0m'
|
|
65
|
+
yellow = '\x1b[33m'
|
|
66
|
+
blue = '\x1b[34m'
|
|
67
|
+
green = '\x1b[32m'
|
|
68
|
+
red = '\x1b[31m'
|
|
69
|
+
magenta = '\x1b[35m'
|
|
68
70
|
pad = Array(offset + 1).join(' ')
|
|
69
71
|
|
|
70
72
|
if include_name:
|
|
@@ -78,7 +80,7 @@ class AST_Node(AST):
|
|
|
78
80
|
p(pad + ' ' + blue + key + ': ' + reset + '[')
|
|
79
81
|
if depth > 1:
|
|
80
82
|
for element in self[key]:
|
|
81
|
-
element._dump(depth-1, omit, offset+1, True)
|
|
83
|
+
element._dump(depth - 1, omit, offset + 1, True)
|
|
82
84
|
else:
|
|
83
85
|
for element in self[key]:
|
|
84
86
|
p(pad + ' ' + yellow + element.constructor.name.slice(4) + reset)
|
|
@@ -95,10 +97,10 @@ class AST_Node(AST):
|
|
|
95
97
|
else:
|
|
96
98
|
p(pad + ' ' + blue + key + ': ' + yellow + tname + reset)
|
|
97
99
|
if depth > 1:
|
|
98
|
-
self[key]._dump(depth-1, omit, offset+1, False)
|
|
99
|
-
elif jstype(self[key]) is
|
|
100
|
+
self[key]._dump(depth - 1, omit, offset + 1, False)
|
|
101
|
+
elif jstype(self[key]) is 'string':
|
|
100
102
|
p(pad + ' ' + blue + key + ': ' + green + '"' + self[key] + '"' + reset)
|
|
101
|
-
elif jstype(self[key]) is
|
|
103
|
+
elif jstype(self[key]) is 'number':
|
|
102
104
|
p(pad + ' ' + blue + key + ': ' + green + self[key] + reset)
|
|
103
105
|
else:
|
|
104
106
|
# unexpected object
|
|
@@ -114,39 +116,44 @@ class AST_Node(AST):
|
|
|
114
116
|
|
|
115
117
|
# Statements {{{
|
|
116
118
|
|
|
119
|
+
|
|
117
120
|
class AST_Statement(AST_Node):
|
|
118
|
-
|
|
121
|
+
'Base class of all statements'
|
|
122
|
+
|
|
119
123
|
|
|
120
124
|
class AST_Debugger(AST_Statement):
|
|
121
|
-
|
|
125
|
+
'Represents a debugger statement'
|
|
126
|
+
|
|
122
127
|
|
|
123
128
|
class AST_Directive(AST_Statement):
|
|
124
129
|
'Represents a directive, like "use strict";'
|
|
125
130
|
properties = {
|
|
126
131
|
'value': "[string] The value of this directive as a plain string (it's not an AST_String!)",
|
|
127
|
-
'scope':
|
|
132
|
+
'scope': '[AST_Scope/S] The scope that this directive affects'
|
|
128
133
|
}
|
|
129
134
|
|
|
135
|
+
|
|
130
136
|
class AST_SimpleStatement(AST_Statement):
|
|
131
|
-
|
|
132
|
-
properties =
|
|
133
|
-
'body':
|
|
137
|
+
'A statement consisting of an expression, i.e. a = 1 + 2'
|
|
138
|
+
properties = {
|
|
139
|
+
'body': '[AST_Node] an expression node (should not be instanceof AST_Statement)'
|
|
134
140
|
}
|
|
135
141
|
|
|
136
142
|
def _walk(self, visitor):
|
|
137
|
-
return visitor._visit(self, def():
|
|
143
|
+
return visitor._visit(self, def ():
|
|
138
144
|
self.body._walk(visitor)
|
|
139
145
|
)
|
|
140
146
|
|
|
147
|
+
|
|
141
148
|
class AST_Assert(AST_Statement):
|
|
142
149
|
"An assert statement, e.g. assert True, 'an error message'"
|
|
143
150
|
properties = {
|
|
144
|
-
'condition':
|
|
145
|
-
'message':
|
|
151
|
+
'condition': '[AST_Node] the expression that should be tested',
|
|
152
|
+
'message': '[AST_Node*] the expression that is the error message or None',
|
|
146
153
|
}
|
|
147
154
|
|
|
148
155
|
def _walk(self, visitor):
|
|
149
|
-
return visitor._visit(self, def():
|
|
156
|
+
return visitor._visit(self, def ():
|
|
150
157
|
self.condition._walk(visitor)
|
|
151
158
|
if self.message:
|
|
152
159
|
self.message._walk(visitor)
|
|
@@ -160,68 +167,76 @@ def walk_body(node, visitor):
|
|
|
160
167
|
for stat in node.body:
|
|
161
168
|
stat._walk(visitor)
|
|
162
169
|
|
|
170
|
+
|
|
163
171
|
class AST_Block(AST_Statement):
|
|
164
|
-
|
|
165
|
-
properties =
|
|
166
|
-
'body':
|
|
172
|
+
'A body of statements (usually bracketed)'
|
|
173
|
+
properties = {
|
|
174
|
+
'body': '[AST_Statement*] an array of statements'
|
|
167
175
|
}
|
|
168
176
|
|
|
169
177
|
def _walk(self, visitor):
|
|
170
|
-
return visitor._visit(self, def():
|
|
178
|
+
return visitor._visit(self, def ():
|
|
171
179
|
walk_body(self, visitor)
|
|
172
180
|
)
|
|
173
181
|
|
|
182
|
+
|
|
174
183
|
class AST_BlockStatement(AST_Block):
|
|
175
|
-
|
|
184
|
+
'A block statement'
|
|
185
|
+
|
|
176
186
|
|
|
177
187
|
class AST_EmptyStatement(AST_Statement):
|
|
178
|
-
|
|
188
|
+
'The empty statement (empty block or simply a semicolon)'
|
|
179
189
|
properties = {
|
|
180
|
-
'stype':
|
|
190
|
+
'stype': '[string] the type of empty statement. Is ; for semicolons',
|
|
181
191
|
}
|
|
182
192
|
|
|
183
193
|
def _walk(self, visitor):
|
|
184
194
|
return visitor._visit(self)
|
|
185
195
|
|
|
196
|
+
|
|
186
197
|
class AST_StatementWithBody(AST_Statement):
|
|
187
|
-
|
|
198
|
+
'Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`'
|
|
188
199
|
properties = {
|
|
189
200
|
'body': "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement"
|
|
190
201
|
}
|
|
191
202
|
|
|
192
203
|
def _walk(self, visitor):
|
|
193
|
-
return visitor._visit(self, def():
|
|
204
|
+
return visitor._visit(self, def ():
|
|
194
205
|
self.body._walk(visitor)
|
|
195
206
|
)
|
|
196
207
|
|
|
208
|
+
|
|
197
209
|
class AST_DWLoop(AST_StatementWithBody):
|
|
198
|
-
|
|
210
|
+
'Base class for do/while statements'
|
|
199
211
|
properties = {
|
|
200
|
-
'condition':
|
|
212
|
+
'condition': '[AST_Node] the loop condition. Should not be instanceof AST_Statement'
|
|
201
213
|
}
|
|
202
214
|
|
|
203
215
|
def _walk(self, visitor):
|
|
204
|
-
return visitor._visit(self, def():
|
|
216
|
+
return visitor._visit(self, def ():
|
|
205
217
|
self.condition._walk(visitor)
|
|
206
218
|
self.body._walk(visitor)
|
|
207
219
|
)
|
|
208
220
|
|
|
221
|
+
|
|
209
222
|
class AST_Do(AST_DWLoop):
|
|
210
|
-
|
|
223
|
+
'A `do` statement'
|
|
224
|
+
|
|
211
225
|
|
|
212
226
|
class AST_While(AST_DWLoop):
|
|
213
|
-
|
|
227
|
+
'A `while` statement'
|
|
228
|
+
|
|
214
229
|
|
|
215
230
|
class AST_ForIn(AST_StatementWithBody):
|
|
216
|
-
|
|
231
|
+
'A `for ... in` statement'
|
|
217
232
|
properties = {
|
|
218
|
-
'init':
|
|
219
|
-
'name':
|
|
233
|
+
'init': '[AST_Node] the `for/in` initialization code',
|
|
234
|
+
'name': '[AST_SymbolRef?] the loop variable, only if `init` is AST_Var',
|
|
220
235
|
'object': "[AST_Node] the object that we're looping through"
|
|
221
236
|
}
|
|
222
237
|
|
|
223
238
|
def _walk(self, visitor):
|
|
224
|
-
return visitor._visit(self, def():
|
|
239
|
+
return visitor._visit(self, def ():
|
|
225
240
|
self.init._walk(visitor)
|
|
226
241
|
if (self.name) self.name._walk(visitor)
|
|
227
242
|
self.object._walk(visitor)
|
|
@@ -229,40 +244,44 @@ class AST_ForIn(AST_StatementWithBody):
|
|
|
229
244
|
self.body._walk(visitor)
|
|
230
245
|
)
|
|
231
246
|
|
|
247
|
+
|
|
232
248
|
class AST_ForJS(AST_StatementWithBody):
|
|
233
|
-
|
|
249
|
+
'A `for ... in` statement'
|
|
234
250
|
properties = {
|
|
235
|
-
'condition':
|
|
251
|
+
'condition': '[AST_Verbatim] raw JavaScript conditional'
|
|
236
252
|
}
|
|
237
253
|
|
|
254
|
+
|
|
238
255
|
class AST_ListComprehension(AST_ForIn):
|
|
239
|
-
|
|
256
|
+
'A list comprehension expression'
|
|
240
257
|
properties = {
|
|
241
|
-
'condition':
|
|
242
|
-
'statement':
|
|
258
|
+
'condition': '[AST_Node] the `if` condition',
|
|
259
|
+
'statement': '[AST_Node] statement to perform on each element before returning it'
|
|
243
260
|
}
|
|
244
261
|
|
|
245
262
|
def _walk(self, visitor):
|
|
246
|
-
return visitor._visit(self, def():
|
|
263
|
+
return visitor._visit(self, def ():
|
|
247
264
|
self.init._walk(visitor)
|
|
248
265
|
self.object._walk(visitor)
|
|
249
266
|
self.statement._walk(visitor)
|
|
250
267
|
if (self.condition) self.condition._walk(visitor)
|
|
251
268
|
)
|
|
252
269
|
|
|
270
|
+
|
|
253
271
|
class AST_SetComprehension(AST_ListComprehension):
|
|
254
272
|
'A set comprehension'
|
|
255
273
|
|
|
274
|
+
|
|
256
275
|
class AST_DictComprehension(AST_ListComprehension):
|
|
257
276
|
'A set comprehension'
|
|
258
277
|
properties = {
|
|
259
|
-
'value_statement':
|
|
260
|
-
'is_pydict':
|
|
261
|
-
'is_jshash':
|
|
278
|
+
'value_statement': '[AST_Node] statement to perform on each value before returning it',
|
|
279
|
+
'is_pydict': '[bool] True if this comprehension is for a python dict',
|
|
280
|
+
'is_jshash': '[bool] True if this comprehension is for a js hash',
|
|
262
281
|
}
|
|
263
282
|
|
|
264
283
|
def _walk(self, visitor):
|
|
265
|
-
return visitor._visit(self, def():
|
|
284
|
+
return visitor._visit(self, def ():
|
|
266
285
|
self.init._walk(visitor)
|
|
267
286
|
self.object._walk(visitor)
|
|
268
287
|
self.statement._walk(visitor)
|
|
@@ -270,22 +289,25 @@ class AST_DictComprehension(AST_ListComprehension):
|
|
|
270
289
|
if (self.condition) self.condition._walk(visitor)
|
|
271
290
|
)
|
|
272
291
|
|
|
292
|
+
|
|
273
293
|
class AST_GeneratorComprehension(AST_ListComprehension):
|
|
274
294
|
'A generator comprehension'
|
|
275
295
|
|
|
296
|
+
|
|
276
297
|
class AST_With(AST_StatementWithBody):
|
|
277
|
-
|
|
298
|
+
'A `with` statement'
|
|
278
299
|
properties = {
|
|
279
|
-
'clauses':
|
|
300
|
+
'clauses': '[AST_WithClause*] the `with` clauses (comma separated)'
|
|
280
301
|
}
|
|
281
302
|
|
|
282
303
|
def _walk(self, visitor):
|
|
283
|
-
return visitor._visit(self, def():
|
|
304
|
+
return visitor._visit(self, def ():
|
|
284
305
|
for exp in self.clauses:
|
|
285
306
|
exp._walk(visitor)
|
|
286
307
|
self.body._walk(visitor)
|
|
287
308
|
)
|
|
288
309
|
|
|
310
|
+
|
|
289
311
|
class AST_WithClause(AST_Node):
|
|
290
312
|
'A clause in a with statement'
|
|
291
313
|
properties = {
|
|
@@ -294,7 +316,7 @@ class AST_WithClause(AST_Node):
|
|
|
294
316
|
}
|
|
295
317
|
|
|
296
318
|
def _walk(self, visitor):
|
|
297
|
-
return visitor._visit(self, def():
|
|
319
|
+
return visitor._visit(self, def ():
|
|
298
320
|
self.expression._walk(visitor)
|
|
299
321
|
if self.alias:
|
|
300
322
|
self.alias._walk(visitor)
|
|
@@ -303,45 +325,47 @@ class AST_WithClause(AST_Node):
|
|
|
303
325
|
|
|
304
326
|
# Scope and functions {{{
|
|
305
327
|
|
|
328
|
+
|
|
306
329
|
class AST_Scope(AST_Block):
|
|
307
|
-
|
|
330
|
+
'Base class for all statements introducing a lexical scope'
|
|
308
331
|
properties = {
|
|
309
|
-
'localvars':
|
|
310
|
-
'docstrings':
|
|
332
|
+
'localvars': '[SymbolDef*] list of variables local to this scope',
|
|
333
|
+
'docstrings': '[AST_String*] list of docstrings for this scope',
|
|
311
334
|
}
|
|
312
335
|
|
|
313
336
|
|
|
314
337
|
class AST_Toplevel(AST_Scope):
|
|
315
|
-
|
|
338
|
+
'The toplevel scope'
|
|
316
339
|
properties = {
|
|
317
|
-
'globals':
|
|
318
|
-
'baselib':
|
|
319
|
-
'imports':
|
|
320
|
-
'imported_module_ids':
|
|
321
|
-
'nonlocalvars':
|
|
322
|
-
'shebang':
|
|
323
|
-
'import_order':
|
|
324
|
-
'module_id':
|
|
325
|
-
'exports':
|
|
326
|
-
'classes':
|
|
327
|
-
'filename':
|
|
328
|
-
'srchash':
|
|
340
|
+
'globals': '[Object/S] a map of name -> SymbolDef for all undeclared names',
|
|
341
|
+
'baselib': '[Object/s] a collection of used parts of baselib',
|
|
342
|
+
'imports': '[Object/S] a map of module_id->AST_Toplevel for all imported modules (this represents all imported modules across all source files)',
|
|
343
|
+
'imported_module_ids': '[string*] a list of module ids that were imported by this module, specifically',
|
|
344
|
+
'nonlocalvars': '[String*] a list of all non-local variable names (names that come from the global scope)',
|
|
345
|
+
'shebang': '[string] If #! line is present, it will be stored here',
|
|
346
|
+
'import_order': '[number] The global order in which this scope was imported',
|
|
347
|
+
'module_id': '[string] The id of this module',
|
|
348
|
+
'exports': '[SymbolDef*] list of names exported from this module',
|
|
349
|
+
'classes': '[Object/S] a map of class names to AST_Class for classes defined in this module',
|
|
350
|
+
'filename': '[string] The absolute path to the file from which this module was read',
|
|
351
|
+
'srchash': '[string] SHA1 hash of source code, used for caching',
|
|
329
352
|
'comments_after': '[array] True iff there were comments before this token',
|
|
330
353
|
}
|
|
331
354
|
|
|
355
|
+
|
|
332
356
|
class AST_Import(AST_Statement):
|
|
333
|
-
|
|
357
|
+
'Container for a single import'
|
|
334
358
|
|
|
335
359
|
properties = {
|
|
336
360
|
'module': "[AST_SymbolVar] name of the module we're importing",
|
|
337
|
-
'key':
|
|
338
|
-
'alias':
|
|
339
|
-
'argnames':
|
|
340
|
-
'body':
|
|
361
|
+
'key': '[string] The key by which this module is stored in the global modules mapping',
|
|
362
|
+
'alias': '[AST_SymbolAlias] The name this module is imported as, can be None. For import x as y statements.',
|
|
363
|
+
'argnames': '[AST_ImportedVar*] names of objects to be imported',
|
|
364
|
+
'body': '[AST_TopLevel] parsed contents of the imported file',
|
|
341
365
|
}
|
|
342
366
|
|
|
343
367
|
def _walk(self, visitor):
|
|
344
|
-
return visitor._visit(self, def():
|
|
368
|
+
return visitor._visit(self, def ():
|
|
345
369
|
if self.alias:
|
|
346
370
|
self.alias._walk(visitor)
|
|
347
371
|
if self.argnames:
|
|
@@ -349,43 +373,46 @@ class AST_Import(AST_Statement):
|
|
|
349
373
|
arg._walk(visitor)
|
|
350
374
|
)
|
|
351
375
|
|
|
376
|
+
|
|
352
377
|
class AST_Imports(AST_Statement):
|
|
353
|
-
|
|
378
|
+
'Container for a single import'
|
|
354
379
|
properties = {
|
|
355
|
-
'imports':
|
|
380
|
+
'imports': '[AST_Import+] array of imports',
|
|
356
381
|
}
|
|
357
382
|
|
|
358
383
|
def _walk(self, visitor):
|
|
359
|
-
return visitor._visit(self, def():
|
|
384
|
+
return visitor._visit(self, def ():
|
|
360
385
|
for imp in self.imports:
|
|
361
386
|
imp._walk(visitor)
|
|
362
387
|
)
|
|
363
388
|
|
|
389
|
+
|
|
364
390
|
class AST_Decorator(AST_Node):
|
|
365
|
-
|
|
391
|
+
'Class for function decorators'
|
|
366
392
|
properties = {
|
|
367
|
-
'expression':
|
|
393
|
+
'expression': '[AST_Node] the decorator expression'
|
|
368
394
|
}
|
|
369
395
|
|
|
370
396
|
def _walk(self, visitor):
|
|
371
|
-
return visitor._visit(self, def():
|
|
397
|
+
return visitor._visit(self, def ():
|
|
372
398
|
if self.expression:
|
|
373
399
|
self.expression.walk(visitor)
|
|
374
400
|
)
|
|
375
401
|
|
|
402
|
+
|
|
376
403
|
class AST_ArgsDef(AST_Node):
|
|
377
|
-
|
|
404
|
+
'The formal argument definition list for a function'
|
|
378
405
|
properties = {
|
|
379
|
-
'args':
|
|
380
|
-
'starargs':
|
|
381
|
-
'kwargs':
|
|
382
|
-
'defaults':
|
|
383
|
-
'has_defaults':
|
|
384
|
-
'is_simple_func':
|
|
406
|
+
'args': '[AST_SymbolFunarg*] formal positional parameters',
|
|
407
|
+
'starargs': '[AST_SymbolFunarg?] *args parameter, or None',
|
|
408
|
+
'kwargs': '[AST_SymbolFunarg?] **kwargs parameter, or None',
|
|
409
|
+
'defaults': '[Object] map of parameter name to default value expression',
|
|
410
|
+
'has_defaults': '[bool] True if any parameter has a default value',
|
|
411
|
+
'is_simple_func': '[bool] True if no starargs, no kwargs, and no defaults',
|
|
385
412
|
}
|
|
386
413
|
|
|
387
414
|
def _walk(self, visitor):
|
|
388
|
-
return visitor._visit(self, def():
|
|
415
|
+
return visitor._visit(self, def ():
|
|
389
416
|
for arg in self.args:
|
|
390
417
|
arg._walk(visitor)
|
|
391
418
|
if self.starargs:
|
|
@@ -394,21 +421,22 @@ class AST_ArgsDef(AST_Node):
|
|
|
394
421
|
self.kwargs._walk(visitor)
|
|
395
422
|
)
|
|
396
423
|
|
|
424
|
+
|
|
397
425
|
class AST_Lambda(AST_Scope):
|
|
398
|
-
|
|
426
|
+
'Base class for functions'
|
|
399
427
|
properties = {
|
|
400
|
-
'name':
|
|
401
|
-
'argnames':
|
|
402
|
-
'decorators':
|
|
403
|
-
'is_generator':
|
|
404
|
-
'is_async':
|
|
405
|
-
'is_expression':
|
|
406
|
-
'is_anonymous':
|
|
407
|
-
|
|
428
|
+
'name': '[AST_SymbolDeclaration?] the name of this function',
|
|
429
|
+
'argnames': '[AST_ArgsDef] the function argument definitions',
|
|
430
|
+
'decorators': '[AST_Decorator*] function decorators, if any',
|
|
431
|
+
'is_generator': '[bool*] True iff this function is a generator',
|
|
432
|
+
'is_async': '[bool*] True iff this function is an async function',
|
|
433
|
+
'is_expression': '[bool*] True iff this function is a function expression',
|
|
434
|
+
'is_anonymous': '[bool*] True iff this function is an anonymous function',
|
|
435
|
+
'return_annotation': '[AST_Node?] The return type annotation provided (if any)',
|
|
408
436
|
}
|
|
409
437
|
|
|
410
438
|
def _walk(self, visitor):
|
|
411
|
-
return visitor._visit(self, def():
|
|
439
|
+
return visitor._visit(self, def ():
|
|
412
440
|
if self.decorators:
|
|
413
441
|
for d in self.decorators:
|
|
414
442
|
d.walk(visitor)
|
|
@@ -418,28 +446,30 @@ class AST_Lambda(AST_Scope):
|
|
|
418
446
|
walk_body(self, visitor)
|
|
419
447
|
)
|
|
420
448
|
|
|
449
|
+
|
|
421
450
|
class AST_Function(AST_Lambda):
|
|
422
|
-
|
|
451
|
+
'A function expression'
|
|
452
|
+
|
|
423
453
|
|
|
424
454
|
class AST_Class(AST_Scope):
|
|
425
|
-
|
|
455
|
+
'A class declaration'
|
|
426
456
|
properties = {
|
|
427
|
-
'name':
|
|
428
|
-
'init':
|
|
429
|
-
'parent':
|
|
430
|
-
'bases':
|
|
431
|
-
|
|
432
|
-
'external':
|
|
433
|
-
'bound':
|
|
434
|
-
'decorators':
|
|
435
|
-
'module_id':
|
|
436
|
-
'statements':
|
|
457
|
+
'name': '[AST_SymbolDeclaration?] the name of this class',
|
|
458
|
+
'init': '[AST_Function] constructor for the class',
|
|
459
|
+
'parent': '[AST_Symbol?] parent class this class inherits from',
|
|
460
|
+
'bases': '[AST_Symbol*] list of base classes this class inherits from',
|
|
461
|
+
'static': '[dict] A hash whose keys are names of static methods for this class',
|
|
462
|
+
'external': '[boolean] true if class is declared elsewhere, but will be within current scope at runtime',
|
|
463
|
+
'bound': '[string*] list of methods that need to be bound to self',
|
|
464
|
+
'decorators': '[AST_Decorator*] function decorators, if any',
|
|
465
|
+
'module_id': '[string] The id of the module this class is defined in',
|
|
466
|
+
'statements': '[AST_Node*] list of statements in the class scope (excluding method definitions)',
|
|
437
467
|
'dynamic_properties': '[dict] map of dynamic property names to property descriptors of the form {getter:AST_Method, setter:AST_Method',
|
|
438
468
|
'classvars': '[dict] map containing all class variables as keys, to be used to easily test for existence of a class variable',
|
|
439
469
|
}
|
|
440
470
|
|
|
441
471
|
def _walk(self, visitor):
|
|
442
|
-
return visitor._visit(self, def():
|
|
472
|
+
return visitor._visit(self, def ():
|
|
443
473
|
if self.decorators:
|
|
444
474
|
for d in self.decorators:
|
|
445
475
|
d.walk(visitor)
|
|
@@ -448,77 +478,88 @@ class AST_Class(AST_Scope):
|
|
|
448
478
|
if (self.parent) self.parent._walk(visitor)
|
|
449
479
|
)
|
|
450
480
|
|
|
481
|
+
|
|
451
482
|
class AST_Method(AST_Lambda):
|
|
452
|
-
|
|
483
|
+
'A class method definition'
|
|
453
484
|
properties = {
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
485
|
+
'static': '[boolean] true if method is static',
|
|
486
|
+
'is_getter': '[boolean] true if method is a property getter',
|
|
487
|
+
'is_setter': '[boolean] true if method is a property setter',
|
|
457
488
|
}
|
|
458
489
|
|
|
459
490
|
# }}}
|
|
460
491
|
|
|
461
492
|
# Jumps(break/continue/etc) {{{
|
|
462
493
|
|
|
494
|
+
|
|
463
495
|
class AST_Jump(AST_Statement):
|
|
464
496
|
"Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)"
|
|
465
497
|
|
|
498
|
+
|
|
466
499
|
class AST_Exit(AST_Jump):
|
|
467
|
-
|
|
500
|
+
'Base class for “exits” (`return` and `throw`)'
|
|
468
501
|
properties = {
|
|
469
|
-
'value':
|
|
502
|
+
'value': '[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return'
|
|
470
503
|
}
|
|
471
504
|
|
|
472
505
|
def _walk(self, visitor):
|
|
473
|
-
return visitor._visit(self, def():
|
|
506
|
+
return visitor._visit(self, def ():
|
|
474
507
|
if self.value:
|
|
475
508
|
self.value._walk(visitor)
|
|
476
509
|
)
|
|
477
510
|
|
|
511
|
+
|
|
478
512
|
class AST_Return(AST_Exit):
|
|
479
|
-
|
|
513
|
+
'A `return` statement'
|
|
514
|
+
|
|
480
515
|
|
|
481
516
|
class AST_Yield(AST_Return):
|
|
482
|
-
|
|
517
|
+
'A `yield` statement'
|
|
483
518
|
properties = {
|
|
484
|
-
'is_yield_from':
|
|
519
|
+
'is_yield_from': '[bool] True iff this is a yield from, False otherwise'
|
|
485
520
|
}
|
|
486
521
|
|
|
522
|
+
|
|
487
523
|
class AST_Await(AST_Node):
|
|
488
|
-
|
|
524
|
+
'An await expression'
|
|
489
525
|
properties = {
|
|
490
|
-
'value':
|
|
526
|
+
'value': '[AST_Node] the expression being awaited'
|
|
491
527
|
}
|
|
492
528
|
|
|
493
529
|
def _walk(self, visitor):
|
|
494
|
-
return visitor._visit(self, def():
|
|
530
|
+
return visitor._visit(self, def ():
|
|
495
531
|
if self.value:
|
|
496
532
|
self.value._walk(visitor)
|
|
497
533
|
)
|
|
498
534
|
|
|
535
|
+
|
|
499
536
|
class AST_Throw(AST_Exit):
|
|
500
|
-
|
|
537
|
+
'A `throw` statement'
|
|
538
|
+
|
|
501
539
|
|
|
502
540
|
class AST_LoopControl(AST_Jump):
|
|
503
|
-
|
|
541
|
+
'Base class for loop control statements (`break` and `continue`)'
|
|
542
|
+
|
|
504
543
|
|
|
505
544
|
class AST_Break(AST_LoopControl):
|
|
506
|
-
|
|
545
|
+
'A `break` statement'
|
|
546
|
+
|
|
507
547
|
|
|
508
548
|
class AST_Continue(AST_LoopControl):
|
|
509
|
-
|
|
549
|
+
'A `continue` statement'
|
|
510
550
|
# }}}
|
|
511
551
|
|
|
552
|
+
|
|
512
553
|
# If {{{
|
|
513
554
|
class AST_If(AST_StatementWithBody):
|
|
514
|
-
|
|
555
|
+
'A `if` statement'
|
|
515
556
|
properties = {
|
|
516
|
-
'condition':
|
|
517
|
-
'alternative':
|
|
557
|
+
'condition': '[AST_Node] the `if` condition',
|
|
558
|
+
'alternative': '[AST_Statement?] the `else` part, or null if not present'
|
|
518
559
|
}
|
|
519
560
|
|
|
520
561
|
def _walk(self, visitor):
|
|
521
|
-
return visitor._visit(self, def():
|
|
562
|
+
return visitor._visit(self, def ():
|
|
522
563
|
self.condition._walk(visitor)
|
|
523
564
|
self.body._walk(visitor)
|
|
524
565
|
if self.alternative:
|
|
@@ -528,39 +569,40 @@ class AST_If(AST_StatementWithBody):
|
|
|
528
569
|
|
|
529
570
|
# EXCEPTIONS {{{
|
|
530
571
|
|
|
572
|
+
|
|
531
573
|
class AST_Try(AST_Block):
|
|
532
|
-
|
|
574
|
+
'A `try` statement'
|
|
533
575
|
properties = {
|
|
534
|
-
'bcatch':
|
|
535
|
-
'bfinally':
|
|
576
|
+
'bcatch': '[AST_Catch?] the catch block, or null if not present',
|
|
577
|
+
'bfinally': '[AST_Finally?] the finally block, or null if not present',
|
|
536
578
|
'belse': '[AST_Else?] the else block for null if not present',
|
|
537
579
|
}
|
|
538
580
|
|
|
539
581
|
def _walk(self, visitor):
|
|
540
|
-
return visitor._visit(self, def():
|
|
582
|
+
return visitor._visit(self, def ():
|
|
541
583
|
walk_body(self, visitor)
|
|
542
584
|
if self.bcatch:
|
|
543
585
|
self.bcatch._walk(visitor)
|
|
544
|
-
|
|
545
586
|
if self.belse:
|
|
546
587
|
self.belse._walk(visitor)
|
|
547
|
-
|
|
548
588
|
if self.bfinally:
|
|
549
589
|
self.bfinally._walk(visitor)
|
|
550
590
|
)
|
|
551
591
|
|
|
592
|
+
|
|
552
593
|
class AST_Catch(AST_Block):
|
|
553
|
-
|
|
594
|
+
'A `catch` node; only makes sense as part of a `try` statement'
|
|
595
|
+
|
|
554
596
|
|
|
555
597
|
class AST_Except(AST_Block):
|
|
556
|
-
|
|
598
|
+
'An `except` node for RapydScript, which resides inside the catch block'
|
|
557
599
|
properties = {
|
|
558
|
-
'argname':
|
|
559
|
-
'errors':
|
|
600
|
+
'argname': '[AST_SymbolCatch] symbol for the exception',
|
|
601
|
+
'errors': '[AST_SymbolVar*] error classes to catch in this block'
|
|
560
602
|
}
|
|
561
603
|
|
|
562
604
|
def _walk(self, visitor):
|
|
563
|
-
return visitor._visit(this, def():
|
|
605
|
+
return visitor._visit(this, def ():
|
|
564
606
|
if (self.argname):
|
|
565
607
|
self.argname.walk(visitor)
|
|
566
608
|
if (self.errors):
|
|
@@ -568,39 +610,44 @@ class AST_Except(AST_Block):
|
|
|
568
610
|
walk_body(self, visitor)
|
|
569
611
|
)
|
|
570
612
|
|
|
613
|
+
|
|
571
614
|
class AST_Finally(AST_Block):
|
|
572
|
-
|
|
615
|
+
'A `finally` node; only makes sense as part of a `try` statement'
|
|
616
|
+
|
|
573
617
|
|
|
574
618
|
class AST_Else(AST_Block):
|
|
575
619
|
'An `else` node; only makes sense as part of `try` statement'
|
|
576
620
|
|
|
577
621
|
# }}}
|
|
578
622
|
|
|
623
|
+
|
|
579
624
|
# VAR/CONST {{{
|
|
580
625
|
class AST_Definitions(AST_Statement):
|
|
581
|
-
|
|
626
|
+
'Base class for `var` or `const` nodes (variable declarations/initializations)'
|
|
582
627
|
properties = {
|
|
583
|
-
'definitions':
|
|
628
|
+
'definitions': '[AST_VarDef*] array of variable definitions'
|
|
584
629
|
}
|
|
585
630
|
|
|
586
631
|
def _walk(self, visitor):
|
|
587
|
-
return visitor._visit(self, def():
|
|
632
|
+
return visitor._visit(self, def ():
|
|
588
633
|
for def_ in self.definitions:
|
|
589
634
|
def_._walk(visitor)
|
|
590
635
|
)
|
|
591
636
|
|
|
637
|
+
|
|
592
638
|
class AST_Var(AST_Definitions):
|
|
593
|
-
|
|
639
|
+
'A `var` statement'
|
|
640
|
+
|
|
594
641
|
|
|
595
642
|
class AST_VarDef(AST_Node):
|
|
596
|
-
|
|
643
|
+
'A variable declaration; only appears in a AST_Definitions node'
|
|
597
644
|
properties = {
|
|
598
|
-
'name':
|
|
645
|
+
'name': '[AST_SymbolVar|AST_SymbolNonlocal] name of the variable',
|
|
599
646
|
'value': "[AST_Node?] initializer, or null if there's no initializer"
|
|
600
647
|
}
|
|
601
648
|
|
|
602
649
|
def _walk(self, visitor):
|
|
603
|
-
return visitor._visit(self, def():
|
|
650
|
+
return visitor._visit(self, def ():
|
|
604
651
|
self.name._walk(visitor)
|
|
605
652
|
if self.value:
|
|
606
653
|
self.value._walk(visitor)
|
|
@@ -609,29 +656,31 @@ class AST_VarDef(AST_Node):
|
|
|
609
656
|
|
|
610
657
|
# Miscellaneous {{{
|
|
611
658
|
|
|
659
|
+
|
|
612
660
|
class AST_CallArg(AST_Node):
|
|
613
|
-
|
|
661
|
+
'A single positional argument in a function call'
|
|
614
662
|
properties = {
|
|
615
|
-
'value':
|
|
616
|
-
'is_array':
|
|
663
|
+
'value': '[AST_Node] the argument expression',
|
|
664
|
+
'is_array': '[bool] True if this is a *arg (already an array/iterable)',
|
|
617
665
|
}
|
|
618
666
|
|
|
619
667
|
def _walk(self, visitor):
|
|
620
|
-
return visitor._visit(self, def():
|
|
668
|
+
return visitor._visit(self, def ():
|
|
621
669
|
self.value._walk(visitor)
|
|
622
670
|
)
|
|
623
671
|
|
|
672
|
+
|
|
624
673
|
class AST_CallArgs(AST_Node):
|
|
625
|
-
|
|
674
|
+
'The argument list for a function call'
|
|
626
675
|
properties = {
|
|
627
|
-
'args':
|
|
628
|
-
'kwargs':
|
|
629
|
-
'kwarg_items':
|
|
630
|
-
'starargs':
|
|
676
|
+
'args': '[AST_CallArg*] positional arguments',
|
|
677
|
+
'kwargs': '[pair*] keyword argument pairs [key_node, value_node]',
|
|
678
|
+
'kwarg_items': '[AST_SymbolRef*] **kwargs symbol references',
|
|
679
|
+
'starargs': '[bool] True if *args were used in this call',
|
|
631
680
|
}
|
|
632
681
|
|
|
633
682
|
def _walk(self, visitor):
|
|
634
|
-
return visitor._visit(self, def():
|
|
683
|
+
return visitor._visit(self, def ():
|
|
635
684
|
for arg in self.args:
|
|
636
685
|
arg._walk(visitor)
|
|
637
686
|
if self.kwargs:
|
|
@@ -643,47 +692,51 @@ class AST_CallArgs(AST_Node):
|
|
|
643
692
|
arg._walk(visitor)
|
|
644
693
|
)
|
|
645
694
|
|
|
695
|
+
|
|
646
696
|
class AST_BaseCall(AST_Node):
|
|
647
|
-
|
|
697
|
+
'A base class for function calls'
|
|
648
698
|
properties = {
|
|
649
|
-
'args':
|
|
699
|
+
'args': '[AST_CallArgs] the function call argument list'
|
|
650
700
|
}
|
|
651
701
|
|
|
702
|
+
|
|
652
703
|
class AST_Call(AST_BaseCall):
|
|
653
|
-
|
|
704
|
+
'A function call expression'
|
|
654
705
|
properties = {
|
|
655
|
-
'expression':
|
|
706
|
+
'expression': '[AST_Node] expression to invoke as function'
|
|
656
707
|
}
|
|
657
708
|
|
|
658
709
|
def _walk(self, visitor):
|
|
659
|
-
return visitor._visit(self, def():
|
|
710
|
+
return visitor._visit(self, def ():
|
|
660
711
|
self.expression._walk(visitor)
|
|
661
712
|
self.args._walk(visitor)
|
|
662
713
|
)
|
|
663
714
|
|
|
664
715
|
|
|
665
716
|
class AST_ClassCall(AST_BaseCall):
|
|
666
|
-
|
|
717
|
+
'A function call expression'
|
|
667
718
|
properties = {
|
|
668
|
-
|
|
669
|
-
'method':
|
|
670
|
-
|
|
719
|
+
'class': '[string] name of the class method belongs to',
|
|
720
|
+
'method': '[string] class method being called',
|
|
721
|
+
'static': '[boolean] defines whether the method is static'
|
|
671
722
|
}
|
|
672
723
|
|
|
673
724
|
def _walk(self, visitor):
|
|
674
|
-
return visitor._visit(self, def():
|
|
725
|
+
return visitor._visit(self, def ():
|
|
675
726
|
if (self.expression) self.expression._walk(visitor)
|
|
676
727
|
self.args._walk(visitor)
|
|
677
728
|
)
|
|
678
729
|
|
|
730
|
+
|
|
679
731
|
class AST_New(AST_Call):
|
|
680
|
-
|
|
732
|
+
'An object instantiation. Derives from a function call since it has exactly the same properties'
|
|
733
|
+
|
|
681
734
|
|
|
682
735
|
class AST_Seq(AST_Node):
|
|
683
|
-
|
|
736
|
+
'A sequence expression (two comma-separated expressions)'
|
|
684
737
|
properties = {
|
|
685
|
-
'car':
|
|
686
|
-
'cdr':
|
|
738
|
+
'car': '[AST_Node] first element in sequence',
|
|
739
|
+
'cdr': '[AST_Node] second element in sequence'
|
|
687
740
|
}
|
|
688
741
|
|
|
689
742
|
def to_array(self):
|
|
@@ -706,7 +759,7 @@ class AST_Seq(AST_Node):
|
|
|
706
759
|
p = p.cdr
|
|
707
760
|
|
|
708
761
|
def _walk(self, visitor):
|
|
709
|
-
return visitor._visit(self, def():
|
|
762
|
+
return visitor._visit(self, def ():
|
|
710
763
|
self.car._walk(visitor)
|
|
711
764
|
if self.cdr:
|
|
712
765
|
self.cdr._walk(visitor)
|
|
@@ -728,7 +781,7 @@ class AST_Seq(AST_Node):
|
|
|
728
781
|
return array[0].clone()
|
|
729
782
|
|
|
730
783
|
ans = None
|
|
731
|
-
for i in range(array.length-1, -1, -1):
|
|
784
|
+
for i in range(array.length - 1, -1, -1):
|
|
732
785
|
ans = AST_Seq.cons(array[i], ans)
|
|
733
786
|
|
|
734
787
|
p = ans
|
|
@@ -739,120 +792,131 @@ class AST_Seq(AST_Node):
|
|
|
739
792
|
p = p.cdr
|
|
740
793
|
return ans
|
|
741
794
|
|
|
795
|
+
|
|
742
796
|
class AST_PropAccess(AST_Node):
|
|
743
797
|
'Base class for property access expressions, i.e. `a.foo` or `a["foo"]`'
|
|
744
798
|
properties = {
|
|
745
|
-
'expression':
|
|
799
|
+
'expression': '[AST_Node] the “container” expression',
|
|
746
800
|
'property': "[AST_Node|string] the property to access. For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node",
|
|
747
801
|
}
|
|
748
802
|
|
|
803
|
+
|
|
749
804
|
class AST_Dot(AST_PropAccess):
|
|
750
|
-
|
|
805
|
+
'A dotted property access expression'
|
|
751
806
|
|
|
752
807
|
def _walk(self, visitor):
|
|
753
|
-
return visitor._visit(self, def():
|
|
808
|
+
return visitor._visit(self, def ():
|
|
754
809
|
self.expression._walk(visitor)
|
|
755
810
|
)
|
|
756
811
|
|
|
812
|
+
|
|
757
813
|
class AST_Sub(AST_PropAccess):
|
|
758
814
|
'Index-style property access, i.e. `a["foo"]`'
|
|
759
815
|
|
|
760
816
|
def _walk(self, visitor):
|
|
761
|
-
return visitor._visit(self, def():
|
|
817
|
+
return visitor._visit(self, def ():
|
|
762
818
|
self.expression._walk(visitor)
|
|
763
819
|
self.property._walk(visitor)
|
|
764
820
|
)
|
|
765
821
|
|
|
822
|
+
|
|
766
823
|
class AST_ItemAccess(AST_PropAccess):
|
|
767
824
|
'Python index-style property access, i.e. `a.__getitem__("foo")`'
|
|
768
825
|
properties = {
|
|
769
|
-
'assignment':
|
|
770
|
-
'assign_operator':
|
|
826
|
+
'assignment': '[AST_Node or None] Not None if this is an assignment (a[x] = y) rather than a simple access',
|
|
827
|
+
'assign_operator': '[String] The operator for a assignment like += or empty string if plain assignment',
|
|
771
828
|
}
|
|
772
829
|
|
|
773
830
|
def _walk(self, visitor):
|
|
774
|
-
return visitor._visit(self, def():
|
|
831
|
+
return visitor._visit(self, def ():
|
|
775
832
|
self.expression._walk(visitor)
|
|
776
833
|
self.property._walk(visitor)
|
|
777
834
|
if self.assignment:
|
|
778
835
|
self.assignment._walk(visitor)
|
|
779
836
|
)
|
|
780
837
|
|
|
838
|
+
|
|
781
839
|
class AST_Splice(AST_PropAccess):
|
|
782
840
|
'Index-style property access, i.e. `a[3:5]`'
|
|
783
841
|
properties = {
|
|
784
|
-
'property2':
|
|
785
|
-
'assignment':
|
|
842
|
+
'property2': '[AST_Node] the 2nd property to access - typically ending index for the array.',
|
|
843
|
+
'assignment': '[AST_Node] The data being spliced in.'
|
|
786
844
|
}
|
|
787
845
|
|
|
788
846
|
def _walk(self, visitor):
|
|
789
|
-
return visitor._visit(self, def():
|
|
847
|
+
return visitor._visit(self, def ():
|
|
790
848
|
self.expression._walk(visitor)
|
|
791
849
|
self.property._walk(visitor)
|
|
792
850
|
self.property2._walk(visitor)
|
|
793
851
|
)
|
|
794
852
|
|
|
853
|
+
|
|
795
854
|
class AST_Unary(AST_Node):
|
|
796
|
-
|
|
855
|
+
'Base class for unary expressions'
|
|
797
856
|
properties = {
|
|
798
|
-
'operator':
|
|
799
|
-
'expression':
|
|
800
|
-
'parenthesized':
|
|
857
|
+
'operator': '[string] the operator',
|
|
858
|
+
'expression': '[AST_Node] expression that this unary operator applies to',
|
|
859
|
+
'parenthesized': '[bool] Whether this unary expression was parenthesized',
|
|
801
860
|
}
|
|
802
861
|
|
|
803
862
|
def _walk(self, visitor):
|
|
804
|
-
return visitor._visit(self, def():
|
|
863
|
+
return visitor._visit(self, def ():
|
|
805
864
|
self.expression._walk(visitor)
|
|
806
865
|
)
|
|
807
866
|
|
|
867
|
+
|
|
808
868
|
class AST_UnaryPrefix(AST_Unary):
|
|
809
|
-
|
|
869
|
+
'Unary prefix expression, i.e. `typeof i` or `del i`'
|
|
870
|
+
|
|
810
871
|
|
|
811
872
|
class AST_Binary(AST_Node):
|
|
812
|
-
|
|
873
|
+
'Binary expression, i.e. `a + b`'
|
|
813
874
|
properties = {
|
|
814
|
-
'left':
|
|
815
|
-
'operator':
|
|
816
|
-
'right':
|
|
875
|
+
'left': '[AST_Node] left-hand side expression',
|
|
876
|
+
'operator': '[string] the operator',
|
|
877
|
+
'right': '[AST_Node] right-hand side expression'
|
|
817
878
|
}
|
|
818
879
|
|
|
819
880
|
def _walk(self, visitor):
|
|
820
|
-
return visitor._visit(self, def():
|
|
881
|
+
return visitor._visit(self, def ():
|
|
821
882
|
self.left._walk(visitor)
|
|
822
883
|
self.right._walk(visitor)
|
|
823
884
|
)
|
|
824
885
|
|
|
886
|
+
|
|
825
887
|
class AST_Existential(AST_Node):
|
|
826
|
-
|
|
888
|
+
'Existential operator a?'
|
|
827
889
|
properties = {
|
|
828
|
-
'expression':
|
|
829
|
-
|
|
890
|
+
'expression': '[AST_Node] The expression whose existence we need to check',
|
|
891
|
+
'after': '[None|string|AST_Node] is None when there is nothing following this operator, is a string when there is as AST_PropAccess following this operator, is an AST_Node if it is used a a shorthand for the conditional ternary, i.e. a ? b == a if a? else b',
|
|
830
892
|
}
|
|
831
893
|
|
|
832
894
|
def _walk(self, visitor):
|
|
833
|
-
return visitor._visit(self, def():
|
|
895
|
+
return visitor._visit(self, def ():
|
|
834
896
|
self.expression._walk(visitor)
|
|
835
897
|
if self.after is not None and jstype(self.after) is 'object':
|
|
836
898
|
self.after._walk(visitor)
|
|
837
899
|
)
|
|
838
900
|
|
|
901
|
+
|
|
839
902
|
class AST_Conditional(AST_Node):
|
|
840
|
-
|
|
903
|
+
'Conditional expression using the ternary operator, i.e. `a if b else c`'
|
|
841
904
|
properties = {
|
|
842
|
-
'condition':
|
|
843
|
-
'consequent':
|
|
844
|
-
'alternative':
|
|
905
|
+
'condition': '[AST_Node]',
|
|
906
|
+
'consequent': '[AST_Node]',
|
|
907
|
+
'alternative': '[AST_Node]',
|
|
845
908
|
}
|
|
846
909
|
|
|
847
910
|
def _walk(self, visitor):
|
|
848
|
-
return visitor._visit(self, def():
|
|
911
|
+
return visitor._visit(self, def ():
|
|
849
912
|
self.condition._walk(visitor)
|
|
850
913
|
self.consequent._walk(visitor)
|
|
851
914
|
self.alternative._walk(visitor)
|
|
852
915
|
)
|
|
853
916
|
|
|
917
|
+
|
|
854
918
|
class AST_Assign(AST_Binary):
|
|
855
|
-
|
|
919
|
+
'An assignment expression — `a = b + 5`'
|
|
856
920
|
|
|
857
921
|
def is_chained(self):
|
|
858
922
|
return is_node_type(self.right, AST_Assign) or (
|
|
@@ -868,7 +932,7 @@ class AST_Assign(AST_Binary):
|
|
|
868
932
|
continue
|
|
869
933
|
if is_node_type(right, AST_Seq):
|
|
870
934
|
if is_node_type(right.car, AST_Assign):
|
|
871
|
-
right = new AST_Seq({'car':right.car.right, 'cdr': right.cdr})
|
|
935
|
+
right = new AST_Seq({'car': right.car.right, 'cdr': right.cdr})
|
|
872
936
|
continue
|
|
873
937
|
if is_node_type(right.cdr, AST_Assign):
|
|
874
938
|
right = right.cdr.right
|
|
@@ -884,7 +948,7 @@ class AST_Assign(AST_Binary):
|
|
|
884
948
|
if is_node_type(next, AST_Seq):
|
|
885
949
|
if is_node_type(next.cdr, AST_Assign):
|
|
886
950
|
assign = next.cdr
|
|
887
|
-
left_hand_sides.push(new AST_Seq({'car':next.car, 'cdr':assign.left}))
|
|
951
|
+
left_hand_sides.push(new AST_Seq({'car': next.car, 'cdr': assign.left}))
|
|
888
952
|
next = assign.right
|
|
889
953
|
continue
|
|
890
954
|
break
|
|
@@ -895,14 +959,15 @@ class AST_Assign(AST_Binary):
|
|
|
895
959
|
|
|
896
960
|
# LITERALS {{{
|
|
897
961
|
|
|
962
|
+
|
|
898
963
|
class AST_Array(AST_Node):
|
|
899
|
-
|
|
964
|
+
'An array literal'
|
|
900
965
|
properties = {
|
|
901
|
-
'elements':
|
|
966
|
+
'elements': '[AST_Node*] array of elements'
|
|
902
967
|
}
|
|
903
968
|
|
|
904
969
|
def _walk(self, visitor):
|
|
905
|
-
return visitor._visit(self, def():
|
|
970
|
+
return visitor._visit(self, def ():
|
|
906
971
|
for el in self.elements:
|
|
907
972
|
el._walk(visitor)
|
|
908
973
|
)
|
|
@@ -922,194 +987,227 @@ class AST_Array(AST_Node):
|
|
|
922
987
|
return ans
|
|
923
988
|
return flatten(self.elements)
|
|
924
989
|
|
|
990
|
+
|
|
925
991
|
class AST_Object(AST_Node):
|
|
926
|
-
|
|
992
|
+
'An object literal'
|
|
927
993
|
properties = {
|
|
928
|
-
'properties':
|
|
929
|
-
'is_pydict':
|
|
930
|
-
'is_jshash':
|
|
994
|
+
'properties': '[AST_ObjectProperty*] array of properties',
|
|
995
|
+
'is_pydict': '[bool] True if this object is a python dict literal',
|
|
996
|
+
'is_jshash': '[bool] True if this object is a js hash literal',
|
|
931
997
|
}
|
|
932
998
|
|
|
933
999
|
def _walk(self, visitor):
|
|
934
|
-
return visitor._visit(self, def():
|
|
1000
|
+
return visitor._visit(self, def ():
|
|
935
1001
|
for prop in self.properties:
|
|
936
1002
|
prop._walk(visitor)
|
|
937
1003
|
)
|
|
938
1004
|
|
|
1005
|
+
|
|
939
1006
|
class AST_ExpressiveObject(AST_Object):
|
|
940
1007
|
'An object literal with expressions for some keys'
|
|
941
1008
|
|
|
1009
|
+
|
|
942
1010
|
class AST_ObjectProperty(AST_Node):
|
|
943
|
-
|
|
1011
|
+
'Base class for literal object properties'
|
|
944
1012
|
properties = {
|
|
945
|
-
'key':
|
|
946
|
-
'value':
|
|
1013
|
+
'key': '[AST_Node] the property expression',
|
|
1014
|
+
'value': '[AST_Node] property value. For setters and getters this is an AST_Function.',
|
|
947
1015
|
'quoted': '',
|
|
948
1016
|
}
|
|
949
1017
|
|
|
950
1018
|
def _walk(self, visitor):
|
|
951
|
-
return visitor._visit(self, def():
|
|
1019
|
+
return visitor._visit(self, def ():
|
|
952
1020
|
self.key._walk(visitor)
|
|
953
1021
|
self.value._walk(visitor)
|
|
954
1022
|
)
|
|
955
1023
|
|
|
1024
|
+
|
|
956
1025
|
class AST_ObjectKeyVal(AST_ObjectProperty):
|
|
957
|
-
|
|
1026
|
+
'A key: value object property'
|
|
1027
|
+
|
|
958
1028
|
|
|
959
1029
|
class AST_Set(AST_Node):
|
|
960
|
-
|
|
1030
|
+
'A set literal'
|
|
961
1031
|
properties = {
|
|
962
|
-
'items':
|
|
1032
|
+
'items': '[AST_SetItem*] array of items'
|
|
963
1033
|
}
|
|
964
1034
|
|
|
965
1035
|
def _walk(self, visitor):
|
|
966
|
-
return visitor._visit(self, def():
|
|
1036
|
+
return visitor._visit(self, def ():
|
|
967
1037
|
for prop in self.items:
|
|
968
1038
|
prop._walk(visitor)
|
|
969
1039
|
)
|
|
970
1040
|
|
|
1041
|
+
|
|
971
1042
|
class AST_SetItem(AST_Node):
|
|
972
|
-
|
|
1043
|
+
'An item in a set literal'
|
|
973
1044
|
properties = {
|
|
974
|
-
'value':
|
|
1045
|
+
'value': '[AST_Node] The value of this item',
|
|
975
1046
|
}
|
|
976
1047
|
|
|
977
1048
|
def _walk(self, visitor):
|
|
978
|
-
return visitor._visit(self, def():
|
|
1049
|
+
return visitor._visit(self, def ():
|
|
979
1050
|
self.value._walk(visitor)
|
|
980
1051
|
)
|
|
981
1052
|
|
|
1053
|
+
|
|
982
1054
|
class AST_Symbol(AST_Node):
|
|
983
|
-
|
|
1055
|
+
'Base class for all symbols'
|
|
984
1056
|
properties = {
|
|
985
|
-
'name':
|
|
986
|
-
'scope':
|
|
987
|
-
'thedef':
|
|
1057
|
+
'name': '[string] name of this symbol',
|
|
1058
|
+
'scope': '[AST_Scope/S] the current scope (not necessarily the definition scope)',
|
|
1059
|
+
'thedef': '[SymbolDef/S] the definition of this symbol'
|
|
988
1060
|
}
|
|
989
1061
|
|
|
1062
|
+
|
|
990
1063
|
class AST_SymbolAlias(AST_Symbol):
|
|
991
|
-
|
|
1064
|
+
'An alias used in an import statement or with statement'
|
|
1065
|
+
|
|
992
1066
|
|
|
993
1067
|
class AST_SymbolDeclaration(AST_Symbol):
|
|
994
|
-
|
|
1068
|
+
'A declaration symbol (symbol in var/const, function name or argument, symbol in catch)'
|
|
995
1069
|
properties = {
|
|
996
|
-
'init':
|
|
1070
|
+
'init': '[AST_Node*/S] array of initializers for this declaration.'
|
|
997
1071
|
}
|
|
998
1072
|
|
|
1073
|
+
|
|
999
1074
|
class AST_SymbolVar(AST_SymbolDeclaration):
|
|
1000
|
-
|
|
1075
|
+
'Symbol defining a variable'
|
|
1076
|
+
|
|
1001
1077
|
|
|
1002
1078
|
class AST_ImportedVar(AST_SymbolVar):
|
|
1003
|
-
|
|
1079
|
+
'Symbol defining an imported symbol'
|
|
1004
1080
|
properties = {
|
|
1005
|
-
'alias':
|
|
1081
|
+
'alias': 'AST_SymbolAlias the alias for this imported symbol'
|
|
1006
1082
|
}
|
|
1007
1083
|
|
|
1084
|
+
|
|
1008
1085
|
class AST_SymbolNonlocal(AST_SymbolDeclaration):
|
|
1009
|
-
|
|
1086
|
+
'A nonlocal declaration'
|
|
1087
|
+
|
|
1010
1088
|
|
|
1011
1089
|
class AST_SymbolFunarg(AST_SymbolVar):
|
|
1012
|
-
|
|
1090
|
+
'Symbol naming a function argument, possibly with an annotation.'
|
|
1013
1091
|
properties = {
|
|
1014
|
-
'annotation':
|
|
1092
|
+
'annotation': '[AST_Node?] The annotation provided for this argument (if any)'
|
|
1015
1093
|
}
|
|
1016
1094
|
|
|
1095
|
+
|
|
1017
1096
|
class AST_SymbolDefun(AST_SymbolDeclaration):
|
|
1018
|
-
|
|
1097
|
+
'Symbol defining a function'
|
|
1098
|
+
|
|
1019
1099
|
|
|
1020
1100
|
class AST_SymbolLambda(AST_SymbolDeclaration):
|
|
1021
|
-
|
|
1101
|
+
'Symbol naming a function expression'
|
|
1102
|
+
|
|
1022
1103
|
|
|
1023
1104
|
class AST_SymbolCatch(AST_SymbolDeclaration):
|
|
1024
|
-
|
|
1105
|
+
'Symbol naming the exception in catch'
|
|
1106
|
+
|
|
1025
1107
|
|
|
1026
1108
|
class AST_SymbolRef(AST_Symbol):
|
|
1027
|
-
|
|
1109
|
+
'Reference to some symbol (not definition/declaration)'
|
|
1028
1110
|
properties = {
|
|
1029
|
-
'parens':
|
|
1111
|
+
'parens': '[boolean/S] if true, this variable is wrapped in parentheses'
|
|
1030
1112
|
}
|
|
1031
1113
|
|
|
1114
|
+
|
|
1032
1115
|
class AST_This(AST_Symbol):
|
|
1033
|
-
|
|
1116
|
+
'The `this` symbol'
|
|
1117
|
+
|
|
1034
1118
|
|
|
1035
1119
|
class AST_Constant(AST_Node):
|
|
1036
|
-
|
|
1120
|
+
'Base class for all constants'
|
|
1121
|
+
|
|
1037
1122
|
|
|
1038
1123
|
class AST_String(AST_Constant):
|
|
1039
|
-
|
|
1124
|
+
'A string literal'
|
|
1040
1125
|
properties = {
|
|
1041
|
-
'value':
|
|
1126
|
+
'value': '[string] the contents of this string'
|
|
1042
1127
|
}
|
|
1043
1128
|
|
|
1129
|
+
|
|
1044
1130
|
class AST_Verbatim(AST_Constant):
|
|
1045
|
-
|
|
1131
|
+
'Raw JavaScript code'
|
|
1046
1132
|
properties = {
|
|
1047
|
-
'value':
|
|
1133
|
+
'value': '[string] A string of raw JS code'
|
|
1048
1134
|
}
|
|
1049
1135
|
|
|
1136
|
+
|
|
1050
1137
|
class AST_Number(AST_Constant):
|
|
1051
|
-
|
|
1138
|
+
'A number literal'
|
|
1052
1139
|
properties = {
|
|
1053
|
-
'value':
|
|
1140
|
+
'value': '[number] the numeric value'
|
|
1054
1141
|
}
|
|
1055
1142
|
|
|
1143
|
+
|
|
1056
1144
|
class AST_RegExp(AST_Constant):
|
|
1057
|
-
|
|
1145
|
+
'A regexp literal'
|
|
1058
1146
|
properties = {
|
|
1059
|
-
'value':
|
|
1147
|
+
'value': '[RegExp] the actual regexp'
|
|
1060
1148
|
}
|
|
1061
1149
|
|
|
1150
|
+
|
|
1062
1151
|
class AST_Atom(AST_Constant):
|
|
1063
|
-
|
|
1152
|
+
'Base class for atoms'
|
|
1153
|
+
|
|
1064
1154
|
def __init__(self, initializer):
|
|
1065
1155
|
if initializer:
|
|
1066
1156
|
self.start = initializer.start
|
|
1067
1157
|
self.end = initializer.end
|
|
1068
1158
|
|
|
1159
|
+
|
|
1069
1160
|
class AST_Null(AST_Atom):
|
|
1070
|
-
|
|
1161
|
+
'The `null` atom'
|
|
1071
1162
|
value = None
|
|
1072
1163
|
|
|
1164
|
+
|
|
1073
1165
|
class AST_NaN(AST_Atom):
|
|
1074
|
-
|
|
1166
|
+
'The impossible value'
|
|
1075
1167
|
value = v'NaN'
|
|
1076
1168
|
|
|
1169
|
+
|
|
1077
1170
|
class AST_Undefined(AST_Atom):
|
|
1078
|
-
|
|
1171
|
+
'The `undefined` value'
|
|
1079
1172
|
value = v'undefined'
|
|
1080
1173
|
|
|
1174
|
+
|
|
1081
1175
|
class AST_Hole(AST_Atom):
|
|
1082
|
-
|
|
1176
|
+
'A hole in an array'
|
|
1083
1177
|
value = v'undefined'
|
|
1084
1178
|
|
|
1179
|
+
|
|
1085
1180
|
class AST_Infinity(AST_Atom):
|
|
1086
|
-
|
|
1181
|
+
'The `Infinity` value'
|
|
1087
1182
|
value = v'Infinity'
|
|
1088
1183
|
|
|
1184
|
+
|
|
1089
1185
|
class AST_Boolean(AST_Atom):
|
|
1090
|
-
|
|
1186
|
+
'Base class for booleans'
|
|
1187
|
+
|
|
1091
1188
|
|
|
1092
1189
|
class AST_False(AST_Boolean):
|
|
1093
|
-
|
|
1190
|
+
'The `false` atom'
|
|
1094
1191
|
value = False
|
|
1095
1192
|
|
|
1193
|
+
|
|
1096
1194
|
class AST_True(AST_Boolean):
|
|
1097
|
-
|
|
1195
|
+
'The `true` atom'
|
|
1098
1196
|
value = True
|
|
1099
1197
|
|
|
1100
1198
|
# }}}
|
|
1101
1199
|
|
|
1102
1200
|
# TreeWalker {{{
|
|
1103
1201
|
|
|
1104
|
-
class TreeWalker:
|
|
1105
1202
|
|
|
1203
|
+
class TreeWalker:
|
|
1106
1204
|
def __init__(self, callback):
|
|
1107
1205
|
self.visit = callback
|
|
1108
1206
|
self.stack = []
|
|
1109
1207
|
|
|
1110
1208
|
def _visit(self, node, descend):
|
|
1111
1209
|
self.stack.push(node)
|
|
1112
|
-
ret = self.visit(node, ((def(): descend.call(node);) if descend else noop))
|
|
1210
|
+
ret = self.visit(node, ((def (): descend.call(node);) if descend else noop))
|
|
1113
1211
|
if not ret and descend:
|
|
1114
1212
|
descend.call(node)
|
|
1115
1213
|
|
|
@@ -1130,7 +1228,7 @@ class TreeWalker:
|
|
|
1130
1228
|
|
|
1131
1229
|
def find_parent(self, type):
|
|
1132
1230
|
stack = self.stack
|
|
1133
|
-
for i in range(stack.length-1, -1, -1):
|
|
1231
|
+
for i in range(stack.length - 1, -1, -1):
|
|
1134
1232
|
x = stack[i]
|
|
1135
1233
|
if is_node_type(x, type):
|
|
1136
1234
|
return x
|
|
@@ -1144,16 +1242,18 @@ class TreeWalker:
|
|
|
1144
1242
|
if is_node_type(p, AST_If) and p.condition is self
|
|
1145
1243
|
or is_node_type(p, AST_Conditional) and p.condition is self
|
|
1146
1244
|
or is_node_type(p, AST_DWLoop) and p.condition is self
|
|
1147
|
-
or is_node_type(p, AST_UnaryPrefix) and p.operator is
|
|
1245
|
+
or is_node_type(p, AST_UnaryPrefix) and p.operator is '!' and p.expression is self:
|
|
1148
1246
|
return True
|
|
1149
|
-
if not (is_node_type(p, AST_Binary) and (p.operator is
|
|
1247
|
+
if not (is_node_type(p, AST_Binary) and (p.operator is '&&' or p.operator is '||')):
|
|
1150
1248
|
return False
|
|
1151
1249
|
self = p
|
|
1152
1250
|
# }}}
|
|
1153
1251
|
|
|
1252
|
+
|
|
1154
1253
|
class Found(Exception):
|
|
1155
1254
|
pass
|
|
1156
1255
|
|
|
1256
|
+
|
|
1157
1257
|
def has_calls(expression):
|
|
1158
1258
|
# Technically, in JavaScript property access is also dynamic and can
|
|
1159
1259
|
# involve function calls. However, there is no way to determine which
|
|
@@ -1162,7 +1262,7 @@ def has_calls(expression):
|
|
|
1162
1262
|
if not expression:
|
|
1163
1263
|
return False
|
|
1164
1264
|
try:
|
|
1165
|
-
expression.walk(new TreeWalker(def(node):
|
|
1265
|
+
expression.walk(new TreeWalker(def (node):
|
|
1166
1266
|
if is_node_type(node, AST_BaseCall) or is_node_type(node, AST_ItemAccess):
|
|
1167
1267
|
raise Found()
|
|
1168
1268
|
))
|