vladx 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +256 -0
  2. package/bin/cli.js +486 -0
  3. package/bin/vlad.js +539 -0
  4. package/bin/vladpm.js +710 -0
  5. package/bin/vladx.js +491 -0
  6. package/package.json +57 -0
  7. package/src/engine/jit-compiler.js +285 -0
  8. package/src/engine/vladx-engine.js +941 -0
  9. package/src/index.js +44 -0
  10. package/src/interpreter/interpreter.js +2114 -0
  11. package/src/lexer/lexer.js +658 -0
  12. package/src/lexer/optimized-lexer.js +106 -0
  13. package/src/lexer/regex-cache.js +83 -0
  14. package/src/parser/ast-nodes.js +472 -0
  15. package/src/parser/parser.js +1408 -0
  16. package/src/runtime/advanced-type-system.js +209 -0
  17. package/src/runtime/async-manager.js +252 -0
  18. package/src/runtime/builtins.js +143 -0
  19. package/src/runtime/bundler.js +422 -0
  20. package/src/runtime/cache-manager.js +126 -0
  21. package/src/runtime/data-structures.js +612 -0
  22. package/src/runtime/debugger.js +260 -0
  23. package/src/runtime/enhanced-module-system.js +196 -0
  24. package/src/runtime/environment-enhanced.js +272 -0
  25. package/src/runtime/environment.js +140 -0
  26. package/src/runtime/event-emitter.js +232 -0
  27. package/src/runtime/formatter.js +280 -0
  28. package/src/runtime/functional.js +359 -0
  29. package/src/runtime/io-operations.js +390 -0
  30. package/src/runtime/linter.js +374 -0
  31. package/src/runtime/logging.js +314 -0
  32. package/src/runtime/minifier.js +242 -0
  33. package/src/runtime/module-system.js +377 -0
  34. package/src/runtime/network-operations.js +373 -0
  35. package/src/runtime/profiler.js +295 -0
  36. package/src/runtime/repl.js +336 -0
  37. package/src/runtime/security-manager.js +244 -0
  38. package/src/runtime/source-map-generator.js +208 -0
  39. package/src/runtime/test-runner.js +394 -0
  40. package/src/runtime/transformer.js +277 -0
  41. package/src/runtime/type-system.js +244 -0
  42. package/src/runtime/vladx-object.js +250 -0
