ether-code 0.9.1 → 0.9.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/cli/ether.js +1 -1
- package/generators/php-generator.js +816 -737
- package/lexer/ether-lexer.js +5 -3
- package/package.json +1 -1
- package/parsers/ether-parser-php.js +17 -4
|
@@ -5,571 +5,794 @@ class PHPGenerator {
|
|
|
5
5
|
this.i18n = null
|
|
6
6
|
this.indent = 0
|
|
7
7
|
this.output = ''
|
|
8
|
-
this.translationMap = {}
|
|
9
|
-
this.functionMap = {}
|
|
10
|
-
this.supportedLanguages = ['fr', 'en', 'es', 'ru', 'zh', 'ja']
|
|
11
8
|
|
|
12
9
|
if (i18nPath) {
|
|
13
10
|
this.loadI18n(i18nPath)
|
|
14
11
|
}
|
|
12
|
+
|
|
13
|
+
this.buildFunctionMap()
|
|
15
14
|
}
|
|
16
15
|
|
|
17
16
|
loadI18n(filePath) {
|
|
18
17
|
const content = fs.readFileSync(filePath, 'utf-8')
|
|
19
18
|
this.i18n = JSON.parse(content)
|
|
20
|
-
this.buildTranslationMap()
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
buildTranslationMap() {
|
|
24
|
-
this.translationMap = {}
|
|
25
|
-
this.functionMap = {}
|
|
26
|
-
|
|
27
|
-
if (!this.i18n) return
|
|
28
|
-
|
|
29
|
-
for (const [sectionName, section] of Object.entries(this.i18n)) {
|
|
30
|
-
if (sectionName === 'metadata' || typeof section !== 'object') continue
|
|
31
|
-
|
|
32
|
-
for (const lang of this.supportedLanguages) {
|
|
33
|
-
if (!section[lang]) continue
|
|
34
|
-
|
|
35
|
-
for (const [etherWord, phpCode] of Object.entries(section[lang])) {
|
|
36
|
-
const fixed = this.normalizeUTF8(etherWord)
|
|
37
|
-
const normalizedKey = fixed.toLowerCase().trim()
|
|
38
|
-
const cleanPhp = this.cleanPhpValue(phpCode)
|
|
39
|
-
|
|
40
|
-
if (phpCode.endsWith('()')) {
|
|
41
|
-
this.functionMap[normalizedKey] = cleanPhp
|
|
42
|
-
const withoutAccents = this.removeAccents(normalizedKey)
|
|
43
|
-
if (withoutAccents !== normalizedKey) {
|
|
44
|
-
this.functionMap[withoutAccents] = cleanPhp
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
this.translationMap[normalizedKey] = cleanPhp
|
|
49
|
-
|
|
50
|
-
const withoutAccents = this.removeAccents(normalizedKey)
|
|
51
|
-
if (withoutAccents !== normalizedKey) {
|
|
52
|
-
this.translationMap[withoutAccents] = cleanPhp
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
19
|
}
|
|
58
20
|
|
|
59
|
-
|
|
21
|
+
normalizeAccents(str) {
|
|
60
22
|
if (typeof str !== 'string') return String(str)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
23
|
+
return str.toLowerCase()
|
|
24
|
+
.normalize('NFD')
|
|
25
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
26
|
+
.replace(/-/g, ' ')
|
|
27
|
+
.replace(/_/g, ' ')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
buildFunctionMap() {
|
|
31
|
+
this.functionMap = {
|
|
32
|
+
'est chaine': 'is_string',
|
|
33
|
+
'est entier': 'is_int',
|
|
34
|
+
'est flottant': 'is_float',
|
|
35
|
+
'est tableau': 'is_array',
|
|
36
|
+
'est booleen': 'is_bool',
|
|
37
|
+
'est nul': 'is_null',
|
|
38
|
+
'est null': 'is_null',
|
|
39
|
+
'est objet': 'is_object',
|
|
40
|
+
'est numerique': 'is_numeric',
|
|
41
|
+
'est callable': 'is_callable',
|
|
42
|
+
'est appelable': 'is_callable',
|
|
43
|
+
'est ressource': 'is_resource',
|
|
44
|
+
'est scalaire': 'is_scalar',
|
|
45
|
+
'est vide': 'empty',
|
|
46
|
+
'est iterable': 'is_iterable',
|
|
47
|
+
'est comptable': 'is_countable',
|
|
48
|
+
'obtenir type': 'gettype',
|
|
49
|
+
'definir type': 'settype',
|
|
50
|
+
'valeur entier': 'intval',
|
|
51
|
+
'valeur entiere': 'intval',
|
|
52
|
+
'valeur flottant': 'floatval',
|
|
53
|
+
'valeur chaine': 'strval',
|
|
54
|
+
'valeur booleen': 'boolval',
|
|
55
|
+
'longueur': 'strlen',
|
|
56
|
+
'sous chaine': 'substr',
|
|
57
|
+
'sous-chaine': 'substr',
|
|
58
|
+
'position': 'strpos',
|
|
59
|
+
'remplacer': 'str_replace',
|
|
60
|
+
'exploser': 'explode',
|
|
61
|
+
'imploser': 'implode',
|
|
62
|
+
'majuscules': 'strtoupper',
|
|
63
|
+
'minuscules': 'strtolower',
|
|
64
|
+
'couper espaces': 'trim',
|
|
65
|
+
'rogner': 'trim',
|
|
66
|
+
'rogner gauche': 'ltrim',
|
|
67
|
+
'rogner droite': 'rtrim',
|
|
68
|
+
'repeter': 'str_repeat',
|
|
69
|
+
'inverser chaine': 'strrev',
|
|
70
|
+
'remplir': 'str_pad',
|
|
71
|
+
'remplir gauche': 'str_pad',
|
|
72
|
+
'compter': 'count',
|
|
73
|
+
'trier': 'sort',
|
|
74
|
+
'trier inverse': 'rsort',
|
|
75
|
+
'trier associatif': 'asort',
|
|
76
|
+
'trier cles': 'ksort',
|
|
77
|
+
'inverser': 'array_reverse',
|
|
78
|
+
'fusionner': 'array_merge',
|
|
79
|
+
'fusionner tableaux': 'array_merge',
|
|
80
|
+
'filtrer': 'array_filter',
|
|
81
|
+
'filtrer tableau': 'array_filter',
|
|
82
|
+
'mapper': 'array_map',
|
|
83
|
+
'mapper tableau': 'array_map',
|
|
84
|
+
'transformer': 'array_map',
|
|
85
|
+
'reduire': 'array_reduce',
|
|
86
|
+
'reduire tableau': 'array_reduce',
|
|
87
|
+
'cles': 'array_keys',
|
|
88
|
+
'tableau cles': 'array_keys',
|
|
89
|
+
'valeurs': 'array_values',
|
|
90
|
+
'tableau valeurs': 'array_values',
|
|
91
|
+
'pousser': 'array_push',
|
|
92
|
+
'ajouter': 'array_push',
|
|
93
|
+
'retirer': 'array_pop',
|
|
94
|
+
'rechercher': 'array_search',
|
|
95
|
+
'existe': 'array_key_exists',
|
|
96
|
+
'cle existe': 'array_key_exists',
|
|
97
|
+
'dans tableau': 'in_array',
|
|
98
|
+
'somme': 'array_sum',
|
|
99
|
+
'somme tableau': 'array_sum',
|
|
100
|
+
'unique': 'array_unique',
|
|
101
|
+
'decouper': 'array_slice',
|
|
102
|
+
'epissure': 'array_splice',
|
|
103
|
+
'combiner': 'array_combine',
|
|
104
|
+
'remplir tableau': 'array_fill',
|
|
105
|
+
'colonne': 'array_column',
|
|
106
|
+
'compter valeurs': 'array_count_values',
|
|
107
|
+
'difference': 'array_diff',
|
|
108
|
+
'intersection': 'array_intersect',
|
|
109
|
+
'premier': 'reset',
|
|
110
|
+
'dernier': 'end',
|
|
111
|
+
'suivant': 'next',
|
|
112
|
+
'precedent': 'prev',
|
|
113
|
+
'courant': 'current',
|
|
114
|
+
'cle courante': 'key',
|
|
115
|
+
'melanger': 'shuffle',
|
|
116
|
+
'absolu': 'abs',
|
|
117
|
+
'plafond': 'ceil',
|
|
118
|
+
'plancher': 'floor',
|
|
119
|
+
'arrondir': 'round',
|
|
120
|
+
'arrondi': 'round',
|
|
121
|
+
'racine carree': 'sqrt',
|
|
122
|
+
'puissance': 'pow',
|
|
123
|
+
'aleatoire': 'rand',
|
|
124
|
+
'aleatoire entier': 'random_int',
|
|
125
|
+
'maximum': 'max',
|
|
126
|
+
'minimum': 'min',
|
|
127
|
+
'pi': 'pi',
|
|
128
|
+
'exponentielle': 'exp',
|
|
129
|
+
'logarithme': 'log',
|
|
130
|
+
'logarithme10': 'log10',
|
|
131
|
+
'sinus': 'sin',
|
|
132
|
+
'cosinus': 'cos',
|
|
133
|
+
'tangente': 'tan',
|
|
134
|
+
'formater nombre': 'number_format',
|
|
135
|
+
'date': 'date',
|
|
136
|
+
'temps': 'time',
|
|
137
|
+
'maintenant': 'time',
|
|
138
|
+
'creer date': 'mktime',
|
|
139
|
+
'date vers temps': 'strtotime',
|
|
140
|
+
'formater date': 'date_format',
|
|
141
|
+
'fichier existe': 'file_exists',
|
|
142
|
+
'lire fichier': 'file_get_contents',
|
|
143
|
+
'ecrire fichier': 'file_put_contents',
|
|
144
|
+
'ouvrir fichier': 'fopen',
|
|
145
|
+
'fermer fichier': 'fclose',
|
|
146
|
+
'lire ligne': 'fgets',
|
|
147
|
+
'ecrire ligne': 'fputs',
|
|
148
|
+
'est fichier': 'is_file',
|
|
149
|
+
'est repertoire': 'is_dir',
|
|
150
|
+
'creer repertoire': 'mkdir',
|
|
151
|
+
'supprimer fichier': 'unlink',
|
|
152
|
+
'renommer': 'rename',
|
|
153
|
+
'copier': 'copy',
|
|
154
|
+
'taille fichier': 'filesize',
|
|
155
|
+
'encoder json': 'json_encode',
|
|
156
|
+
'decoder json': 'json_decode',
|
|
157
|
+
'json encoder': 'json_encode',
|
|
158
|
+
'json decoder': 'json_decode',
|
|
159
|
+
'correspondre': 'preg_match',
|
|
160
|
+
'regex correspondance': 'preg_match',
|
|
161
|
+
'regex toutes': 'preg_match_all',
|
|
162
|
+
'regex remplacer': 'preg_replace',
|
|
163
|
+
'demarrer session': 'session_start',
|
|
164
|
+
'detruire session': 'session_destroy',
|
|
165
|
+
'definir cookie': 'setcookie',
|
|
166
|
+
'hacher': 'hash',
|
|
167
|
+
'hacher mot de passe': 'password_hash',
|
|
168
|
+
'verifier mot de passe': 'password_verify',
|
|
169
|
+
'md5': 'md5',
|
|
170
|
+
'sha1': 'sha1',
|
|
171
|
+
'base64 encoder': 'base64_encode',
|
|
172
|
+
'base64 decoder': 'base64_decode',
|
|
173
|
+
'url encoder': 'urlencode',
|
|
174
|
+
'url decoder': 'urldecode',
|
|
175
|
+
'htmlentites': 'htmlentities',
|
|
176
|
+
'html special': 'htmlspecialchars',
|
|
177
|
+
'enlever balises': 'strip_tags',
|
|
178
|
+
'echapper': 'addslashes',
|
|
179
|
+
'preparer': 'prepare',
|
|
180
|
+
'executer': 'execute',
|
|
181
|
+
'recuperer': 'fetch',
|
|
182
|
+
'recuperer tout': 'fetchAll',
|
|
183
|
+
'nombre lignes': 'rowCount',
|
|
184
|
+
'dernier id': 'lastInsertId',
|
|
185
|
+
'afficher info': 'var_dump',
|
|
186
|
+
'imprimer r': 'print_r',
|
|
187
|
+
'exporter': 'var_export',
|
|
188
|
+
'vide': 'empty',
|
|
189
|
+
'defini': 'isset',
|
|
190
|
+
'supprimer': 'unset',
|
|
191
|
+
'sortie': 'exit',
|
|
192
|
+
'mourir': 'die',
|
|
193
|
+
'dormir': 'sleep',
|
|
194
|
+
'micro dormir': 'usleep',
|
|
195
|
+
'entete': 'header',
|
|
196
|
+
'en tete': 'header',
|
|
197
|
+
'rediriger': 'header',
|
|
198
|
+
'serialiser': 'serialize',
|
|
199
|
+
'deserialiser': 'unserialize',
|
|
200
|
+
'formater': 'format',
|
|
201
|
+
'getmessage': 'getMessage'
|
|
70
202
|
}
|
|
71
|
-
}
|
|
72
203
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
204
|
+
this.keywordMap = {
|
|
205
|
+
'variable': '',
|
|
206
|
+
'constante': 'const',
|
|
207
|
+
'fonction': 'function',
|
|
208
|
+
'retourner': 'return',
|
|
209
|
+
'si': 'if',
|
|
210
|
+
'sinon': 'else',
|
|
211
|
+
'sinon si': 'elseif',
|
|
212
|
+
'pour': 'for',
|
|
213
|
+
'pour chaque': 'foreach',
|
|
214
|
+
'tant que': 'while',
|
|
215
|
+
'faire': 'do',
|
|
216
|
+
'selon': 'switch',
|
|
217
|
+
'cas': 'case',
|
|
218
|
+
'defaut': 'default',
|
|
219
|
+
'sortir': 'break',
|
|
220
|
+
'continuer': 'continue',
|
|
221
|
+
'essayer': 'try',
|
|
222
|
+
'attraper': 'catch',
|
|
223
|
+
'finalement': 'finally',
|
|
224
|
+
'lancer': 'throw',
|
|
225
|
+
'nouveau': 'new',
|
|
226
|
+
'nouvelle': 'new',
|
|
227
|
+
'classe': 'class',
|
|
228
|
+
'interface': 'interface',
|
|
229
|
+
'trait': 'trait',
|
|
230
|
+
'etend': 'extends',
|
|
231
|
+
'etendre': 'extends',
|
|
232
|
+
'implemente': 'implements',
|
|
233
|
+
'implementer': 'implements',
|
|
234
|
+
'utiliser': 'use',
|
|
235
|
+
'public': 'public',
|
|
236
|
+
'publique': 'public',
|
|
237
|
+
'prive': 'private',
|
|
238
|
+
'privee': 'private',
|
|
239
|
+
'protege': 'protected',
|
|
240
|
+
'protegee': 'protected',
|
|
241
|
+
'statique': 'static',
|
|
242
|
+
'final': 'final',
|
|
243
|
+
'finale': 'final',
|
|
244
|
+
'abstrait': 'abstract',
|
|
245
|
+
'abstraite': 'abstract',
|
|
246
|
+
'constructeur': '__construct',
|
|
247
|
+
'destructeur': '__destruct',
|
|
248
|
+
'obtenir': '__get',
|
|
249
|
+
'definir': '__set',
|
|
250
|
+
'appeler': '__call',
|
|
251
|
+
'vers chaine': '__toString',
|
|
252
|
+
'espace de noms': 'namespace',
|
|
253
|
+
'comme': 'as',
|
|
254
|
+
'vrai': 'true',
|
|
255
|
+
'faux': 'false',
|
|
256
|
+
'nul': 'null',
|
|
257
|
+
'rien': 'null',
|
|
258
|
+
'ceci': '$this',
|
|
259
|
+
'parent': 'parent',
|
|
260
|
+
'self': 'self',
|
|
261
|
+
'soi': 'self',
|
|
262
|
+
'et': '&&',
|
|
263
|
+
'ou': '||',
|
|
264
|
+
'non': '!',
|
|
265
|
+
'egal': '===',
|
|
266
|
+
'different': '!==',
|
|
267
|
+
'concatener': '.',
|
|
268
|
+
'tableau': 'array',
|
|
269
|
+
'chaine': 'string',
|
|
270
|
+
'entier': 'int',
|
|
271
|
+
'flottant': 'float',
|
|
272
|
+
'booleen': 'bool',
|
|
273
|
+
'objet': 'object',
|
|
274
|
+
'vide type': 'void',
|
|
275
|
+
'void': 'void',
|
|
276
|
+
'mixte': 'mixed',
|
|
277
|
+
'afficher': 'echo',
|
|
278
|
+
'imprimer': 'print',
|
|
279
|
+
'inclure': 'include',
|
|
280
|
+
'inclure une fois': 'include_once',
|
|
281
|
+
'requiert': 'require',
|
|
282
|
+
'requerir': 'require',
|
|
283
|
+
'requiert une fois': 'require_once',
|
|
284
|
+
'requerir une fois': 'require_once',
|
|
285
|
+
'rendement': 'yield',
|
|
286
|
+
'rendement de': 'yield from'
|
|
287
|
+
}
|
|
77
288
|
}
|
|
78
289
|
|
|
79
290
|
translate(word) {
|
|
80
|
-
if (!word
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (this.translationMap[normalized]) {
|
|
85
|
-
return this.translationMap[normalized]
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const withoutAccents = this.removeAccents(normalized)
|
|
89
|
-
if (this.translationMap[withoutAccents]) {
|
|
90
|
-
return this.translationMap[withoutAccents]
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return word
|
|
291
|
+
if (!word) return word
|
|
292
|
+
const normalized = this.normalizeAccents(word)
|
|
293
|
+
return this.functionMap[normalized] || this.keywordMap[normalized] || word
|
|
94
294
|
}
|
|
95
295
|
|
|
96
296
|
translateFunction(word) {
|
|
97
|
-
if (!word
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const withoutAccents = this.removeAccents(normalized)
|
|
101
|
-
|
|
102
|
-
if (this.functionMap[normalized]) {
|
|
103
|
-
return this.functionMap[normalized]
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (this.functionMap[withoutAccents]) {
|
|
107
|
-
return this.functionMap[withoutAccents]
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (this.translationMap[normalized]) {
|
|
111
|
-
return this.translationMap[normalized]
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (this.translationMap[withoutAccents]) {
|
|
115
|
-
return this.translationMap[withoutAccents]
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return word
|
|
297
|
+
if (!word) return word
|
|
298
|
+
const normalized = this.normalizeAccents(word)
|
|
299
|
+
return this.functionMap[normalized] || word
|
|
119
300
|
}
|
|
120
301
|
|
|
121
|
-
|
|
122
|
-
|
|
302
|
+
translateKeyword(word) {
|
|
303
|
+
if (!word) return word
|
|
304
|
+
const normalized = this.normalizeAccents(word)
|
|
305
|
+
return this.keywordMap[normalized] || word
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
extractTypeName(typeNode) {
|
|
309
|
+
if (!typeNode) return ''
|
|
310
|
+
if (typeof typeNode === 'string') return this.translateKeyword(typeNode)
|
|
311
|
+
if (typeNode.type === 'TypeHint') {
|
|
312
|
+
const types = (typeNode.types || []).map(t => this.translateKeyword(t))
|
|
313
|
+
const result = types.join('|')
|
|
314
|
+
return typeNode.nullable ? '?' + result : result
|
|
315
|
+
}
|
|
316
|
+
if (typeNode.name) return this.translateKeyword(typeNode.name)
|
|
317
|
+
if (typeNode.type === 'Identifier') return this.translateKeyword(typeNode.name || typeNode.value || '')
|
|
318
|
+
if (typeNode.value) return this.translateKeyword(typeNode.value)
|
|
319
|
+
return ''
|
|
123
320
|
}
|
|
124
321
|
|
|
125
322
|
generate(ast) {
|
|
126
|
-
this.output = '
|
|
323
|
+
this.output = ''
|
|
127
324
|
this.indent = 0
|
|
128
|
-
|
|
129
|
-
if (ast.
|
|
130
|
-
this.
|
|
131
|
-
this.writeLine('')
|
|
325
|
+
|
|
326
|
+
if (ast.phpTag !== false) {
|
|
327
|
+
this.output = '<?php\n'
|
|
132
328
|
}
|
|
133
329
|
|
|
134
|
-
if (Array.isArray(ast
|
|
135
|
-
for (const node of ast
|
|
330
|
+
if (Array.isArray(ast)) {
|
|
331
|
+
for (const node of ast) {
|
|
136
332
|
this.generateNode(node)
|
|
137
333
|
}
|
|
138
|
-
} else if (ast.
|
|
139
|
-
|
|
140
|
-
|
|
334
|
+
} else if (ast && ast.type === 'Program') {
|
|
335
|
+
for (const node of ast.body || []) {
|
|
336
|
+
this.generateNode(node)
|
|
337
|
+
}
|
|
338
|
+
} else if (ast && ast.type) {
|
|
141
339
|
this.generateNode(ast)
|
|
340
|
+
} else if (ast && ast.body) {
|
|
341
|
+
for (const node of ast.body) {
|
|
342
|
+
this.generateNode(node)
|
|
343
|
+
}
|
|
142
344
|
}
|
|
143
345
|
|
|
144
|
-
return this.output
|
|
346
|
+
return this.output.trim()
|
|
145
347
|
}
|
|
146
348
|
|
|
147
349
|
generateNode(node) {
|
|
148
350
|
if (!node) return ''
|
|
149
351
|
|
|
150
|
-
|
|
151
|
-
|
|
352
|
+
switch (node.type) {
|
|
353
|
+
case 'Program':
|
|
354
|
+
for (const stmt of node.body || []) {
|
|
355
|
+
this.generateNode(stmt)
|
|
356
|
+
}
|
|
357
|
+
return ''
|
|
358
|
+
case 'DeclareStatement':
|
|
359
|
+
return this.generateDeclareStatement(node)
|
|
360
|
+
case 'NamespaceDeclaration':
|
|
361
|
+
return this.generateNamespace(node)
|
|
362
|
+
case 'UseStatement':
|
|
363
|
+
return this.generateUseStatement(node)
|
|
364
|
+
case 'ConstantDeclaration':
|
|
365
|
+
return this.generateConstantDeclaration(node)
|
|
366
|
+
case 'VariableDeclaration':
|
|
367
|
+
return this.generateVariableDeclaration(node)
|
|
368
|
+
case 'FunctionDeclaration':
|
|
369
|
+
return this.generateFunctionDeclaration(node)
|
|
370
|
+
case 'ClassDeclaration':
|
|
371
|
+
return this.generateClassDeclaration(node)
|
|
372
|
+
case 'InterfaceDeclaration':
|
|
373
|
+
return this.generateInterfaceDeclaration(node)
|
|
374
|
+
case 'TraitDeclaration':
|
|
375
|
+
return this.generateTraitDeclaration(node)
|
|
376
|
+
case 'EnumDeclaration':
|
|
377
|
+
return this.generateEnumDeclaration(node)
|
|
378
|
+
case 'IfStatement':
|
|
379
|
+
return this.generateIfStatement(node)
|
|
380
|
+
case 'ForStatement':
|
|
381
|
+
return this.generateForStatement(node)
|
|
382
|
+
case 'ForEachStatement':
|
|
383
|
+
return this.generateForEachStatement(node)
|
|
384
|
+
case 'WhileStatement':
|
|
385
|
+
return this.generateWhileStatement(node)
|
|
386
|
+
case 'DoWhileStatement':
|
|
387
|
+
return this.generateDoWhileStatement(node)
|
|
388
|
+
case 'SwitchStatement':
|
|
389
|
+
return this.generateSwitchStatement(node)
|
|
390
|
+
case 'TryStatement':
|
|
391
|
+
return this.generateTryStatement(node)
|
|
392
|
+
case 'ReturnStatement':
|
|
393
|
+
return this.generateReturnStatement(node)
|
|
394
|
+
case 'ThrowStatement':
|
|
395
|
+
return this.generateThrowStatement(node)
|
|
396
|
+
case 'BreakStatement':
|
|
397
|
+
this.writeLine('break;')
|
|
398
|
+
return ''
|
|
399
|
+
case 'ContinueStatement':
|
|
400
|
+
this.writeLine('continue;')
|
|
401
|
+
return ''
|
|
402
|
+
case 'ExpressionStatement':
|
|
403
|
+
return this.generateExpressionStatement(node)
|
|
404
|
+
case 'EchoStatement':
|
|
405
|
+
return this.generateEchoStatement(node)
|
|
406
|
+
case 'BlockStatement':
|
|
407
|
+
return this.generateBlockStatement(node)
|
|
408
|
+
case 'CallExpression':
|
|
409
|
+
return this.generateCallExpression(node)
|
|
410
|
+
case 'MemberExpression':
|
|
411
|
+
return this.generateMemberExpression(node)
|
|
412
|
+
case 'StaticMemberExpression':
|
|
413
|
+
return this.generateStaticMemberExpression(node)
|
|
414
|
+
case 'BinaryExpression':
|
|
415
|
+
return this.generateBinaryExpression(node)
|
|
416
|
+
case 'LogicalExpression':
|
|
417
|
+
return this.generateBinaryExpression(node)
|
|
418
|
+
case 'AssignmentExpression':
|
|
419
|
+
return this.generateAssignmentExpression(node)
|
|
420
|
+
case 'UnaryExpression':
|
|
421
|
+
return this.generateUnaryExpression(node)
|
|
422
|
+
case 'UpdateExpression':
|
|
423
|
+
return this.generateUpdateExpression(node)
|
|
424
|
+
case 'ConditionalExpression':
|
|
425
|
+
return this.generateConditionalExpression(node)
|
|
426
|
+
case 'ArrayExpression':
|
|
427
|
+
return this.generateArrayExpression(node)
|
|
428
|
+
case 'ObjectExpression':
|
|
429
|
+
return this.generateObjectExpression(node)
|
|
430
|
+
case 'Identifier':
|
|
431
|
+
return this.generateIdentifier(node)
|
|
432
|
+
case 'Variable':
|
|
433
|
+
return this.generateVariable(node)
|
|
434
|
+
case 'Literal':
|
|
435
|
+
return this.generateLiteral(node)
|
|
436
|
+
case 'StringLiteral':
|
|
437
|
+
return this.generateStringLiteral(node)
|
|
438
|
+
case 'NewExpression':
|
|
439
|
+
return this.generateNewExpression(node)
|
|
440
|
+
case 'ThisExpression':
|
|
441
|
+
return '$this'
|
|
442
|
+
case 'FunctionExpression':
|
|
443
|
+
return this.generateFunctionExpression(node)
|
|
444
|
+
case 'ArrowFunctionExpression':
|
|
445
|
+
return this.generateArrowFunctionExpression(node)
|
|
446
|
+
case 'IndexExpression':
|
|
447
|
+
return this.generateIndexExpression(node)
|
|
448
|
+
case 'NullCoalesceExpression':
|
|
449
|
+
return this.generateNullCoalesceExpression(node)
|
|
450
|
+
case 'YieldExpression':
|
|
451
|
+
return this.generateYieldExpression(node)
|
|
452
|
+
default:
|
|
453
|
+
return ''
|
|
152
454
|
}
|
|
455
|
+
}
|
|
153
456
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
'
|
|
158
|
-
'FunctionDeclaration': () => this.generateFunctionDeclaration(node),
|
|
159
|
-
'ClassDeclaration': () => this.generateClassDeclaration(node),
|
|
160
|
-
'InterfaceDeclaration': () => this.generateInterfaceDeclaration(node),
|
|
161
|
-
'TraitDeclaration': () => this.generateTraitDeclaration(node),
|
|
162
|
-
'EnumDeclaration': () => this.generateEnumDeclaration(node),
|
|
163
|
-
'MethodDefinition': () => this.generateMethodDefinition(node),
|
|
164
|
-
'MethodDeclaration': () => this.generateMethodDefinition(node),
|
|
165
|
-
'PropertyDeclaration': () => this.generatePropertyDeclaration(node),
|
|
166
|
-
'VariableDeclaration': () => this.generateVariableDeclaration(node),
|
|
167
|
-
'ConstantDeclaration': () => this.generateConstantDeclaration(node),
|
|
168
|
-
'IfStatement': () => this.generateIfStatement(node),
|
|
169
|
-
'ForStatement': () => this.generateForStatement(node),
|
|
170
|
-
'ForEachStatement': () => this.generateForEachStatement(node),
|
|
171
|
-
'ForeachStatement': () => this.generateForEachStatement(node),
|
|
172
|
-
'WhileStatement': () => this.generateWhileStatement(node),
|
|
173
|
-
'DoWhileStatement': () => this.generateDoWhileStatement(node),
|
|
174
|
-
'SwitchStatement': () => this.generateSwitchStatement(node),
|
|
175
|
-
'MatchExpression': () => this.generateMatchExpression(node),
|
|
176
|
-
'TryStatement': () => this.generateTryStatement(node),
|
|
177
|
-
'ReturnStatement': () => this.generateReturnStatement(node),
|
|
178
|
-
'YieldExpression': () => this.generateYieldExpression(node),
|
|
179
|
-
'ThrowStatement': () => this.generateThrowStatement(node),
|
|
180
|
-
'BreakStatement': () => this.writeLine('break;'),
|
|
181
|
-
'ContinueStatement': () => this.writeLine('continue;'),
|
|
182
|
-
'ExpressionStatement': () => this.generateExpressionStatement(node),
|
|
183
|
-
'EchoStatement': () => this.generateEchoStatement(node),
|
|
184
|
-
'PrintStatement': () => this.generatePrintStatement(node),
|
|
185
|
-
'Namespace': () => this.generateNamespace(node),
|
|
186
|
-
'UseStatement': () => this.generateUseStatement(node),
|
|
187
|
-
'DeclareStatement': () => this.generateDeclareStatement(node),
|
|
188
|
-
'IncludeStatement': () => this.generateIncludeStatement(node),
|
|
189
|
-
'Include': () => this.generateInclude(node),
|
|
190
|
-
'CallExpression': () => this.generateCallExpression(node),
|
|
191
|
-
'MemberExpression': () => this.generateMemberExpression(node),
|
|
192
|
-
'StaticMemberExpression': () => this.generateStaticMemberExpression(node),
|
|
193
|
-
'IndexExpression': () => this.generateIndexExpression(node),
|
|
194
|
-
'BinaryExpression': () => this.generateBinaryExpression(node),
|
|
195
|
-
'LogicalExpression': () => this.generateBinaryExpression(node),
|
|
196
|
-
'UnaryExpression': () => this.generateUnaryExpression(node),
|
|
197
|
-
'AssignmentExpression': () => this.generateAssignmentExpression(node),
|
|
198
|
-
'UpdateExpression': () => this.generateUpdateExpression(node),
|
|
199
|
-
'ConditionalExpression': () => this.generateConditionalExpression(node),
|
|
200
|
-
'NullCoalescing': () => this.generateNullCoalescing(node),
|
|
201
|
-
'ArrayExpression': () => this.generateArrayExpression(node),
|
|
202
|
-
'ObjectExpression': () => this.generateObjectExpression(node),
|
|
203
|
-
'ArrowFunction': () => this.generateArrowFunction(node),
|
|
204
|
-
'ArrowFunctionExpression': () => this.generateArrowFunction(node),
|
|
205
|
-
'FunctionExpression': () => this.generateFunctionExpression(node),
|
|
206
|
-
'Closure': () => this.generateClosure(node),
|
|
207
|
-
'Identifier': () => this.generateIdentifier(node),
|
|
208
|
-
'ThisExpression': () => '$this',
|
|
209
|
-
'Literal': () => this.generateLiteral(node),
|
|
210
|
-
'StringLiteral': () => this.generateLiteral(node),
|
|
211
|
-
'NumericLiteral': () => this.generateLiteral(node),
|
|
212
|
-
'BooleanLiteral': () => this.generateLiteral(node),
|
|
213
|
-
'NullLiteral': () => 'null',
|
|
214
|
-
'NewExpression': () => this.generateNewExpression(node),
|
|
215
|
-
'InstanceOf': () => this.generateInstanceOf(node),
|
|
216
|
-
'BlockStatement': () => this.generateBlockStatement(node),
|
|
217
|
-
'NamespaceDeclaration': () => this.generateNamespace(node),
|
|
218
|
-
'EmptyStatement': () => '',
|
|
219
|
-
'Comment': () => ''
|
|
457
|
+
generateDeclareStatement(node) {
|
|
458
|
+
const directives = []
|
|
459
|
+
if (node.strictTypes) {
|
|
460
|
+
directives.push('strict_types=1')
|
|
220
461
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
462
|
+
if (node.ticks) {
|
|
463
|
+
directives.push(`ticks=${node.ticks}`)
|
|
464
|
+
}
|
|
465
|
+
if (node.encoding) {
|
|
466
|
+
directives.push(`encoding='${node.encoding}'`)
|
|
224
467
|
}
|
|
468
|
+
if (directives.length > 0) {
|
|
469
|
+
this.writeLine(`declare(${directives.join(', ')});`)
|
|
470
|
+
}
|
|
471
|
+
return ''
|
|
472
|
+
}
|
|
225
473
|
|
|
226
|
-
|
|
227
|
-
|
|
474
|
+
generateNamespace(node) {
|
|
475
|
+
const name = node.name || node.path
|
|
476
|
+
this.writeLine(`namespace ${name};`)
|
|
477
|
+
this.writeLine('')
|
|
478
|
+
return ''
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
generateUseStatement(node) {
|
|
482
|
+
if (node.imports && node.imports.length > 0) {
|
|
483
|
+
for (const imp of node.imports) {
|
|
484
|
+
const name = imp.path || imp.name
|
|
485
|
+
const alias = imp.alias ? ` as ${imp.alias}` : ''
|
|
486
|
+
const useType = node.useType ? `${node.useType} ` : ''
|
|
487
|
+
this.writeLine(`use ${useType}${name}${alias};`)
|
|
488
|
+
}
|
|
489
|
+
} else {
|
|
490
|
+
const name = node.name || node.source
|
|
491
|
+
const alias = node.alias ? ` as ${node.alias}` : ''
|
|
492
|
+
const useType = node.useType ? `${node.useType} ` : ''
|
|
493
|
+
this.writeLine(`use ${useType}${name}${alias};`)
|
|
228
494
|
}
|
|
495
|
+
return ''
|
|
496
|
+
}
|
|
229
497
|
|
|
498
|
+
generateConstantDeclaration(node) {
|
|
499
|
+
const name = node.name || node.id?.name
|
|
500
|
+
const value = this.generateNode(node.value || node.init)
|
|
501
|
+
this.writeLine(`define('${name}', ${value});`)
|
|
230
502
|
return ''
|
|
231
503
|
}
|
|
232
504
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
505
|
+
generateVariableDeclaration(node) {
|
|
506
|
+
const declarations = node.declarations || [node]
|
|
507
|
+
|
|
508
|
+
for (const decl of declarations) {
|
|
509
|
+
const name = this.generateVariable(decl.id || decl)
|
|
510
|
+
if (decl.init) {
|
|
511
|
+
const init = this.generateNode(decl.init)
|
|
512
|
+
this.writeLine(`${name} = ${init};`)
|
|
513
|
+
}
|
|
236
514
|
}
|
|
515
|
+
return ''
|
|
237
516
|
}
|
|
238
517
|
|
|
239
518
|
generateFunctionDeclaration(node) {
|
|
240
|
-
const name = node.name || node.id?.name || '
|
|
241
|
-
const params =
|
|
242
|
-
|
|
519
|
+
const name = node.name || node.id?.name || ''
|
|
520
|
+
const params = (node.params || []).map(p => this.generateParam(p)).join(', ')
|
|
521
|
+
let returnType = ''
|
|
243
522
|
|
|
523
|
+
if (node.returnType) {
|
|
524
|
+
const type = this.extractTypeName(node.returnType)
|
|
525
|
+
if (type) returnType = ': ' + type
|
|
526
|
+
}
|
|
527
|
+
|
|
244
528
|
this.writeLine(`function ${name}(${params})${returnType} {`)
|
|
245
529
|
this.indent++
|
|
246
|
-
|
|
530
|
+
|
|
531
|
+
if (node.body) {
|
|
532
|
+
this.generateBody(node.body)
|
|
533
|
+
}
|
|
534
|
+
|
|
247
535
|
this.indent--
|
|
248
536
|
this.writeLine('}')
|
|
249
537
|
this.writeLine('')
|
|
538
|
+
return ''
|
|
250
539
|
}
|
|
251
540
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
let result = ''
|
|
255
|
-
|
|
256
|
-
if (p.visibility) {
|
|
257
|
-
result += this.translate(p.visibility) + ' '
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
if (p.typeHint) {
|
|
261
|
-
result += this.translateType(p.typeHint) + ' '
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
if (p.variadic) {
|
|
265
|
-
result += '...'
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
if (p.reference || p.byReference) {
|
|
269
|
-
result += '&'
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
const name = p.name || p.id?.name || p
|
|
273
|
-
result += '$' + (typeof name === 'string' ? name : name.name || 'param')
|
|
274
|
-
|
|
275
|
-
if (p.default !== undefined && p.default !== null) {
|
|
276
|
-
result += ' = ' + this.generateNode(p.default)
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
return result
|
|
280
|
-
}).join(', ')
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
translateType(type) {
|
|
284
|
-
if (!type) return ''
|
|
541
|
+
generateParam(param) {
|
|
542
|
+
let result = ''
|
|
285
543
|
|
|
286
|
-
if (
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
'booléen': 'bool', 'booleen': 'bool', 'boolean': 'bool', 'bool': 'bool',
|
|
293
|
-
'tableau': 'array', 'array': 'array',
|
|
294
|
-
'objet': 'object', 'object': 'object',
|
|
295
|
-
'nul': 'null', 'null': 'null',
|
|
296
|
-
'vide': 'void', 'void': 'void',
|
|
297
|
-
'mixte': 'mixed', 'mixed': 'mixed',
|
|
298
|
-
'appelable': 'callable', 'callable': 'callable',
|
|
299
|
-
'itérable': 'iterable', 'iterable': 'iterable',
|
|
300
|
-
'jamais': 'never', 'never': 'never'
|
|
544
|
+
if (param.typeHint || (param.type && param.type !== 'Parameter' && param.type !== 'Identifier')) {
|
|
545
|
+
const type = param.typeHint || param.type
|
|
546
|
+
if (typeof type === 'string' && type !== 'Parameter' && type !== 'Identifier') {
|
|
547
|
+
result += this.translateKeyword(type) + ' '
|
|
548
|
+
} else if (type && type.name) {
|
|
549
|
+
result += this.translateKeyword(type.name) + ' '
|
|
301
550
|
}
|
|
302
|
-
return typeMap[translated.toLowerCase()] || typeMap[type.toLowerCase()] || type
|
|
303
551
|
}
|
|
304
552
|
|
|
305
|
-
if (
|
|
306
|
-
|
|
307
|
-
if (type.union || type.types.length > 1) {
|
|
308
|
-
return prefix + type.types.map(t => this.translateType(t)).join('|')
|
|
309
|
-
}
|
|
310
|
-
return prefix + this.translateType(type.types[0])
|
|
553
|
+
if (param.reference) {
|
|
554
|
+
result += '&'
|
|
311
555
|
}
|
|
312
556
|
|
|
313
|
-
if (
|
|
314
|
-
|
|
557
|
+
if (param.variadic) {
|
|
558
|
+
result += '...'
|
|
315
559
|
}
|
|
316
560
|
|
|
317
|
-
|
|
318
|
-
return type.types.map(t => this.translateType(t)).join('&')
|
|
319
|
-
}
|
|
561
|
+
result += this.generateVariable(param)
|
|
320
562
|
|
|
321
|
-
if (
|
|
322
|
-
|
|
563
|
+
if (param.default !== undefined && param.default !== null) {
|
|
564
|
+
result += ' = ' + this.generateNode(param.default)
|
|
323
565
|
}
|
|
324
566
|
|
|
325
|
-
return
|
|
567
|
+
return result
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
generateBody(body) {
|
|
571
|
+
if (Array.isArray(body)) {
|
|
572
|
+
for (const stmt of body) {
|
|
573
|
+
this.generateNode(stmt)
|
|
574
|
+
}
|
|
575
|
+
} else if (body && body.body) {
|
|
576
|
+
for (const stmt of body.body) {
|
|
577
|
+
this.generateNode(stmt)
|
|
578
|
+
}
|
|
579
|
+
} else if (body) {
|
|
580
|
+
this.generateNode(body)
|
|
581
|
+
}
|
|
326
582
|
}
|
|
327
583
|
|
|
328
584
|
generateClassDeclaration(node) {
|
|
329
585
|
let declaration = ''
|
|
330
586
|
|
|
331
|
-
|
|
332
|
-
if (
|
|
333
|
-
if (
|
|
334
|
-
if (modifiers.includes('readonly') || node.readonly) declaration += 'readonly '
|
|
335
|
-
|
|
336
|
-
declaration += 'class ' + (node.name || node.id?.name)
|
|
587
|
+
if (node.abstract) declaration += 'abstract '
|
|
588
|
+
if (node.final) declaration += 'final '
|
|
589
|
+
if (node.readonly) declaration += 'readonly '
|
|
337
590
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
declaration += ' extends ' + (typeof node.extends === 'string' ? node.extends : node.extends.name)
|
|
591
|
+
declaration += 'class ' + (node.name || node.id?.name || '')
|
|
592
|
+
|
|
593
|
+
if (node.extends || node.superClass) {
|
|
594
|
+
declaration += ' extends ' + (node.extends || node.superClass)
|
|
343
595
|
}
|
|
344
|
-
|
|
345
|
-
if (node.
|
|
346
|
-
declaration += ' implements ' + node.
|
|
347
|
-
} else if (node.implements && node.implements.length > 0) {
|
|
348
|
-
declaration += ' implements ' + node.implements.map(i => typeof i === 'string' ? i : i.name).join(', ')
|
|
596
|
+
|
|
597
|
+
if (node.implements && node.implements.length > 0) {
|
|
598
|
+
declaration += ' implements ' + node.implements.join(', ')
|
|
349
599
|
}
|
|
350
|
-
|
|
600
|
+
|
|
351
601
|
this.writeLine(declaration + ' {')
|
|
352
602
|
this.indent++
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
603
|
+
|
|
604
|
+
const members = node.body?.body || node.members || node.body || []
|
|
605
|
+
for (const member of members) {
|
|
606
|
+
this.generateClassMember(member)
|
|
356
607
|
}
|
|
357
|
-
|
|
608
|
+
|
|
358
609
|
this.indent--
|
|
359
610
|
this.writeLine('}')
|
|
360
611
|
this.writeLine('')
|
|
612
|
+
return ''
|
|
361
613
|
}
|
|
362
614
|
|
|
363
|
-
|
|
364
|
-
|
|
615
|
+
generateClassMember(node) {
|
|
616
|
+
if (!node) return
|
|
617
|
+
|
|
618
|
+
if (node.type === 'UseTraitStatement') {
|
|
619
|
+
this.writeLine(`use ${node.traits.join(', ')};`)
|
|
620
|
+
return
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
const visibility = node.visibility || 'public'
|
|
624
|
+
const isStatic = node.static ? 'static ' : ''
|
|
625
|
+
const isReadonly = node.readonly ? 'readonly ' : ''
|
|
365
626
|
|
|
627
|
+
if (node.type === 'Property' || node.kind === 'property' || node.type === 'PropertyDeclaration') {
|
|
628
|
+
const name = '$' + (node.name || node.key?.name || node.id?.name || '')
|
|
629
|
+
let typeHint = ''
|
|
630
|
+
if (node.typeHint) {
|
|
631
|
+
typeHint = this.translateKeyword(node.typeHint) + ' '
|
|
632
|
+
}
|
|
633
|
+
const value = node.value ? ' = ' + this.generateNode(node.value) : ''
|
|
634
|
+
this.writeLine(`${visibility} ${isStatic}${isReadonly}${typeHint}${name}${value};`)
|
|
635
|
+
} else if (node.type === 'Method' || node.kind === 'method' || node.type === 'MethodDeclaration') {
|
|
636
|
+
const name = node.name || node.key?.name || ''
|
|
637
|
+
const translatedName = this.translateKeyword(name)
|
|
638
|
+
const params = (node.params || []).map(p => this.generateParam(p)).join(', ')
|
|
639
|
+
let returnType = ''
|
|
640
|
+
|
|
641
|
+
if (node.returnType) {
|
|
642
|
+
const type = this.extractTypeName(node.returnType)
|
|
643
|
+
if (type) returnType = ': ' + type
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
const abstractMod = node.abstract ? 'abstract ' : ''
|
|
647
|
+
|
|
648
|
+
if (node.abstract) {
|
|
649
|
+
this.writeLine(`${abstractMod}${visibility} ${isStatic}function ${translatedName}(${params})${returnType};`)
|
|
650
|
+
} else {
|
|
651
|
+
this.writeLine(`${visibility} ${isStatic}function ${translatedName}(${params})${returnType} {`)
|
|
652
|
+
this.indent++
|
|
653
|
+
|
|
654
|
+
if (node.body) {
|
|
655
|
+
this.generateBody(node.body)
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
this.indent--
|
|
659
|
+
this.writeLine('}')
|
|
660
|
+
}
|
|
661
|
+
this.writeLine('')
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
generateInterfaceDeclaration(node) {
|
|
666
|
+
let declaration = 'interface ' + (node.name || '')
|
|
667
|
+
|
|
366
668
|
if (node.extends && node.extends.length > 0) {
|
|
367
|
-
declaration += ' extends ' + node.extends.
|
|
669
|
+
declaration += ' extends ' + node.extends.join(', ')
|
|
368
670
|
}
|
|
369
|
-
|
|
671
|
+
|
|
370
672
|
this.writeLine(declaration + ' {')
|
|
371
673
|
this.indent++
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
674
|
+
|
|
675
|
+
const members = node.body?.body || node.members || node.body || []
|
|
676
|
+
for (const member of members) {
|
|
677
|
+
this.generateInterfaceMember(member)
|
|
375
678
|
}
|
|
376
|
-
|
|
679
|
+
|
|
377
680
|
this.indent--
|
|
378
681
|
this.writeLine('}')
|
|
379
682
|
this.writeLine('')
|
|
683
|
+
return ''
|
|
380
684
|
}
|
|
381
685
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
686
|
+
generateInterfaceMember(node) {
|
|
687
|
+
if (!node) return
|
|
688
|
+
|
|
689
|
+
const visibility = 'public'
|
|
690
|
+
const name = node.name || node.key?.name || ''
|
|
691
|
+
const translatedName = this.translateKeyword(name)
|
|
692
|
+
const params = (node.params || []).map(p => this.generateParam(p)).join(', ')
|
|
693
|
+
let returnType = ''
|
|
385
694
|
|
|
386
|
-
|
|
387
|
-
this.
|
|
695
|
+
if (node.returnType) {
|
|
696
|
+
const type = this.extractTypeName(node.returnType)
|
|
697
|
+
if (type) returnType = ': ' + type
|
|
388
698
|
}
|
|
389
699
|
|
|
390
|
-
this.
|
|
391
|
-
this.writeLine('}')
|
|
700
|
+
this.writeLine(`${visibility} function ${translatedName}(${params})${returnType};`)
|
|
392
701
|
this.writeLine('')
|
|
393
702
|
}
|
|
394
703
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
if (node.backingType) {
|
|
399
|
-
declaration += ': ' + this.translateType(node.backingType)
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
this.writeLine(declaration + ' {')
|
|
704
|
+
generateTraitDeclaration(node) {
|
|
705
|
+
this.writeLine('trait ' + (node.name || '') + ' {')
|
|
403
706
|
this.indent++
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
} else {
|
|
409
|
-
this.writeLine(`case ${member.name};`)
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
for (const method of node.methods || []) {
|
|
414
|
-
this.generateNode(method)
|
|
707
|
+
|
|
708
|
+
const members = node.body?.body || node.members || node.body || []
|
|
709
|
+
for (const member of members) {
|
|
710
|
+
this.generateClassMember(member)
|
|
415
711
|
}
|
|
416
|
-
|
|
712
|
+
|
|
417
713
|
this.indent--
|
|
418
714
|
this.writeLine('}')
|
|
419
715
|
this.writeLine('')
|
|
716
|
+
return ''
|
|
420
717
|
}
|
|
421
718
|
|
|
422
|
-
|
|
423
|
-
let declaration = ''
|
|
424
|
-
|
|
425
|
-
const visibility = node.visibility || node.access || 'public'
|
|
426
|
-
declaration += this.translate(visibility) + ' '
|
|
427
|
-
|
|
428
|
-
if (node.static) declaration += 'static '
|
|
429
|
-
if (node.final) declaration += 'final '
|
|
430
|
-
if (node.abstract) declaration += 'abstract '
|
|
431
|
-
|
|
432
|
-
const name = this.translateMethodName(node.name || node.key?.name)
|
|
433
|
-
const params = this.generateParams(node.params || node.value?.params || [])
|
|
434
|
-
const returnType = node.returnType ? ': ' + this.translateType(node.returnType) : ''
|
|
435
|
-
|
|
436
|
-
const body = node.body || node.value?.body
|
|
437
|
-
const hasEmptyBody = !body || (body.type === 'BlockStatement' && (!body.body || body.body.length === 0))
|
|
438
|
-
|
|
439
|
-
if (node.abstract || hasEmptyBody) {
|
|
440
|
-
this.writeLine(`${declaration}function ${name}(${params})${returnType};`)
|
|
441
|
-
} else {
|
|
442
|
-
this.writeLine(`${declaration}function ${name}(${params})${returnType} {`)
|
|
443
|
-
this.indent++
|
|
444
|
-
this.generateNode(body)
|
|
445
|
-
this.indent--
|
|
446
|
-
this.writeLine('}')
|
|
447
|
-
}
|
|
448
|
-
this.writeLine('')
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
translateMethodName(name) {
|
|
452
|
-
if (!name) return 'method'
|
|
719
|
+
generateEnumDeclaration(node) {
|
|
720
|
+
let declaration = 'enum ' + (node.name || '')
|
|
453
721
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
'
|
|
457
|
-
'destructeur': '__destruct',
|
|
458
|
-
'destructor': '__destruct',
|
|
459
|
-
'obtenir': '__get',
|
|
460
|
-
'get': '__get',
|
|
461
|
-
'définir': '__set',
|
|
462
|
-
'definir': '__set',
|
|
463
|
-
'set': '__set',
|
|
464
|
-
'appeler': '__call',
|
|
465
|
-
'call': '__call',
|
|
466
|
-
'appeler statique': '__callStatic',
|
|
467
|
-
'call static': '__callStatic',
|
|
468
|
-
'vers chaîne': '__toString',
|
|
469
|
-
'vers chaine': '__toString',
|
|
470
|
-
'to string': '__toString',
|
|
471
|
-
'invoquer': '__invoke',
|
|
472
|
-
'invoke': '__invoke',
|
|
473
|
-
'cloner': '__clone',
|
|
474
|
-
'clone': '__clone',
|
|
475
|
-
'dormir': '__sleep',
|
|
476
|
-
'sleep': '__sleep',
|
|
477
|
-
'réveiller': '__wakeup',
|
|
478
|
-
'reveiller': '__wakeup',
|
|
479
|
-
'wakeup': '__wakeup',
|
|
480
|
-
'sérialiser': '__serialize',
|
|
481
|
-
'serialiser': '__serialize',
|
|
482
|
-
'serialize': '__serialize',
|
|
483
|
-
'désérialiser': '__unserialize',
|
|
484
|
-
'deserialiser': '__unserialize',
|
|
485
|
-
'unserialize': '__unserialize',
|
|
486
|
-
'isset': '__isset',
|
|
487
|
-
'existe propriété': '__isset',
|
|
488
|
-
'existe propriete': '__isset',
|
|
489
|
-
'unset': '__unset',
|
|
490
|
-
'détruire propriété': '__unset',
|
|
491
|
-
'detruire propriete': '__unset',
|
|
492
|
-
'déboguer info': '__debugInfo',
|
|
493
|
-
'deboguer info': '__debugInfo',
|
|
494
|
-
'debug info': '__debugInfo'
|
|
722
|
+
if (node.backingType) {
|
|
723
|
+
const type = this.extractTypeName(node.backingType)
|
|
724
|
+
if (type) declaration += ': ' + type
|
|
495
725
|
}
|
|
496
|
-
|
|
497
|
-
const normalized = name.toLowerCase().trim()
|
|
498
|
-
return magicMethods[normalized] || name
|
|
499
|
-
}
|
|
500
726
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
const visibility = node.visibility || node.access || 'public'
|
|
505
|
-
declaration += this.translate(visibility) + ' '
|
|
506
|
-
|
|
507
|
-
if (node.static) declaration += 'static '
|
|
508
|
-
if (node.readonly) declaration += 'readonly '
|
|
509
|
-
|
|
510
|
-
if (node.typeHint) {
|
|
511
|
-
declaration += this.translateType(node.typeHint) + ' '
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
const name = node.name || node.key?.name
|
|
515
|
-
declaration += '$' + name
|
|
516
|
-
|
|
517
|
-
if (node.default !== undefined && node.default !== null) {
|
|
518
|
-
declaration += ' = ' + this.generateNode(node.default)
|
|
519
|
-
} else if (node.value !== undefined && node.value !== null) {
|
|
520
|
-
declaration += ' = ' + this.generateNode(node.value)
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
this.writeLine(declaration + ';')
|
|
524
|
-
}
|
|
727
|
+
this.writeLine(declaration + ' {')
|
|
728
|
+
this.indent++
|
|
525
729
|
|
|
526
|
-
|
|
527
|
-
for (const
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
if (decl.init !== undefined) {
|
|
532
|
-
const value = this.generateNode(decl.init)
|
|
533
|
-
this.writeLine(`${varName} = ${value};`)
|
|
730
|
+
const cases = node.cases || node.members || []
|
|
731
|
+
for (const caseNode of cases) {
|
|
732
|
+
if (caseNode.value !== undefined) {
|
|
733
|
+
this.writeLine(`case ${caseNode.name} = ${this.generateNode(caseNode.value)};`)
|
|
534
734
|
} else {
|
|
535
|
-
this.writeLine(
|
|
735
|
+
this.writeLine(`case ${caseNode.name};`)
|
|
536
736
|
}
|
|
537
737
|
}
|
|
538
|
-
}
|
|
539
738
|
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
if (node.classLevel) {
|
|
545
|
-
const visibility = node.visibility ? this.translate(node.visibility) + ' ' : ''
|
|
546
|
-
this.writeLine(`${visibility}const ${name.toUpperCase()} = ${value};`)
|
|
547
|
-
} else {
|
|
548
|
-
this.writeLine(`define('${name.toUpperCase()}', ${value});`)
|
|
549
|
-
}
|
|
739
|
+
this.indent--
|
|
740
|
+
this.writeLine('}')
|
|
741
|
+
this.writeLine('')
|
|
742
|
+
return ''
|
|
550
743
|
}
|
|
551
744
|
|
|
552
745
|
generateIfStatement(node) {
|
|
553
|
-
const test = this.generateNode(node.test
|
|
746
|
+
const test = this.generateNode(node.test)
|
|
554
747
|
this.writeLine(`if (${test}) {`)
|
|
555
748
|
this.indent++
|
|
556
|
-
this.
|
|
749
|
+
this.generateBody(node.consequent)
|
|
557
750
|
this.indent--
|
|
558
|
-
|
|
751
|
+
|
|
559
752
|
if (node.alternate) {
|
|
560
|
-
if (node.alternate.type === 'IfStatement'
|
|
561
|
-
this.
|
|
562
|
-
this.
|
|
753
|
+
if (node.alternate.type === 'IfStatement') {
|
|
754
|
+
const altTest = this.generateNode(node.alternate.test)
|
|
755
|
+
this.writeLine(`} elseif (${altTest}) {`)
|
|
756
|
+
this.indent++
|
|
757
|
+
this.generateBody(node.alternate.consequent)
|
|
758
|
+
this.indent--
|
|
759
|
+
if (node.alternate.alternate) {
|
|
760
|
+
this.generateElse(node.alternate.alternate)
|
|
761
|
+
} else {
|
|
762
|
+
this.writeLine('}')
|
|
763
|
+
}
|
|
563
764
|
} else {
|
|
564
765
|
this.writeLine('} else {')
|
|
565
766
|
this.indent++
|
|
566
|
-
this.
|
|
767
|
+
this.generateBody(node.alternate)
|
|
567
768
|
this.indent--
|
|
568
769
|
this.writeLine('}')
|
|
569
770
|
}
|
|
570
771
|
} else {
|
|
571
772
|
this.writeLine('}')
|
|
572
773
|
}
|
|
774
|
+
return ''
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
generateElse(node) {
|
|
778
|
+
if (node.type === 'IfStatement') {
|
|
779
|
+
const altTest = this.generateNode(node.test)
|
|
780
|
+
this.writeLine(`} elseif (${altTest}) {`)
|
|
781
|
+
this.indent++
|
|
782
|
+
this.generateBody(node.consequent)
|
|
783
|
+
this.indent--
|
|
784
|
+
if (node.alternate) {
|
|
785
|
+
this.generateElse(node.alternate)
|
|
786
|
+
} else {
|
|
787
|
+
this.writeLine('}')
|
|
788
|
+
}
|
|
789
|
+
} else {
|
|
790
|
+
this.writeLine('} else {')
|
|
791
|
+
this.indent++
|
|
792
|
+
this.generateBody(node)
|
|
793
|
+
this.indent--
|
|
794
|
+
this.writeLine('}')
|
|
795
|
+
}
|
|
573
796
|
}
|
|
574
797
|
|
|
575
798
|
generateForStatement(node) {
|
|
@@ -579,48 +802,43 @@ class PHPGenerator {
|
|
|
579
802
|
|
|
580
803
|
this.writeLine(`for (${init}; ${test}; ${update}) {`)
|
|
581
804
|
this.indent++
|
|
582
|
-
this.
|
|
805
|
+
this.generateBody(node.body)
|
|
583
806
|
this.indent--
|
|
584
807
|
this.writeLine('}')
|
|
808
|
+
return ''
|
|
585
809
|
}
|
|
586
810
|
|
|
587
811
|
generateForEachStatement(node) {
|
|
588
|
-
const array = this.generateNode(node.array || node.right
|
|
589
|
-
|
|
590
|
-
const
|
|
591
|
-
const value = typeof valueNode === 'string'
|
|
592
|
-
? '$' + valueNode
|
|
593
|
-
: this.generateIdentifier(valueNode)
|
|
594
|
-
|
|
595
|
-
let key = ''
|
|
596
|
-
const keyNode = node.key || node.keyVar
|
|
597
|
-
if (keyNode) {
|
|
598
|
-
key = (typeof keyNode === 'string' ? '$' + keyNode : this.generateIdentifier(keyNode)) + ' => '
|
|
599
|
-
}
|
|
812
|
+
const array = this.generateNode(node.array || node.right)
|
|
813
|
+
const value = this.generateVariable(node.value || node.left)
|
|
814
|
+
const key = node.key ? this.generateVariable(node.key) + ' => ' : ''
|
|
600
815
|
|
|
601
816
|
this.writeLine(`foreach (${array} as ${key}${value}) {`)
|
|
602
817
|
this.indent++
|
|
603
|
-
this.
|
|
818
|
+
this.generateBody(node.body)
|
|
604
819
|
this.indent--
|
|
605
820
|
this.writeLine('}')
|
|
821
|
+
return ''
|
|
606
822
|
}
|
|
607
823
|
|
|
608
824
|
generateWhileStatement(node) {
|
|
609
|
-
const test = this.generateNode(node.test
|
|
825
|
+
const test = this.generateNode(node.test)
|
|
610
826
|
this.writeLine(`while (${test}) {`)
|
|
611
827
|
this.indent++
|
|
612
|
-
this.
|
|
828
|
+
this.generateBody(node.body)
|
|
613
829
|
this.indent--
|
|
614
830
|
this.writeLine('}')
|
|
831
|
+
return ''
|
|
615
832
|
}
|
|
616
833
|
|
|
617
834
|
generateDoWhileStatement(node) {
|
|
618
835
|
this.writeLine('do {')
|
|
619
836
|
this.indent++
|
|
620
|
-
this.
|
|
837
|
+
this.generateBody(node.body)
|
|
621
838
|
this.indent--
|
|
622
|
-
const test = this.generateNode(node.test
|
|
839
|
+
const test = this.generateNode(node.test)
|
|
623
840
|
this.writeLine(`} while (${test});`)
|
|
841
|
+
return ''
|
|
624
842
|
}
|
|
625
843
|
|
|
626
844
|
generateSwitchStatement(node) {
|
|
@@ -644,56 +862,35 @@ class PHPGenerator {
|
|
|
644
862
|
|
|
645
863
|
this.indent--
|
|
646
864
|
this.writeLine('}')
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
generateMatchExpression(node) {
|
|
650
|
-
const subject = this.generateNode(node.subject || node.discriminant)
|
|
651
|
-
let result = `match (${subject}) {\n`
|
|
652
|
-
|
|
653
|
-
for (const arm of node.arms || node.cases || []) {
|
|
654
|
-
this.indent++
|
|
655
|
-
if (arm.conditions) {
|
|
656
|
-
const conditions = arm.conditions.map(c => this.generateNode(c)).join(', ')
|
|
657
|
-
result += this.getIndent() + `${conditions} => ${this.generateNode(arm.body)},\n`
|
|
658
|
-
} else if (arm.default) {
|
|
659
|
-
result += this.getIndent() + `default => ${this.generateNode(arm.body)},\n`
|
|
660
|
-
}
|
|
661
|
-
this.indent--
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
result += this.getIndent() + '}'
|
|
665
|
-
return result
|
|
865
|
+
return ''
|
|
666
866
|
}
|
|
667
867
|
|
|
668
868
|
generateTryStatement(node) {
|
|
669
869
|
this.writeLine('try {')
|
|
670
870
|
this.indent++
|
|
671
|
-
this.
|
|
871
|
+
this.generateBody(node.block)
|
|
672
872
|
this.indent--
|
|
673
873
|
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
const
|
|
677
|
-
? handler.
|
|
678
|
-
: (handler.type || 'Exception')
|
|
679
|
-
const param = handler.param
|
|
680
|
-
? (typeof handler.param === 'string' ? '$' + handler.param : this.generateIdentifier(handler.param))
|
|
874
|
+
if (node.handler) {
|
|
875
|
+
const exceptionType = node.handler.exceptionType || node.handler.type || 'Exception'
|
|
876
|
+
const param = node.handler.param
|
|
877
|
+
? this.generateVariable(node.handler.param)
|
|
681
878
|
: '$e'
|
|
682
|
-
this.writeLine(`} catch (${
|
|
879
|
+
this.writeLine(`} catch (${exceptionType} ${param}) {`)
|
|
683
880
|
this.indent++
|
|
684
|
-
this.
|
|
881
|
+
this.generateBody(node.handler.body)
|
|
685
882
|
this.indent--
|
|
686
883
|
}
|
|
687
884
|
|
|
688
|
-
|
|
689
|
-
if (finallyBlock) {
|
|
885
|
+
if (node.finalizer) {
|
|
690
886
|
this.writeLine('} finally {')
|
|
691
887
|
this.indent++
|
|
692
|
-
this.
|
|
888
|
+
this.generateBody(node.finalizer)
|
|
693
889
|
this.indent--
|
|
694
890
|
}
|
|
695
891
|
|
|
696
892
|
this.writeLine('}')
|
|
893
|
+
return ''
|
|
697
894
|
}
|
|
698
895
|
|
|
699
896
|
generateReturnStatement(node) {
|
|
@@ -703,80 +900,34 @@ class PHPGenerator {
|
|
|
703
900
|
} else {
|
|
704
901
|
this.writeLine('return;')
|
|
705
902
|
}
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
generateYieldExpression(node) {
|
|
709
|
-
const arg = node.argument ? this.generateNode(node.argument) : ''
|
|
710
|
-
if (node.delegate) {
|
|
711
|
-
return `yield from ${arg}`
|
|
712
|
-
}
|
|
713
|
-
return `yield ${arg}`
|
|
903
|
+
return ''
|
|
714
904
|
}
|
|
715
905
|
|
|
716
906
|
generateThrowStatement(node) {
|
|
717
907
|
const arg = this.generateNode(node.argument)
|
|
718
908
|
this.writeLine(`throw ${arg};`)
|
|
909
|
+
return ''
|
|
719
910
|
}
|
|
720
911
|
|
|
721
912
|
generateExpressionStatement(node) {
|
|
722
913
|
const expr = this.generateNode(node.expression)
|
|
723
|
-
|
|
914
|
+
if (expr) {
|
|
915
|
+
this.writeLine(`${expr};`)
|
|
916
|
+
}
|
|
917
|
+
return ''
|
|
724
918
|
}
|
|
725
919
|
|
|
726
920
|
generateEchoStatement(node) {
|
|
727
|
-
const
|
|
728
|
-
const args = exprs.filter(Boolean).map(a => this.generateNode(a)).join(', ')
|
|
921
|
+
const args = (node.expressions || node.arguments || [node.argument]).filter(Boolean).map(a => this.generateNode(a)).join(', ')
|
|
729
922
|
this.writeLine(`echo ${args};`)
|
|
923
|
+
return ''
|
|
730
924
|
}
|
|
731
925
|
|
|
732
|
-
|
|
733
|
-
const
|
|
734
|
-
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
generateNamespace(node) {
|
|
738
|
-
this.writeLine(`namespace ${node.name};`)
|
|
739
|
-
this.writeLine('')
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
generateUseStatement(node) {
|
|
743
|
-
const typePrefix = node.useType === 'function' ? 'function ' : (node.useType === 'const' ? 'const ' : '')
|
|
744
|
-
|
|
745
|
-
if (node.imports && node.imports.length > 0) {
|
|
746
|
-
for (const imp of node.imports) {
|
|
747
|
-
const path = imp.path || imp.name || imp
|
|
748
|
-
const alias = imp.alias ? ' as ' + imp.alias : ''
|
|
749
|
-
this.writeLine(`use ${typePrefix}${path}${alias};`)
|
|
750
|
-
}
|
|
751
|
-
} else {
|
|
752
|
-
const name = node.name || node.source || 'undefined'
|
|
753
|
-
const alias = node.alias ? ' as ' + node.alias : ''
|
|
754
|
-
this.writeLine(`use ${typePrefix}${name}${alias};`)
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
generateDeclareStatement(node) {
|
|
759
|
-
const directives = (node.directives || []).map(d => {
|
|
760
|
-
const value = typeof d.value === 'object' ? this.generateNode(d.value) : d.value
|
|
761
|
-
return `${d.name}=${value}`
|
|
762
|
-
}).join(', ')
|
|
763
|
-
this.writeLine(`declare(${directives});`)
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
generateIncludeStatement(node) {
|
|
767
|
-
const type = node.once
|
|
768
|
-
? (node.required ? 'require_once' : 'include_once')
|
|
769
|
-
: (node.required ? 'require' : 'include')
|
|
770
|
-
const path = typeof node.path === 'string' ? `'${node.path}'` : this.generateNode(node.path)
|
|
771
|
-
this.writeLine(`${type} ${path};`)
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
generateInclude(node) {
|
|
775
|
-
if (node.resolved && node.children) {
|
|
776
|
-
for (const child of node.children) {
|
|
777
|
-
this.generateNode(child)
|
|
778
|
-
}
|
|
926
|
+
generateBlockStatement(node) {
|
|
927
|
+
for (const stmt of node.body || []) {
|
|
928
|
+
this.generateNode(stmt)
|
|
779
929
|
}
|
|
930
|
+
return ''
|
|
780
931
|
}
|
|
781
932
|
|
|
782
933
|
generateCallExpression(node) {
|
|
@@ -784,34 +935,15 @@ class PHPGenerator {
|
|
|
784
935
|
|
|
785
936
|
if (typeof node.callee === 'string') {
|
|
786
937
|
callee = this.translateFunction(node.callee)
|
|
787
|
-
} else if (node.callee.type === 'MemberExpression') {
|
|
788
|
-
callee = this.generateMemberExpression(node.callee)
|
|
789
|
-
} else if (node.callee.type === 'StaticMemberExpression') {
|
|
790
|
-
callee = this.generateStaticMemberExpression(node.callee)
|
|
791
938
|
} else if (node.callee.type === 'Identifier') {
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
callee = translated
|
|
796
|
-
} else if (name.includes(' ')) {
|
|
797
|
-
callee = name.replace(/ /g, '_')
|
|
798
|
-
} else {
|
|
799
|
-
callee = name
|
|
800
|
-
}
|
|
939
|
+
callee = this.translateFunction(node.callee.name)
|
|
940
|
+
} else if (node.callee.type === 'MemberExpression' || node.callee.type === 'StaticMemberExpression') {
|
|
941
|
+
callee = this.generateNode(node.callee)
|
|
801
942
|
} else {
|
|
802
943
|
callee = this.generateNode(node.callee)
|
|
803
944
|
}
|
|
804
945
|
|
|
805
|
-
const args = (node.arguments || []).map(a =>
|
|
806
|
-
if (a.spread) {
|
|
807
|
-
return '...' + this.generateNode(a.argument || a)
|
|
808
|
-
}
|
|
809
|
-
if (a.name && a.value) {
|
|
810
|
-
return `${a.name}: ${this.generateNode(a.value)}`
|
|
811
|
-
}
|
|
812
|
-
return this.generateNode(a)
|
|
813
|
-
}).join(', ')
|
|
814
|
-
|
|
946
|
+
const args = (node.arguments || []).map(a => this.generateNode(a)).join(', ')
|
|
815
947
|
return `${callee}(${args})`
|
|
816
948
|
}
|
|
817
949
|
|
|
@@ -822,53 +954,24 @@ class PHPGenerator {
|
|
|
822
954
|
if (typeof node.property === 'string') {
|
|
823
955
|
property = node.property
|
|
824
956
|
} else if (node.property.type === 'Identifier') {
|
|
825
|
-
|
|
826
|
-
let translated = this.translateFunction(propName)
|
|
827
|
-
if (translated.includes('->')) {
|
|
828
|
-
translated = translated.split('->').pop()
|
|
829
|
-
} else if (translated.includes('::')) {
|
|
830
|
-
translated = translated.split('::').pop()
|
|
831
|
-
} else if (translated !== propName && !translated.includes('(')) {
|
|
832
|
-
translated = propName
|
|
833
|
-
}
|
|
834
|
-
property = translated
|
|
957
|
+
property = this.translateFunction(node.property.name)
|
|
835
958
|
} else {
|
|
836
959
|
property = this.generateNode(node.property)
|
|
837
960
|
}
|
|
838
961
|
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
}
|
|
962
|
+
const operator = node.nullsafe ? '?->' : '->'
|
|
963
|
+
|
|
842
964
|
if (node.computed) {
|
|
843
965
|
return `${object}[${property}]`
|
|
844
966
|
}
|
|
845
|
-
|
|
846
|
-
return `${object}?->${property}`
|
|
847
|
-
}
|
|
848
|
-
return `${object}->${property}`
|
|
967
|
+
return `${object}${operator}${property}`
|
|
849
968
|
}
|
|
850
969
|
|
|
851
970
|
generateStaticMemberExpression(node) {
|
|
852
|
-
const
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
let memberName
|
|
857
|
-
if (typeof memberNode === 'string') {
|
|
858
|
-
memberName = memberNode
|
|
859
|
-
} else if (memberNode.type === 'Identifier') {
|
|
860
|
-
memberName = this.translateMethodName(memberNode.name)
|
|
861
|
-
} else {
|
|
862
|
-
memberName = this.generateNode(memberNode)
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
return `${className}::${memberName}`
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
generateIndexExpression(node) {
|
|
869
|
-
const object = this.generateNode(node.object)
|
|
870
|
-
const index = this.generateNode(node.index)
|
|
871
|
-
return `${object}[${index}]`
|
|
971
|
+
const cls = node.class?.name || this.generateNode(node.class)
|
|
972
|
+
let member = node.member?.name || this.generateNode(node.member)
|
|
973
|
+
member = this.translateKeyword(member)
|
|
974
|
+
return `${cls}::${member}`
|
|
872
975
|
}
|
|
873
976
|
|
|
874
977
|
generateBinaryExpression(node) {
|
|
@@ -877,47 +980,41 @@ class PHPGenerator {
|
|
|
877
980
|
let op = node.operator
|
|
878
981
|
|
|
879
982
|
const opMap = {
|
|
880
|
-
'et': '&&',
|
|
881
|
-
'ou': '||',
|
|
882
|
-
'
|
|
883
|
-
'
|
|
884
|
-
'différent': '!==', 'different': '!==', 'not equal': '!==',
|
|
885
|
-
'concaténer': '.', 'concatener': '.', 'concatenate': '.',
|
|
886
|
-
'vaisseau spatial': '<=>', 'spaceship': '<=>',
|
|
887
|
-
'fusion null': '??', 'null coalescing': '??'
|
|
983
|
+
'et': '&&',
|
|
984
|
+
'ou': '||',
|
|
985
|
+
'concatener': '.',
|
|
986
|
+
'concat': '.'
|
|
888
987
|
}
|
|
889
|
-
|
|
890
|
-
op = opMap[op?.toLowerCase()] || op
|
|
988
|
+
op = opMap[this.normalizeAccents(op)] || op
|
|
891
989
|
|
|
892
|
-
|
|
893
|
-
|
|
990
|
+
return `${left} ${op} ${right}`
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
generateAssignmentExpression(node) {
|
|
994
|
+
const left = this.generateNode(node.left)
|
|
995
|
+
const right = this.generateNode(node.right)
|
|
996
|
+
const op = node.operator || '='
|
|
997
|
+
return `${left} ${op} ${right}`
|
|
894
998
|
}
|
|
895
999
|
|
|
896
1000
|
generateUnaryExpression(node) {
|
|
897
|
-
const
|
|
898
|
-
const op = node.operator === 'non'
|
|
1001
|
+
const operand = this.generateNode(node.operand || node.argument)
|
|
1002
|
+
const op = node.operator === 'non' ? '!' : node.operator
|
|
899
1003
|
|
|
900
1004
|
if (node.prefix !== false) {
|
|
901
|
-
return `${op}${
|
|
1005
|
+
return `${op}${operand}`
|
|
902
1006
|
}
|
|
903
|
-
return `${
|
|
1007
|
+
return `${operand}${op}`
|
|
904
1008
|
}
|
|
905
1009
|
|
|
906
1010
|
generateUpdateExpression(node) {
|
|
907
|
-
const
|
|
1011
|
+
const operand = this.generateNode(node.operand || node.argument)
|
|
908
1012
|
const op = node.operator
|
|
909
1013
|
|
|
910
1014
|
if (node.prefix) {
|
|
911
|
-
return `${op}${
|
|
1015
|
+
return `${op}${operand}`
|
|
912
1016
|
}
|
|
913
|
-
return `${
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
generateAssignmentExpression(node) {
|
|
917
|
-
const left = this.generateNode(node.left)
|
|
918
|
-
const right = this.generateNode(node.right)
|
|
919
|
-
const op = node.operator || '='
|
|
920
|
-
return `${left} ${op} ${right}`
|
|
1017
|
+
return `${operand}${op}`
|
|
921
1018
|
}
|
|
922
1019
|
|
|
923
1020
|
generateConditionalExpression(node) {
|
|
@@ -927,31 +1024,24 @@ class PHPGenerator {
|
|
|
927
1024
|
return `${test} ? ${consequent} : ${alternate}`
|
|
928
1025
|
}
|
|
929
1026
|
|
|
930
|
-
generateNullCoalescing(node) {
|
|
931
|
-
const left = this.generateNode(node.left)
|
|
932
|
-
const right = this.generateNode(node.right)
|
|
933
|
-
return `${left} ?? ${right}`
|
|
934
|
-
}
|
|
935
|
-
|
|
936
1027
|
generateArrayExpression(node) {
|
|
937
1028
|
const elements = (node.elements || []).map(e => {
|
|
938
|
-
if (!e) return 'null'
|
|
939
1029
|
if (e.type === 'ArrayElement') {
|
|
940
|
-
if (e.key
|
|
1030
|
+
if (e.key) {
|
|
941
1031
|
const key = this.generateNode(e.key)
|
|
942
1032
|
const value = this.generateNode(e.value)
|
|
943
1033
|
return `${key} => ${value}`
|
|
944
1034
|
}
|
|
945
1035
|
return this.generateNode(e.value)
|
|
946
1036
|
}
|
|
947
|
-
if (e.
|
|
1037
|
+
if (e.type === 'SpreadElement') {
|
|
1038
|
+
return '...' + this.generateNode(e.argument)
|
|
1039
|
+
}
|
|
1040
|
+
if (e.key) {
|
|
948
1041
|
const key = this.generateNode(e.key)
|
|
949
1042
|
const value = this.generateNode(e.value || e)
|
|
950
1043
|
return `${key} => ${value}`
|
|
951
1044
|
}
|
|
952
|
-
if (e.spread) {
|
|
953
|
-
return '...' + this.generateNode(e.argument || e)
|
|
954
|
-
}
|
|
955
1045
|
return this.generateNode(e)
|
|
956
1046
|
})
|
|
957
1047
|
|
|
@@ -966,112 +1056,44 @@ class PHPGenerator {
|
|
|
966
1056
|
return this.generateArrayExpression(node)
|
|
967
1057
|
}
|
|
968
1058
|
|
|
969
|
-
|
|
970
|
-
const
|
|
971
|
-
|
|
972
|
-
return `fn(${params}) => ${body}`
|
|
973
|
-
}
|
|
974
|
-
|
|
975
|
-
generateFunctionExpression(node) {
|
|
976
|
-
const params = this.generateParams(node.params || [])
|
|
977
|
-
const uses = node.uses || node.use || []
|
|
978
|
-
const useVars = uses.length > 0
|
|
979
|
-
? ` use (${uses.map(u => (u.byReference || u.byRef ? '&' : '') + '$' + (u.name || u)).join(', ')})`
|
|
980
|
-
: ''
|
|
981
|
-
const returnType = node.returnType ? ': ' + this.translateType(node.returnType) : ''
|
|
982
|
-
|
|
983
|
-
let result = `function(${params})${useVars}${returnType} {\n`
|
|
1059
|
+
generateIdentifier(node) {
|
|
1060
|
+
const name = node.name || node
|
|
1061
|
+
if (typeof name !== 'string') return '$var'
|
|
984
1062
|
|
|
985
|
-
const
|
|
986
|
-
const savedIndent = this.indent
|
|
987
|
-
this.output = ''
|
|
988
|
-
this.indent++
|
|
1063
|
+
const normalized = this.normalizeAccents(name)
|
|
989
1064
|
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
for (const stmt of body.body) {
|
|
993
|
-
this.generateNode(stmt)
|
|
994
|
-
}
|
|
995
|
-
} else if (body) {
|
|
996
|
-
this.writeLine('return ' + this.generateNode(body) + ';')
|
|
1065
|
+
if (this.functionMap[normalized]) {
|
|
1066
|
+
return this.functionMap[normalized]
|
|
997
1067
|
}
|
|
998
1068
|
|
|
999
|
-
const
|
|
1000
|
-
this.output = savedOutput
|
|
1001
|
-
this.indent = savedIndent
|
|
1002
|
-
|
|
1003
|
-
result += bodyOutput
|
|
1004
|
-
result += this.getIndent() + '}'
|
|
1005
|
-
return result
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
generateClosure(node) {
|
|
1009
|
-
const params = this.generateParams(node.params || [])
|
|
1010
|
-
const useVars = node.use && node.use.length > 0
|
|
1011
|
-
? ` use (${node.use.map(u => (u.byRef ? '&' : '') + '$' + this.translate(u.name || u)).join(', ')})`
|
|
1012
|
-
: ''
|
|
1013
|
-
const returnType = node.returnType ? ': ' + this.translateType(node.returnType) : ''
|
|
1014
|
-
|
|
1015
|
-
let result = `function(${params})${useVars}${returnType} {\n`
|
|
1016
|
-
this.indent++
|
|
1069
|
+
const translated = this.translateKeyword(name)
|
|
1017
1070
|
|
|
1018
|
-
if (
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1071
|
+
if (translated.startsWith('$')) return translated
|
|
1072
|
+
if (['true', 'false', 'null', 'self', 'parent', 'static'].includes(translated)) {
|
|
1073
|
+
return translated
|
|
1074
|
+
}
|
|
1075
|
+
if (/^[A-Z]/.test(translated)) return translated
|
|
1076
|
+
if (translated === name && !name.startsWith('$')) {
|
|
1077
|
+
return '$' + name
|
|
1024
1078
|
}
|
|
1025
1079
|
|
|
1026
|
-
|
|
1027
|
-
result += this.getIndent() + '}'
|
|
1028
|
-
return result
|
|
1080
|
+
return translated.startsWith('$') ? translated : '$' + translated
|
|
1029
1081
|
}
|
|
1030
1082
|
|
|
1031
|
-
|
|
1083
|
+
generateVariable(node) {
|
|
1084
|
+
if (!node) return '$var'
|
|
1085
|
+
|
|
1032
1086
|
const name = node.name || node.id?.name || node
|
|
1033
1087
|
if (typeof name !== 'string') return '$var'
|
|
1034
1088
|
|
|
1035
|
-
const keywords = [
|
|
1036
|
-
'true', 'false', 'null',
|
|
1037
|
-
'self', 'parent', 'static',
|
|
1038
|
-
'this', '$this', 'vrai', 'faux', 'nul', 'ceci'
|
|
1039
|
-
]
|
|
1040
|
-
const lowerName = name.toLowerCase()
|
|
1041
|
-
|
|
1042
|
-
if (lowerName === 'vrai') return 'true'
|
|
1043
|
-
if (lowerName === 'faux') return 'false'
|
|
1044
|
-
if (lowerName === 'nul') return 'null'
|
|
1045
|
-
if (lowerName === 'ceci' || lowerName === 'this') return '$this'
|
|
1046
|
-
|
|
1047
|
-
if (keywords.includes(lowerName)) {
|
|
1048
|
-
return name
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
1089
|
if (name.startsWith('$')) return name
|
|
1052
|
-
|
|
1053
|
-
if (/^[A-Z]/.test(name)) return name
|
|
1054
|
-
|
|
1055
|
-
if (name.includes('(') || name.includes('::') || name.includes('->')) return name
|
|
1056
|
-
|
|
1057
|
-
const superglobals = ['_GET', '_POST', '_SERVER', '_SESSION', '_COOKIE', '_FILES', '_REQUEST', '_ENV', 'GLOBALS']
|
|
1058
|
-
if (superglobals.includes(name) || superglobals.includes(name.toUpperCase())) {
|
|
1059
|
-
return '$' + name.toUpperCase()
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
1090
|
return '$' + name
|
|
1063
1091
|
}
|
|
1064
1092
|
|
|
1065
1093
|
generateLiteral(node) {
|
|
1066
|
-
if (node.raw
|
|
1094
|
+
if (node.raw) return node.raw
|
|
1067
1095
|
if (typeof node.value === 'string') {
|
|
1068
|
-
|
|
1069
|
-
.replace(/\\/g, '\\\\')
|
|
1070
|
-
.replace(/"/g, '\\"')
|
|
1071
|
-
.replace(/\n/g, '\\n')
|
|
1072
|
-
.replace(/\r/g, '\\r')
|
|
1073
|
-
.replace(/\t/g, '\\t')
|
|
1074
|
-
return `"${escaped}"`
|
|
1096
|
+
return `"${node.value.replace(/"/g, '\\"')}"`
|
|
1075
1097
|
}
|
|
1076
1098
|
if (node.value === null) return 'null'
|
|
1077
1099
|
if (node.value === true) return 'true'
|
|
@@ -1079,28 +1101,83 @@ class PHPGenerator {
|
|
|
1079
1101
|
return String(node.value)
|
|
1080
1102
|
}
|
|
1081
1103
|
|
|
1104
|
+
generateStringLiteral(node) {
|
|
1105
|
+
const quote = node.doubleQuoted ? '"' : "'"
|
|
1106
|
+
const value = node.value.replace(new RegExp(quote, 'g'), '\\' + quote)
|
|
1107
|
+
return `${quote}${value}${quote}`
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1082
1110
|
generateNewExpression(node) {
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1111
|
+
let callee
|
|
1112
|
+
if (typeof node.callee === 'string') {
|
|
1113
|
+
callee = node.callee
|
|
1114
|
+
} else if (node.callee.type === 'Identifier') {
|
|
1115
|
+
callee = node.callee.name
|
|
1116
|
+
} else {
|
|
1117
|
+
callee = this.generateNode(node.callee)
|
|
1118
|
+
}
|
|
1086
1119
|
const args = (node.arguments || []).map(a => this.generateNode(a)).join(', ')
|
|
1087
1120
|
return `new ${callee}(${args})`
|
|
1088
1121
|
}
|
|
1089
1122
|
|
|
1090
|
-
|
|
1123
|
+
generateFunctionExpression(node) {
|
|
1124
|
+
const params = (node.params || []).map(p => this.generateParam(p)).join(', ')
|
|
1125
|
+
|
|
1126
|
+
let uses = ''
|
|
1127
|
+
if (node.uses && node.uses.length > 0) {
|
|
1128
|
+
const useVars = node.uses.map(u => {
|
|
1129
|
+
const ref = u.byRef ? '&' : ''
|
|
1130
|
+
return ref + this.generateVariable(u)
|
|
1131
|
+
}).join(', ')
|
|
1132
|
+
uses = ` use (${useVars})`
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
let returnType = ''
|
|
1136
|
+
if (node.returnType) {
|
|
1137
|
+
returnType = ': ' + this.translateKeyword(node.returnType)
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
let body = ''
|
|
1141
|
+
if (node.body) {
|
|
1142
|
+
const savedOutput = this.output
|
|
1143
|
+
const savedIndent = this.indent
|
|
1144
|
+
this.output = ''
|
|
1145
|
+
this.indent = 0
|
|
1146
|
+
this.generateBody(node.body)
|
|
1147
|
+
body = this.output
|
|
1148
|
+
this.output = savedOutput
|
|
1149
|
+
this.indent = savedIndent
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
return `function(${params})${uses}${returnType} {\n${body}}`
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
generateArrowFunctionExpression(node) {
|
|
1156
|
+
const params = (node.params || []).map(p => this.generateParam(p)).join(', ')
|
|
1157
|
+
const body = this.generateNode(node.body)
|
|
1158
|
+
return `fn(${params}) => ${body}`
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
generateIndexExpression(node) {
|
|
1162
|
+
const object = this.generateNode(node.object)
|
|
1163
|
+
const index = node.index ? this.generateNode(node.index) : ''
|
|
1164
|
+
return `${object}[${index}]`
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
generateNullCoalesceExpression(node) {
|
|
1091
1168
|
const left = this.generateNode(node.left)
|
|
1092
1169
|
const right = this.generateNode(node.right)
|
|
1093
|
-
return `${left}
|
|
1170
|
+
return `${left} ?? ${right}`
|
|
1094
1171
|
}
|
|
1095
1172
|
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
this.generateNode(
|
|
1173
|
+
generateYieldExpression(node) {
|
|
1174
|
+
if (node.delegate) {
|
|
1175
|
+
return `yield from ${this.generateNode(node.argument)}`
|
|
1099
1176
|
}
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1177
|
+
if (node.argument) {
|
|
1178
|
+
return `yield ${this.generateNode(node.argument)}`
|
|
1179
|
+
}
|
|
1180
|
+
return 'yield'
|
|
1104
1181
|
}
|
|
1105
1182
|
|
|
1106
1183
|
writeLine(text) {
|
|
@@ -1112,4 +1189,6 @@ class PHPGenerator {
|
|
|
1112
1189
|
}
|
|
1113
1190
|
}
|
|
1114
1191
|
|
|
1115
|
-
module.exports = {
|
|
1192
|
+
module.exports = {
|
|
1193
|
+
PHPGenerator
|
|
1194
|
+
}
|