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
package/bin/vladx.js ADDED
@@ -0,0 +1,491 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI — Интерфейс командной строки для VladX
4
+ */
5
+
6
+ import { VladXEngine } from '../src/engine/vladx-engine.js';
7
+ import { Linter } from '../src/runtime/linter.js';
8
+ import { Formatter } from '../src/runtime/formatter.js';
9
+ import { Logging } from '../src/runtime/logging.js';
10
+ import { readFileSync, writeFileSync, existsSync } from 'fs';
11
+ import { resolve, dirname, join, basename } from 'path';
12
+
13
+ const logger = new Logging({ level: 'info' });
14
+
15
+ export class CLI {
16
+ constructor() {
17
+ this.engine = null;
18
+ this.commands = new Map();
19
+ this.registerCommands();
20
+ }
21
+
22
+ /**
23
+ * Регистрация команд
24
+ */
25
+ registerCommands() {
26
+ this.commands.set('run', this.run.bind(this));
27
+ this.commands.set('repl', this.repl.bind(this));
28
+ this.commands.set('compile', this.compile.bind(this));
29
+ this.commands.set('lint', this.lint.bind(this));
30
+ this.commands.set('format', this.format.bind(this));
31
+ this.commands.set('test', this.test.bind(this));
32
+ this.commands.set('bundle', this.bundle.bind(this));
33
+ this.commands.set('watch', this.watch.bind(this));
34
+ this.commands.set('debug', this.debug.bind(this));
35
+ this.commands.set('help', this.help.bind(this));
36
+ }
37
+
38
+ /**
39
+ * Запуск CLI
40
+ */
41
+ async run(argv) {
42
+ const command = argv[2];
43
+ const args = argv.slice(3);
44
+
45
+ if (!command || !this.commands.has(command)) {
46
+ this.help();
47
+ return;
48
+ }
49
+
50
+ const cmd = this.commands.get(command);
51
+
52
+ try {
53
+ await cmd(args);
54
+ } catch (error) {
55
+ logger.error(`Ошибка: ${error.message}`);
56
+ process.exit(1);
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Выполнить файл
62
+ */
63
+ async run(args) {
64
+ if (args.length === 0) {
65
+ logger.error('Укажите файл для выполнения');
66
+ return;
67
+ }
68
+
69
+ const filepath = resolve(args[0]);
70
+ const options = this.parseOptions(args.slice(1));
71
+
72
+ if (!existsSync(filepath)) {
73
+ throw new Error(`Файл не найден: ${filepath}`);
74
+ }
75
+
76
+ const startTime = Date.now();
77
+ this.engine = new VladXEngine({
78
+ debug: options.debug || false,
79
+ strictMode: options.strict || false,
80
+ maxExecutionTime: options.timeout || 30000,
81
+ cache: options.cache,
82
+ security: options.security
83
+ });
84
+
85
+ try {
86
+ const result = await this.engine.executeFile(filepath);
87
+
88
+ if (options.time) {
89
+ const duration = Date.now() - startTime;
90
+ logger.info(`Время выполнения: ${duration}ms`);
91
+ }
92
+
93
+ if (result !== undefined && !options.silent) {
94
+ logger.info('Результат:', result);
95
+ }
96
+
97
+ process.exit(0);
98
+ } catch (error) {
99
+ logger.error(error.message);
100
+ process.exit(1);
101
+ }
102
+ }
103
+
104
+ /**
105
+ * REPL режим
106
+ */
107
+ async repl(args) {
108
+ const options = this.parseOptions(args);
109
+
110
+ this.engine = new VladXEngine({
111
+ debug: options.debug || false,
112
+ cache: options.cache,
113
+ security: options.security
114
+ });
115
+
116
+ await this.engine.repl();
117
+ }
118
+
119
+ /**
120
+ * Компиляция
121
+ */
122
+ async compile(args) {
123
+ if (args.length === 0) {
124
+ logger.error('Укажите файл для компиляции');
125
+ return;
126
+ }
127
+
128
+ const filepath = resolve(args[0]);
129
+ const options = this.parseOptions(args.slice(1));
130
+
131
+ if (!existsSync(filepath)) {
132
+ throw new Error(`Файл не найден: ${filepath}`);
133
+ }
134
+
135
+ this.engine = new VladXEngine();
136
+
137
+ const jsCode = this.engine.compile(readFileSync(filepath, 'utf-8'));
138
+
139
+ let output = options.output || filepath.replace(/\.vx$/, '.js');
140
+
141
+ if (options.format === 'cjs') {
142
+ jsCode = `"use strict";\n${jsCode}`;
143
+ }
144
+
145
+ writeFileSync(output, jsCode, 'utf-8');
146
+ logger.info(`Скомпилировано: ${filepath} -> ${output}`);
147
+ }
148
+
149
+ /**
150
+ * Линтинг
151
+ */
152
+ async lint(args) {
153
+ if (args.length === 0) {
154
+ logger.error('Укажите файл для линтинга');
155
+ return;
156
+ }
157
+
158
+ const filepath = resolve(args[0]);
159
+ const options = this.parseOptions(args.slice(1));
160
+
161
+ if (!existsSync(filepath)) {
162
+ throw new Error(`Файл не найден: ${filepath}`);
163
+ }
164
+
165
+ const linter = new Linter({
166
+ autoFix: options.fix || false,
167
+ config: options.config
168
+ });
169
+
170
+ const source = readFileSync(filepath, 'utf-8');
171
+ const results = linter.lint(source, filepath);
172
+
173
+ if (options.fix && results.all.length > 0) {
174
+ const fixed = linter.fix(source, filepath);
175
+ if (fixed.fixed) {
176
+ writeFileSync(filepath, fixed.source, 'utf-8');
177
+ logger.info('Автофикс применен');
178
+ }
179
+ }
180
+
181
+ if (results.hasErrors) {
182
+ logger.error('Найдены ошибки:');
183
+ results.errors.forEach(err => {
184
+ logger.error(` ${filepath}:${err.line}:${err.column} - ${err.message}`);
185
+ });
186
+ process.exit(1);
187
+ }
188
+
189
+ if (results.warnings.length > 0) {
190
+ logger.warn('Предупреждения:');
191
+ results.warnings.forEach(warn => {
192
+ logger.warn(` ${filepath}:${warn.line}:${warn.column} - ${warn.message}`);
193
+ });
194
+ }
195
+
196
+ if (results.all.length === 0) {
197
+ logger.info('Проблем не найдено');
198
+ }
199
+
200
+ process.exit(0);
201
+ }
202
+
203
+ /**
204
+ * Форматирование
205
+ */
206
+ async format(args) {
207
+ if (args.length === 0) {
208
+ logger.error('Укажите файл для форматирования');
209
+ return;
210
+ }
211
+
212
+ const filepath = resolve(args[0]);
213
+ const options = this.parseOptions(args.slice(1));
214
+
215
+ if (!existsSync(filepath)) {
216
+ throw new Error(`Файл не найден: ${filepath}`);
217
+ }
218
+
219
+ const formatter = new Formatter({
220
+ indentSize: options.indent || 4,
221
+ useTabs: options.tabs || false,
222
+ printWidth: options.width || 100
223
+ });
224
+
225
+ const source = readFileSync(filepath, 'utf-8');
226
+ const formatted = formatter.format(source, filepath);
227
+
228
+ writeFileSync(filepath, formatted, 'utf-8');
229
+ logger.info(`Отформатировано: ${filepath}`);
230
+ }
231
+
232
+ /**
233
+ * Тесты
234
+ */
235
+ async test(args) {
236
+ const TestRunner = await import('./runtime/test-runner.js');
237
+ const runner = new TestRunner.default();
238
+
239
+ const filepath = args[0] ? resolve(args[0]) : null;
240
+
241
+ if (filepath) {
242
+ if (!existsSync(filepath)) {
243
+ throw new Error(`Файл не найден: ${filepath}`);
244
+ }
245
+
246
+ const source = readFileSync(filepath, 'utf-8');
247
+ await this.engine.execute(source, { filename: filepath });
248
+ } else {
249
+ // Искать тесты
250
+ const files = this.findTestFiles();
251
+
252
+ for (const file of files) {
253
+ const source = readFileSync(file, 'utf-8');
254
+ await this.engine.execute(source, { filename: file });
255
+ }
256
+ }
257
+
258
+ const results = await runner.run();
259
+
260
+ if (results.failed > 0) {
261
+ logger.error(`Тесты провалены: ${results.failed}/${results.total}`);
262
+ process.exit(1);
263
+ }
264
+
265
+ logger.info(`Тесты пройдены: ${results.passed}/${results.total}`);
266
+ process.exit(0);
267
+ }
268
+
269
+ /**
270
+ * Сборка модулей
271
+ */
272
+ async bundle(args) {
273
+ if (args.length === 0) {
274
+ logger.error('Укажите точку входа');
275
+ return;
276
+ }
277
+
278
+ const entry = resolve(args[0]);
279
+ const options = this.parseOptions(args.slice(1));
280
+
281
+ if (!existsSync(entry)) {
282
+ throw new Error(`Файл не найден: ${entry}`);
283
+ }
284
+
285
+ const { Bundle } = await import('./runtime/bundler.js');
286
+ const bundler = new Bundle({
287
+ entry,
288
+ output: options.output || 'bundle.vx',
289
+ format: options.format || 'esm',
290
+ minify: options.minify || false,
291
+ sourceMap: options.sourcemap || false
292
+ });
293
+
294
+ const bundled = await bundler.build();
295
+ await bundler.write(bundled);
296
+
297
+ logger.info(`Собрано: ${bundled.modules} модулей -> ${bundler.output}`);
298
+ }
299
+
300
+ /**
301
+ * Watch режим
302
+ */
303
+ async watch(args) {
304
+ if (args.length === 0) {
305
+ logger.error('Укажите файл для слежения');
306
+ return;
307
+ }
308
+
309
+ const filepath = resolve(args[0]);
310
+ const options = this.parseOptions(args.slice(1));
311
+
312
+ if (!existsSync(filepath)) {
313
+ throw new Error(`Файл не найден: ${filepath}`);
314
+ }
315
+
316
+ logger.info(`Слежение за: ${filepath}`);
317
+
318
+ this.engine = new VladXEngine({
319
+ debug: options.debug || false
320
+ });
321
+
322
+ const runFile = async () => {
323
+ try {
324
+ await this.engine.executeFile(filepath);
325
+ } catch (error) {
326
+ logger.error(error.message);
327
+ }
328
+ };
329
+
330
+ await runFile();
331
+
332
+ const fs = await import('fs');
333
+ fs.watchFile(filepath, { interval: options.interval || 1000 }, async () => {
334
+ logger.info('Файл изменен, перезапуск...');
335
+ await runFile();
336
+ });
337
+ }
338
+
339
+ /**
340
+ * Отладка
341
+ */
342
+ async debug(args) {
343
+ if (args.length === 0) {
344
+ logger.error('Укажите файл для отладки');
345
+ return;
346
+ }
347
+
348
+ const filepath = resolve(args[0]);
349
+
350
+ if (!existsSync(filepath)) {
351
+ throw new Error(`Файл не найден: ${filepath}`);
352
+ }
353
+
354
+ this.engine = new VladXEngine({
355
+ debug: true
356
+ });
357
+
358
+ logger.info('Отладочный режим включен');
359
+ logger.info('Команды: точкиОстанова, пошаговыйРежим, продолжить');
360
+
361
+ await this.engine.executeFile(filepath);
362
+ }
363
+
364
+ /**
365
+ * Справка
366
+ */
367
+ help() {
368
+ console.log(`
369
+ VladX - Мощный интерпретируемый язык программирования
370
+
371
+ Использование:
372
+ vladx <команда> [опции] [аргументы]
373
+
374
+ Команды:
375
+ run <файл> Выполнить файл
376
+ repl Интерактивная консоль
377
+ compile <файл> Скомпилировать в JavaScript
378
+ lint <файл> Проверить код на ошибки
379
+ format <файл> Отформатировать код
380
+ test [файл] Запустить тесты
381
+ bundle <entry> Собрать модули
382
+ watch <файл> Смотреть за изменениями файла
383
+ debug <файл> Отладочный режим
384
+ help Показать эту справку
385
+
386
+ Опции:
387
+ --debug Режим отладки
388
+ --strict Строгий режим
389
+ --timeout <ms> Таймаут выполнения
390
+ --output <file> Файл вывода
391
+ --format <format> Формат (esm, cjs, iife, umd)
392
+ --minify Минифицировать
393
+ --fix Автофикс для линтера
394
+ --watch Смотреть за изменениями
395
+ --time Показать время выполнения
396
+ --silent Без вывода результатов
397
+
398
+ Примеры:
399
+ vladx run main.vx
400
+ vladx repl
401
+ vladx compile main.vx --output main.js
402
+ vladx lint main.vx --fix
403
+ vladx format main.vx --indent 2
404
+ vladx bundle main.vx --format iife --minify
405
+ vladx watch main.vx
406
+ vladx debug main.vx
407
+
408
+ Документация: https://vladx.dev
409
+ `.trim());
410
+ }
411
+
412
+ /**
413
+ * Парсинг опций
414
+ */
415
+ parseOptions(args) {
416
+ const options = {};
417
+
418
+ for (let i = 0; i < args.length; i++) {
419
+ const arg = args[i];
420
+
421
+ if (arg === '--debug') {
422
+ options.debug = true;
423
+ } else if (arg === '--strict') {
424
+ options.strict = true;
425
+ } else if (arg === '--timeout' && args[i + 1]) {
426
+ options.timeout = parseInt(args[++i]);
427
+ } else if (arg === '--output' && args[i + 1]) {
428
+ options.output = args[++i];
429
+ } else if (arg === '--format' && args[i + 1]) {
430
+ options.format = args[++i];
431
+ } else if (arg === '--minify') {
432
+ options.minify = true;
433
+ } else if (arg === '--fix') {
434
+ options.fix = true;
435
+ } else if (arg === '--watch') {
436
+ options.watch = true;
437
+ } else if (arg === '--time') {
438
+ options.time = true;
439
+ } else if (arg === '--silent') {
440
+ options.silent = true;
441
+ } else if (arg === '--indent' && args[i + 1]) {
442
+ options.indent = parseInt(args[++i]);
443
+ } else if (arg === '--tabs') {
444
+ options.tabs = true;
445
+ } else if (arg === '--width' && args[i + 1]) {
446
+ options.width = parseInt(args[++i]);
447
+ }
448
+ }
449
+
450
+ return options;
451
+ }
452
+
453
+ /**
454
+ * Найти тестовые файлы
455
+ */
456
+ findTestFiles() {
457
+ const fs = require('fs');
458
+ const path = require('path');
459
+
460
+ const testFiles = [];
461
+
462
+ const findFiles = (dir) => {
463
+ const files = fs.readdirSync(dir);
464
+
465
+ for (const file of files) {
466
+ const filepath = path.join(dir, file);
467
+ const stat = fs.statSync(filepath);
468
+
469
+ if (stat.isDirectory()) {
470
+ if (file === 'node_modules' || file.startsWith('.')) continue;
471
+ findFiles(filepath);
472
+ } else if (file.endsWith('.test.vx') || file.endsWith('.spec.vx')) {
473
+ testFiles.push(filepath);
474
+ }
475
+ }
476
+ };
477
+
478
+ findFiles(process.cwd());
479
+ return testFiles;
480
+ }
481
+ }
482
+
483
+ /**
484
+ * Запуск CLI
485
+ */
486
+ if (import.meta.url === `file://${process.argv[1]}`) {
487
+ const cli = new CLI();
488
+ cli.run(process.argv);
489
+ }
490
+
491
+ export default CLI;
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "vladx",
3
+ "version": "1.0.0",
4
+ "description": "Мощный интерпретируемый язык программирования с русским синтаксисом",
5
+ "main": "src/index.js",
6
+ "bin": {
7
+ "vladx": "./bin/vladx.js",
8
+ "vladpm": "./bin/vladpm.js"
9
+ },
10
+ "scripts": {
11
+ "start": "node bin/vladx.js run examples/demo.vx",
12
+ "repl": "node bin/vladx.js repl",
13
+ "test": "node bin/vladx.js test",
14
+ "lint": "node bin/vladx.js lint src/",
15
+ "format": "node bin/vladx.js format src/",
16
+ "build": "node bin/vladx.js compile src/index.vx --output dist/vladx.js",
17
+ "watch": "node bin/vladx.js watch examples/"
18
+ },
19
+ "keywords": [
20
+ "interpreter",
21
+ "programming-language",
22
+ "russian",
23
+ "javascript",
24
+ "vladx"
25
+ ],
26
+ "author": "VladX Team",
27
+ "license": "MIT",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/vladx/vladx"
31
+ },
32
+ "bugs": {
33
+ "url": "https://github.com/vladx/vladx/issues"
34
+ },
35
+ "homepage": "https://vladx.dev",
36
+ "dependencies": {
37
+ "tar": "^6.2.0"
38
+ },
39
+ "devDependencies": {},
40
+ "engines": {
41
+ "node": ">=14.0.0"
42
+ },
43
+ "files": [
44
+ "src/",
45
+ "bin/",
46
+ "README.md",
47
+ "LICENSE"
48
+ ],
49
+ "exports": {
50
+ ".": {
51
+ "import": "./src/index.js",
52
+ "require": "./src/index.js"
53
+ },
54
+ "./bin/*": "./bin/*"
55
+ },
56
+ "type": "module"
57
+ }