ether-code 0.9.0 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/ether.js +1 -1
- package/generators/php-generator.js +788 -722
- package/i18n/i18n-php.json +8 -0
- package/lexer/ether-lexer.js +401 -392
- package/package.json +1 -1
- package/parsers/ether-parser-php.js +303 -316
|
@@ -5,361 +5,565 @@ class PHPGenerator {
|
|
|
5
5
|
this.i18n = null
|
|
6
6
|
this.indent = 0
|
|
7
7
|
this.output = ''
|
|
8
|
-
this.translationMap = {}
|
|
9
|
-
this.supportedLanguages = ['fr', 'en', 'es', 'ru', 'zh', 'ja']
|
|
10
8
|
|
|
11
9
|
if (i18nPath) {
|
|
12
10
|
this.loadI18n(i18nPath)
|
|
13
11
|
}
|
|
12
|
+
|
|
13
|
+
this.buildFunctionMap()
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
loadI18n(filePath) {
|
|
17
17
|
const content = fs.readFileSync(filePath, 'utf-8')
|
|
18
18
|
this.i18n = JSON.parse(content)
|
|
19
|
-
this.buildTranslationMap()
|
|
20
19
|
}
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
normalizeAccents(str) {
|
|
22
|
+
if (typeof str !== 'string') return String(str)
|
|
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'
|
|
202
|
+
}
|
|
26
203
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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'
|
|
45
287
|
}
|
|
46
288
|
}
|
|
47
289
|
|
|
48
|
-
|
|
49
|
-
if (
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const bytes = new Uint8Array(str.length)
|
|
53
|
-
for (let i = 0; i < str.length; i++) {
|
|
54
|
-
bytes[i] = str.charCodeAt(i)
|
|
55
|
-
}
|
|
56
|
-
const decoder = new TextDecoder('utf-8')
|
|
57
|
-
return decoder.decode(bytes)
|
|
58
|
-
} catch (e) {
|
|
59
|
-
return str
|
|
60
|
-
}
|
|
290
|
+
translate(word) {
|
|
291
|
+
if (!word) return word
|
|
292
|
+
const normalized = this.normalizeAccents(word)
|
|
293
|
+
return this.functionMap[normalized] || this.keywordMap[normalized] || word
|
|
61
294
|
}
|
|
62
295
|
|
|
63
|
-
|
|
64
|
-
if (
|
|
65
|
-
|
|
66
|
-
return
|
|
296
|
+
translateFunction(word) {
|
|
297
|
+
if (!word) return word
|
|
298
|
+
const normalized = this.normalizeAccents(word)
|
|
299
|
+
return this.functionMap[normalized] || word
|
|
67
300
|
}
|
|
68
301
|
|
|
69
|
-
|
|
302
|
+
translateKeyword(word) {
|
|
70
303
|
if (!word) return word
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const normalized = word.toLowerCase().trim()
|
|
74
|
-
|
|
75
|
-
if (this.translationMap[normalized]) {
|
|
76
|
-
return this.translationMap[normalized]
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const withoutAccents = this.removeAccents(normalized)
|
|
80
|
-
if (this.translationMap[withoutAccents]) {
|
|
81
|
-
return this.translationMap[withoutAccents]
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (normalized.includes(' ')) {
|
|
85
|
-
const words = normalized.split(' ')
|
|
86
|
-
|
|
87
|
-
for (let i = words.length - 1; i >= 1; i--) {
|
|
88
|
-
const partial = words.slice(0, i + 1).join(' ')
|
|
89
|
-
if (this.translationMap[partial]) {
|
|
90
|
-
return this.translationMap[partial]
|
|
91
|
-
}
|
|
92
|
-
const partialNoAccent = this.removeAccents(partial)
|
|
93
|
-
if (this.translationMap[partialNoAccent]) {
|
|
94
|
-
return this.translationMap[partialNoAccent]
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const firstWord = words[0]
|
|
99
|
-
if (this.translationMap[firstWord]) {
|
|
100
|
-
const result = this.translationMap[firstWord]
|
|
101
|
-
if (!result.startsWith('__') && !result.startsWith('$')) {
|
|
102
|
-
return result
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
const firstWordNoAccent = this.removeAccents(firstWord)
|
|
106
|
-
if (this.translationMap[firstWordNoAccent]) {
|
|
107
|
-
const result = this.translationMap[firstWordNoAccent]
|
|
108
|
-
if (!result.startsWith('__') && !result.startsWith('$')) {
|
|
109
|
-
return result
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return word
|
|
304
|
+
const normalized = this.normalizeAccents(word)
|
|
305
|
+
return this.keywordMap[normalized] || word
|
|
115
306
|
}
|
|
116
307
|
|
|
117
|
-
|
|
118
|
-
if (
|
|
119
|
-
|
|
308
|
+
extractTypeName(typeNode) {
|
|
309
|
+
if (!typeNode) return ''
|
|
310
|
+
if (typeof typeNode === 'string') return this.translateKeyword(typeNode)
|
|
311
|
+
if (typeNode.name) return this.translateKeyword(typeNode.name)
|
|
312
|
+
if (typeNode.type === 'Identifier') return this.translateKeyword(typeNode.name || typeNode.value || '')
|
|
313
|
+
if (typeNode.value) return this.translateKeyword(typeNode.value)
|
|
314
|
+
return ''
|
|
120
315
|
}
|
|
121
316
|
|
|
122
317
|
generate(ast) {
|
|
123
|
-
this.output = '
|
|
318
|
+
this.output = ''
|
|
124
319
|
this.indent = 0
|
|
125
|
-
|
|
126
|
-
if (ast.
|
|
127
|
-
this.
|
|
128
|
-
this.writeLine('')
|
|
320
|
+
|
|
321
|
+
if (ast.phpTag !== false) {
|
|
322
|
+
this.output = '<?php\n'
|
|
129
323
|
}
|
|
130
324
|
|
|
131
|
-
if (Array.isArray(ast
|
|
132
|
-
for (const node of ast
|
|
325
|
+
if (Array.isArray(ast)) {
|
|
326
|
+
for (const node of ast) {
|
|
133
327
|
this.generateNode(node)
|
|
134
328
|
}
|
|
135
|
-
} else if (ast.
|
|
136
|
-
|
|
137
|
-
|
|
329
|
+
} else if (ast && ast.type === 'Program') {
|
|
330
|
+
for (const node of ast.body || []) {
|
|
331
|
+
this.generateNode(node)
|
|
332
|
+
}
|
|
333
|
+
} else if (ast && ast.type) {
|
|
138
334
|
this.generateNode(ast)
|
|
335
|
+
} else if (ast && ast.body) {
|
|
336
|
+
for (const node of ast.body) {
|
|
337
|
+
this.generateNode(node)
|
|
338
|
+
}
|
|
139
339
|
}
|
|
140
340
|
|
|
141
|
-
return this.output
|
|
341
|
+
return this.output.trim()
|
|
142
342
|
}
|
|
143
343
|
|
|
144
344
|
generateNode(node) {
|
|
145
345
|
if (!node) return ''
|
|
146
346
|
|
|
147
|
-
|
|
148
|
-
|
|
347
|
+
switch (node.type) {
|
|
348
|
+
case 'Program':
|
|
349
|
+
for (const stmt of node.body || []) {
|
|
350
|
+
this.generateNode(stmt)
|
|
351
|
+
}
|
|
352
|
+
return ''
|
|
353
|
+
case 'DeclareStatement':
|
|
354
|
+
return this.generateDeclareStatement(node)
|
|
355
|
+
case 'NamespaceDeclaration':
|
|
356
|
+
return this.generateNamespace(node)
|
|
357
|
+
case 'UseStatement':
|
|
358
|
+
return this.generateUseStatement(node)
|
|
359
|
+
case 'ConstantDeclaration':
|
|
360
|
+
return this.generateConstantDeclaration(node)
|
|
361
|
+
case 'VariableDeclaration':
|
|
362
|
+
return this.generateVariableDeclaration(node)
|
|
363
|
+
case 'FunctionDeclaration':
|
|
364
|
+
return this.generateFunctionDeclaration(node)
|
|
365
|
+
case 'ClassDeclaration':
|
|
366
|
+
return this.generateClassDeclaration(node)
|
|
367
|
+
case 'InterfaceDeclaration':
|
|
368
|
+
return this.generateInterfaceDeclaration(node)
|
|
369
|
+
case 'TraitDeclaration':
|
|
370
|
+
return this.generateTraitDeclaration(node)
|
|
371
|
+
case 'EnumDeclaration':
|
|
372
|
+
return this.generateEnumDeclaration(node)
|
|
373
|
+
case 'IfStatement':
|
|
374
|
+
return this.generateIfStatement(node)
|
|
375
|
+
case 'ForStatement':
|
|
376
|
+
return this.generateForStatement(node)
|
|
377
|
+
case 'ForEachStatement':
|
|
378
|
+
return this.generateForEachStatement(node)
|
|
379
|
+
case 'WhileStatement':
|
|
380
|
+
return this.generateWhileStatement(node)
|
|
381
|
+
case 'DoWhileStatement':
|
|
382
|
+
return this.generateDoWhileStatement(node)
|
|
383
|
+
case 'SwitchStatement':
|
|
384
|
+
return this.generateSwitchStatement(node)
|
|
385
|
+
case 'TryStatement':
|
|
386
|
+
return this.generateTryStatement(node)
|
|
387
|
+
case 'ReturnStatement':
|
|
388
|
+
return this.generateReturnStatement(node)
|
|
389
|
+
case 'ThrowStatement':
|
|
390
|
+
return this.generateThrowStatement(node)
|
|
391
|
+
case 'BreakStatement':
|
|
392
|
+
this.writeLine('break;')
|
|
393
|
+
return ''
|
|
394
|
+
case 'ContinueStatement':
|
|
395
|
+
this.writeLine('continue;')
|
|
396
|
+
return ''
|
|
397
|
+
case 'ExpressionStatement':
|
|
398
|
+
return this.generateExpressionStatement(node)
|
|
399
|
+
case 'EchoStatement':
|
|
400
|
+
return this.generateEchoStatement(node)
|
|
401
|
+
case 'BlockStatement':
|
|
402
|
+
return this.generateBlockStatement(node)
|
|
403
|
+
case 'CallExpression':
|
|
404
|
+
return this.generateCallExpression(node)
|
|
405
|
+
case 'MemberExpression':
|
|
406
|
+
return this.generateMemberExpression(node)
|
|
407
|
+
case 'StaticMemberExpression':
|
|
408
|
+
return this.generateStaticMemberExpression(node)
|
|
409
|
+
case 'BinaryExpression':
|
|
410
|
+
return this.generateBinaryExpression(node)
|
|
411
|
+
case 'LogicalExpression':
|
|
412
|
+
return this.generateBinaryExpression(node)
|
|
413
|
+
case 'AssignmentExpression':
|
|
414
|
+
return this.generateAssignmentExpression(node)
|
|
415
|
+
case 'UnaryExpression':
|
|
416
|
+
return this.generateUnaryExpression(node)
|
|
417
|
+
case 'UpdateExpression':
|
|
418
|
+
return this.generateUpdateExpression(node)
|
|
419
|
+
case 'ConditionalExpression':
|
|
420
|
+
return this.generateConditionalExpression(node)
|
|
421
|
+
case 'ArrayExpression':
|
|
422
|
+
return this.generateArrayExpression(node)
|
|
423
|
+
case 'ObjectExpression':
|
|
424
|
+
return this.generateObjectExpression(node)
|
|
425
|
+
case 'Identifier':
|
|
426
|
+
return this.generateIdentifier(node)
|
|
427
|
+
case 'Variable':
|
|
428
|
+
return this.generateVariable(node)
|
|
429
|
+
case 'Literal':
|
|
430
|
+
return this.generateLiteral(node)
|
|
431
|
+
case 'StringLiteral':
|
|
432
|
+
return this.generateStringLiteral(node)
|
|
433
|
+
case 'NewExpression':
|
|
434
|
+
return this.generateNewExpression(node)
|
|
435
|
+
case 'ThisExpression':
|
|
436
|
+
return '$this'
|
|
437
|
+
case 'FunctionExpression':
|
|
438
|
+
return this.generateFunctionExpression(node)
|
|
439
|
+
case 'ArrowFunctionExpression':
|
|
440
|
+
return this.generateArrowFunctionExpression(node)
|
|
441
|
+
case 'IndexExpression':
|
|
442
|
+
return this.generateIndexExpression(node)
|
|
443
|
+
case 'NullCoalesceExpression':
|
|
444
|
+
return this.generateNullCoalesceExpression(node)
|
|
445
|
+
case 'YieldExpression':
|
|
446
|
+
return this.generateYieldExpression(node)
|
|
447
|
+
default:
|
|
448
|
+
return ''
|
|
149
449
|
}
|
|
450
|
+
}
|
|
150
451
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
'
|
|
155
|
-
'DeclareStatement': () => this.generateDeclareStatement(node),
|
|
156
|
-
'NamespaceDeclaration': () => this.generateNamespaceDeclaration(node),
|
|
157
|
-
'FunctionDeclaration': () => this.generateFunctionDeclaration(node),
|
|
158
|
-
'ClassDeclaration': () => this.generateClassDeclaration(node),
|
|
159
|
-
'InterfaceDeclaration': () => this.generateInterfaceDeclaration(node),
|
|
160
|
-
'TraitDeclaration': () => this.generateTraitDeclaration(node),
|
|
161
|
-
'EnumDeclaration': () => this.generateEnumDeclaration(node),
|
|
162
|
-
'MethodDefinition': () => this.generateMethodDefinition(node),
|
|
163
|
-
'PropertyDeclaration': () => this.generatePropertyDeclaration(node),
|
|
164
|
-
'VariableDeclaration': () => this.generateVariableDeclaration(node),
|
|
165
|
-
'ConstantDeclaration': () => this.generateConstantDeclaration(node),
|
|
166
|
-
'DefineDeclaration': () => this.generateDefineDeclaration(node),
|
|
167
|
-
'IfStatement': () => this.generateIfStatement(node),
|
|
168
|
-
'ForStatement': () => this.generateForStatement(node),
|
|
169
|
-
'ForEachStatement': () => this.generateForEachStatement(node),
|
|
170
|
-
'ForeachStatement': () => this.generateForEachStatement(node),
|
|
171
|
-
'WhileStatement': () => this.generateWhileStatement(node),
|
|
172
|
-
'DoWhileStatement': () => this.generateDoWhileStatement(node),
|
|
173
|
-
'SwitchStatement': () => this.generateSwitchStatement(node),
|
|
174
|
-
'MatchExpression': () => this.generateMatchExpression(node),
|
|
175
|
-
'TryStatement': () => this.generateTryStatement(node),
|
|
176
|
-
'ReturnStatement': () => this.generateReturnStatement(node),
|
|
177
|
-
'ThrowStatement': () => this.generateThrowStatement(node),
|
|
178
|
-
'BreakStatement': () => this.writeLine('break;'),
|
|
179
|
-
'ContinueStatement': () => this.writeLine('continue;'),
|
|
180
|
-
'ExpressionStatement': () => this.generateExpressionStatement(node),
|
|
181
|
-
'EchoStatement': () => this.generateEchoStatement(node),
|
|
182
|
-
'PrintStatement': () => this.generatePrintStatement(node),
|
|
183
|
-
'Namespace': () => this.generateNamespace(node),
|
|
184
|
-
'UseStatement': () => this.generateUseStatement(node),
|
|
185
|
-
'IncludeStatement': () => this.generateIncludeStatement(node),
|
|
186
|
-
'Include': () => this.generateInclude(node),
|
|
187
|
-
'CallExpression': () => this.generateCallExpression(node),
|
|
188
|
-
'MemberExpression': () => this.generateMemberExpression(node),
|
|
189
|
-
'BinaryExpression': () => this.generateBinaryExpression(node),
|
|
190
|
-
'LogicalExpression': () => this.generateBinaryExpression(node),
|
|
191
|
-
'UnaryExpression': () => this.generateUnaryExpression(node),
|
|
192
|
-
'AssignmentExpression': () => this.generateAssignmentExpression(node),
|
|
193
|
-
'UpdateExpression': () => this.generateUpdateExpression(node),
|
|
194
|
-
'ConditionalExpression': () => this.generateConditionalExpression(node),
|
|
195
|
-
'NullCoalescing': () => this.generateNullCoalescing(node),
|
|
196
|
-
'ArrayExpression': () => this.generateArrayExpression(node),
|
|
197
|
-
'ObjectExpression': () => this.generateObjectExpression(node),
|
|
198
|
-
'ArrowFunction': () => this.generateArrowFunction(node),
|
|
199
|
-
'ArrowFunctionExpression': () => this.generateArrowFunction(node),
|
|
200
|
-
'Closure': () => this.generateClosure(node),
|
|
201
|
-
'FunctionExpression': () => this.generateClosure(node),
|
|
202
|
-
'Identifier': () => this.generateIdentifier(node),
|
|
203
|
-
'Variable': () => this.generateVariable(node),
|
|
204
|
-
'Literal': () => this.generateLiteral(node),
|
|
205
|
-
'StringLiteral': () => this.generateStringLiteral(node),
|
|
206
|
-
'NewExpression': () => this.generateNewExpression(node),
|
|
207
|
-
'InstanceOf': () => this.generateInstanceOf(node),
|
|
208
|
-
'BlockStatement': () => this.generateBlockStatement(node),
|
|
209
|
-
'ThisExpression': () => '$this',
|
|
210
|
-
'StaticMemberExpression': () => this.generateStaticMemberExpression(node),
|
|
211
|
-
'IndexExpression': () => this.generateIndexExpression(node),
|
|
212
|
-
'YieldExpression': () => this.generateYieldExpression(node),
|
|
213
|
-
'EmptyStatement': () => '',
|
|
214
|
-
'Comment': () => ''
|
|
452
|
+
generateDeclareStatement(node) {
|
|
453
|
+
const directives = []
|
|
454
|
+
if (node.strictTypes) {
|
|
455
|
+
directives.push('strict_types=1')
|
|
215
456
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
return generators[type]()
|
|
457
|
+
if (node.ticks) {
|
|
458
|
+
directives.push(`ticks=${node.ticks}`)
|
|
219
459
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
460
|
+
if (node.encoding) {
|
|
461
|
+
directives.push(`encoding='${node.encoding}'`)
|
|
462
|
+
}
|
|
463
|
+
if (directives.length > 0) {
|
|
464
|
+
this.writeLine(`declare(${directives.join(', ')});`)
|
|
223
465
|
}
|
|
466
|
+
return ''
|
|
467
|
+
}
|
|
224
468
|
|
|
469
|
+
generateNamespace(node) {
|
|
470
|
+
const name = node.name || node.path
|
|
471
|
+
this.writeLine(`namespace ${name};`)
|
|
472
|
+
this.writeLine('')
|
|
225
473
|
return ''
|
|
226
474
|
}
|
|
227
475
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
}
|
|
476
|
+
generateUseStatement(node) {
|
|
477
|
+
const name = node.name || node.source
|
|
478
|
+
const alias = node.alias ? ` as ${node.alias}` : ''
|
|
479
|
+
this.writeLine(`use ${name}${alias};`)
|
|
480
|
+
return ''
|
|
232
481
|
}
|
|
233
482
|
|
|
234
|
-
|
|
235
|
-
const
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
}).join(', ')
|
|
240
|
-
|
|
241
|
-
this.writeLine(`declare(${directives});`)
|
|
242
|
-
this.writeLine('')
|
|
483
|
+
generateConstantDeclaration(node) {
|
|
484
|
+
const name = node.name || node.id?.name
|
|
485
|
+
const value = this.generateNode(node.value || node.init)
|
|
486
|
+
this.writeLine(`define('${name}', ${value});`)
|
|
487
|
+
return ''
|
|
243
488
|
}
|
|
244
489
|
|
|
245
|
-
|
|
246
|
-
const
|
|
247
|
-
this.writeLine(`namespace ${name};`)
|
|
248
|
-
this.writeLine('')
|
|
490
|
+
generateVariableDeclaration(node) {
|
|
491
|
+
const declarations = node.declarations || [node]
|
|
249
492
|
|
|
250
|
-
|
|
251
|
-
this.
|
|
493
|
+
for (const decl of declarations) {
|
|
494
|
+
const name = this.generateVariable(decl.id || decl)
|
|
495
|
+
if (decl.init) {
|
|
496
|
+
const init = this.generateNode(decl.init)
|
|
497
|
+
this.writeLine(`${name} = ${init};`)
|
|
498
|
+
}
|
|
252
499
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
generateDefineDeclaration(node) {
|
|
256
|
-
const name = this.safeString(node.name)
|
|
257
|
-
const value = this.generateNode(node.value)
|
|
258
|
-
this.writeLine(`define('${name}', ${value});`)
|
|
500
|
+
return ''
|
|
259
501
|
}
|
|
260
502
|
|
|
261
503
|
generateFunctionDeclaration(node) {
|
|
262
|
-
const name =
|
|
263
|
-
const
|
|
264
|
-
|
|
265
|
-
const returnType = node.returnType ? ': ' + this.translateType(node.returnType) : ''
|
|
504
|
+
const name = node.name || node.id?.name || ''
|
|
505
|
+
const params = (node.params || []).map(p => this.generateParam(p)).join(', ')
|
|
506
|
+
let returnType = ''
|
|
266
507
|
|
|
267
|
-
|
|
508
|
+
if (node.returnType) {
|
|
509
|
+
const type = this.extractTypeName(node.returnType)
|
|
510
|
+
if (type) returnType = ': ' + type
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
this.writeLine(`function ${name}(${params})${returnType} {`)
|
|
268
514
|
this.indent++
|
|
269
|
-
|
|
515
|
+
|
|
516
|
+
if (node.body) {
|
|
517
|
+
this.generateBody(node.body)
|
|
518
|
+
}
|
|
519
|
+
|
|
270
520
|
this.indent--
|
|
271
521
|
this.writeLine('}')
|
|
272
522
|
this.writeLine('')
|
|
523
|
+
return ''
|
|
273
524
|
}
|
|
274
525
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
let result = ''
|
|
278
|
-
|
|
279
|
-
if (p.visibility) {
|
|
280
|
-
result += this.translate(p.visibility) + ' '
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
if (p.readonly) {
|
|
284
|
-
result += 'readonly '
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
const typeHint = p.typeHint || (p.type !== 'Parameter' ? p.type : null)
|
|
288
|
-
if (typeHint && typeHint !== 'Parameter') {
|
|
289
|
-
result += this.translateType(typeHint) + ' '
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
if (p.variadic) {
|
|
293
|
-
result += '...'
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
if (p.byReference || p.reference) {
|
|
297
|
-
result += '&'
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
const name = this.safeString(p.name || p.id?.name || p)
|
|
301
|
-
result += '$' + name
|
|
302
|
-
|
|
303
|
-
if (p.default !== undefined && p.default !== null) {
|
|
304
|
-
result += ' = ' + this.generateNode(p.default)
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
return result
|
|
308
|
-
}).join(', ')
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
safeString(value) {
|
|
312
|
-
if (typeof value === 'string') return value
|
|
313
|
-
if (value && typeof value === 'object') {
|
|
314
|
-
return value.name || value.value || 'unknown'
|
|
315
|
-
}
|
|
316
|
-
return String(value || 'unknown')
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
translateType(type) {
|
|
320
|
-
if (!type) return ''
|
|
526
|
+
generateParam(param) {
|
|
527
|
+
let result = ''
|
|
321
528
|
|
|
322
|
-
if (
|
|
323
|
-
const
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
'tableau': 'array', 'array': 'array',
|
|
329
|
-
'objet': 'object', 'object': 'object',
|
|
330
|
-
'nul': 'null', 'null': 'null',
|
|
331
|
-
'vide': 'void', 'void': 'void',
|
|
332
|
-
'mixte': 'mixed', 'mixed': 'mixed',
|
|
333
|
-
'appelable': 'callable', 'callable': 'callable',
|
|
334
|
-
'itérable': 'iterable', 'iterable': 'iterable',
|
|
335
|
-
'jamais': 'never', 'never': 'never'
|
|
529
|
+
if (param.typeHint || (param.type && param.type !== 'Parameter' && param.type !== 'Identifier')) {
|
|
530
|
+
const type = param.typeHint || param.type
|
|
531
|
+
if (typeof type === 'string' && type !== 'Parameter' && type !== 'Identifier') {
|
|
532
|
+
result += this.translateKeyword(type) + ' '
|
|
533
|
+
} else if (type && type.name) {
|
|
534
|
+
result += this.translateKeyword(type.name) + ' '
|
|
336
535
|
}
|
|
337
|
-
const lower = type.toLowerCase()
|
|
338
|
-
return typeMap[lower] || type
|
|
339
536
|
}
|
|
340
537
|
|
|
341
|
-
if (
|
|
342
|
-
|
|
343
|
-
return (type.nullable ? '?' : '') + typeStr
|
|
538
|
+
if (param.reference) {
|
|
539
|
+
result += '&'
|
|
344
540
|
}
|
|
345
541
|
|
|
346
|
-
if (
|
|
347
|
-
|
|
542
|
+
if (param.variadic) {
|
|
543
|
+
result += '...'
|
|
348
544
|
}
|
|
349
545
|
|
|
350
|
-
|
|
351
|
-
return type.types.map(t => this.translateType(t)).join('&')
|
|
352
|
-
}
|
|
546
|
+
result += this.generateVariable(param)
|
|
353
547
|
|
|
354
|
-
if (
|
|
355
|
-
|
|
548
|
+
if (param.default !== undefined && param.default !== null) {
|
|
549
|
+
result += ' = ' + this.generateNode(param.default)
|
|
356
550
|
}
|
|
357
551
|
|
|
358
|
-
|
|
359
|
-
|
|
552
|
+
return result
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
generateBody(body) {
|
|
556
|
+
if (Array.isArray(body)) {
|
|
557
|
+
for (const stmt of body) {
|
|
558
|
+
this.generateNode(stmt)
|
|
559
|
+
}
|
|
560
|
+
} else if (body && body.body) {
|
|
561
|
+
for (const stmt of body.body) {
|
|
562
|
+
this.generateNode(stmt)
|
|
563
|
+
}
|
|
564
|
+
} else if (body) {
|
|
565
|
+
this.generateNode(body)
|
|
360
566
|
}
|
|
361
|
-
|
|
362
|
-
return String(type)
|
|
363
567
|
}
|
|
364
568
|
|
|
365
569
|
generateClassDeclaration(node) {
|
|
@@ -369,237 +573,210 @@ class PHPGenerator {
|
|
|
369
573
|
if (node.final) declaration += 'final '
|
|
370
574
|
if (node.readonly) declaration += 'readonly '
|
|
371
575
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
declaration += ' extends ' + this.translate(this.safeString(node.extends))
|
|
576
|
+
declaration += 'class ' + (node.name || node.id?.name || '')
|
|
577
|
+
|
|
578
|
+
if (node.extends || node.superClass) {
|
|
579
|
+
declaration += ' extends ' + (node.extends || node.superClass)
|
|
377
580
|
}
|
|
378
|
-
|
|
581
|
+
|
|
379
582
|
if (node.implements && node.implements.length > 0) {
|
|
380
|
-
declaration += ' implements ' + node.implements.
|
|
583
|
+
declaration += ' implements ' + node.implements.join(', ')
|
|
381
584
|
}
|
|
382
|
-
|
|
585
|
+
|
|
383
586
|
this.writeLine(declaration + ' {')
|
|
384
587
|
this.indent++
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
588
|
+
|
|
589
|
+
const members = node.body?.body || node.members || node.body || []
|
|
590
|
+
for (const member of members) {
|
|
591
|
+
this.generateClassMember(member)
|
|
388
592
|
}
|
|
389
|
-
|
|
593
|
+
|
|
390
594
|
this.indent--
|
|
391
595
|
this.writeLine('}')
|
|
392
596
|
this.writeLine('')
|
|
597
|
+
return ''
|
|
393
598
|
}
|
|
394
599
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
600
|
+
generateClassMember(node) {
|
|
601
|
+
if (!node) return
|
|
602
|
+
|
|
603
|
+
if (node.type === 'UseTraitStatement') {
|
|
604
|
+
this.writeLine(`use ${node.traits.join(', ')};`)
|
|
605
|
+
return
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
const visibility = node.visibility || 'public'
|
|
609
|
+
const isStatic = node.static ? 'static ' : ''
|
|
610
|
+
const isReadonly = node.readonly ? 'readonly ' : ''
|
|
398
611
|
|
|
612
|
+
if (node.type === 'Property' || node.kind === 'property' || node.type === 'PropertyDeclaration') {
|
|
613
|
+
const name = '$' + (node.name || node.key?.name || node.id?.name || '')
|
|
614
|
+
let typeHint = ''
|
|
615
|
+
if (node.typeHint) {
|
|
616
|
+
typeHint = this.translateKeyword(node.typeHint) + ' '
|
|
617
|
+
}
|
|
618
|
+
const value = node.value ? ' = ' + this.generateNode(node.value) : ''
|
|
619
|
+
this.writeLine(`${visibility} ${isStatic}${isReadonly}${typeHint}${name}${value};`)
|
|
620
|
+
} else if (node.type === 'Method' || node.kind === 'method' || node.type === 'MethodDeclaration') {
|
|
621
|
+
const name = node.name || node.key?.name || ''
|
|
622
|
+
const translatedName = this.translateKeyword(name)
|
|
623
|
+
const params = (node.params || []).map(p => this.generateParam(p)).join(', ')
|
|
624
|
+
let returnType = ''
|
|
625
|
+
|
|
626
|
+
if (node.returnType) {
|
|
627
|
+
const type = this.extractTypeName(node.returnType)
|
|
628
|
+
if (type) returnType = ': ' + type
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
const abstractMod = node.abstract ? 'abstract ' : ''
|
|
632
|
+
|
|
633
|
+
if (node.abstract) {
|
|
634
|
+
this.writeLine(`${abstractMod}${visibility} ${isStatic}function ${translatedName}(${params})${returnType};`)
|
|
635
|
+
} else {
|
|
636
|
+
this.writeLine(`${visibility} ${isStatic}function ${translatedName}(${params})${returnType} {`)
|
|
637
|
+
this.indent++
|
|
638
|
+
|
|
639
|
+
if (node.body) {
|
|
640
|
+
this.generateBody(node.body)
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
this.indent--
|
|
644
|
+
this.writeLine('}')
|
|
645
|
+
}
|
|
646
|
+
this.writeLine('')
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
generateInterfaceDeclaration(node) {
|
|
651
|
+
let declaration = 'interface ' + (node.name || '')
|
|
652
|
+
|
|
399
653
|
if (node.extends && node.extends.length > 0) {
|
|
400
|
-
declaration += ' extends ' + node.extends.
|
|
654
|
+
declaration += ' extends ' + node.extends.join(', ')
|
|
401
655
|
}
|
|
402
|
-
|
|
656
|
+
|
|
403
657
|
this.writeLine(declaration + ' {')
|
|
404
658
|
this.indent++
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
659
|
+
|
|
660
|
+
const members = node.body?.body || node.members || node.body || []
|
|
661
|
+
for (const member of members) {
|
|
662
|
+
this.generateInterfaceMember(member)
|
|
408
663
|
}
|
|
409
|
-
|
|
664
|
+
|
|
410
665
|
this.indent--
|
|
411
666
|
this.writeLine('}')
|
|
412
667
|
this.writeLine('')
|
|
668
|
+
return ''
|
|
413
669
|
}
|
|
414
670
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
671
|
+
generateInterfaceMember(node) {
|
|
672
|
+
if (!node) return
|
|
673
|
+
|
|
674
|
+
const visibility = 'public'
|
|
675
|
+
const name = node.name || node.key?.name || ''
|
|
676
|
+
const translatedName = this.translateKeyword(name)
|
|
677
|
+
const params = (node.params || []).map(p => this.generateParam(p)).join(', ')
|
|
678
|
+
let returnType = ''
|
|
419
679
|
|
|
420
|
-
|
|
421
|
-
this.
|
|
680
|
+
if (node.returnType) {
|
|
681
|
+
const type = this.extractTypeName(node.returnType)
|
|
682
|
+
if (type) returnType = ': ' + type
|
|
422
683
|
}
|
|
423
684
|
|
|
424
|
-
this.
|
|
425
|
-
this.writeLine('}')
|
|
685
|
+
this.writeLine(`${visibility} function ${translatedName}(${params})${returnType};`)
|
|
426
686
|
this.writeLine('')
|
|
427
687
|
}
|
|
428
688
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
let declaration = 'enum ' + this.translate(name)
|
|
432
|
-
|
|
433
|
-
if (node.backingType) {
|
|
434
|
-
declaration += ': ' + this.translateType(node.backingType)
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
this.writeLine(declaration + ' {')
|
|
689
|
+
generateTraitDeclaration(node) {
|
|
690
|
+
this.writeLine('trait ' + (node.name || '') + ' {')
|
|
438
691
|
this.indent++
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
} else {
|
|
444
|
-
this.writeLine(`case ${member.name};`)
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
for (const method of node.methods || []) {
|
|
449
|
-
this.generateNode(method)
|
|
692
|
+
|
|
693
|
+
const members = node.body?.body || node.members || node.body || []
|
|
694
|
+
for (const member of members) {
|
|
695
|
+
this.generateClassMember(member)
|
|
450
696
|
}
|
|
451
|
-
|
|
697
|
+
|
|
452
698
|
this.indent--
|
|
453
699
|
this.writeLine('}')
|
|
454
700
|
this.writeLine('')
|
|
701
|
+
return ''
|
|
455
702
|
}
|
|
456
703
|
|
|
457
|
-
|
|
458
|
-
let declaration = ''
|
|
459
|
-
|
|
460
|
-
const visibility = node.visibility || node.access || 'public'
|
|
461
|
-
declaration += this.translate(visibility) + ' '
|
|
462
|
-
|
|
463
|
-
if (node.static) declaration += 'static '
|
|
464
|
-
if (node.final) declaration += 'final '
|
|
465
|
-
if (node.abstract) declaration += 'abstract '
|
|
466
|
-
|
|
467
|
-
const name = this.translateMethodName(this.safeString(node.name || node.key?.name))
|
|
468
|
-
const params = this.generateParams(node.params || node.value?.params || [])
|
|
469
|
-
const returnType = node.returnType ? ': ' + this.translateType(node.returnType) : ''
|
|
470
|
-
|
|
471
|
-
if (node.abstract) {
|
|
472
|
-
this.writeLine(`${declaration}function ${name}(${params})${returnType};`)
|
|
473
|
-
} else {
|
|
474
|
-
this.writeLine(`${declaration}function ${name}(${params})${returnType} {`)
|
|
475
|
-
this.indent++
|
|
476
|
-
this.generateNode(node.body || node.value?.body)
|
|
477
|
-
this.indent--
|
|
478
|
-
this.writeLine('}')
|
|
479
|
-
}
|
|
480
|
-
this.writeLine('')
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
translateMethodName(name) {
|
|
484
|
-
if (!name) return 'method'
|
|
704
|
+
generateEnumDeclaration(node) {
|
|
705
|
+
let declaration = 'enum ' + (node.name || '')
|
|
485
706
|
|
|
486
|
-
|
|
487
|
-
'
|
|
488
|
-
'constructor': '__construct',
|
|
489
|
-
'destructeur': '__destruct',
|
|
490
|
-
'destructor': '__destruct',
|
|
491
|
-
'obtenir': '__get',
|
|
492
|
-
'get': '__get',
|
|
493
|
-
'définir': '__set',
|
|
494
|
-
'definir': '__set',
|
|
495
|
-
'set': '__set',
|
|
496
|
-
'appeler': '__call',
|
|
497
|
-
'call': '__call',
|
|
498
|
-
'appeler statique': '__callStatic',
|
|
499
|
-
'call static': '__callStatic',
|
|
500
|
-
'vers chaîne': '__toString',
|
|
501
|
-
'vers chaine': '__toString',
|
|
502
|
-
'to string': '__toString',
|
|
503
|
-
'invoquer': '__invoke',
|
|
504
|
-
'invoke': '__invoke',
|
|
505
|
-
'cloner': '__clone',
|
|
506
|
-
'clone': '__clone',
|
|
507
|
-
'dormir': '__sleep',
|
|
508
|
-
'sleep': '__sleep',
|
|
509
|
-
'réveiller': '__wakeup',
|
|
510
|
-
'reveiller': '__wakeup',
|
|
511
|
-
'wakeup': '__wakeup',
|
|
512
|
-
'sérialiser': '__serialize',
|
|
513
|
-
'serialiser': '__serialize',
|
|
514
|
-
'serialize': '__serialize',
|
|
515
|
-
'désérialiser': '__unserialize',
|
|
516
|
-
'deserialiser': '__unserialize',
|
|
517
|
-
'unserialize': '__unserialize',
|
|
518
|
-
'isset': '__isset',
|
|
519
|
-
'existe propriété': '__isset',
|
|
520
|
-
'existe propriete': '__isset',
|
|
521
|
-
'unset': '__unset',
|
|
522
|
-
'détruire propriété': '__unset',
|
|
523
|
-
'detruire propriete': '__unset',
|
|
524
|
-
'déboguer info': '__debugInfo',
|
|
525
|
-
'deboguer info': '__debugInfo',
|
|
526
|
-
'debug info': '__debugInfo'
|
|
707
|
+
if (node.backingType) {
|
|
708
|
+
declaration += ': ' + this.translateKeyword(node.backingType)
|
|
527
709
|
}
|
|
528
|
-
|
|
529
|
-
const normalized = name.toLowerCase().trim()
|
|
530
|
-
return magicMethods[normalized] || this.translate(name)
|
|
531
|
-
}
|
|
532
710
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
const visibility = node.visibility || node.access || 'public'
|
|
537
|
-
declaration += this.translate(visibility) + ' '
|
|
538
|
-
|
|
539
|
-
if (node.static) declaration += 'static '
|
|
540
|
-
if (node.readonly) declaration += 'readonly '
|
|
541
|
-
|
|
542
|
-
if (node.type) {
|
|
543
|
-
declaration += this.translateType(node.type) + ' '
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
const name = this.safeString(node.name || node.key?.name)
|
|
547
|
-
declaration += '$' + this.translate(name)
|
|
548
|
-
|
|
549
|
-
if (node.value !== undefined) {
|
|
550
|
-
declaration += ' = ' + this.generateNode(node.value)
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
this.writeLine(declaration + ';')
|
|
554
|
-
}
|
|
711
|
+
this.writeLine(declaration + ' {')
|
|
712
|
+
this.indent++
|
|
555
713
|
|
|
556
|
-
|
|
557
|
-
for (const
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
if (decl.init !== undefined) {
|
|
562
|
-
const value = this.generateNode(decl.init)
|
|
563
|
-
this.writeLine(`${varName} = ${value};`)
|
|
714
|
+
const cases = node.cases || node.members || []
|
|
715
|
+
for (const caseNode of cases) {
|
|
716
|
+
if (caseNode.value !== undefined) {
|
|
717
|
+
this.writeLine(`case ${caseNode.name} = ${this.generateNode(caseNode.value)};`)
|
|
564
718
|
} else {
|
|
565
|
-
this.writeLine(
|
|
719
|
+
this.writeLine(`case ${caseNode.name};`)
|
|
566
720
|
}
|
|
567
721
|
}
|
|
568
|
-
}
|
|
569
722
|
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
if (node.classLevel) {
|
|
575
|
-
const visibility = node.visibility ? this.translate(node.visibility) + ' ' : ''
|
|
576
|
-
this.writeLine(`${visibility}const ${name.toUpperCase()} = ${value};`)
|
|
577
|
-
} else {
|
|
578
|
-
this.writeLine(`define('${name.toUpperCase()}', ${value});`)
|
|
579
|
-
}
|
|
723
|
+
this.indent--
|
|
724
|
+
this.writeLine('}')
|
|
725
|
+
this.writeLine('')
|
|
726
|
+
return ''
|
|
580
727
|
}
|
|
581
728
|
|
|
582
729
|
generateIfStatement(node) {
|
|
583
|
-
const test = this.generateNode(node.test
|
|
730
|
+
const test = this.generateNode(node.test)
|
|
584
731
|
this.writeLine(`if (${test}) {`)
|
|
585
732
|
this.indent++
|
|
586
|
-
this.
|
|
733
|
+
this.generateBody(node.consequent)
|
|
587
734
|
this.indent--
|
|
588
|
-
|
|
735
|
+
|
|
589
736
|
if (node.alternate) {
|
|
590
737
|
if (node.alternate.type === 'IfStatement') {
|
|
591
|
-
this.
|
|
592
|
-
this.
|
|
738
|
+
const altTest = this.generateNode(node.alternate.test)
|
|
739
|
+
this.writeLine(`} elseif (${altTest}) {`)
|
|
740
|
+
this.indent++
|
|
741
|
+
this.generateBody(node.alternate.consequent)
|
|
742
|
+
this.indent--
|
|
743
|
+
if (node.alternate.alternate) {
|
|
744
|
+
this.generateElse(node.alternate.alternate)
|
|
745
|
+
} else {
|
|
746
|
+
this.writeLine('}')
|
|
747
|
+
}
|
|
593
748
|
} else {
|
|
594
749
|
this.writeLine('} else {')
|
|
595
750
|
this.indent++
|
|
596
|
-
this.
|
|
751
|
+
this.generateBody(node.alternate)
|
|
597
752
|
this.indent--
|
|
598
753
|
this.writeLine('}')
|
|
599
754
|
}
|
|
600
755
|
} else {
|
|
601
756
|
this.writeLine('}')
|
|
602
757
|
}
|
|
758
|
+
return ''
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
generateElse(node) {
|
|
762
|
+
if (node.type === 'IfStatement') {
|
|
763
|
+
const altTest = this.generateNode(node.test)
|
|
764
|
+
this.writeLine(`} elseif (${altTest}) {`)
|
|
765
|
+
this.indent++
|
|
766
|
+
this.generateBody(node.consequent)
|
|
767
|
+
this.indent--
|
|
768
|
+
if (node.alternate) {
|
|
769
|
+
this.generateElse(node.alternate)
|
|
770
|
+
} else {
|
|
771
|
+
this.writeLine('}')
|
|
772
|
+
}
|
|
773
|
+
} else {
|
|
774
|
+
this.writeLine('} else {')
|
|
775
|
+
this.indent++
|
|
776
|
+
this.generateBody(node)
|
|
777
|
+
this.indent--
|
|
778
|
+
this.writeLine('}')
|
|
779
|
+
}
|
|
603
780
|
}
|
|
604
781
|
|
|
605
782
|
generateForStatement(node) {
|
|
@@ -609,39 +786,43 @@ class PHPGenerator {
|
|
|
609
786
|
|
|
610
787
|
this.writeLine(`for (${init}; ${test}; ${update}) {`)
|
|
611
788
|
this.indent++
|
|
612
|
-
this.
|
|
789
|
+
this.generateBody(node.body)
|
|
613
790
|
this.indent--
|
|
614
791
|
this.writeLine('}')
|
|
792
|
+
return ''
|
|
615
793
|
}
|
|
616
794
|
|
|
617
795
|
generateForEachStatement(node) {
|
|
618
|
-
const array = this.generateNode(node.array || node.right
|
|
619
|
-
const value = this.generateVariable(node.value || node.left
|
|
620
|
-
const key = node.key
|
|
796
|
+
const array = this.generateNode(node.array || node.right)
|
|
797
|
+
const value = this.generateVariable(node.value || node.left)
|
|
798
|
+
const key = node.key ? this.generateVariable(node.key) + ' => ' : ''
|
|
621
799
|
|
|
622
800
|
this.writeLine(`foreach (${array} as ${key}${value}) {`)
|
|
623
801
|
this.indent++
|
|
624
|
-
this.
|
|
802
|
+
this.generateBody(node.body)
|
|
625
803
|
this.indent--
|
|
626
804
|
this.writeLine('}')
|
|
805
|
+
return ''
|
|
627
806
|
}
|
|
628
807
|
|
|
629
808
|
generateWhileStatement(node) {
|
|
630
|
-
const test = this.generateNode(node.test
|
|
809
|
+
const test = this.generateNode(node.test)
|
|
631
810
|
this.writeLine(`while (${test}) {`)
|
|
632
811
|
this.indent++
|
|
633
|
-
this.
|
|
812
|
+
this.generateBody(node.body)
|
|
634
813
|
this.indent--
|
|
635
814
|
this.writeLine('}')
|
|
815
|
+
return ''
|
|
636
816
|
}
|
|
637
817
|
|
|
638
818
|
generateDoWhileStatement(node) {
|
|
639
819
|
this.writeLine('do {')
|
|
640
820
|
this.indent++
|
|
641
|
-
this.
|
|
821
|
+
this.generateBody(node.body)
|
|
642
822
|
this.indent--
|
|
643
|
-
const test = this.generateNode(node.test
|
|
823
|
+
const test = this.generateNode(node.test)
|
|
644
824
|
this.writeLine(`} while (${test});`)
|
|
825
|
+
return ''
|
|
645
826
|
}
|
|
646
827
|
|
|
647
828
|
generateSwitchStatement(node) {
|
|
@@ -665,50 +846,35 @@ class PHPGenerator {
|
|
|
665
846
|
|
|
666
847
|
this.indent--
|
|
667
848
|
this.writeLine('}')
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
generateMatchExpression(node) {
|
|
671
|
-
const subject = this.generateNode(node.subject || node.discriminant)
|
|
672
|
-
let result = `match (${subject}) {\n`
|
|
673
|
-
|
|
674
|
-
for (const arm of node.arms || node.cases || []) {
|
|
675
|
-
this.indent++
|
|
676
|
-
if (arm.conditions) {
|
|
677
|
-
const conditions = arm.conditions.map(c => this.generateNode(c)).join(', ')
|
|
678
|
-
result += this.getIndent() + `${conditions} => ${this.generateNode(arm.body)},\n`
|
|
679
|
-
} else if (arm.default) {
|
|
680
|
-
result += this.getIndent() + `default => ${this.generateNode(arm.body)},\n`
|
|
681
|
-
}
|
|
682
|
-
this.indent--
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
result += this.getIndent() + '}'
|
|
686
|
-
return result
|
|
849
|
+
return ''
|
|
687
850
|
}
|
|
688
851
|
|
|
689
852
|
generateTryStatement(node) {
|
|
690
853
|
this.writeLine('try {')
|
|
691
854
|
this.indent++
|
|
692
|
-
this.
|
|
855
|
+
this.generateBody(node.block)
|
|
693
856
|
this.indent--
|
|
694
857
|
|
|
695
|
-
|
|
696
|
-
const exceptionType = handler.
|
|
697
|
-
const param =
|
|
858
|
+
if (node.handler) {
|
|
859
|
+
const exceptionType = node.handler.exceptionType || node.handler.type || 'Exception'
|
|
860
|
+
const param = node.handler.param
|
|
861
|
+
? this.generateVariable(node.handler.param)
|
|
862
|
+
: '$e'
|
|
698
863
|
this.writeLine(`} catch (${exceptionType} ${param}) {`)
|
|
699
864
|
this.indent++
|
|
700
|
-
this.
|
|
865
|
+
this.generateBody(node.handler.body)
|
|
701
866
|
this.indent--
|
|
702
867
|
}
|
|
703
868
|
|
|
704
869
|
if (node.finalizer) {
|
|
705
870
|
this.writeLine('} finally {')
|
|
706
871
|
this.indent++
|
|
707
|
-
this.
|
|
872
|
+
this.generateBody(node.finalizer)
|
|
708
873
|
this.indent--
|
|
709
874
|
}
|
|
710
875
|
|
|
711
876
|
this.writeLine('}')
|
|
877
|
+
return ''
|
|
712
878
|
}
|
|
713
879
|
|
|
714
880
|
generateReturnStatement(node) {
|
|
@@ -718,93 +884,50 @@ class PHPGenerator {
|
|
|
718
884
|
} else {
|
|
719
885
|
this.writeLine('return;')
|
|
720
886
|
}
|
|
887
|
+
return ''
|
|
721
888
|
}
|
|
722
889
|
|
|
723
890
|
generateThrowStatement(node) {
|
|
724
891
|
const arg = this.generateNode(node.argument)
|
|
725
892
|
this.writeLine(`throw ${arg};`)
|
|
893
|
+
return ''
|
|
726
894
|
}
|
|
727
895
|
|
|
728
896
|
generateExpressionStatement(node) {
|
|
729
897
|
const expr = this.generateNode(node.expression)
|
|
730
|
-
|
|
898
|
+
if (expr) {
|
|
899
|
+
this.writeLine(`${expr};`)
|
|
900
|
+
}
|
|
901
|
+
return ''
|
|
731
902
|
}
|
|
732
903
|
|
|
733
904
|
generateEchoStatement(node) {
|
|
734
|
-
const
|
|
735
|
-
const args = exprs.filter(Boolean).map(a => this.generateNode(a)).join(', ')
|
|
905
|
+
const args = (node.expressions || node.arguments || [node.argument]).filter(Boolean).map(a => this.generateNode(a)).join(', ')
|
|
736
906
|
this.writeLine(`echo ${args};`)
|
|
907
|
+
return ''
|
|
737
908
|
}
|
|
738
909
|
|
|
739
|
-
|
|
740
|
-
const
|
|
741
|
-
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
generateNamespace(node) {
|
|
745
|
-
const name = this.safeString(node.name)
|
|
746
|
-
this.writeLine(`namespace ${name};`)
|
|
747
|
-
this.writeLine('')
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
generateUseStatement(node) {
|
|
751
|
-
const typePrefix = node.useType === 'function' ? 'function ' : (node.useType === 'const' ? 'const ' : '')
|
|
752
|
-
|
|
753
|
-
if (node.imports && node.imports.length > 0) {
|
|
754
|
-
for (const imp of node.imports) {
|
|
755
|
-
const path = this.safeString(imp.path)
|
|
756
|
-
const alias = imp.alias ? ' as ' + imp.alias : ''
|
|
757
|
-
this.writeLine(`use ${typePrefix}${path}${alias};`)
|
|
758
|
-
}
|
|
759
|
-
} else {
|
|
760
|
-
const name = this.safeString(node.name || node.source)
|
|
761
|
-
const alias = node.alias ? ' as ' + node.alias : ''
|
|
762
|
-
this.writeLine(`use ${typePrefix}${name}${alias};`)
|
|
763
|
-
}
|
|
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
|
-
}
|
|
910
|
+
generateBlockStatement(node) {
|
|
911
|
+
for (const stmt of node.body || []) {
|
|
912
|
+
this.generateNode(stmt)
|
|
779
913
|
}
|
|
914
|
+
return ''
|
|
780
915
|
}
|
|
781
916
|
|
|
782
917
|
generateCallExpression(node) {
|
|
783
918
|
let callee
|
|
784
919
|
|
|
785
920
|
if (typeof node.callee === 'string') {
|
|
786
|
-
callee = this.
|
|
787
|
-
} else if (node.callee
|
|
788
|
-
callee = this.
|
|
789
|
-
} else if (node.callee
|
|
790
|
-
callee = this.
|
|
791
|
-
} else if (node.callee && node.callee.type === 'Identifier') {
|
|
792
|
-
const name = this.safeString(node.callee.name)
|
|
793
|
-
callee = this.translate(name)
|
|
921
|
+
callee = this.translateFunction(node.callee)
|
|
922
|
+
} else if (node.callee.type === 'Identifier') {
|
|
923
|
+
callee = this.translateFunction(node.callee.name)
|
|
924
|
+
} else if (node.callee.type === 'MemberExpression' || node.callee.type === 'StaticMemberExpression') {
|
|
925
|
+
callee = this.generateNode(node.callee)
|
|
794
926
|
} else {
|
|
795
927
|
callee = this.generateNode(node.callee)
|
|
796
928
|
}
|
|
797
929
|
|
|
798
|
-
const args = (node.arguments || []).map(a =>
|
|
799
|
-
if (a && a.type === 'SpreadElement') {
|
|
800
|
-
return '...' + this.generateNode(a.argument || a)
|
|
801
|
-
}
|
|
802
|
-
if (a && a.type === 'NamedArgument') {
|
|
803
|
-
return `${a.name}: ${this.generateNode(a.value)}`
|
|
804
|
-
}
|
|
805
|
-
return this.generateNode(a)
|
|
806
|
-
}).join(', ')
|
|
807
|
-
|
|
930
|
+
const args = (node.arguments || []).map(a => this.generateNode(a)).join(', ')
|
|
808
931
|
return `${callee}(${args})`
|
|
809
932
|
}
|
|
810
933
|
|
|
@@ -813,118 +936,69 @@ class PHPGenerator {
|
|
|
813
936
|
let property
|
|
814
937
|
|
|
815
938
|
if (typeof node.property === 'string') {
|
|
816
|
-
property =
|
|
817
|
-
} else if (node.property
|
|
818
|
-
property = this.
|
|
819
|
-
} else if (node.property && node.property.type === 'Identifier') {
|
|
820
|
-
property = this.translateMethodName(node.property.name || node.property.value)
|
|
939
|
+
property = node.property
|
|
940
|
+
} else if (node.property.type === 'Identifier') {
|
|
941
|
+
property = this.translateFunction(node.property.name)
|
|
821
942
|
} else {
|
|
822
943
|
property = this.generateNode(node.property)
|
|
823
944
|
}
|
|
824
945
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
}
|
|
946
|
+
const operator = node.nullsafe ? '?->' : '->'
|
|
947
|
+
|
|
828
948
|
if (node.computed) {
|
|
829
949
|
return `${object}[${property}]`
|
|
830
950
|
}
|
|
831
|
-
|
|
832
|
-
return `${object}?->${property}`
|
|
833
|
-
}
|
|
834
|
-
return `${object}->${property}`
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
translateMethodName(name) {
|
|
838
|
-
if (!name) return name
|
|
839
|
-
const translated = this.translate(name)
|
|
840
|
-
if (translated.includes('->')) {
|
|
841
|
-
const parts = translated.split('->')
|
|
842
|
-
return parts[parts.length - 1].replace(/\(\)$/, '')
|
|
843
|
-
}
|
|
844
|
-
if (translated.includes('::')) {
|
|
845
|
-
const parts = translated.split('::')
|
|
846
|
-
return parts[parts.length - 1].replace(/\(\)$/, '')
|
|
847
|
-
}
|
|
848
|
-
return translated.replace(/\(\)$/, '')
|
|
951
|
+
return `${object}${operator}${property}`
|
|
849
952
|
}
|
|
850
953
|
|
|
851
954
|
generateStaticMemberExpression(node) {
|
|
852
|
-
const cls = this.generateNode(node.class)
|
|
853
|
-
let member
|
|
854
|
-
|
|
855
|
-
if (typeof node.member === 'string') {
|
|
856
|
-
member = node.member
|
|
857
|
-
} else if (node.member && node.member.name) {
|
|
858
|
-
member = node.member.name
|
|
859
|
-
} else {
|
|
860
|
-
member = this.generateNode(node.member)
|
|
861
|
-
}
|
|
862
|
-
|
|
955
|
+
const cls = node.class?.name || this.generateNode(node.class)
|
|
956
|
+
let member = node.member?.name || this.generateNode(node.member)
|
|
957
|
+
member = this.translateKeyword(member)
|
|
863
958
|
return `${cls}::${member}`
|
|
864
959
|
}
|
|
865
960
|
|
|
866
|
-
generateIndexExpression(node) {
|
|
867
|
-
const object = this.generateNode(node.object)
|
|
868
|
-
const index = node.index ? this.generateNode(node.index) : ''
|
|
869
|
-
return `${object}[${index}]`
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
generateYieldExpression(node) {
|
|
873
|
-
const argument = node.argument ? this.generateNode(node.argument) : ''
|
|
874
|
-
if (node.delegate) {
|
|
875
|
-
return `yield from ${argument}`
|
|
876
|
-
}
|
|
877
|
-
return argument ? `yield ${argument}` : 'yield'
|
|
878
|
-
}
|
|
879
|
-
|
|
880
961
|
generateBinaryExpression(node) {
|
|
881
962
|
const left = this.generateNode(node.left)
|
|
882
963
|
const right = this.generateNode(node.right)
|
|
883
964
|
let op = node.operator
|
|
884
965
|
|
|
885
966
|
const opMap = {
|
|
886
|
-
'et': '&&',
|
|
887
|
-
'ou': '||',
|
|
888
|
-
'
|
|
889
|
-
'
|
|
890
|
-
'différent': '!==', 'different': '!==', 'not equal': '!==',
|
|
891
|
-
'concaténer': '.', 'concatener': '.', 'concatenate': '.',
|
|
892
|
-
'vaisseau spatial': '<=>', 'spaceship': '<=>',
|
|
893
|
-
'fusion null': '??', 'null coalescing': '??'
|
|
967
|
+
'et': '&&',
|
|
968
|
+
'ou': '||',
|
|
969
|
+
'concatener': '.',
|
|
970
|
+
'concat': '.'
|
|
894
971
|
}
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
972
|
+
op = opMap[this.normalizeAccents(op)] || op
|
|
973
|
+
|
|
974
|
+
return `${left} ${op} ${right}`
|
|
975
|
+
}
|
|
898
976
|
|
|
977
|
+
generateAssignmentExpression(node) {
|
|
978
|
+
const left = this.generateNode(node.left)
|
|
979
|
+
const right = this.generateNode(node.right)
|
|
980
|
+
const op = node.operator || '='
|
|
899
981
|
return `${left} ${op} ${right}`
|
|
900
982
|
}
|
|
901
983
|
|
|
902
984
|
generateUnaryExpression(node) {
|
|
903
|
-
const
|
|
904
|
-
|
|
905
|
-
if (op === 'non' || op === 'not') op = '!'
|
|
985
|
+
const operand = this.generateNode(node.operand || node.argument)
|
|
986
|
+
const op = node.operator === 'non' ? '!' : node.operator
|
|
906
987
|
|
|
907
988
|
if (node.prefix !== false) {
|
|
908
|
-
return `${op}${
|
|
989
|
+
return `${op}${operand}`
|
|
909
990
|
}
|
|
910
|
-
return `${
|
|
991
|
+
return `${operand}${op}`
|
|
911
992
|
}
|
|
912
993
|
|
|
913
994
|
generateUpdateExpression(node) {
|
|
914
|
-
const
|
|
995
|
+
const operand = this.generateNode(node.operand || node.argument)
|
|
915
996
|
const op = node.operator
|
|
916
997
|
|
|
917
|
-
if (node.prefix
|
|
918
|
-
return `${op}${
|
|
998
|
+
if (node.prefix) {
|
|
999
|
+
return `${op}${operand}`
|
|
919
1000
|
}
|
|
920
|
-
return `${
|
|
921
|
-
}
|
|
922
|
-
|
|
923
|
-
generateAssignmentExpression(node) {
|
|
924
|
-
const left = this.generateNode(node.left)
|
|
925
|
-
const right = this.generateNode(node.right)
|
|
926
|
-
const op = node.operator || '='
|
|
927
|
-
return `${left} ${op} ${right}`
|
|
1001
|
+
return `${operand}${op}`
|
|
928
1002
|
}
|
|
929
1003
|
|
|
930
1004
|
generateConditionalExpression(node) {
|
|
@@ -934,27 +1008,20 @@ class PHPGenerator {
|
|
|
934
1008
|
return `${test} ? ${consequent} : ${alternate}`
|
|
935
1009
|
}
|
|
936
1010
|
|
|
937
|
-
generateNullCoalescing(node) {
|
|
938
|
-
const left = this.generateNode(node.left)
|
|
939
|
-
const right = this.generateNode(node.right)
|
|
940
|
-
return `${left} ?? ${right}`
|
|
941
|
-
}
|
|
942
|
-
|
|
943
1011
|
generateArrayExpression(node) {
|
|
944
1012
|
const elements = (node.elements || []).map(e => {
|
|
945
|
-
if (!e) return 'null'
|
|
946
|
-
if (e.type === 'SpreadElement') {
|
|
947
|
-
return '...' + this.generateNode(e.argument || e)
|
|
948
|
-
}
|
|
949
1013
|
if (e.type === 'ArrayElement') {
|
|
950
|
-
if (e.key
|
|
1014
|
+
if (e.key) {
|
|
951
1015
|
const key = this.generateNode(e.key)
|
|
952
1016
|
const value = this.generateNode(e.value)
|
|
953
1017
|
return `${key} => ${value}`
|
|
954
1018
|
}
|
|
955
1019
|
return this.generateNode(e.value)
|
|
956
1020
|
}
|
|
957
|
-
if (e.
|
|
1021
|
+
if (e.type === 'SpreadElement') {
|
|
1022
|
+
return '...' + this.generateNode(e.argument)
|
|
1023
|
+
}
|
|
1024
|
+
if (e.key) {
|
|
958
1025
|
const key = this.generateNode(e.key)
|
|
959
1026
|
const value = this.generateNode(e.value || e)
|
|
960
1027
|
return `${key} => ${value}`
|
|
@@ -973,86 +1040,44 @@ class PHPGenerator {
|
|
|
973
1040
|
return this.generateArrayExpression(node)
|
|
974
1041
|
}
|
|
975
1042
|
|
|
976
|
-
|
|
977
|
-
const
|
|
978
|
-
|
|
979
|
-
return `fn(${params}) => ${body}`
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
generateClosure(node) {
|
|
983
|
-
const params = this.generateParams(node.params || [])
|
|
984
|
-
const useVars = node.uses && node.uses.length > 0
|
|
985
|
-
? ` use (${node.uses.map(u => (u.byRef ? '&' : '') + '$' + this.translate(this.safeString(u.name || u))).join(', ')})`
|
|
986
|
-
: ''
|
|
987
|
-
const returnType = node.returnType ? ': ' + this.translateType(node.returnType) : ''
|
|
1043
|
+
generateIdentifier(node) {
|
|
1044
|
+
const name = node.name || node
|
|
1045
|
+
if (typeof name !== 'string') return '$var'
|
|
988
1046
|
|
|
989
|
-
|
|
990
|
-
this.indent++
|
|
1047
|
+
const normalized = this.normalizeAccents(name)
|
|
991
1048
|
|
|
992
|
-
if (
|
|
993
|
-
|
|
994
|
-
result += this.getIndent() + this.generateNode(stmt)
|
|
995
|
-
}
|
|
996
|
-
} else if (node.body) {
|
|
997
|
-
result += this.getIndent() + 'return ' + this.generateNode(node.body) + ';\n'
|
|
1049
|
+
if (this.functionMap[normalized]) {
|
|
1050
|
+
return this.functionMap[normalized]
|
|
998
1051
|
}
|
|
999
1052
|
|
|
1000
|
-
this.
|
|
1001
|
-
result += this.getIndent() + '}'
|
|
1002
|
-
return result
|
|
1003
|
-
}
|
|
1004
|
-
|
|
1005
|
-
generateVariable(node) {
|
|
1006
|
-
if (!node) return '$var'
|
|
1053
|
+
const translated = this.translateKeyword(name)
|
|
1007
1054
|
|
|
1008
|
-
|
|
1009
|
-
|
|
1055
|
+
if (translated.startsWith('$')) return translated
|
|
1056
|
+
if (['true', 'false', 'null', 'self', 'parent', 'static'].includes(translated)) {
|
|
1057
|
+
return translated
|
|
1058
|
+
}
|
|
1059
|
+
if (/^[A-Z]/.test(translated)) return translated
|
|
1060
|
+
if (translated === name && !name.startsWith('$')) {
|
|
1061
|
+
return '$' + name
|
|
1062
|
+
}
|
|
1010
1063
|
|
|
1011
|
-
|
|
1012
|
-
return '$' + nameStr
|
|
1064
|
+
return translated.startsWith('$') ? translated : '$' + translated
|
|
1013
1065
|
}
|
|
1014
1066
|
|
|
1015
|
-
|
|
1067
|
+
generateVariable(node) {
|
|
1016
1068
|
if (!node) return '$var'
|
|
1017
1069
|
|
|
1018
|
-
const name =
|
|
1019
|
-
|
|
1070
|
+
const name = node.name || node.id?.name || node
|
|
1071
|
+
if (typeof name !== 'string') return '$var'
|
|
1020
1072
|
|
|
1021
|
-
if (
|
|
1022
|
-
|
|
1023
|
-
const keywords = [
|
|
1024
|
-
'true', 'false', 'null',
|
|
1025
|
-
'self', 'parent', 'static',
|
|
1026
|
-
'this', '$this'
|
|
1027
|
-
]
|
|
1028
|
-
if (keywords.includes(nameStr.toLowerCase())) {
|
|
1029
|
-
if (nameStr.toLowerCase() === 'this') return '$this'
|
|
1030
|
-
return nameStr
|
|
1031
|
-
}
|
|
1032
|
-
|
|
1033
|
-
if (/^[A-Z]/.test(nameStr)) return nameStr
|
|
1034
|
-
|
|
1035
|
-
if (nameStr.includes('(') || nameStr.includes('::')) return nameStr
|
|
1036
|
-
|
|
1037
|
-
const superglobals = ['_GET', '_POST', '_SERVER', '_SESSION', '_COOKIE', '_FILES', '_REQUEST', '_ENV', 'GLOBALS']
|
|
1038
|
-
const upper = nameStr.toUpperCase()
|
|
1039
|
-
if (superglobals.includes(nameStr) || superglobals.includes(upper)) {
|
|
1040
|
-
return '$' + upper
|
|
1041
|
-
}
|
|
1042
|
-
|
|
1043
|
-
return '$' + nameStr
|
|
1073
|
+
if (name.startsWith('$')) return name
|
|
1074
|
+
return '$' + name
|
|
1044
1075
|
}
|
|
1045
1076
|
|
|
1046
1077
|
generateLiteral(node) {
|
|
1047
|
-
if (node.raw
|
|
1078
|
+
if (node.raw) return node.raw
|
|
1048
1079
|
if (typeof node.value === 'string') {
|
|
1049
|
-
|
|
1050
|
-
.replace(/\\/g, '\\\\')
|
|
1051
|
-
.replace(/"/g, '\\"')
|
|
1052
|
-
.replace(/\n/g, '\\n')
|
|
1053
|
-
.replace(/\r/g, '\\r')
|
|
1054
|
-
.replace(/\t/g, '\\t')
|
|
1055
|
-
return `"${escaped}"`
|
|
1080
|
+
return `"${node.value.replace(/"/g, '\\"')}"`
|
|
1056
1081
|
}
|
|
1057
1082
|
if (node.value === null) return 'null'
|
|
1058
1083
|
if (node.value === true) return 'true'
|
|
@@ -1061,22 +1086,17 @@ class PHPGenerator {
|
|
|
1061
1086
|
}
|
|
1062
1087
|
|
|
1063
1088
|
generateStringLiteral(node) {
|
|
1064
|
-
const
|
|
1065
|
-
const
|
|
1066
|
-
|
|
1067
|
-
.replace(/"/g, '\\"')
|
|
1068
|
-
.replace(/\n/g, '\\n')
|
|
1069
|
-
.replace(/\r/g, '\\r')
|
|
1070
|
-
.replace(/\t/g, '\\t')
|
|
1071
|
-
return node.doubleQuoted !== false ? `"${escaped}"` : `'${escaped}'`
|
|
1089
|
+
const quote = node.doubleQuoted ? '"' : "'"
|
|
1090
|
+
const value = node.value.replace(new RegExp(quote, 'g'), '\\' + quote)
|
|
1091
|
+
return `${quote}${value}${quote}`
|
|
1072
1092
|
}
|
|
1073
1093
|
|
|
1074
1094
|
generateNewExpression(node) {
|
|
1075
1095
|
let callee
|
|
1076
1096
|
if (typeof node.callee === 'string') {
|
|
1077
|
-
callee =
|
|
1078
|
-
} else if (node.callee
|
|
1079
|
-
callee =
|
|
1097
|
+
callee = node.callee
|
|
1098
|
+
} else if (node.callee.type === 'Identifier') {
|
|
1099
|
+
callee = node.callee.name
|
|
1080
1100
|
} else {
|
|
1081
1101
|
callee = this.generateNode(node.callee)
|
|
1082
1102
|
}
|
|
@@ -1084,20 +1104,64 @@ class PHPGenerator {
|
|
|
1084
1104
|
return `new ${callee}(${args})`
|
|
1085
1105
|
}
|
|
1086
1106
|
|
|
1087
|
-
|
|
1107
|
+
generateFunctionExpression(node) {
|
|
1108
|
+
const params = (node.params || []).map(p => this.generateParam(p)).join(', ')
|
|
1109
|
+
|
|
1110
|
+
let uses = ''
|
|
1111
|
+
if (node.uses && node.uses.length > 0) {
|
|
1112
|
+
const useVars = node.uses.map(u => {
|
|
1113
|
+
const ref = u.byRef ? '&' : ''
|
|
1114
|
+
return ref + this.generateVariable(u)
|
|
1115
|
+
}).join(', ')
|
|
1116
|
+
uses = ` use (${useVars})`
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
let returnType = ''
|
|
1120
|
+
if (node.returnType) {
|
|
1121
|
+
returnType = ': ' + this.translateKeyword(node.returnType)
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
let body = ''
|
|
1125
|
+
if (node.body) {
|
|
1126
|
+
const savedOutput = this.output
|
|
1127
|
+
const savedIndent = this.indent
|
|
1128
|
+
this.output = ''
|
|
1129
|
+
this.indent = 0
|
|
1130
|
+
this.generateBody(node.body)
|
|
1131
|
+
body = this.output
|
|
1132
|
+
this.output = savedOutput
|
|
1133
|
+
this.indent = savedIndent
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
return `function(${params})${uses}${returnType} {\n${body}}`
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
generateArrowFunctionExpression(node) {
|
|
1140
|
+
const params = (node.params || []).map(p => this.generateParam(p)).join(', ')
|
|
1141
|
+
const body = this.generateNode(node.body)
|
|
1142
|
+
return `fn(${params}) => ${body}`
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
generateIndexExpression(node) {
|
|
1146
|
+
const object = this.generateNode(node.object)
|
|
1147
|
+
const index = node.index ? this.generateNode(node.index) : ''
|
|
1148
|
+
return `${object}[${index}]`
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
generateNullCoalesceExpression(node) {
|
|
1088
1152
|
const left = this.generateNode(node.left)
|
|
1089
1153
|
const right = this.generateNode(node.right)
|
|
1090
|
-
return `${left}
|
|
1154
|
+
return `${left} ?? ${right}`
|
|
1091
1155
|
}
|
|
1092
1156
|
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
this.generateNode(
|
|
1157
|
+
generateYieldExpression(node) {
|
|
1158
|
+
if (node.delegate) {
|
|
1159
|
+
return `yield from ${this.generateNode(node.argument)}`
|
|
1096
1160
|
}
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1161
|
+
if (node.argument) {
|
|
1162
|
+
return `yield ${this.generateNode(node.argument)}`
|
|
1163
|
+
}
|
|
1164
|
+
return 'yield'
|
|
1101
1165
|
}
|
|
1102
1166
|
|
|
1103
1167
|
writeLine(text) {
|
|
@@ -1109,4 +1173,6 @@ class PHPGenerator {
|
|
|
1109
1173
|
}
|
|
1110
1174
|
}
|
|
1111
1175
|
|
|
1112
|
-
module.exports = {
|
|
1176
|
+
module.exports = {
|
|
1177
|
+
PHPGenerator
|
|
1178
|
+
}
|