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,140 @@
1
+ /**
2
+ * VladX Environment — Окружение выполнения
3
+ * Управляет областями видимости переменных
4
+ */
5
+
6
+ export class Environment {
7
+ constructor(parent = null, name = '<anonymous>') {
8
+ this.parent = parent;
9
+ this.name = name;
10
+ this.variables = new Map();
11
+ this.constants = new Set();
12
+ }
13
+
14
+ /**
15
+ * Определение переменной
16
+ */
17
+ define(name, value, isConst = false) {
18
+ // Check if it's already defined as a constant in the current environment only
19
+ // Local variables should be able to shadow parent constants/functions
20
+ if (this.constants.has(name)) {
21
+ throw new Error(`Константа ${name} уже объявлена`);
22
+ }
23
+
24
+ if (this.variables.has(name) && !isConst) {
25
+ // Предупреждение о переопределении
26
+ }
27
+
28
+ this.variables.set(name, value);
29
+
30
+ if (isConst) {
31
+ this.constants.add(name);
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Получение значения переменной
37
+ */
38
+ get(name) {
39
+ if (this.variables.has(name)) {
40
+ return this.variables.get(name);
41
+ }
42
+
43
+ if (this.parent) {
44
+ return this.parent.get(name);
45
+ }
46
+
47
+ throw new Error(`Переменная "${name}" не найдена в окружении ${this.name}`);
48
+
49
+ }
50
+
51
+ /**
52
+ * Присваивание значения переменной
53
+ */
54
+ assign(name, value) {
55
+ if (this.variables.has(name)) {
56
+ if (this.constants.has(name)) {
57
+ throw new Error(`Нельзя изменить константу ${name}`);
58
+ }
59
+ this.variables.set(name, value);
60
+ return true;
61
+ }
62
+
63
+ if (this.parent) {
64
+ return this.parent.assign(name, value);
65
+ }
66
+
67
+ throw new Error(`Переменная ${name} не найдена`);
68
+ }
69
+
70
+ /**
71
+ * Проверка существования переменной
72
+ */
73
+ has(name) {
74
+ return this.variables.has(name) || (this.parent && this.parent.has(name));
75
+ }
76
+
77
+ /**
78
+ * Создание дочернего окружения
79
+ */
80
+ child(name = '<child>') {
81
+ return new Environment(this, name);
82
+ }
83
+
84
+ /**
85
+ * Клонирование окружения
86
+ */
87
+ clone() {
88
+ const cloned = new Environment(this.parent, this.name);
89
+
90
+ for (const [key, value] of this.variables) {
91
+ cloned.variables.set(key, value);
92
+ }
93
+
94
+ for (const constant of this.constants) {
95
+ cloned.constants.add(constant);
96
+ }
97
+
98
+ return cloned;
99
+ }
100
+
101
+ /**
102
+ * Получение всех переменных
103
+ */
104
+ getAll() {
105
+ const result = {};
106
+
107
+ if (this.parent) {
108
+ Object.assign(result, this.parent.getAll());
109
+ }
110
+
111
+ for (const [key, value] of this.variables) {
112
+ result[key] = value;
113
+ }
114
+
115
+ return result;
116
+ }
117
+
118
+ /**
119
+ * Удаление переменной
120
+ */
121
+ delete(name) {
122
+ if (this.variables.has(name)) {
123
+ this.variables.delete(name);
124
+ this.constants.delete(name);
125
+ return true;
126
+ }
127
+
128
+ return false;
129
+ }
130
+
131
+ /**
132
+ * Очистка окружения
133
+ */
134
+ clear() {
135
+ this.variables.clear();
136
+ this.constants.clear();
137
+ }
138
+ }
139
+
140
+ export default Environment;
@@ -0,0 +1,232 @@
1
+ /**
2
+ * EventEmitter — Реализация события emitter
3
+ */
4
+
5
+ export class EventEmitter {
6
+ constructor() {
7
+ this.events = new Map();
8
+ this.onceEvents = new Map();
9
+ this.maxListeners = 10;
10
+ }
11
+
12
+ /**
13
+ * Добавить listener
14
+ */
15
+ on(event, listener) {
16
+ if (!this.events.has(event)) {
17
+ this.events.set(event, []);
18
+ }
19
+
20
+ const listeners = this.events.get(event);
21
+
22
+ // Проверка на maxListeners
23
+ if (listeners.length >= this.maxListeners) {
24
+ console.warn(`Possible memory leak detected. ${listeners.length} ${event} listeners added.`);
25
+ }
26
+
27
+ listeners.push(listener);
28
+ return this;
29
+ }
30
+
31
+ /**
32
+ * Добавить one-time listener
33
+ */
34
+ once(event, listener) {
35
+ const wrapper = (...args) => {
36
+ this.off(event, wrapper);
37
+ listener(...args);
38
+ };
39
+
40
+ this.on(event, wrapper);
41
+ return this;
42
+ }
43
+
44
+ /**
45
+ * Удалить listener
46
+ */
47
+ off(event, listener) {
48
+ const listeners = this.events.get(event);
49
+ if (listeners) {
50
+ const index = listeners.indexOf(listener);
51
+ if (index !== -1) {
52
+ listeners.splice(index, 1);
53
+ }
54
+
55
+ if (listeners.length === 0) {
56
+ this.events.delete(event);
57
+ }
58
+ }
59
+ return this;
60
+ }
61
+
62
+ /**
63
+ * Запустить событие
64
+ */
65
+ emit(event, ...args) {
66
+ const listeners = this.events.get(event);
67
+ if (listeners) {
68
+ // Копируем массив для безопасной модификации во время итерации
69
+ const listenersCopy = [...listeners];
70
+
71
+ for (const listener of listenersCopy) {
72
+ try {
73
+ listener(...args);
74
+ } catch (error) {
75
+ // Ошибка в listener не должна прерывать других
76
+ console.error(`Error in ${event} listener:`, error);
77
+ }
78
+ }
79
+
80
+ return listeners.length > 0;
81
+ }
82
+ return false;
83
+ }
84
+
85
+ /**
86
+ * Добавить listener (синоним on)
87
+ */
88
+ addListener(event, listener) {
89
+ return this.on(event, listener);
90
+ }
91
+
92
+ /**
93
+ * Удалить listener (синоним off)
94
+ */
95
+ removeListener(event, listener) {
96
+ return this.off(event, listener);
97
+ }
98
+
99
+ /**
100
+ * Удалить все listeners для события
101
+ */
102
+ removeAllListeners(event) {
103
+ if (event) {
104
+ this.events.delete(event);
105
+ } else {
106
+ this.events.clear();
107
+ }
108
+ return this;
109
+ }
110
+
111
+ /**
112
+ * Получить listeners для события
113
+ */
114
+ listeners(event) {
115
+ return this.events.get(event) || [];
116
+ }
117
+
118
+ /**
119
+ * Получить количество listeners для события
120
+ */
121
+ listenerCount(event) {
122
+ return (this.events.get(event) || []).length;
123
+ }
124
+
125
+ /**
126
+ * Получить все имена событий
127
+ */
128
+ eventNames() {
129
+ return Array.from(this.events.keys());
130
+ }
131
+
132
+ /**
133
+ * Установить максимальное количество listeners
134
+ */
135
+ setMaxListeners(n) {
136
+ this.maxListeners = n;
137
+ return this;
138
+ }
139
+
140
+ /**
141
+ * Получить максимальное количество listeners
142
+ */
143
+ getMaxListeners() {
144
+ return this.maxListeners;
145
+ }
146
+
147
+ /**
148
+ * Добавить prepend listener (добавляется в начало)
149
+ */
150
+ prependListener(event, listener) {
151
+ if (!this.events.has(event)) {
152
+ this.events.set(event, []);
153
+ }
154
+
155
+ this.events.get(event).unshift(listener);
156
+ return this;
157
+ }
158
+
159
+ /**
160
+ * Добавить prepend once listener
161
+ */
162
+ prependOnceListener(event, listener) {
163
+ const wrapper = (...args) => {
164
+ this.off(event, wrapper);
165
+ listener(...args);
166
+ };
167
+
168
+ this.prependListener(event, wrapper);
169
+ return this;
170
+ }
171
+
172
+ /**
173
+ * Статический метод для создания emitter
174
+ */
175
+ static create() {
176
+ return new EventEmitter();
177
+ }
178
+
179
+ /**
180
+ * Асинхронный emit (Promise)
181
+ */
182
+ async emitAsync(event, ...args) {
183
+ const listeners = this.events.get(event);
184
+ if (!listeners) {
185
+ return false;
186
+ }
187
+
188
+ const results = [];
189
+
190
+ for (const listener of listeners) {
191
+ try {
192
+ const result = listener(...args);
193
+ if (result && typeof result.then === 'function') {
194
+ results.push(await result);
195
+ } else {
196
+ results.push(result);
197
+ }
198
+ } catch (error) {
199
+ console.error(`Error in ${event} async listener:`, error);
200
+ results.push(Promise.reject(error));
201
+ }
202
+ }
203
+
204
+ return results;
205
+ }
206
+
207
+ /**
208
+ * Проверить, есть ли listeners
209
+ */
210
+ hasListeners(event) {
211
+ return this.listenerCount(event) > 0;
212
+ }
213
+
214
+ /**
215
+ * Получить информацию о памяти
216
+ */
217
+ getMemoryUsage() {
218
+ let totalListeners = 0;
219
+
220
+ for (const [event, listeners] of this.events) {
221
+ totalListeners += listeners.length;
222
+ }
223
+
224
+ return {
225
+ events: this.events.size,
226
+ totalListeners,
227
+ maxListeners: this.maxListeners
228
+ };
229
+ }
230
+ }
231
+
232
+ export default EventEmitter;
@@ -0,0 +1,280 @@
1
+ /**
2
+ * Formatter — Форматирование кода VladX
3
+ */
4
+
5
+ import { Lexer } from '../lexer/lexer.js';
6
+ import { Parser } from '../parser/parser.js';
7
+
8
+ export class Formatter {
9
+ constructor(options = {}) {
10
+ this.indentSize = options.indentSize || 4;
11
+ this.indentChar = options.indentChar || ' ';
12
+ this.useTabs = options.useTabs || false;
13
+ this.semicolons = options.semicolons !== false;
14
+ this.trailingComma = options.trailingComma || false;
15
+ this.singleQuote = options.singleQuote || false;
16
+ this.printWidth = options.printWidth || 100;
17
+ this.insertFinalNewline = options.insertFinalNewline !== false;
18
+ }
19
+
20
+ /**
21
+ * Отформатировать код
22
+ */
23
+ format(source, filename = '<anonymous>') {
24
+ let formatted = source;
25
+
26
+ // Шаг 1: Нормализация пробелов
27
+ formatted = this.normalizeWhitespace(formatted);
28
+
29
+ // Шаг 2: Форматирование блоков
30
+ formatted = this.formatBlocks(formatted);
31
+
32
+ // Шаг 3: Форматирование отступов
33
+ formatted = this.formatIndentation(formatted);
34
+
35
+ // Шаг 4: Форматирование операторов
36
+ formatted = this.formatOperators(formatted);
37
+
38
+ // Шаг 5: Удаление лишних пустых строк
39
+ formatted = this.formatEmptyLines(formatted);
40
+
41
+ // Шаг 6: Добавление перевода строки в конце
42
+ if (this.insertFinalNewline && !formatted.endsWith('\n')) {
43
+ formatted += '\n';
44
+ }
45
+
46
+ return formatted;
47
+ }
48
+
49
+ /**
50
+ * Нормализация пробелов
51
+ */
52
+ normalizeWhitespace(source) {
53
+ // Удалить trailing whitespace
54
+ let formatted = source.split('\n').map(line => line.trimEnd()).join('\n');
55
+
56
+ // Нормализировать табы в пробелы или наоборот
57
+ if (this.useTabs) {
58
+ formatted = formatted.replace(/ {4}/g, '\t');
59
+ } else {
60
+ formatted = formatted.replace(/\t/g, ' '.repeat(this.indentSize));
61
+ }
62
+
63
+ return formatted;
64
+ }
65
+
66
+ /**
67
+ * Форматирование блоков
68
+ */
69
+ formatBlocks(source) {
70
+ let formatted = source;
71
+
72
+ // Форматирование if/else
73
+ formatted = formatted.replace(
74
+ /(?:если|if)\s*\(([^)]*)\)\s*([^{])/g,
75
+ (match, condition, nextChar) => {
76
+ const indent = ' '.repeat(this.indentSize);
77
+ return `если (${condition}) {\n${indent}${nextChar}`;
78
+ }
79
+ );
80
+
81
+ // Форматирование while
82
+ formatted = formatted.replace(
83
+ /(?:пока|while)\s*\(([^)]*)\)\s*([^{])/g,
84
+ (match, condition, nextChar) => {
85
+ const indent = ' '.repeat(this.indentSize);
86
+ return `пока (${condition}) {\n${indent}${nextChar}`;
87
+ }
88
+ );
89
+
90
+ // Форматирование for
91
+ formatted = formatted.replace(
92
+ /(?:для|for)\s*\(([^)]*)\)\s*([^{])/g,
93
+ (match, condition, nextChar) => {
94
+ const indent = ' '.repeat(this.indentSize);
95
+ return `для (${condition}) {\n${indent}${nextChar}`;
96
+ }
97
+ );
98
+
99
+ return formatted;
100
+ }
101
+
102
+ /**
103
+ * Форматирование отступов
104
+ */
105
+ formatIndentation(source) {
106
+ const lines = source.split('\n');
107
+ const formattedLines = [];
108
+ let indentLevel = 0;
109
+
110
+ for (const line of lines) {
111
+ const trimmed = line.trim();
112
+
113
+ if (trimmed.length === 0) {
114
+ formattedLines.push('');
115
+ continue;
116
+ }
117
+
118
+ // Уменьшить отступ перед закрывающей скобкой
119
+ if (trimmed.startsWith('}') || trimmed.startsWith('иначе')) {
120
+ indentLevel = Math.max(0, indentLevel - 1);
121
+ }
122
+
123
+ // Добавить отступ
124
+ const indent = this.useTabs
125
+ ? '\t'.repeat(indentLevel)
126
+ : ' '.repeat(indentLevel * this.indentSize);
127
+ formattedLines.push(indent + trimmed);
128
+
129
+ // Увеличить отступ после открывающей скобки
130
+ if (trimmed.endsWith('{')) {
131
+ indentLevel++;
132
+ }
133
+ }
134
+
135
+ return formattedLines.join('\n');
136
+ }
137
+
138
+ /**
139
+ * Форматирование операторов
140
+ */
141
+ formatOperators(source) {
142
+ let formatted = source;
143
+
144
+ // Пробелы вокруг операторов
145
+ const operators = ['+', '-', '*', '/', '%', '=', '==', '!=', '<', '>', '<=', '>=', '&&', '||', '!'];
146
+
147
+ for (const op of operators) {
148
+ formatted = formatted.replace(
149
+ new RegExp(`([^\\s])\\${op}([^\\s])`, 'g'),
150
+ `$1 ${op} $2`
151
+ );
152
+ }
153
+
154
+ // Пробелы после запятых
155
+ formatted = formatted.replace(/,(\S)/g, ', $1');
156
+
157
+ // Пробелы после точек с запятой
158
+ formatted = formatted.replace(/;(\S)/g, '; $1');
159
+
160
+ return formatted;
161
+ }
162
+
163
+ /**
164
+ * Форматирование пустых строк
165
+ */
166
+ formatEmptyLines(source) {
167
+ const lines = source.split('\n');
168
+ const formattedLines = [];
169
+ let emptyCount = 0;
170
+
171
+ for (const line of lines) {
172
+ if (line.trim().length === 0) {
173
+ emptyCount++;
174
+ if (emptyCount <= 2) {
175
+ formattedLines.push(line);
176
+ }
177
+ } else {
178
+ emptyCount = 0;
179
+ formattedLines.push(line);
180
+ }
181
+ }
182
+
183
+ return formattedLines.join('\n');
184
+ }
185
+
186
+ /**
187
+ * Проверить код
188
+ */
189
+ check(source, filename = '<anonymous>') {
190
+ const issues = [];
191
+
192
+ // Проверить длину строк
193
+ const lines = source.split('\n');
194
+ lines.forEach((line, index) => {
195
+ if (line.length > this.printWidth) {
196
+ issues.push({
197
+ message: `Строка слишком длинная: ${line.length} > ${this.printWidth}`,
198
+ line: index + 1,
199
+ severity: 'warning'
200
+ });
201
+ }
202
+ });
203
+
204
+ // Проверить trailing whitespace
205
+ lines.forEach((line, index) => {
206
+ if (line !== line.trimEnd()) {
207
+ issues.push({
208
+ message: 'Trailing whitespace в конце строки',
209
+ line: index + 1,
210
+ severity: 'info'
211
+ });
212
+ }
213
+ });
214
+
215
+ // Проверить смешивание табов и пробелов
216
+ lines.forEach((line, index) => {
217
+ if (line.includes('\t') && line.includes(' ')) {
218
+ issues.push({
219
+ message: 'Смешивание табов и пробелов',
220
+ line: index + 1,
221
+ severity: 'error'
222
+ });
223
+ }
224
+ });
225
+
226
+ return {
227
+ issues,
228
+ hasIssues: issues.length > 0
229
+ };
230
+ }
231
+
232
+ /**
233
+ * Форматировать с автофиксом
234
+ */
235
+ formatWithFix(source, filename = '<anonymous>') {
236
+ const checkResult = this.check(source, filename);
237
+
238
+ if (!checkResult.hasIssues) {
239
+ return {
240
+ source,
241
+ formatted: false,
242
+ issues: []
243
+ };
244
+ }
245
+
246
+ const formatted = this.format(source, filename);
247
+
248
+ return {
249
+ source: formatted,
250
+ formatted: true,
251
+ issues: checkResult.issues
252
+ };
253
+ }
254
+
255
+ /**
256
+ * Получить конфигурацию
257
+ */
258
+ getConfig() {
259
+ return {
260
+ indentSize: this.indentSize,
261
+ indentChar: this.indentChar,
262
+ useTabs: this.useTabs,
263
+ semicolons: this.semicolons,
264
+ trailingComma: this.trailingComma,
265
+ singleQuote: this.singleQuote,
266
+ printWidth: this.printWidth,
267
+ insertFinalNewline: this.insertFinalNewline
268
+ };
269
+ }
270
+
271
+ /**
272
+ * Установить конфигурацию
273
+ */
274
+ setConfig(config) {
275
+ Object.assign(this, config);
276
+ return this;
277
+ }
278
+ }
279
+
280
+ export default Formatter;