@@ -0,0 +1,941 @@
1
+ /**
2
+ * VladX Engine — Основной движок языка
3
+ * Объединяет лексер, парсер и интерпретатор
4
+ */
5
+
6
+ import { Lexer } from '../lexer/lexer.js';
7
+ import { Parser } from '../parser/parser.js';
8
+ import { Interpreter } from '../interpreter/interpreter.js';
9
+ import { ModuleSystem } from '../runtime/module-system.js';
10
+ import { Builtins } from '../runtime/builtins.js';
11
+ import { VladXObject } from '../runtime/vladx-object.js';
12
+ import { CacheManager } from '../runtime/cache-manager.js';
13
+ import { SecurityManager } from '../runtime/security-manager.js';
14
+ import { Debugger } from '../runtime/debugger.js';
15
+ import { Profiler } from '../runtime/profiler.js';
16
+ import { REPL } from '../runtime/repl.js';
17
+ import { IOOperations } from '../runtime/io-operations.js';
18
+ import { NetworkOperations } from '../runtime/network-operations.js';
19
+ import { Functional } from '../runtime/functional.js';
20
+ import DataStructures from '../runtime/data-structures.js';
21
+ import { readFileSync, writeFileSync, existsSync } from 'fs';
22
+ import { dirname, join, extname } from 'path';
23
+ import { fileURLToPath } from 'url';
24
+
25
+ const __dirname = dirname(fileURLToPath(import.meta.url));
26
+
27
+ export class VladXEngine {
28
+ constructor(options = {}) {
29
+ this.debug = options.debug || false;
30
+ this.strictMode = options.strictMode || false;
31
+ this.maxExecutionTime = options.maxExecutionTime || 30000; // 30 секунд по умолчанию
32
+
33
+ this.cacheManager = new CacheManager(options.cache);
34
+ this.securityManager = new SecurityManager(options.security);
35
+ this.debugger = new Debugger(null);
36
+ this.profiler = new Profiler();
37
+
38
+ this.moduleSystem = new ModuleSystem(null);
39
+ this.moduleSystem.securityManager = this.securityManager;
40
+
41
+ this.interpreter = new Interpreter({
42
+ debug: this.debug,
43
+ maxExecutionTime: this.maxExecutionTime,
44
+ moduleSystem: this.moduleSystem
45
+ });
46
+
47
+ this.interpreter.debugger = this.debugger;
48
+ this.interpreter.profiler = this.profiler;
49
+
50
+ this.ioOperations = new IOOperations(this.securityManager);
51
+ this.networkOperations = new NetworkOperations(this.securityManager);
52
+
53
+ this.builtins = new Builtins(this.interpreter);
54
+
55
+ this.updateNodeModulesPaths(process.cwd());
56
+
57
+ this.registerBuiltins();
58
+ this.registerAdvancedBuiltins();
59
+ }
60
+
61
+ /**
62
+ * Обновление путей для поиска модулей в node_modules
63
+ */
64
+ updateNodeModulesPaths(projectPath) {
65
+ const paths = [];
66
+
67
+ // Добавляем локальную node_modules
68
+ paths.push(join(projectPath, 'node_modules'));
69
+
70
+ // Добавляем родительские node_modules (аналог Node.js)
71
+ let currentPath = projectPath;
72
+ const rootDir = process.env.HOME || process.env.USERPROFILE || '/';
73
+
74
+ while (currentPath !== rootDir && currentPath !== '/' && currentPath !== 'C:\\') {
75
+ currentPath = dirname(currentPath);
76
+ paths.push(join(currentPath, 'node_modules'));
77
+ }
78
+
79
+ // Добавляем глобальные модули vladpm
80
+ const globalPath = join(process.env.HOME || process.env.USERPROFILE, '.vladx', 'global_modules');
81
+ paths.push(globalPath);
82
+
83
+ this.moduleSystem.setNodeModulesPaths(paths);
84
+ }
85
+
86
+ /**
87
+ * Форматирование значения для вывода
88
+ */
89
+ formatValue(arg) {
90
+ // Проверяем, является ли это VladXObject
91
+ if (arg && typeof arg === 'object' && arg.type !== undefined) {
92
+ switch (arg.type) {
93
+ case 'null':
94
+ return 'nothing';
95
+ case 'string':
96
+ return arg.value;
97
+ case 'number':
98
+ return String(arg.value);
99
+ case 'boolean':
100
+ return arg.value ? 'истина' : 'ложь';
101
+ case 'object':
102
+ // Красивый вывод объекта
103
+ const props = [];
104
+ for (const [key, val] of Object.entries(arg.value || {})) {
105
+ props.push(`${key}: ${this.formatValue(val)}`);
106
+ }
107
+ return '{ ' + props.join(', ') + ' }';
108
+ case 'array':
109
+ const elements = (arg.value || []).map(v => this.formatValue(v));
110
+ return '[' + elements.join(', ') + ']';
111
+ case 'function':
112
+ return `<функция ${arg.name}>`;
113
+ default:
114
+ return String(arg.value);
115
+ }
116
+ }
117
+ // Обычные объекты JS
118
+ if (typeof arg === 'object' && arg !== null) {
119
+ // Проверяем, не является ли это массивом
120
+ if (Array.isArray(arg)) {
121
+ return '[' + arg.map(v => this.formatValue(v)).join(', ') + ']';
122
+ }
123
+ return JSON.stringify(arg, null, 2);
124
+ }
125
+ return String(arg);
126
+ }
127
+
128
+ /**
129
+ * Регистрация встроенных модулей и функций
130
+ */
131
+ registerBuiltins() {
132
+ // Математические функции
133
+ this.interpreter.builtins.set('максимум', (...args) => Math.max(...args));
134
+ this.interpreter.builtins.set('минимум', (...args) => Math.min(...args));
135
+ this.interpreter.builtins.set('случайный', () => Math.random());
136
+ this.interpreter.builtins.set('случайноеЦелое', (min, max) =>
137
+ Math.floor(Math.random() * (max - min + 1)) + min);
138
+ this.interpreter.builtins.set('abs', (n) => Math.abs(n));
139
+ this.interpreter.builtins.set('округлить', (n) => Math.round(n));
140
+ this.interpreter.builtins.set('пол', (n) => Math.floor(n));
141
+ this.interpreter.builtins.set('потолок', (n) => Math.ceil(n));
142
+ this.interpreter.builtins.set('корень', (n) => Math.sqrt(n));
143
+ this.interpreter.builtins.set('степень', (base, exp) => Math.pow(base, exp));
144
+ this.interpreter.builtins.set('ln', (n) => Math.log(n));
145
+ this.interpreter.builtins.set('log10', (n) => Math.log10(n));
146
+ this.interpreter.builtins.set('sin', (n) => Math.sin(n));
147
+ this.interpreter.builtins.set('cos', (n) => Math.cos(n));
148
+ this.interpreter.builtins.set('tan', (n) => Math.tan(n));
149
+ this.interpreter.builtins.set('asin', (n) => Math.asin(n));
150
+ this.interpreter.builtins.set('acos', (n) => Math.acos(n));
151
+ this.interpreter.builtins.set('atan', (n) => Math.atan(n));
152
+ this.interpreter.builtins.set('пи', () => Math.PI);
153
+ this.interpreter.builtins.set('e', () => Math.E);
154
+
155
+ // Строковые функции
156
+ this.interpreter.builtins.set('длина', (str) => str?.length ?? 0);
157
+ this.interpreter.builtins.set('нижнийРегистр', (str) => str.toLowerCase());
158
+ this.interpreter.builtins.set('верхнийРегистр', (str) => str.toUpperCase());
159
+ this.interpreter.builtins.set('обрезка', (str) => str.trim());
160
+ this.interpreter.builtins.set('заменить', (str, old, replacement) =>
161
+ str.replaceAll(old, replacement));
162
+ this.interpreter.builtins.set('разделить', (str, delimiter) => str.split(delimiter));
163
+ this.interpreter.builtins.set('соединить', (arr, delimiter) => arr.join(delimiter));
164
+ this.interpreter.builtins.set('подстрока', (str, start, end) =>
165
+ str.substring(start, end));
166
+ this.interpreter.builtins.set('кодСимвола', (str, index) => str.charCodeAt(index));
167
+ this.interpreter.builtins.set('символПоКоду', (code) => String.fromCharCode(code));
168
+ this.interpreter.builtins.set('код', (val) => JSON.stringify(val));
169
+ this.interpreter.builtins.set('разкод', (str) => JSON.parse(str));
170
+
171
+ // Функции для работы с массивами
172
+ this.interpreter.builtins.set('создатьМассив', (...args) => {
173
+ // Args are already native values since they came from nativeArgs
174
+ return VladXObject.array([...args]);
175
+ });
176
+ this.interpreter.builtins.set('объединить', (...arrays) => {
177
+ // Arrays are already native arrays since they came from nativeArgs
178
+ const nativeArrays = arrays.map(arr => Array.isArray(arr) ? arr : []);
179
+ return VladXObject.array(nativeArrays.reduce((acc, arr) => [...acc, ...arr], []));
180
+ });
181
+ this.interpreter.builtins.set('фильтр', (arr, callback) => {
182
+ // arr is already a native array since it came from nativeArgs
183
+ const nativeArray = Array.isArray(arr) ? arr : [];
184
+ return VladXObject.array(nativeArray.filter(callback));
185
+ });
186
+ this.interpreter.builtins.set('отобразить', (arr, callback) => {
187
+ // arr is already a native array since it came from nativeArgs
188
+ const nativeArray = Array.isArray(arr) ? arr : [];
189
+ return VladXObject.array(nativeArray.map(callback));
190
+ });
191
+ this.interpreter.builtins.set('уменьшить', (arr, callback, initial) => {
192
+ // arr is already a native array since it came from nativeArgs
193
+ const nativeArray = Array.isArray(arr) ? arr : [];
194
+ return nativeArray.reduce(callback, initial);
195
+ });
196
+ this.interpreter.builtins.set('найти', (arr, callback) => {
197
+ // arr is already a native array since it came from nativeArgs
198
+ const nativeArray = Array.isArray(arr) ? arr : [];
199
+ return nativeArray.find(callback);
200
+ });
201
+ this.interpreter.builtins.set('найтиИндекс', (arr, callback) => {
202
+ // arr is already a native array since it came from nativeArgs
203
+ const nativeArray = Array.isArray(arr) ? arr : [];
204
+ return nativeArray.findIndex(callback);
205
+ });
206
+ this.interpreter.builtins.set('включает', (arr, item) => {
207
+ // arr is already a native array since it came from nativeArgs
208
+ const nativeArray = Array.isArray(arr) ? arr : [];
209
+ return nativeArray.includes(item);
210
+ });
211
+ this.interpreter.builtins.set('сортировать', (arr, comparator) => {
212
+ // arr is already a native array since it came from nativeArgs
213
+ const nativeArray = Array.isArray(arr) ? arr : [];
214
+ return VladXObject.array([...nativeArray].sort(comparator));
215
+ });
216
+ this.interpreter.builtins.set('перевернуть', (arr) => {
217
+ // arr is already a native array since it came from nativeArgs
218
+ const nativeArray = Array.isArray(arr) ? arr : [];
219
+ return VladXObject.array([...nativeArray].reverse());
220
+ });
221
+ this.interpreter.builtins.set('копировать', (arr) => {
222
+ // arr is already a native array since it came from nativeArgs
223
+ const nativeArray = Array.isArray(arr) ? arr : [];
224
+ return VladXObject.array([...nativeArray]);
225
+ });
226
+ this.interpreter.builtins.set('пустой', (arr) => {
227
+ // arr is already a native array since it came from nativeArgs
228
+ const nativeArray = Array.isArray(arr) ? arr : [];
229
+ return nativeArray.length === 0;
230
+ });
231
+ this.interpreter.builtins.set('первый', (arr) => {
232
+ // arr is already a native array since it came from nativeArgs
233
+ const nativeArray = Array.isArray(arr) ? arr : [];
234
+ return nativeArray.length > 0 ? nativeArray[0] : undefined;
235
+ });
236
+ this.interpreter.builtins.set('последний', (arr) => {
237
+ // arr is already a native array since it came from nativeArgs
238
+ const nativeArray = Array.isArray(arr) ? arr : [];
239
+ return nativeArray.length > 0 ? nativeArray[nativeArray.length - 1] : undefined;
240
+ });
241
+ this.interpreter.builtins.set('хвост', (arr) => {
242
+ // arr is already a native array since it came from nativeArgs
243
+ const nativeArray = Array.isArray(arr) ? arr : [];
244
+ return VladXObject.array(nativeArray.length > 0 ? nativeArray.slice(1) : []);
245
+ });
246
+ this.interpreter.builtins.set('голова', (arr) => {
247
+ // arr is already a native array since it came from nativeArgs
248
+ const nativeArray = Array.isArray(arr) ? arr : [];
249
+ return VladXObject.array(nativeArray.length > 0 ? nativeArray.slice(0, -1) : []);
250
+ });
251
+ this.interpreter.builtins.set('добавить', (arr, item) => {
252
+ // arr is already a native array since it came from nativeArgs
253
+ const nativeArray = Array.isArray(arr) ? arr : [];
254
+ const newArr = [...nativeArray];
255
+ newArr.push(item);
256
+ return VladXObject.array(newArr);
257
+ });
258
+ this.interpreter.builtins.set('вставить', (arr, index, item) => {
259
+ // arr is already a native array since it came from nativeArgs
260
+ if (!Array.isArray(arr)) {
261
+ console.warn(`Предупреждение: функция 'вставить' ожидает массив, получено: ${typeof arr}`);
262
+ return VladXObject.array([item]);
263
+ }
264
+ if (typeof index !== 'number' || !Number.isInteger(index)) {
265
+ throw new Error(`Индекс должен быть целым числом, получено: ${typeof index} (${index})`);
266
+ }
267
+ if (index < 0 || index > arr.length) {
268
+ throw new Error(`Индекс ${index} выходит за пределы допустимого диапазона [0, ${arr.length}]`);
269
+ }
270
+ const newArr = [...arr];
271
+ newArr.splice(index, 0, item);
272
+ return VladXObject.array(newArr);
273
+ });
274
+ this.interpreter.builtins.set('удалить', (arr, index) => {
275
+ // arr is already a native array since it came from nativeArgs
276
+ if (!Array.isArray(arr)) {
277
+ console.warn(`Предупреждение: функция 'удалить' ожидает массив, получено: ${typeof arr}`);
278
+ return VladXObject.array([]);
279
+ }
280
+ if (typeof index !== 'number' || !Number.isInteger(index)) {
281
+ throw new Error(`Индекс должен быть целым числом, получено: ${typeof index} (${index})`);
282
+ }
283
+ if (index < 0 || index >= arr.length) {
284
+ throw new Error(`Индекс ${index} выходит за пределы массива длиной ${arr.length}`);
285
+ }
286
+ const newArr = [...arr];
287
+ newArr.splice(index, 1);
288
+ return VladXObject.array(newArr);
289
+ });
290
+ this.interpreter.builtins.set('размер', (arr) => {
291
+ // arr is already a native array since it came from nativeArgs
292
+ const nativeArray = Array.isArray(arr) ? arr : [];
293
+ return nativeArray.length;
294
+ });
295
+ this.interpreter.builtins.set('каждый', (arr, callback) => {
296
+ // arr is already a native array since it came from nativeArgs
297
+ const nativeArray = Array.isArray(arr) ? arr : [];
298
+ return nativeArray.every(callback);
299
+ });
300
+ this.interpreter.builtins.set('некоторые', (arr, callback) => {
301
+ // arr is already a native array since it came from nativeArgs
302
+ const nativeArray = Array.isArray(arr) ? arr : [];
303
+ return nativeArray.some(callback);
304
+ });
305
+ this.interpreter.builtins.set('срез', (arr, start, end) => {
306
+ // arr is already a native array since it came from nativeArgs
307
+ if (!Array.isArray(arr)) {
308
+ console.warn(`Предупреждение: функция 'срез' ожидает массив, получено: ${typeof arr}`);
309
+ return VladXObject.array([]);
310
+ }
311
+ if (typeof start !== 'number' || !Number.isInteger(start)) {
312
+ throw new Error(`Начальный индекс должен быть целым числом, получено: ${typeof start} (${start})`);
313
+ }
314
+ if (typeof end !== 'number' && end !== undefined) {
315
+ throw new Error(`Конечный индекс должен быть числом или undefined, получено: ${typeof end} (${end})`);
316
+ }
317
+ if (start < 0) start = Math.max(0, arr.length + start);
318
+ if (end !== undefined && end < 0) end = arr.length + end;
319
+ if (start > arr.length) start = arr.length;
320
+ if (end !== undefined && end > arr.length) end = arr.length;
321
+ if (start < 0) start = 0;
322
+ if (end !== undefined && end < 0) end = 0;
323
+
324
+ return VladXObject.array(arr.slice(start, end));
325
+ });
326
+ this.interpreter.builtins.set('заполнить', (arr, value, start = 0, end = arr.length) => {
327
+ // arr is already a native array since it came from nativeArgs
328
+ if (!Array.isArray(arr)) {
329
+ console.warn(`Предупреждение: функция 'заполнить' ожидает массив, получено: ${typeof arr}`);
330
+ return VladXObject.array([]);
331
+ }
332
+ if (typeof start !== 'number' || !Number.isInteger(start)) {
333
+ throw new Error(`Начальный индекс должен быть целым числом, получено: ${typeof start} (${start})`);
334
+ }
335
+ if (typeof end !== 'number' || !Number.isInteger(end)) {
336
+ throw new Error(`Конечный индекс должен быть целым числом, получено: ${typeof end} (${end})`);
337
+ }
338
+ const newArr = [...arr];
339
+ newArr.fill(value, start, end);
340
+ return VladXObject.array(newArr);
341
+ });
342
+ this.interpreter.builtins.set('развернуть', (arr) => {
343
+ // arr is already a native array since it came from nativeArgs
344
+ const nativeArray = Array.isArray(arr) ? arr : [];
345
+ return VladXObject.array(nativeArray.flat());
346
+ });
347
+ this.interpreter.builtins.set('развернутьГлубоко', (arr, depth = 1) => {
348
+ // arr is already a native array since it came from nativeArgs
349
+ const nativeArray = Array.isArray(arr) ? arr : [];
350
+ return VladXObject.array(nativeArray.flat(depth));
351
+ });
352
+
353
+ // Функции для работы с объектами
354
+ this.interpreter.builtins.set('объект', (obj = {}) => {
355
+ // obj is already a native object since it came from nativeArgs
356
+ const nativeObj = obj && typeof obj === 'object' ? obj : {};
357
+ return VladXObject.object({...nativeObj});
358
+ });
359
+ this.interpreter.builtins.set('ключи', (obj) => Object.keys(obj));
360
+ this.interpreter.builtins.set('значения', (obj) => Object.values(obj));
361
+ this.interpreter.builtins.set('пары', (obj) => Object.entries(obj));
362
+ this.interpreter.builtins.set('слить', (...objects) =>
363
+ objects.reduce((acc, obj) => ({...acc, ...obj}), {}));
364
+ this.interpreter.builtins.set('из', (obj, key) => obj[key]);
365
+ this.interpreter.builtins.set('в', (obj, key, value) => {
366
+ const newObj = {...obj};
367
+ newObj[key] = value;
368
+ return newObj;
369
+ });
370
+ this.interpreter.builtins.set('удалитьСвойство', (obj, key) => {
371
+ const newObj = {...obj};
372
+ delete newObj[key];
373
+ return newObj;
374
+ });
375
+ this.interpreter.builtins.set('проверить', (obj, key) => key in obj);
376
+
377
+ // Системные функции
378
+ const engine = this; // Capture engine reference for use in builtins
379
+ this.interpreter.builtins.set('печать', (...args) => {
380
+ console.log(...args.map(arg => engine.formatValue(arg)));
381
+ });
382
+ this.interpreter.builtins.set('вывод', (...args) => {
383
+ process.stdout.write(args.map(arg => engine.formatValue(arg)).join(' '));
384
+ });
385
+ this.interpreter.builtins.set('ждать', (ms) => new Promise(resolve =>
386
+ setTimeout(resolve, ms)));
387
+ this.interpreter.builtins.set('время', () => Date.now());
388
+ this.interpreter.builtins.set('дата', () => new Date());
389
+ this.interpreter.builtins.set('форматДаты', (date, format) => {
390
+ const pad = n => String(n).padStart(2, '0');
391
+ return format
392
+ .replace('YYYY', date.getFullYear())
393
+ .replace('MM', pad(date.getMonth() + 1))
394
+ .replace('DD', pad(date.getDate()))
395
+ .replace('HH', pad(date.getHours()))
396
+ .replace('mm', pad(date.getMinutes()))
397
+ .replace('ss', pad(date.getSeconds()));
398
+ });
399
+
400
+ // Ввод от пользователя
401
+ this.interpreter.builtins.set('ввести', async (prompt = '') => {
402
+ const readline = await import('readline');
403
+ const rl = readline.createInterface({
404
+ input: process.stdin,
405
+ output: process.stdout
406
+ });
407
+
408
+ return new Promise((resolve) => {
409
+ rl.question(prompt, (answer) => {
410
+ rl.close();
411
+ resolve(answer);
412
+ });
413
+ });
414
+ });
415
+
416
+ // Файловые операции (улучшенные)
417
+ this.interpreter.builtins.set('файлЧитать', (path) => {
418
+ try {
419
+ return readFileSync(path, 'utf-8');
420
+ } catch (e) {
421
+ throw new Error(`Не удалось прочитать файл: ${path}: ${e.message}`);
422
+ }
423
+ });
424
+ this.interpreter.builtins.set('файлЗаписать', (path, content) => {
425
+ try {
426
+ writeFileSync(path, content, 'utf-8');
427
+ return true;
428
+ } catch (e) {
429
+ throw new Error(`Не удалось записать файл: ${path}: ${e.message}`);
430
+ }
431
+ });
432
+ this.interpreter.builtins.set('файлСуществует', (path) => existsSync(path));
433
+
434
+ // Сетевые функции (улучшенные)
435
+ this.interpreter.builtins.set('запрос', async (url, options = {}) => {
436
+ const https = await import('https');
437
+ const http = await import('http');
438
+
439
+ return new Promise((resolve, reject) => {
440
+ const urlObj = new URL(url);
441
+ const client = urlObj.protocol === 'https:' ? https : http;
442
+
443
+ const req = client.request(url, {
444
+ method: options.method || 'GET',
445
+ headers: options.headers || {}
446
+ }, (res) => {
447
+ let data = '';
448
+ res.on('data', chunk => data += chunk);
449
+ res.on('end', () => {
450
+ if (options.raw) {
451
+ resolve({
452
+ status: res.statusCode,
453
+ headers: res.headers,
454
+ body: data
455
+ });
456
+ } else {
457
+ try {
458
+ resolve(JSON.parse(data));
459
+ } catch {
460
+ resolve(data);
461
+ }
462
+ }
463
+ });
464
+ });
465
+
466
+ req.on('error', reject);
467
+ if (options.body) {
468
+ req.write(options.body);
469
+ }
470
+ req.end();
471
+ });
472
+ });
473
+
474
+ // Криптографические функции
475
+ this.interpreter.builtins.set('хешMD5', async (str) => {
476
+ const crypto = await import('crypto');
477
+ return crypto.createHash('md5').update(str).digest('hex');
478
+ });
479
+ this.interpreter.builtins.set('хешSHA256', async (str) => {
480
+ const crypto = await import('crypto');
481
+ return crypto.createHash('sha256').update(str).digest('hex');
482
+ });
483
+ this.interpreter.builtins.set('генUUID', () => {
484
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
485
+ const r = Math.random() * 16 | 0;
486
+ return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
487
+ });
488
+ });
489
+
490
+ // Регулярные выражения
491
+ this.interpreter.builtins.set('регex', (pattern, flags = '') => new RegExp(pattern, flags));
492
+ this.interpreter.builtins.set('сопоставить', (str, regex) => str.match(regex));
493
+ this.interpreter.builtins.set('заменитьРВ', (str, regex, replacement) =>
494
+ str.replace(regex, replacement));
495
+ this.interpreter.builtins.set('разбитьРВ', (str, regex) => str.split(regex));
496
+
497
+ // Типы и проверки
498
+ this.interpreter.builtins.set('тип', (val) => {
499
+ // Проверяем, является ли это VladXObject
500
+ if (val && typeof val === 'object' && val.type !== undefined) {
501
+ switch (val.type) {
502
+ case 'null': return 'ничто';
503
+ case 'string': return 'строка';
504
+ case 'number': return 'число';
505
+ case 'boolean': return 'логический';
506
+ case 'array': return 'массив';
507
+ case 'object': return 'объект';
508
+ case 'function': return 'функция';
509
+ case 'closure': return 'замыкание';
510
+ case 'class': return 'класс';
511
+ case 'instance': return 'экземпляр';
512
+ default: return val.type;
513
+ }
514
+ }
515
+ if (val === null) return 'ничто';
516
+ if (val === undefined) return 'неопределено';
517
+ if (Array.isArray(val)) return 'массив';
518
+ return typeof val;
519
+ });
520
+ this.interpreter.builtins.set('этоЧисло', (val) => typeof val === 'number' && !isNaN(val));
521
+ this.interpreter.builtins.set('этоСтрока', (val) => typeof val === 'string');
522
+ this.interpreter.builtins.set('этоМассив', (val) => Array.isArray(val));
523
+ this.interpreter.builtins.set('этоОбъект', (val) => typeof val === 'object' && val !== null && !Array.isArray(val));
524
+ this.interpreter.builtins.set('этоФункция', (val) => typeof val === 'function');
525
+ this.interpreter.builtins.set('этоЛогическое', (val) => typeof val === 'boolean');
526
+ this.interpreter.builtins.set('этоПустой', (val) => {
527
+ if (val === null || val === undefined) return true;
528
+ if (typeof val === 'string') return val.length === 0;
529
+ if (Array.isArray(val)) return val.length === 0;
530
+ if (typeof val === 'object') return Object.keys(val).length === 0;
531
+ return false;
532
+ });
533
+
534
+ // Конвертация типов
535
+ this.interpreter.builtins.set('вСтроку', (val) => String(val));
536
+ this.interpreter.builtins.set('вЧисло', (val) => {
537
+ const n = Number(val);
538
+ if (isNaN(n)) throw new Error('Не удалось конвертировать в число');
539
+ return n;
540
+ });
541
+ this.interpreter.builtins.set('вМассив', (val) => {
542
+ if (Array.isArray(val)) return val;
543
+ if (val === null || val === undefined) return [];
544
+ return [val];
545
+ });
546
+
547
+ // Функциональное программирование
548
+ this.interpreter.builtins.set('частичное', (fn, ...args) =>
549
+ (...moreArgs) => fn(...args, ...moreArgs));
550
+ this.interpreter.builtins.set('композиция', (...fns) =>
551
+ (arg) => fns.reduce((acc, fn) => fn(acc), arg));
552
+ this.interpreter.builtins.set('труба', (val, ...fns) =>
553
+ fns.reduce((acc, fn) => fn(acc), val));
554
+ this.interpreter.builtins.set('мемоизировать', (fn) => {
555
+ const cache = new Map();
556
+ return (...args) => {
557
+ const key = JSON.stringify(args);
558
+ if (cache.has(key)) return cache.get(key);
559
+ const result = fn(...args);
560
+ cache.set(key, result);
561
+ return result;
562
+ };
563
+ });
564
+
565
+ // Асинхронные утилиты
566
+ this.interpreter.builtins.set('обещание', (executor) => new Promise(executor));
567
+ this.interpreter.builtins.set('всеОбещания', (promises) => Promise.all(promises));
568
+ this.interpreter.builtins.set('любоеОбещание', (promises) => Promise.any(promises));
569
+ this.interpreter.builtins.set('всеОбещанияКакОбъект', async (obj) => {
570
+ const keys = Object.keys(obj);
571
+ const promises = Object.values(obj);
572
+ const results = await Promise.all(promises);
573
+ return keys.reduce((acc, key, i) => {
574
+ acc[key] = results[i];
575
+ return acc;
576
+ }, {});
577
+ });
578
+
579
+ // Генераторы
580
+ this.interpreter.builtins.set('диапазон', function* (start, end, step = 1) {
581
+ if (end === undefined) {
582
+ end = start;
583
+ start = 0;
584
+ }
585
+ for (let i = start; step > 0 ? i < end : i > end; i += step) {
586
+ yield i;
587
+ }
588
+ });
589
+ this.interpreter.builtins.set('генерировать', function* (callback) {
590
+ let index = 0;
591
+ while (true) {
592
+ const result = callback(index++);
593
+ if (result.done) break;
594
+ yield result.value;
595
+ }
596
+ });
597
+
598
+ // Бинарные операции
599
+ this.interpreter.builtins.set('битИ', (a, b) => a & b);
600
+ this.interpreter.builtins.set('битИЛИ', (a, b) => a | b);
601
+ this.interpreter.builtins.set('битИСКЛ', (a, b) => a ^ b);
602
+ this.interpreter.builtins.set('битНЕ', (a) => ~a);
603
+ this.interpreter.builtins.set('сдвигВлево', (a, n) => a << n);
604
+ this.interpreter.builtins.set('сдвигВправо', (a, n) => a >> n);
605
+ this.interpreter.builtins.set('беззнаковыйСдвиг', (a, n) => a >>> n);
606
+ }
607
+
608
+ /**
609
+ * Регистрация продвинутых встроенных функций
610
+ */
611
+ registerAdvancedBuiltins() {
612
+ // Кэш менеджер
613
+ this.interpreter.builtins.set('кэшПолучить', (key) => this.cacheManager.get(key));
614
+ this.interpreter.builtins.set('кэшУстановить', (key, value) => {
615
+ this.cacheManager.set(key, value);
616
+ return true;
617
+ });
618
+ this.interpreter.builtins.set('кэшУдалить', (key) => this.cacheManager.delete(key));
619
+ this.interpreter.builtins.set('кэшОчистить', () => {
620
+ this.cacheManager.clear();
621
+ return true;
622
+ });
623
+ this.interpreter.builtins.set('кэшСтатистика', () => this.cacheManager.getStats());
624
+
625
+ // Безопасность
626
+ this.interpreter.builtins.set('проверитьПуть', (path) => {
627
+ this.securityManager.checkPath(path);
628
+ return true;
629
+ });
630
+ this.interpreter.builtins.set('проверитьURL', (url) => {
631
+ this.securityManager.checkURL(url);
632
+ return true;
633
+ });
634
+ this.interpreter.builtins.set('санитизировать', (data) => this.securityManager.sanitizeJSON(data));
635
+ this.interpreter.builtins.set('экранироватьHTML', (str) => this.securityManager.escapeHTML(str));
636
+
637
+ // Отладчик
638
+ this.interpreter.builtins.set('точкаОстанова', (filename, line) => {
639
+ this.debugger.setBreakpoint(filename, line);
640
+ return true;
641
+ });
642
+ this.interpreter.builtins.set('удалитьТочкуОстанова', (filename, line) => {
643
+ this.debugger.removeBreakpoint(filename, line);
644
+ return true;
645
+ });
646
+ this.interpreter.builtins.set('пошаговыйРежим', () => {
647
+ this.debugger.stepInto();
648
+ });
649
+ this.interpreter.builtins.set('продолжить', () => {
650
+ this.debugger.continue();
651
+ });
652
+ this.interpreter.builtins.set('стекВызовов', () => this.debugger.getCallStack());
653
+ this.interpreter.builtins.set('локальныеПеременные', () => this.debugger.getLocals(this.debugger.currentFrame));
654
+
655
+ // Профайлер
656
+ this.interpreter.builtins.set('стартПрофилирования', () => {
657
+ this.profiler.start();
658
+ return true;
659
+ });
660
+ this.interpreter.builtins.set('стопПрофилирования', () => this.profiler.stop());
661
+ this.interpreter.builtins.set('результатыПрофилирования', () => this.profiler.getResults());
662
+
663
+ // Функциональное программирование
664
+ this.interpreter.builtins.set('каррировать', Functional.curry);
665
+ this.interpreter.builtins.set('композиция', Functional.compose);
666
+ this.interpreter.builtins.set('труба', Functional.pipe);
667
+ this.interpreter.builtins.set('мемоизировать', Functional.memoize);
668
+ this.interpreter.builtins.set('частично', Functional.partial);
669
+ this.interpreter.builtins.set('инвертировать', Functional.flip);
670
+ this.interpreter.builtins.set('одинРаз', Functional.once);
671
+ this.interpreter.builtins.set('отладить', Functional.trace);
672
+
673
+ // Maybe монада
674
+ this.interpreter.builtins.set('можетБыть', Functional.Maybe);
675
+ this.interpreter.builtins.set('илиИначе', (maybe, defaultValue) => maybe.getOrElse(defaultValue));
676
+
677
+ // Структуры данных
678
+ this.interpreter.builtins.set('Стек', () => new DataStructures.Stack());
679
+ this.interpreter.builtins.set('Очередь', () => new DataStructures.Queue());
680
+ this.interpreter.builtins.set('СвязныйСписок', () => new DataStructures.LinkedList());
681
+ this.interpreter.builtins.set('ПриоритетнаяОчередь', (comparator) => new DataStructures.PriorityQueue(comparator));
682
+ this.interpreter.builtins.set('Множество', () => new DataStructures.SetCustom());
683
+ this.interpreter.builtins.set('Карта', () => new DataStructures.MapCustom());
684
+ this.interpreter.builtins.set('Дерево', () => new DataStructures.Trie());
685
+ this.interpreter.builtins.set('БинарноеДерево', (compareFn) => new DataStructures.BinarySearchTree(compareFn));
686
+
687
+ // I/O операции
688
+ this.interpreter.builtins.set('файлПрочитатьПоток', (path, options) => this.ioOperations.readFileStream(path, options));
689
+ this.interpreter.builtins.set('файлЗаписатьПоток', (path, content, options) => this.ioOperations.writeFileStream(path, content, options));
690
+ this.interpreter.builtins.set('файлИнформация', (path) => this.ioOperations.getFileInfo(path));
691
+ this.interpreter.builtins.set('директорияПрочитать', (path, options) => this.ioOperations.readDirectory(path, options));
692
+ this.interpreter.builtins.set('директорияСоздать', (path, options) => this.ioOperations.createDirectory(path, options));
693
+ this.interpreter.builtins.set('файлУдалить', (path) => this.ioOperations.deleteFile(path));
694
+ this.interpreter.builtins.set('директорияУдалить', (path, options) => this.ioOperations.deleteDirectory(path, options));
695
+ this.interpreter.builtins.set('файлКопировать', (src, dest) => this.ioOperations.copyFile(src, dest));
696
+ this.interpreter.builtins.set('файлПереместить', (src, dest) => this.ioOperations.moveFile(src, dest));
697
+ this.interpreter.builtins.set('смотретьФайл', (path, callback, options) => this.ioOperations.watchFile(path, callback, options));
698
+ this.interpreter.builtins.set('найтиФайлы', (path, pattern, options) => this.ioOperations.findFiles(path, pattern, options));
699
+ this.interpreter.builtins.set('размерДиректории', (path) => this.ioOperations.getDirectorySize(path));
700
+ this.interpreter.builtins.set('mimeТип', (path) => this.ioOperations.getMimeType(path));
701
+
702
+ // Сетевые операции
703
+ this.interpreter.builtins.set('httpGet', (url, options) => this.networkOperations.get(url, options));
704
+ this.interpreter.builtins.set('httpPost', (url, data, options) => this.networkOperations.post(url, data, options));
705
+ this.interpreter.builtins.set('httpPut', (url, data, options) => this.networkOperations.put(url, data, options));
706
+ this.interpreter.builtins.set('httpDelete', (url, options) => this.networkOperations.delete(url, options));
707
+ this.interpreter.builtins.set('httpPatch', (url, data, options) => this.networkOperations.patch(url, data, options));
708
+ this.interpreter.builtins.set('httpЗапрос', (url, options) => this.networkOperations.request(url, options));
709
+ this.interpreter.builtins.set('скачатьФайл', (url, destPath) => this.networkOperations.downloadFile(url, destPath));
710
+ this.interpreter.builtins.set('загрузитьФайл', (url, filePath, options) => this.networkOperations.uploadFile(url, filePath, options));
711
+ this.interpreter.builtins.set('проверитьURL', (url) => this.networkOperations.checkUrl(url));
712
+ this.interpreter.builtins.set('multipartForm', () => this.networkOperations.createMultipartForm());
713
+ }
714
+
715
+ /**
716
+ * Выполнение кода из строки (асинхронное)
717
+ */
718
+ async execute(source, options = {}) {
719
+ const filename = options.filename || '<anonymous>';
720
+ const context = options.context || null;
721
+
722
+ if (this.debug) {
723
+ console.log(`[VladX] Начинаем выполнение: ${filename}`);
724
+ }
725
+
726
+ try {
727
+ if (this.debug) {
728
+ console.log('[Engine] Starting lexing');
729
+ }
730
+ // Лексический анализ
731
+ const lexer = new Lexer(source, filename);
732
+ const tokens = lexer.tokenize();
733
+ if (this.debug) {
734
+ console.log('[Engine] Tokens count:', tokens.length);
735
+ }
736
+
737
+ if (this.debug) {
738
+ console.log(`[VladX] Получено токенов: ${tokens.length}`);
739
+ }
740
+
741
+ if (this.debug) {
742
+ console.log('[Engine] Starting parsing');
743
+ }
744
+ // Синтаксический анализ
745
+ const parser = new Parser(tokens, { debug: this.debug });
746
+ const ast = parser.parse();
747
+ if (this.debug) {
748
+ console.log('[Engine] AST body length:', ast.body.length);
749
+ }
750
+
751
+ if (this.debug) {
752
+ console.log(`[VladX] AST создан: ${ast.body.length} узлов`);
753
+ }
754
+
755
+ if (this.debug) {
756
+ console.log('[Engine] Starting interpretation');
757
+ }
758
+ // Интерпретация
759
+ const result = await this.interpreter.interpret(ast, {
760
+ filename,
761
+ context,
762
+ modulePath: options.modulePath || process.cwd()
763
+ });
764
+
765
+ if (this.debug) {
766
+ console.log('[VladX] Raw result:', result);
767
+ console.log('[VladX] Result type:', result?.type);
768
+ console.log('[VladX] Result value:', result?.value);
769
+ }
770
+
771
+ if (this.debug) {
772
+ console.log(`[VladX] Результат:`, result);
773
+ }
774
+
775
+ return result;
776
+ } catch (error) {
777
+ if (error instanceof VladXObject && error.type === 'error') {
778
+ throw error;
779
+ }
780
+ // Получаем сообщение об ошибке или используем более подробное описание
781
+ let errorMessage = error.toString ? error.toString() : String(error);
782
+ if (!errorMessage) {
783
+ errorMessage = `Ошибка типа: ${error.constructor.name}`;
784
+ if (error.stack) {
785
+ errorMessage += `\nСтек вызовов: ${error.stack}`;
786
+ } else {
787
+ errorMessage += ' (Стек вызовов недоступен)';
788
+ }
789
+ }
790
+ throw new VladXObject('error', errorMessage, {
791
+ stack: error.stack
792
+ });
793
+ }
794
+ }
795
+
796
+ /**
797
+ * Выполнение файла
798
+ */
799
+ async executeFile(filepath) {
800
+ const { readFileSync, existsSync } = await import('fs');
801
+ const { dirname, join } = await import('path');
802
+ const { fileURLToPath } = await import('url');
803
+
804
+ const __dirname = dirname(fileURLToPath(import.meta.url));
805
+
806
+ if (!existsSync(filepath)) {
807
+ throw new VladXObject('error', `Файл не найден: ${filepath}`);
808
+ }
809
+
810
+ // Обновляем пути node_modules для текущего проекта
811
+ this.updateNodeModulesPaths(dirname(filepath));
812
+
813
+ const source = readFileSync(filepath, 'utf-8');
814
+ const modulePath = dirname(filepath);
815
+
816
+ return this.execute(source, {
817
+ filename: filepath,
818
+ modulePath
819
+ });
820
+ }
821
+
822
+ /**
823
+ * REPL режим
824
+ */
825
+ async repl(inputStream = process.stdin, outputStream = process.stdout) {
826
+ const repl = new REPL(this, {
827
+ input: inputStream,
828
+ output: outputStream
829
+ });
830
+
831
+ await repl.start();
832
+ }
833
+
834
+ /**
835
+ * Компиляция в JavaScript (транспиляция)
836
+ */
837
+ compile(source) {
838
+ const lexer = new Lexer(source);
839
+ const tokens = lexer.tokenize();
840
+ const parser = new Parser(tokens);
841
+ const ast = parser.parse();
842
+
843
+ return this.astToJs(ast);
844
+ }
845
+
846
+ /**
847
+ * Преобразование AST в JavaScript код
848
+ */
849
+ astToJs(ast) {
850
+ // Базовое преобразование AST в JS
851
+ return ast.body.map(node => this.nodeToJs(node)).join(';\n');
852
+ }
853
+
854
+ /**
855
+ * Преобразование отдельного узла AST в JS
856
+ */
857
+ nodeToJs(node) {
858
+ switch (node.type) {
859
+ case 'Program':
860
+ return node.body.map(n => this.nodeToJs(n)).join(';\n');
861
+
862
+ case 'LetStatement':
863
+ const init = node.initializer ? this.nodeToJs(node.initializer) : 'undefined';
864
+ return `let ${node.name} = ${init}`;
865
+
866
+ case 'ConstStatement':
867
+ const constInit = node.initializer ? this.nodeToJs(node.initializer) : 'undefined';
868
+ return `const ${node.name} = ${constInit}`;
869
+
870
+ case 'ReturnStatement':
871
+ return `return ${node.value ? this.nodeToJs(node.value) : 'undefined'}`;
872
+
873
+ case 'ExpressionStatement':
874
+ return this.nodeToJs(node.expression);
875
+
876
+ case 'BinaryExpression':
877
+ const left = this.nodeToJs(node.left);
878
+ const right = this.nodeToJs(node.right);
879
+ return `(${left} ${node.operator} ${right})`;
880
+
881
+ case 'UnaryExpression':
882
+ const operand = this.nodeToJs(node.operand);
883
+ return `${node.operator}${operand}`;
884
+
885
+ case 'Identifier':
886
+ return node.name;
887
+
888
+ case 'Literal':
889
+ return JSON.stringify(node.value);
890
+
891
+ case 'FunctionDeclaration':
892
+ const params = node.params.map(p => p.name).join(', ');
893
+ const body = node.body.map(b => this.nodeToJs(b)).join(';\n');
894
+ return `function ${node.name}(${params}) { ${body} }`;
895
+
896
+ case 'CallExpression':
897
+ const args = node.args.map(a => this.nodeToJs(a)).join(', ');
898
+ return `${node.callee}(${args})`;
899
+
900
+ case 'IfStatement':
901
+ const condition = this.nodeToJs(node.condition);
902
+ const thenBranch = node.thenBranch.body ? node.thenBranch.body.map(b => this.nodeToJs(b)).join(';\n') : this.nodeToJs(node.thenBranch);
903
+ let result = `if (${condition}) { ${thenBranch} }`;
904
+ if (node.elseBranch) {
905
+ const elseBranch = node.elseBranch.body ? node.elseBranch.body.map(b => this.nodeToJs(b)).join(';\n') : this.nodeToJs(node.elseBranch);
906
+ result += ` else { ${elseBranch} }`;
907
+ }
908
+ return result;
909
+
910
+ case 'WhileStatement':
911
+ const whileCond = this.nodeToJs(node.condition);
912
+ const whileBody = node.thenBranch.body ? node.thenBranch.body.map(b => this.nodeToJs(b)).join(';\n') : this.nodeToJs(node.body);
913
+ return `while (${whileCond}) { ${whileBody} }`;
914
+
915
+ case 'ForStatement':
916
+ const forInit = this.nodeToJs(node.initializer);
917
+ const forCond = this.nodeToJs(node.condition);
918
+ const forUpdate = this.nodeToJs(node.update);
919
+ const forBody = node.thenBranch.body ? node.thenBranch.body.map(b => this.nodeToJs(b)).join(';\n') : this.nodeToJs(node.body);
920
+ return `for (${forInit}; ${forCond}; ${forUpdate}) { ${forBody} }`;
921
+
922
+ case 'ClassDeclaration':
923
+ const methods = node.methods.map(m => {
924
+ const methodParams = m.params.map(p => p.name).join(', ');
925
+ const methodBody = m.thenBranch.body ? m.thenBranch.body.map(b => this.nodeToJs(b)).join(';\n') : this.nodeToJs(m.body);
926
+ return `${m.name}(${methodParams}) { ${methodBody} }`;
927
+ }).join(', ');
928
+ return `class ${node.name} { ${methods} }`;
929
+
930
+ case 'MemberExpression':
931
+ const obj = this.nodeToJs(node.object);
932
+ const prop = this.nodeToJs(node.property);
933
+ return `${obj}.${prop}`;
934
+
935
+ default:
936
+ throw new Error(`Неизвестный тип узла: ${node.type}`);
937
+ }
938
+ }
939
+ }
940
+
941
+ export default VladXEngine;