ether-code 0.1.0
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/LICENSE +21 -0
- package/README.md +130 -0
- package/cli/compiler.js +298 -0
- package/cli/ether.js +532 -0
- package/cli/watcher.js +106 -0
- package/generators/css-generator.js +583 -0
- package/generators/graphql-generator.js +868 -0
- package/generators/html-generator.js +745 -0
- package/generators/js-generator.js +909 -0
- package/generators/node-generator.js +467 -0
- package/generators/php-generator.js +706 -0
- package/generators/python-generator.js +913 -0
- package/generators/react-generator.js +599 -0
- package/generators/ruby-generator.js +904 -0
- package/generators/sql-generator.js +988 -0
- package/generators/ts-generator.js +569 -0
- package/i18n/i18n-css.json +743 -0
- package/i18n/i18n-graphql.json +1531 -0
- package/i18n/i18n-html.json +572 -0
- package/i18n/i18n-js.json +2790 -0
- package/i18n/i18n-node.json +2442 -0
- package/i18n/i18n-php.json +4306 -0
- package/i18n/i18n-python.json +3080 -0
- package/i18n/i18n-react.json +1784 -0
- package/i18n/i18n-ruby.json +1858 -0
- package/i18n/i18n-sql.json +3466 -0
- package/i18n/i18n-ts.json +442 -0
- package/lexer/ether-lexer.js +728 -0
- package/lexer/tokens.js +292 -0
- package/package.json +45 -0
- package/parsers/ast-css.js +545 -0
- package/parsers/ast-graphql.js +424 -0
- package/parsers/ast-html.js +886 -0
- package/parsers/ast-js.js +750 -0
- package/parsers/ast-node.js +2440 -0
- package/parsers/ast-php.js +957 -0
- package/parsers/ast-react.js +580 -0
- package/parsers/ast-ruby.js +895 -0
- package/parsers/ast-ts.js +1352 -0
- package/parsers/css-parser.js +1981 -0
- package/parsers/graphql-parser.js +2011 -0
- package/parsers/html-parser.js +1181 -0
- package/parsers/js-parser.js +2564 -0
- package/parsers/node-parser.js +2644 -0
- package/parsers/php-parser.js +3037 -0
- package/parsers/react-parser.js +1035 -0
- package/parsers/ruby-parser.js +2680 -0
- package/parsers/ts-parser.js +3881 -0
|
@@ -0,0 +1,913 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
|
|
3
|
+
class PythonGenerator {
|
|
4
|
+
constructor(i18nPath = null) {
|
|
5
|
+
this.i18n = null
|
|
6
|
+
this.indent = 0
|
|
7
|
+
this.output = ''
|
|
8
|
+
this.keywordMap = {}
|
|
9
|
+
this.builtinMap = {}
|
|
10
|
+
|
|
11
|
+
if (i18nPath) {
|
|
12
|
+
this.loadI18n(i18nPath)
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
loadI18n(filePath) {
|
|
17
|
+
const content = fs.readFileSync(filePath, 'utf-8')
|
|
18
|
+
this.i18n = JSON.parse(content)
|
|
19
|
+
this.buildMaps()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
buildMaps() {
|
|
23
|
+
this.keywordMap = {}
|
|
24
|
+
this.builtinMap = {}
|
|
25
|
+
|
|
26
|
+
if (!this.i18n) return
|
|
27
|
+
|
|
28
|
+
const addToMap = (map, section) => {
|
|
29
|
+
if (!section) return
|
|
30
|
+
for (const [key, translations] of Object.entries(section)) {
|
|
31
|
+
if (translations && translations.fr && translations.python) {
|
|
32
|
+
map[translations.fr.toLowerCase()] = translations.python
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
for (const sectionName of Object.keys(this.i18n)) {
|
|
38
|
+
addToMap(this.keywordMap, this.i18n[sectionName])
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
translate(word) {
|
|
43
|
+
if (!word) return ''
|
|
44
|
+
const lower = word.toLowerCase()
|
|
45
|
+
return this.keywordMap[lower] || this.translateGeneric(word)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
translateGeneric(word) {
|
|
49
|
+
const translations = {
|
|
50
|
+
'si': 'if',
|
|
51
|
+
'sinon': 'else',
|
|
52
|
+
'sinon si': 'elif',
|
|
53
|
+
'pour': 'for',
|
|
54
|
+
'dans': 'in',
|
|
55
|
+
'tant que': 'while',
|
|
56
|
+
'définir': 'def',
|
|
57
|
+
'fonction': 'def',
|
|
58
|
+
'classe': 'class',
|
|
59
|
+
'retourner': 'return',
|
|
60
|
+
'produire': 'yield',
|
|
61
|
+
'passer': 'pass',
|
|
62
|
+
'sortir': 'break',
|
|
63
|
+
'continuer': 'continue',
|
|
64
|
+
'essayer': 'try',
|
|
65
|
+
'sauf': 'except',
|
|
66
|
+
'finalement': 'finally',
|
|
67
|
+
'lever': 'raise',
|
|
68
|
+
'affirmer': 'assert',
|
|
69
|
+
'avec': 'with',
|
|
70
|
+
'comme': 'as',
|
|
71
|
+
'importer': 'import',
|
|
72
|
+
'depuis': 'from',
|
|
73
|
+
'global': 'global',
|
|
74
|
+
'non local': 'nonlocal',
|
|
75
|
+
'lambda': 'lambda',
|
|
76
|
+
'et': 'and',
|
|
77
|
+
'ou': 'or',
|
|
78
|
+
'non': 'not',
|
|
79
|
+
'est': 'is',
|
|
80
|
+
'vrai': 'True',
|
|
81
|
+
'faux': 'False',
|
|
82
|
+
'aucun': 'None',
|
|
83
|
+
'soi': 'self',
|
|
84
|
+
'cls': 'cls',
|
|
85
|
+
'asynchrone': 'asynchrone',
|
|
86
|
+
'attendre': 'await',
|
|
87
|
+
'afficher': 'print',
|
|
88
|
+
'saisir': 'input',
|
|
89
|
+
'longueur': 'len',
|
|
90
|
+
'type': 'type',
|
|
91
|
+
'plage': 'range',
|
|
92
|
+
'enumerer': 'enumerate',
|
|
93
|
+
'zipper': 'zip',
|
|
94
|
+
'mapper': 'map',
|
|
95
|
+
'filtrer': 'filter',
|
|
96
|
+
'trier': 'sorted',
|
|
97
|
+
'inverser': 'reversed',
|
|
98
|
+
'tout': 'all',
|
|
99
|
+
'quelconque': 'any',
|
|
100
|
+
'minimum': 'min',
|
|
101
|
+
'maximum': 'max',
|
|
102
|
+
'somme': 'sum',
|
|
103
|
+
'absolu': 'abs',
|
|
104
|
+
'arrondir': 'round',
|
|
105
|
+
'entier': 'int',
|
|
106
|
+
'flottant': 'float',
|
|
107
|
+
'chaîne': 'str',
|
|
108
|
+
'booléen': 'bool',
|
|
109
|
+
'liste': 'list',
|
|
110
|
+
'tuple': 'tuple',
|
|
111
|
+
'ensemble': 'set',
|
|
112
|
+
'dictionnaire': 'dict',
|
|
113
|
+
'octets': 'bytes',
|
|
114
|
+
'ouvrir': 'open',
|
|
115
|
+
'fermer': 'close',
|
|
116
|
+
'lire': 'read',
|
|
117
|
+
'écrire': 'write',
|
|
118
|
+
'ligne': 'readline',
|
|
119
|
+
'lignes': 'readlines',
|
|
120
|
+
'ajouter': 'append',
|
|
121
|
+
'etendre': 'extend',
|
|
122
|
+
'insérer': 'insert',
|
|
123
|
+
'retirer': 'remove',
|
|
124
|
+
'extraire': 'pop',
|
|
125
|
+
'vider': 'clear',
|
|
126
|
+
'copier': 'copy',
|
|
127
|
+
'compter': 'count',
|
|
128
|
+
'indice': 'index',
|
|
129
|
+
'trier liste': 'sort',
|
|
130
|
+
'inverser liste': 'reverse',
|
|
131
|
+
'majuscules': 'upper',
|
|
132
|
+
'minuscules': 'lower',
|
|
133
|
+
'titre': 'title',
|
|
134
|
+
'capitaliser': 'capitalize',
|
|
135
|
+
'supprimer espaces': 'strip',
|
|
136
|
+
'supprimer gauche': 'lstrip',
|
|
137
|
+
'supprimer droite': 'rstrip',
|
|
138
|
+
'diviser': 'split',
|
|
139
|
+
'joindre': 'join',
|
|
140
|
+
'remplacer': 'replace',
|
|
141
|
+
'trouver': 'find',
|
|
142
|
+
'commence par': 'startswith',
|
|
143
|
+
'finit par': 'endswith',
|
|
144
|
+
'est numerique': 'isdigit',
|
|
145
|
+
'est alpha': 'isalpha',
|
|
146
|
+
'est alphanumerique': 'isalnum',
|
|
147
|
+
'est espace': 'isspace',
|
|
148
|
+
'formater': 'format',
|
|
149
|
+
'clés': 'keys',
|
|
150
|
+
'valeurs': 'values',
|
|
151
|
+
'éléments': 'items',
|
|
152
|
+
'obtenir': 'get',
|
|
153
|
+
'définir défaut': 'setdefault',
|
|
154
|
+
'mettre a jour': 'update',
|
|
155
|
+
'union': 'union',
|
|
156
|
+
'intersection': 'intersection',
|
|
157
|
+
'difference': 'difference',
|
|
158
|
+
'sous ensemble': 'issubset',
|
|
159
|
+
'sur ensemble': 'issuperset',
|
|
160
|
+
'exception': 'Exception',
|
|
161
|
+
'erreur valeur': 'ValueError',
|
|
162
|
+
'erreur type': 'TypeError',
|
|
163
|
+
'erreur clé': 'KeyError',
|
|
164
|
+
'erreur index': 'IndexError',
|
|
165
|
+
'erreur attribut': 'AttributeError',
|
|
166
|
+
'erreur fichier': 'FileNotFoundError',
|
|
167
|
+
'erreur zero': 'ZeroDivisionError',
|
|
168
|
+
'decorateur': '@',
|
|
169
|
+
'propriété': 'property',
|
|
170
|
+
'méthode statique': 'staticmethod',
|
|
171
|
+
'méthode classe': 'classmethod',
|
|
172
|
+
'super': 'super',
|
|
173
|
+
'init': '__init__',
|
|
174
|
+
'constructeur': '__init__',
|
|
175
|
+
'representer': '__repr__',
|
|
176
|
+
'chaîne dunder': '__str__',
|
|
177
|
+
'iterateur': '__iter__',
|
|
178
|
+
'suivant': '__next__',
|
|
179
|
+
'longueur dunder': '__len__',
|
|
180
|
+
'obtenir item': '__getitem__',
|
|
181
|
+
'définir item': '__setitem__',
|
|
182
|
+
'supprimer item': '__delitem__',
|
|
183
|
+
'contient': '__contains__',
|
|
184
|
+
'appeler': '__call__',
|
|
185
|
+
'entrer': '__enter__',
|
|
186
|
+
'sortir dunder': '__exit__'
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const lower = word.toLowerCase()
|
|
190
|
+
return translations[lower] || word
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
generate(ast) {
|
|
194
|
+
this.output = ''
|
|
195
|
+
this.indent = 0
|
|
196
|
+
|
|
197
|
+
if (Array.isArray(ast)) {
|
|
198
|
+
for (const node of ast) {
|
|
199
|
+
const result = this.generateNode(node)
|
|
200
|
+
if (result !== undefined && result !== '' && this.output === '') {
|
|
201
|
+
return result
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
} else if (ast && ast.type) {
|
|
205
|
+
const result = this.generateNode(ast)
|
|
206
|
+
if (result !== undefined && result !== '' && this.output === '') {
|
|
207
|
+
return result
|
|
208
|
+
}
|
|
209
|
+
} else if (ast && ast.body) {
|
|
210
|
+
for (const node of ast.body) {
|
|
211
|
+
const result = this.generateNode(node)
|
|
212
|
+
if (result !== undefined && result !== '' && this.output === '') {
|
|
213
|
+
return result
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return this.output.trim()
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
generateNode(node) {
|
|
222
|
+
if (!node) return ''
|
|
223
|
+
|
|
224
|
+
switch (node.type) {
|
|
225
|
+
case 'Module':
|
|
226
|
+
return this.generateModule(node)
|
|
227
|
+
case 'ImportStatement':
|
|
228
|
+
return this.generateImport(node)
|
|
229
|
+
case 'FromImportStatement':
|
|
230
|
+
return this.generateFromImport(node)
|
|
231
|
+
case 'FunctionDef':
|
|
232
|
+
case 'FunctionDeclaration':
|
|
233
|
+
return this.generateFunction(node)
|
|
234
|
+
case 'AsyncFunctionDef':
|
|
235
|
+
return this.generateAsyncFunction(node)
|
|
236
|
+
case 'ClassDef':
|
|
237
|
+
case 'ClassDeclaration':
|
|
238
|
+
return this.generateClass(node)
|
|
239
|
+
case 'IfStatement':
|
|
240
|
+
return this.generateIf(node)
|
|
241
|
+
case 'ForStatement':
|
|
242
|
+
return this.generateFor(node)
|
|
243
|
+
case 'WhileStatement':
|
|
244
|
+
return this.generateWhile(node)
|
|
245
|
+
case 'TryStatement':
|
|
246
|
+
return this.generateTry(node)
|
|
247
|
+
case 'WithStatement':
|
|
248
|
+
return this.generateWith(node)
|
|
249
|
+
case 'ReturnStatement':
|
|
250
|
+
return this.generateReturn(node)
|
|
251
|
+
case 'YieldStatement':
|
|
252
|
+
return this.generateYield(node)
|
|
253
|
+
case 'RaiseStatement':
|
|
254
|
+
return this.generateRaise(node)
|
|
255
|
+
case 'AssertStatement':
|
|
256
|
+
return this.generateAssert(node)
|
|
257
|
+
case 'PassStatement':
|
|
258
|
+
this.writeLine('pass')
|
|
259
|
+
return
|
|
260
|
+
case 'BreakStatement':
|
|
261
|
+
this.writeLine('break')
|
|
262
|
+
return
|
|
263
|
+
case 'ContinueStatement':
|
|
264
|
+
this.writeLine('continue')
|
|
265
|
+
return
|
|
266
|
+
case 'ExpressionStatement':
|
|
267
|
+
return this.generateExpressionStatement(node)
|
|
268
|
+
case 'AssignmentStatement':
|
|
269
|
+
case 'AssignmentExpression':
|
|
270
|
+
return this.generateAssignment(node)
|
|
271
|
+
case 'AugmentedAssignment':
|
|
272
|
+
return this.generateAugmentedAssignment(node)
|
|
273
|
+
case 'Decorator':
|
|
274
|
+
return this.generateDecorator(node)
|
|
275
|
+
case 'CallExpression':
|
|
276
|
+
return this.generateCall(node)
|
|
277
|
+
case 'BinaryExpression':
|
|
278
|
+
return this.generateBinary(node)
|
|
279
|
+
case 'UnaryExpression':
|
|
280
|
+
return this.generateUnary(node)
|
|
281
|
+
case 'CompareExpression':
|
|
282
|
+
return this.generateCompare(node)
|
|
283
|
+
case 'BoolOp':
|
|
284
|
+
return this.generateBoolOp(node)
|
|
285
|
+
case 'IfExpression':
|
|
286
|
+
case 'ConditionalExpression':
|
|
287
|
+
return this.generateIfExpr(node)
|
|
288
|
+
case 'ListExpression':
|
|
289
|
+
case 'ArrayExpression':
|
|
290
|
+
return this.generateList(node)
|
|
291
|
+
case 'DictExpression':
|
|
292
|
+
case 'ObjectExpression':
|
|
293
|
+
return this.generateDict(node)
|
|
294
|
+
case 'SetExpression':
|
|
295
|
+
return this.generateSet(node)
|
|
296
|
+
case 'TupleExpression':
|
|
297
|
+
return this.generateTuple(node)
|
|
298
|
+
case 'ListComprehension':
|
|
299
|
+
return this.generateListComp(node)
|
|
300
|
+
case 'DictComprehension':
|
|
301
|
+
return this.generateDictComp(node)
|
|
302
|
+
case 'SetComprehension':
|
|
303
|
+
return this.generateSetComp(node)
|
|
304
|
+
case 'GeneratorExpression':
|
|
305
|
+
return this.generateGenExpr(node)
|
|
306
|
+
case 'LambdaExpression':
|
|
307
|
+
return this.generateLambda(node)
|
|
308
|
+
case 'Subscript':
|
|
309
|
+
case 'MemberExpression':
|
|
310
|
+
return this.generateSubscript(node)
|
|
311
|
+
case 'Attribute':
|
|
312
|
+
return this.generateAttribute(node)
|
|
313
|
+
case 'Slice':
|
|
314
|
+
return this.generateSlice(node)
|
|
315
|
+
case 'FString':
|
|
316
|
+
case 'TemplateLiteral':
|
|
317
|
+
return this.generateFString(node)
|
|
318
|
+
case 'Identifier':
|
|
319
|
+
return this.translate(node.name)
|
|
320
|
+
case 'Literal':
|
|
321
|
+
return this.generateLiteral(node)
|
|
322
|
+
default:
|
|
323
|
+
return ''
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
generateModule(node) {
|
|
328
|
+
for (const stmt of node.body || []) {
|
|
329
|
+
this.generateNode(stmt)
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
generateImport(node) {
|
|
334
|
+
const names = (node.names || [node.name]).map(n => {
|
|
335
|
+
if (typeof n === 'string') return this.translate(n)
|
|
336
|
+
let result = this.translate(n.name)
|
|
337
|
+
if (n.alias) result += ' as ' + n.alias
|
|
338
|
+
return result
|
|
339
|
+
})
|
|
340
|
+
this.writeLine('import ' + names.join(', '))
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
generateFromImport(node) {
|
|
344
|
+
const module = this.translate(node.module)
|
|
345
|
+
const names = (node.names || []).map(n => {
|
|
346
|
+
if (typeof n === 'string') return this.translate(n)
|
|
347
|
+
let result = this.translate(n.name)
|
|
348
|
+
if (n.alias) result += ' as ' + n.alias
|
|
349
|
+
return result
|
|
350
|
+
})
|
|
351
|
+
this.writeLine(`from ${module} import ${names.join(', ')}`)
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
generateFunction(node) {
|
|
355
|
+
if (node.decorators) {
|
|
356
|
+
for (const dec of node.decorators) {
|
|
357
|
+
this.generateDecorator(dec)
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
const name = this.translate(node.name || node.id?.name || '')
|
|
362
|
+
const params = this.generateParams(node.params || node.args || [])
|
|
363
|
+
const returnType = node.returnType ? ' -> ' + this.translate(node.returnType) : ''
|
|
364
|
+
|
|
365
|
+
this.writeLine(`def ${name}(${params})${returnType}:`)
|
|
366
|
+
this.indent++
|
|
367
|
+
|
|
368
|
+
if (node.docstring) {
|
|
369
|
+
this.writeLine(`"""${node.docstring}"""`)
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
const body = node.body?.body || node.body || []
|
|
373
|
+
if (body.length === 0) {
|
|
374
|
+
this.writeLine('pass')
|
|
375
|
+
} else {
|
|
376
|
+
for (const stmt of body) {
|
|
377
|
+
this.generateNode(stmt)
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
this.indent--
|
|
382
|
+
this.writeLine('')
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
generateAsyncFunction(node) {
|
|
386
|
+
if (node.decorators) {
|
|
387
|
+
for (const dec of node.decorators) {
|
|
388
|
+
this.generateDecorator(dec)
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const name = this.translate(node.name || '')
|
|
393
|
+
const params = this.generateParams(node.params || [])
|
|
394
|
+
|
|
395
|
+
this.writeLine(`async def ${name}(${params}):`)
|
|
396
|
+
this.indent++
|
|
397
|
+
|
|
398
|
+
const body = node.body?.body || node.body || []
|
|
399
|
+
if (body.length === 0) {
|
|
400
|
+
this.writeLine('pass')
|
|
401
|
+
} else {
|
|
402
|
+
for (const stmt of body) {
|
|
403
|
+
this.generateNode(stmt)
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
this.indent--
|
|
408
|
+
this.writeLine('')
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
generateParams(params) {
|
|
412
|
+
return params.map(p => {
|
|
413
|
+
let param = ''
|
|
414
|
+
|
|
415
|
+
if (p.kind === 'vararg' || p.vararg) {
|
|
416
|
+
param = '*'
|
|
417
|
+
} else if (p.kind === 'kwarg' || p.kwarg) {
|
|
418
|
+
param = '**'
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
param += this.translate(p.name || p.arg || p)
|
|
422
|
+
|
|
423
|
+
if (p.annotation || p.type) {
|
|
424
|
+
param += ': ' + this.translate(p.annotation || p.type)
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
if (p.default !== undefined) {
|
|
428
|
+
param += ' = ' + this.generateNode(p.default)
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
return param
|
|
432
|
+
}).join(', ')
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
generateClass(node) {
|
|
436
|
+
if (node.decorators) {
|
|
437
|
+
for (const dec of node.decorators) {
|
|
438
|
+
this.generateDecorator(dec)
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
const name = node.name || node.id?.name || ''
|
|
443
|
+
const bases = (node.bases || node.extends || []).map(b =>
|
|
444
|
+
typeof b === 'string' ? b : this.generateNode(b)
|
|
445
|
+
)
|
|
446
|
+
const basesStr = bases.length > 0 ? `(${bases.join(', ')})` : ''
|
|
447
|
+
|
|
448
|
+
this.writeLine(`class ${name}${basesStr}:`)
|
|
449
|
+
this.indent++
|
|
450
|
+
|
|
451
|
+
if (node.docstring) {
|
|
452
|
+
this.writeLine(`"""${node.docstring}"""`)
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
const body = node.body?.body || node.body || []
|
|
456
|
+
if (body.length === 0) {
|
|
457
|
+
this.writeLine('pass')
|
|
458
|
+
} else {
|
|
459
|
+
for (const member of body) {
|
|
460
|
+
this.generateNode(member)
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
this.indent--
|
|
465
|
+
this.writeLine('')
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
generateDecorator(node) {
|
|
469
|
+
let name = ''
|
|
470
|
+
if (typeof node === 'string') {
|
|
471
|
+
name = node
|
|
472
|
+
} else if (typeof node.name === 'string') {
|
|
473
|
+
name = this.translate(node.name)
|
|
474
|
+
} else if (node.name?.name) {
|
|
475
|
+
name = this.translate(node.name.name)
|
|
476
|
+
} else {
|
|
477
|
+
name = this.generateNode(node)
|
|
478
|
+
}
|
|
479
|
+
const args = node.arguments ?
|
|
480
|
+
'(' + node.arguments.map(a => this.generateNode(a)).join(', ') + ')' : ''
|
|
481
|
+
this.writeLine(`@${name}${args}`)
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
generateIf(node) {
|
|
485
|
+
const test = this.generateNode(node.test)
|
|
486
|
+
this.writeLine(`if ${test}:`)
|
|
487
|
+
this.indent++
|
|
488
|
+
|
|
489
|
+
const consequent = node.consequent?.body || node.consequent || node.body || []
|
|
490
|
+
for (const stmt of (Array.isArray(consequent) ? consequent : [consequent])) {
|
|
491
|
+
this.generateNode(stmt)
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
this.indent--
|
|
495
|
+
|
|
496
|
+
if (node.alternate || node.orelse) {
|
|
497
|
+
const alt = node.alternate || node.orelse
|
|
498
|
+
if (alt.type === 'IfStatement' || (Array.isArray(alt) && alt[0]?.type === 'IfStatement')) {
|
|
499
|
+
const elif = Array.isArray(alt) ? alt[0] : alt
|
|
500
|
+
this.output = this.output.trimEnd() + '\n'
|
|
501
|
+
const elifTest = this.generateNode(elif.test)
|
|
502
|
+
this.writeLine(`elif ${elifTest}:`)
|
|
503
|
+
this.indent++
|
|
504
|
+
const elifBody = elif.consequent?.body || elif.consequent || elif.body || []
|
|
505
|
+
for (const stmt of (Array.isArray(elifBody) ? elifBody : [elifBody])) {
|
|
506
|
+
this.generateNode(stmt)
|
|
507
|
+
}
|
|
508
|
+
this.indent--
|
|
509
|
+
if (elif.alternate || elif.orelse) {
|
|
510
|
+
const nextAlt = elif.alternate || elif.orelse
|
|
511
|
+
if (nextAlt.type === 'IfStatement') {
|
|
512
|
+
this.generateIf({ ...nextAlt, isElif: true })
|
|
513
|
+
} else {
|
|
514
|
+
this.writeLine('else:')
|
|
515
|
+
this.indent++
|
|
516
|
+
const nextBody = Array.isArray(nextAlt) ? nextAlt : [nextAlt]
|
|
517
|
+
for (const stmt of nextBody) {
|
|
518
|
+
this.generateNode(stmt)
|
|
519
|
+
}
|
|
520
|
+
this.indent--
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
} else {
|
|
524
|
+
this.writeLine('else:')
|
|
525
|
+
this.indent++
|
|
526
|
+
const altBody = Array.isArray(alt) ? alt : [alt]
|
|
527
|
+
for (const stmt of altBody) {
|
|
528
|
+
this.generateNode(stmt)
|
|
529
|
+
}
|
|
530
|
+
this.indent--
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
generateFor(node) {
|
|
536
|
+
const target = this.generateNode(node.target || node.left)
|
|
537
|
+
const iter = this.generateNode(node.iter || node.right)
|
|
538
|
+
|
|
539
|
+
this.writeLine(`for ${target} in ${iter}:`)
|
|
540
|
+
this.indent++
|
|
541
|
+
|
|
542
|
+
const body = node.body?.body || node.body || []
|
|
543
|
+
for (const stmt of (Array.isArray(body) ? body : [body])) {
|
|
544
|
+
this.generateNode(stmt)
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
this.indent--
|
|
548
|
+
|
|
549
|
+
if (node.orelse && node.orelse.length > 0) {
|
|
550
|
+
this.writeLine('else:')
|
|
551
|
+
this.indent++
|
|
552
|
+
for (const stmt of node.orelse) {
|
|
553
|
+
this.generateNode(stmt)
|
|
554
|
+
}
|
|
555
|
+
this.indent--
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
generateWhile(node) {
|
|
560
|
+
const test = this.generateNode(node.test)
|
|
561
|
+
|
|
562
|
+
this.writeLine(`while ${test}:`)
|
|
563
|
+
this.indent++
|
|
564
|
+
|
|
565
|
+
const body = node.body?.body || node.body || []
|
|
566
|
+
for (const stmt of (Array.isArray(body) ? body : [body])) {
|
|
567
|
+
this.generateNode(stmt)
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
this.indent--
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
generateTry(node) {
|
|
574
|
+
this.writeLine('try:')
|
|
575
|
+
this.indent++
|
|
576
|
+
|
|
577
|
+
const tryBody = node.body?.body || node.body || node.block?.body || node.block || []
|
|
578
|
+
for (const stmt of (Array.isArray(tryBody) ? tryBody : [tryBody])) {
|
|
579
|
+
this.generateNode(stmt)
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
this.indent--
|
|
583
|
+
|
|
584
|
+
for (const handler of node.handlers || (node.handler ? [node.handler] : [])) {
|
|
585
|
+
let exceptLine = 'except'
|
|
586
|
+
if (handler.type) {
|
|
587
|
+
exceptLine += ' ' + this.translate(handler.type)
|
|
588
|
+
if (handler.name || handler.param) {
|
|
589
|
+
exceptLine += ' as ' + (handler.name || this.generateNode(handler.param))
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
this.writeLine(exceptLine + ':')
|
|
593
|
+
this.indent++
|
|
594
|
+
|
|
595
|
+
const handlerBody = handler.body?.body || handler.body || []
|
|
596
|
+
for (const stmt of (Array.isArray(handlerBody) ? handlerBody : [handlerBody])) {
|
|
597
|
+
this.generateNode(stmt)
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
this.indent--
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
if (node.orelse && node.orelse.length > 0) {
|
|
604
|
+
this.writeLine('else:')
|
|
605
|
+
this.indent++
|
|
606
|
+
for (const stmt of node.orelse) {
|
|
607
|
+
this.generateNode(stmt)
|
|
608
|
+
}
|
|
609
|
+
this.indent--
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
if (node.finalbody || node.finalizer) {
|
|
613
|
+
this.writeLine('finally:')
|
|
614
|
+
this.indent++
|
|
615
|
+
const finalBody = node.finalbody || node.finalizer?.body || node.finalizer || []
|
|
616
|
+
for (const stmt of (Array.isArray(finalBody) ? finalBody : [finalBody])) {
|
|
617
|
+
this.generateNode(stmt)
|
|
618
|
+
}
|
|
619
|
+
this.indent--
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
generateWith(node) {
|
|
624
|
+
const items = (node.items || [node]).map(item => {
|
|
625
|
+
let result = this.generateNode(item.context_expr || item.expression)
|
|
626
|
+
if (item.optional_vars || item.alias) {
|
|
627
|
+
result += ' as ' + this.generateNode(item.optional_vars || item.alias)
|
|
628
|
+
}
|
|
629
|
+
return result
|
|
630
|
+
})
|
|
631
|
+
|
|
632
|
+
this.writeLine(`with ${items.join(', ')}:`)
|
|
633
|
+
this.indent++
|
|
634
|
+
|
|
635
|
+
const body = node.body?.body || node.body || []
|
|
636
|
+
for (const stmt of (Array.isArray(body) ? body : [body])) {
|
|
637
|
+
this.generateNode(stmt)
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
this.indent--
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
generateReturn(node) {
|
|
644
|
+
if (node.value || node.argument) {
|
|
645
|
+
const value = this.generateNode(node.value || node.argument)
|
|
646
|
+
this.writeLine(`return ${value}`)
|
|
647
|
+
} else {
|
|
648
|
+
this.writeLine('return')
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
generateYield(node) {
|
|
653
|
+
if (node.value) {
|
|
654
|
+
const value = this.generateNode(node.value)
|
|
655
|
+
if (node.from) {
|
|
656
|
+
this.writeLine(`yield from ${value}`)
|
|
657
|
+
} else {
|
|
658
|
+
this.writeLine(`yield ${value}`)
|
|
659
|
+
}
|
|
660
|
+
} else {
|
|
661
|
+
this.writeLine('yield')
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
generateRaise(node) {
|
|
666
|
+
if (node.exc || node.argument) {
|
|
667
|
+
const exc = this.generateNode(node.exc || node.argument)
|
|
668
|
+
if (node.cause) {
|
|
669
|
+
this.writeLine(`raise ${exc} from ${this.generateNode(node.cause)}`)
|
|
670
|
+
} else {
|
|
671
|
+
this.writeLine(`raise ${exc}`)
|
|
672
|
+
}
|
|
673
|
+
} else {
|
|
674
|
+
this.writeLine('raise')
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
generateAssert(node) {
|
|
679
|
+
const test = this.generateNode(node.test)
|
|
680
|
+
if (node.msg) {
|
|
681
|
+
this.writeLine(`assert ${test}, ${this.generateNode(node.msg)}`)
|
|
682
|
+
} else {
|
|
683
|
+
this.writeLine(`assert ${test}`)
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
generateExpressionStatement(node) {
|
|
688
|
+
const expr = this.generateNode(node.expression)
|
|
689
|
+
this.writeLine(expr)
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
generateAssignment(node) {
|
|
693
|
+
const targets = (node.targets || [node.left]).map(t => this.generateNode(t))
|
|
694
|
+
const value = this.generateNode(node.value || node.right)
|
|
695
|
+
this.writeLine(`${targets.join(' = ')} = ${value}`)
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
generateAugmentedAssignment(node) {
|
|
699
|
+
const target = this.generateNode(node.target)
|
|
700
|
+
const value = this.generateNode(node.value)
|
|
701
|
+
const op = node.op || node.operator
|
|
702
|
+
this.writeLine(`${target} ${op}= ${value}`)
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
generateCall(node) {
|
|
706
|
+
const func = this.generateNode(node.func || node.callee)
|
|
707
|
+
const args = (node.args || node.arguments || []).map(a => this.generateNode(a))
|
|
708
|
+
const kwargs = (node.keywords || []).map(kw =>
|
|
709
|
+
`${kw.arg}=${this.generateNode(kw.value)}`
|
|
710
|
+
)
|
|
711
|
+
const allArgs = [...args, ...kwargs].join(', ')
|
|
712
|
+
return `${func}(${allArgs})`
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
generateBinary(node) {
|
|
716
|
+
const left = this.generateNode(node.left)
|
|
717
|
+
const right = this.generateNode(node.right)
|
|
718
|
+
const op = this.translateOperator(node.op || node.operator)
|
|
719
|
+
return `${left} ${op} ${right}`
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
generateUnary(node) {
|
|
723
|
+
const operand = this.generateNode(node.operand || node.argument)
|
|
724
|
+
const op = this.translateOperator(node.op || node.operator)
|
|
725
|
+
if (op === 'not') {
|
|
726
|
+
return `not ${operand}`
|
|
727
|
+
}
|
|
728
|
+
return `${op}${operand}`
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
generateCompare(node) {
|
|
732
|
+
let result = this.generateNode(node.left)
|
|
733
|
+
const ops = node.ops || [node.operator]
|
|
734
|
+
const comparators = node.comparators || [node.right]
|
|
735
|
+
|
|
736
|
+
for (let i = 0; i < ops.length; i++) {
|
|
737
|
+
result += ' ' + this.translateOperator(ops[i]) + ' ' + this.generateNode(comparators[i])
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
return result
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
generateBoolOp(node) {
|
|
744
|
+
const op = node.op === 'And' || node.op === 'et' ? ' and ' : ' or '
|
|
745
|
+
return node.values.map(v => this.generateNode(v)).join(op)
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
generateIfExpr(node) {
|
|
749
|
+
const body = this.generateNode(node.body || node.consequent)
|
|
750
|
+
const test = this.generateNode(node.test)
|
|
751
|
+
const orelse = this.generateNode(node.orelse || node.alternate)
|
|
752
|
+
return `${body} if ${test} else ${orelse}`
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
generateList(node) {
|
|
756
|
+
const elements = (node.elts || node.elements || []).map(e => this.generateNode(e))
|
|
757
|
+
return `[${elements.join(', ')}]`
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
generateDict(node) {
|
|
761
|
+
const pairs = []
|
|
762
|
+
const keys = node.keys || []
|
|
763
|
+
const values = node.values || []
|
|
764
|
+
|
|
765
|
+
if (node.properties) {
|
|
766
|
+
for (const prop of node.properties) {
|
|
767
|
+
const key = this.generateNode(prop.key)
|
|
768
|
+
const value = this.generateNode(prop.value)
|
|
769
|
+
pairs.push(`${key}: ${value}`)
|
|
770
|
+
}
|
|
771
|
+
} else {
|
|
772
|
+
for (let i = 0; i < keys.length; i++) {
|
|
773
|
+
const key = this.generateNode(keys[i])
|
|
774
|
+
const value = this.generateNode(values[i])
|
|
775
|
+
pairs.push(`${key}: ${value}`)
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
return `{${pairs.join(', ')}}`
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
generateSet(node) {
|
|
783
|
+
const elements = (node.elts || node.elements || []).map(e => this.generateNode(e))
|
|
784
|
+
return `{${elements.join(', ')}}`
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
generateTuple(node) {
|
|
788
|
+
const elements = (node.elts || node.elements || []).map(e => this.generateNode(e))
|
|
789
|
+
if (elements.length === 1) {
|
|
790
|
+
return `(${elements[0]},)`
|
|
791
|
+
}
|
|
792
|
+
return `(${elements.join(', ')})`
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
generateListComp(node) {
|
|
796
|
+
const elt = this.generateNode(node.elt || node.element)
|
|
797
|
+
const generators = (node.generators || []).map(g => this.generateComprehensionGen(g))
|
|
798
|
+
return `[${elt} ${generators.join(' ')}]`
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
generateDictComp(node) {
|
|
802
|
+
const key = this.generateNode(node.key)
|
|
803
|
+
const value = this.generateNode(node.value)
|
|
804
|
+
const generators = (node.generators || []).map(g => this.generateComprehensionGen(g))
|
|
805
|
+
return `{${key}: ${value} ${generators.join(' ')}}`
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
generateSetComp(node) {
|
|
809
|
+
const elt = this.generateNode(node.elt || node.element)
|
|
810
|
+
const generators = (node.generators || []).map(g => this.generateComprehensionGen(g))
|
|
811
|
+
return `{${elt} ${generators.join(' ')}}`
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
generateGenExpr(node) {
|
|
815
|
+
const elt = this.generateNode(node.elt || node.element)
|
|
816
|
+
const generators = (node.generators || []).map(g => this.generateComprehensionGen(g))
|
|
817
|
+
return `(${elt} ${generators.join(' ')})`
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
generateComprehensionGen(gen) {
|
|
821
|
+
const target = this.generateNode(gen.target)
|
|
822
|
+
const iter = this.generateNode(gen.iter)
|
|
823
|
+
let result = `for ${target} in ${iter}`
|
|
824
|
+
|
|
825
|
+
for (const if_ of gen.ifs || []) {
|
|
826
|
+
result += ` if ${this.generateNode(if_)}`
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
return result
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
generateLambda(node) {
|
|
833
|
+
const args = this.generateParams(node.args?.args || node.params || [])
|
|
834
|
+
const body = this.generateNode(node.body)
|
|
835
|
+
return `lambda ${args}: ${body}`
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
generateSubscript(node) {
|
|
839
|
+
const value = this.generateNode(node.value || node.object)
|
|
840
|
+
const slice = this.generateNode(node.slice || node.property)
|
|
841
|
+
|
|
842
|
+
if (node.computed === false) {
|
|
843
|
+
return `${value}.${slice}`
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
return `${value}[${slice}]`
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
generateAttribute(node) {
|
|
850
|
+
const value = this.generateNode(node.value)
|
|
851
|
+
const attr = this.translate(node.attr)
|
|
852
|
+
return `${value}.${attr}`
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
generateSlice(node) {
|
|
856
|
+
const lower = node.lower ? this.generateNode(node.lower) : ''
|
|
857
|
+
const upper = node.upper ? this.generateNode(node.upper) : ''
|
|
858
|
+
const step = node.step ? ':' + this.generateNode(node.step) : ''
|
|
859
|
+
return `${lower}:${upper}${step}`
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
generateFString(node) {
|
|
863
|
+
let result = 'f"'
|
|
864
|
+
for (const part of node.values || node.parts || []) {
|
|
865
|
+
if (part.type === 'Literal' || typeof part === 'string') {
|
|
866
|
+
result += typeof part === 'string' ? part : part.value
|
|
867
|
+
} else {
|
|
868
|
+
result += '{' + this.generateNode(part.value || part) + '}'
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
result += '"'
|
|
872
|
+
return result
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
generateLiteral(node) {
|
|
876
|
+
if (node.value === null || node.value === undefined) return 'None'
|
|
877
|
+
if (node.value === true) return 'True'
|
|
878
|
+
if (node.value === false) return 'False'
|
|
879
|
+
if (typeof node.value === 'string') {
|
|
880
|
+
return `"${node.value.replace(/"/g, '\\"')}"`
|
|
881
|
+
}
|
|
882
|
+
return String(node.value)
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
translateOperator(op) {
|
|
886
|
+
const operators = {
|
|
887
|
+
'et': 'and',
|
|
888
|
+
'ou': 'or',
|
|
889
|
+
'non': 'not',
|
|
890
|
+
'est': 'is',
|
|
891
|
+
'dans': 'in',
|
|
892
|
+
'pas dans': 'not in',
|
|
893
|
+
'est pas': 'is not',
|
|
894
|
+
'egal': '==',
|
|
895
|
+
'different': '!=',
|
|
896
|
+
'puissance': '**',
|
|
897
|
+
'div entiere': '//'
|
|
898
|
+
}
|
|
899
|
+
return operators[op] || op
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
writeLine(text) {
|
|
903
|
+
this.output += this.getIndent() + text + '\n'
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
getIndent() {
|
|
907
|
+
return ' '.repeat(this.indent)
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
module.exports = {
|
|
912
|
+
PythonGenerator
|
|
913
|
+
}
|