@jishaanyazmi/code-script 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.
package/dist/ast.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ast.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast.js","sourceRoot":"","sources":["../src/ast.ts"],"names":[],"mappings":""}
@@ -0,0 +1,62 @@
1
+ import { ProgramNode, Statement, Expression } from './ast.js';
2
+ interface SemanticError {
3
+ kind: string;
4
+ message: string;
5
+ file: string;
6
+ line: number;
7
+ column: number;
8
+ suggestion?: string;
9
+ }
10
+ interface SemanticWarning {
11
+ message: string;
12
+ file: string;
13
+ line: number;
14
+ column: number;
15
+ }
16
+ export interface SemanticResult {
17
+ errors: SemanticError[];
18
+ warnings: SemanticWarning[];
19
+ }
20
+ export declare class SemanticAnalyzer {
21
+ private readonly file;
22
+ private readonly scope;
23
+ private readonly errors;
24
+ private readonly warnings;
25
+ private insideLoop;
26
+ private insideFunction;
27
+ constructor(file?: string);
28
+ analyze(program: ProgramNode): SemanticResult;
29
+ private err;
30
+ private warn;
31
+ private analyzeStatement;
32
+ private analyzeVarDecl;
33
+ private analyzeFuncDecl;
34
+ private analyzeReturn;
35
+ private analyzeIf;
36
+ private analyzeSwitch;
37
+ private analyzeRepeat;
38
+ private analyzeUntil;
39
+ private analyzeClass;
40
+ private analyzeTry;
41
+ private analyzeExport;
42
+ private analyzeExpr;
43
+ }
44
+ export declare class Optimizer {
45
+ optimize(program: ProgramNode): ProgramNode;
46
+ private optStmt;
47
+ private optExpr;
48
+ }
49
+ export declare class CodeGenerator {
50
+ private out;
51
+ private level;
52
+ private line;
53
+ private emit;
54
+ private indent;
55
+ private dedent;
56
+ generate(program: ProgramNode): string;
57
+ genStmt(stmt: Statement): void;
58
+ private genBlock;
59
+ genExpr(expr: Expression): string;
60
+ }
61
+ export {};
62
+ //# sourceMappingURL=compiler-core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiler-core.d.ts","sourceRoot":"","sources":["../src/compiler-core.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,WAAW,EAAE,SAAS,EAAE,UAAU,EAOrC,MAAM,UAAU,CAAA;AAWjB,UAAU,aAAa;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE;AAC1H,UAAU,eAAe;IAAG,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AAczF,MAAM,WAAW,cAAc;IAAG,MAAM,EAAE,aAAa,EAAE,CAAC;IAAC,QAAQ,EAAE,eAAe,EAAE,CAAA;CAAE;AAExF,qBAAa,gBAAgB;IAOb,OAAO,CAAC,QAAQ,CAAC,IAAI;IANjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAC3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;IAC7C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwB;IACjD,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,cAAc,CAAQ;gBAED,IAAI,GAAE,MAAkB;IAErD,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,cAAc;IAO7C,OAAO,CAAC,GAAG;IAGX,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,gBAAgB;IAoBxB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,WAAW;CAuBtB;AAID,qBAAa,SAAS;IAClB,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,WAAW;IAG3C,OAAO,CAAC,OAAO;IAWf,OAAO,CAAC,OAAO;CAoBlB;AAeD,qBAAa,aAAa;IACtB,OAAO,CAAC,GAAG,CAAK;IAChB,OAAO,CAAC,KAAK,CAAI;IAEjB,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,MAAM;IAEd,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM;IAOtC,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAgE9B,OAAO,CAAC,QAAQ;IAEhB,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM;CA4BpC"}
@@ -0,0 +1,577 @@
1
+ // ─── Semantic Analyzer ────────────────────────────────────────────────────────
2
+ const RESERVED = new Set([
3
+ 'grab', 'share', 'make', 'fixed', 'keep', 'do', 'give', 'say', 'check', 'otherwise',
4
+ 'pick', 'when', 'anyway', 'repeat', 'until', 'stop', 'skip', 'type', 'from', 'create',
5
+ 'me', 'parent', 'attempt', 'oops', 'panic', 'done', 'later', 'wait', 'remove', 'kind',
6
+ 'is', 'mine', 'everyone', 'family', 'shared', 'yes', 'no', 'empty', 'unknown'
7
+ ]);
8
+ class ScopeManager {
9
+ constructor() {
10
+ this.stack = [new Map()];
11
+ }
12
+ enter(_type) { this.stack.push(new Map()); }
13
+ exit() { if (this.stack.length > 1)
14
+ this.stack.pop(); }
15
+ define(name, kind, line, column) { this.stack[this.stack.length - 1].set(name, { kind, line, column }); }
16
+ has(name) { return this.stack[this.stack.length - 1].has(name); }
17
+ lookup(name) {
18
+ for (let i = this.stack.length - 1; i >= 0; i--) {
19
+ const s = this.stack[i].get(name);
20
+ if (s)
21
+ return s;
22
+ }
23
+ return undefined;
24
+ }
25
+ }
26
+ export class SemanticAnalyzer {
27
+ constructor(file = 'unknown') {
28
+ this.file = file;
29
+ this.scope = new ScopeManager();
30
+ this.errors = [];
31
+ this.warnings = [];
32
+ this.insideLoop = false;
33
+ this.insideFunction = false;
34
+ }
35
+ analyze(program) {
36
+ for (const stmt of program.body)
37
+ this.analyzeStatement(stmt);
38
+ for (const err of this.errors)
39
+ console.error(`SemanticError [${err.kind}]\nFile: ${err.file}\nLine: ${err.line}\nColumn: ${err.column}\nMessage: ${err.message}${err.suggestion ? '\nSuggestion: ' + err.suggestion : ''}`);
40
+ for (const w of this.warnings)
41
+ console.warn(`Warning\nFile: ${w.file}\nLine: ${w.line}\nMessage: ${w.message}`);
42
+ return { errors: this.errors, warnings: this.warnings };
43
+ }
44
+ err(kind, message, line, column, suggestion) {
45
+ this.errors.push({ kind, message, file: this.file, line, column, suggestion });
46
+ }
47
+ warn(message, line, column) {
48
+ this.warnings.push({ message, file: this.file, line, column });
49
+ }
50
+ analyzeStatement(stmt) {
51
+ switch (stmt.kind) {
52
+ case 'VariableDeclaration': return this.analyzeVarDecl(stmt);
53
+ case 'FunctionDeclaration': return this.analyzeFuncDecl(stmt);
54
+ case 'ReturnStatement': return this.analyzeReturn(stmt);
55
+ case 'IfStatement': return this.analyzeIf(stmt);
56
+ case 'SwitchStatement': return this.analyzeSwitch(stmt);
57
+ case 'RepeatStatement': return this.analyzeRepeat(stmt);
58
+ case 'UntilStatement': return this.analyzeUntil(stmt);
59
+ case 'BreakStatement':
60
+ if (!this.insideLoop)
61
+ this.err('InvalidBreak', '"stop" can only be used inside a loop.', stmt.loc.line, stmt.loc.column);
62
+ break;
63
+ case 'ContinueStatement':
64
+ if (!this.insideLoop)
65
+ this.err('InvalidContinue', '"skip" can only be used inside a loop.', stmt.loc.line, stmt.loc.column);
66
+ break;
67
+ case 'ClassDeclaration': return this.analyzeClass(stmt);
68
+ case 'TryStatement': return this.analyzeTry(stmt);
69
+ case 'ThrowStatement':
70
+ this.analyzeExpr(stmt.value);
71
+ break;
72
+ case 'ExpressionStatement':
73
+ this.analyzeExpr(stmt.expression);
74
+ break;
75
+ case 'ImportDeclaration': break;
76
+ case 'ExportDeclaration': return this.analyzeExport(stmt);
77
+ }
78
+ }
79
+ analyzeVarDecl(node) {
80
+ const { name, keyword, value, loc } = node;
81
+ if (RESERVED.has(name.name)) {
82
+ this.err('ReservedKeyword', `"${name.name}" is a reserved keyword.`, loc.line, loc.column);
83
+ return;
84
+ }
85
+ if (keyword === 'fixed' && value === null)
86
+ this.err('UninitializedConstant', `Constant "${name.name}" must be initialized.`, loc.line, loc.column);
87
+ if (this.scope.has(name.name))
88
+ this.err('DuplicateDeclaration', `"${name.name}" is already declared.`, loc.line, loc.column);
89
+ else
90
+ this.scope.define(name.name, keyword === 'fixed' ? 'constant' : 'variable', loc.line, loc.column);
91
+ if (value)
92
+ this.analyzeExpr(value);
93
+ }
94
+ analyzeFuncDecl(node) {
95
+ if (node.name.name && this.scope.has(node.name.name))
96
+ this.err('DuplicateDeclaration', `Function "${node.name.name}" is already declared.`, node.loc.line, node.loc.column);
97
+ else if (node.name.name)
98
+ this.scope.define(node.name.name, 'function', node.loc.line, node.loc.column);
99
+ this.scope.enter('function');
100
+ const prev = this.insideFunction;
101
+ this.insideFunction = true;
102
+ for (const p of node.params)
103
+ this.scope.define(p.name, 'parameter', p.loc.line, p.loc.column);
104
+ for (const s of node.body.body)
105
+ this.analyzeStatement(s);
106
+ this.insideFunction = prev;
107
+ this.scope.exit();
108
+ }
109
+ analyzeReturn(node) {
110
+ if (!this.insideFunction)
111
+ this.err('InvalidReturn', '"give" can only be used inside a function.', node.loc.line, node.loc.column);
112
+ if (node.value)
113
+ this.analyzeExpr(node.value);
114
+ }
115
+ analyzeIf(node) {
116
+ this.analyzeExpr(node.condition);
117
+ this.scope.enter('block');
118
+ for (const s of node.consequent.body)
119
+ this.analyzeStatement(s);
120
+ this.scope.exit();
121
+ if (node.alternate) {
122
+ this.scope.enter('block');
123
+ for (const s of node.alternate.body)
124
+ this.analyzeStatement(s);
125
+ this.scope.exit();
126
+ }
127
+ }
128
+ analyzeSwitch(node) {
129
+ this.analyzeExpr(node.discriminant);
130
+ const prev = this.insideLoop;
131
+ this.insideLoop = true;
132
+ for (const c of node.cases) {
133
+ this.analyzeExpr(c.test);
134
+ this.scope.enter('block');
135
+ for (const s of c.body.body)
136
+ this.analyzeStatement(s);
137
+ this.scope.exit();
138
+ }
139
+ if (node.defaultCase) {
140
+ this.scope.enter('block');
141
+ for (const s of node.defaultCase.body)
142
+ this.analyzeStatement(s);
143
+ this.scope.exit();
144
+ }
145
+ this.insideLoop = prev;
146
+ }
147
+ analyzeRepeat(node) {
148
+ this.scope.enter('block');
149
+ const prev = this.insideLoop;
150
+ this.insideLoop = true;
151
+ if (node.init)
152
+ this.analyzeStatement(node.init);
153
+ if (node.condition)
154
+ this.analyzeExpr(node.condition);
155
+ if (node.update)
156
+ this.analyzeExpr(node.update);
157
+ for (const s of node.body.body)
158
+ this.analyzeStatement(s);
159
+ this.insideLoop = prev;
160
+ this.scope.exit();
161
+ }
162
+ analyzeUntil(node) {
163
+ this.analyzeExpr(node.condition);
164
+ this.scope.enter('block');
165
+ const prev = this.insideLoop;
166
+ this.insideLoop = true;
167
+ for (const s of node.body.body)
168
+ this.analyzeStatement(s);
169
+ this.insideLoop = prev;
170
+ this.scope.exit();
171
+ }
172
+ analyzeClass(node) {
173
+ if (this.scope.has(node.name.name))
174
+ this.err('DuplicateDeclaration', `Class "${node.name.name}" is already declared.`, node.loc.line, node.loc.column);
175
+ else
176
+ this.scope.define(node.name.name, 'class', node.loc.line, node.loc.column);
177
+ this.scope.enter('class');
178
+ const prev = this.insideFunction;
179
+ this.insideFunction = true;
180
+ for (const m of node.body.members) {
181
+ this.scope.enter('function');
182
+ for (const p of m.params)
183
+ this.scope.define(p.name, 'parameter', p.loc.line, p.loc.column);
184
+ for (const s of m.body.body)
185
+ this.analyzeStatement(s);
186
+ this.scope.exit();
187
+ }
188
+ this.insideFunction = prev;
189
+ this.scope.exit();
190
+ }
191
+ analyzeTry(node) {
192
+ this.scope.enter('block');
193
+ for (const s of node.body.body)
194
+ this.analyzeStatement(s);
195
+ this.scope.exit();
196
+ if (node.handler) {
197
+ this.scope.enter('block');
198
+ this.scope.define(node.handler.param.name, 'variable', node.handler.param.loc.line, node.handler.param.loc.column);
199
+ for (const s of node.handler.body.body)
200
+ this.analyzeStatement(s);
201
+ this.scope.exit();
202
+ }
203
+ if (node.finalizer) {
204
+ this.scope.enter('block');
205
+ for (const s of node.finalizer.body)
206
+ this.analyzeStatement(s);
207
+ this.scope.exit();
208
+ }
209
+ }
210
+ analyzeExport(node) {
211
+ for (const s of node.specifiers)
212
+ if (!this.scope.lookup(s.name))
213
+ this.warn(`Exported name "${s.name}" may not be defined.`, s.loc.line, s.loc.column);
214
+ }
215
+ analyzeExpr(expr) {
216
+ switch (expr.kind) {
217
+ case 'Identifier': {
218
+ const builtins = new Set(['say', 'math', 'fs', 'json', 'date', 'console', 'this', 'super']);
219
+ if (!builtins.has(expr.name) && !this.scope.lookup(expr.name))
220
+ this.warn(`"${expr.name}" may not be defined.`, expr.loc.line, expr.loc.column);
221
+ break;
222
+ }
223
+ case 'AssignmentExpression': {
224
+ if (expr.left.kind === 'Identifier') {
225
+ const sym = this.scope.lookup(expr.left.name);
226
+ if (sym?.kind === 'constant')
227
+ this.err('ConstantReassignment', `Cannot reassign constant "${expr.left.name}".`, expr.loc.line, expr.loc.column);
228
+ }
229
+ this.analyzeExpr(expr.left);
230
+ this.analyzeExpr(expr.right);
231
+ break;
232
+ }
233
+ case 'BinaryExpression':
234
+ case 'LogicalExpression':
235
+ this.analyzeExpr(expr.left);
236
+ this.analyzeExpr(expr.right);
237
+ break;
238
+ case 'UnaryExpression':
239
+ this.analyzeExpr(expr.operand);
240
+ break;
241
+ case 'CallExpression':
242
+ this.analyzeExpr(expr.callee);
243
+ for (const a of expr.args)
244
+ this.analyzeExpr(a);
245
+ break;
246
+ case 'MemberExpression':
247
+ this.analyzeExpr(expr.object);
248
+ if (expr.computed)
249
+ this.analyzeExpr(expr.property);
250
+ break;
251
+ case 'ArrayExpression':
252
+ for (const e of expr.elements)
253
+ this.analyzeExpr(e);
254
+ break;
255
+ case 'ObjectExpression':
256
+ for (const p of expr.properties)
257
+ this.analyzeExpr(p.value);
258
+ break;
259
+ case 'NewExpression':
260
+ if (!this.scope.lookup(expr.callee.name))
261
+ this.warn(`Class "${expr.callee.name}" may not be defined.`, expr.callee.loc.line, expr.callee.loc.column);
262
+ for (const a of expr.args)
263
+ this.analyzeExpr(a);
264
+ break;
265
+ }
266
+ }
267
+ }
268
+ // ─── Optimizer ────────────────────────────────────────────────────────────────
269
+ export class Optimizer {
270
+ optimize(program) {
271
+ return { ...program, body: program.body.map(s => this.optStmt(s)).filter(s => !(s.kind === 'ExpressionStatement' && s.expression.kind === 'Literal' && s.expression.value === undefined)) };
272
+ }
273
+ optStmt(stmt) {
274
+ switch (stmt.kind) {
275
+ case 'VariableDeclaration': return stmt.value ? { ...stmt, value: this.optExpr(stmt.value) } : stmt;
276
+ case 'ExpressionStatement': return { ...stmt, expression: this.optExpr(stmt.expression) };
277
+ case 'ReturnStatement': return stmt.value ? { ...stmt, value: this.optExpr(stmt.value) } : stmt;
278
+ case 'IfStatement': return { ...stmt, condition: this.optExpr(stmt.condition), consequent: { ...stmt.consequent, body: stmt.consequent.body.map(s => this.optStmt(s)) }, alternate: stmt.alternate ? { ...stmt.alternate, body: stmt.alternate.body.map(s => this.optStmt(s)) } : null };
279
+ case 'RepeatStatement': return { ...stmt, condition: stmt.condition ? this.optExpr(stmt.condition) : null, body: { ...stmt.body, body: stmt.body.body.map(s => this.optStmt(s)) } };
280
+ case 'UntilStatement': return { ...stmt, condition: this.optExpr(stmt.condition), body: { ...stmt.body, body: stmt.body.body.map(s => this.optStmt(s)) } };
281
+ default: return stmt;
282
+ }
283
+ }
284
+ optExpr(expr) {
285
+ if (expr.kind !== 'BinaryExpression')
286
+ return expr;
287
+ const left = this.optExpr(expr.left);
288
+ const right = this.optExpr(expr.right);
289
+ if (left.kind === 'Literal' && right.kind === 'Literal') {
290
+ const l = left.value;
291
+ const r = right.value;
292
+ if (typeof l === 'number' && typeof r === 'number') {
293
+ let result = null;
294
+ switch (expr.operator) {
295
+ case '+':
296
+ result = l + r;
297
+ break;
298
+ case '-':
299
+ result = l - r;
300
+ break;
301
+ case '*':
302
+ result = l * r;
303
+ break;
304
+ case '/':
305
+ result = r !== 0 ? l / r : null;
306
+ break;
307
+ case '%':
308
+ result = l % r;
309
+ break;
310
+ case '**':
311
+ result = l ** r;
312
+ break;
313
+ case '>':
314
+ result = l > r;
315
+ break;
316
+ case '<':
317
+ result = l < r;
318
+ break;
319
+ case '>=':
320
+ result = l >= r;
321
+ break;
322
+ case '<=':
323
+ result = l <= r;
324
+ break;
325
+ case '==':
326
+ result = l == r;
327
+ break;
328
+ case '===':
329
+ result = l === r;
330
+ break;
331
+ case '!=':
332
+ result = l != r;
333
+ break;
334
+ case '!==':
335
+ result = l !== r;
336
+ break;
337
+ }
338
+ if (result !== null)
339
+ return { kind: 'Literal', value: result, raw: String(result), loc: left.loc };
340
+ }
341
+ if (typeof l === 'string' && typeof r === 'string' && expr.operator === '+')
342
+ return { kind: 'Literal', value: l + r, raw: `"${l + r}"`, loc: left.loc };
343
+ }
344
+ return { ...expr, left, right };
345
+ }
346
+ }
347
+ // ─── Code Generator ───────────────────────────────────────────────────────────
348
+ const KW = {
349
+ make: 'let', fixed: 'const', keep: 'var', do: 'function', give: 'return',
350
+ say: 'console.log', check: 'if', otherwise: 'else', pick: 'switch', when: 'case',
351
+ anyway: 'default', repeat: 'for', until: 'while', stop: 'break', skip: 'continue',
352
+ type: 'class', from: 'extends', create: 'new', me: 'this', parent: 'super',
353
+ attempt: 'try', oops: 'catch', panic: 'throw', done: 'finally',
354
+ later: 'async', wait: 'await', remove: 'delete', kind: 'typeof', is: 'instanceof',
355
+ mine: 'private', everyone: 'public', family: 'protected', shared: 'static',
356
+ yes: 'true', no: 'false', empty: 'null', unknown: 'undefined'
357
+ };
358
+ export class CodeGenerator {
359
+ constructor() {
360
+ this.out = '';
361
+ this.level = 0;
362
+ }
363
+ line(s = '') { this.out += ' '.repeat(this.level) + s + '\n'; }
364
+ emit(s) { this.out += s; }
365
+ indent() { this.level++; }
366
+ dedent() { this.level--; }
367
+ generate(program) {
368
+ this.out = '';
369
+ this.level = 0;
370
+ this.line('// Generated by CodeScript v1.0.0');
371
+ this.line();
372
+ for (const stmt of program.body)
373
+ this.genStmt(stmt);
374
+ return this.out;
375
+ }
376
+ genStmt(stmt) {
377
+ switch (stmt.kind) {
378
+ case 'VariableDeclaration': {
379
+ if (stmt.keyword === 'keep')
380
+ console.warn('Warning: "keep" is deprecated. Use "make" instead.');
381
+ const val = stmt.value ? ` = ${this.genExpr(stmt.value)}` : '';
382
+ this.line(`${KW[stmt.keyword]} ${stmt.name.name}${val};`);
383
+ break;
384
+ }
385
+ case 'FunctionDeclaration': {
386
+ const a = stmt.isAsync ? 'async ' : '';
387
+ const p = stmt.params.map(x => x.name).join(', ');
388
+ if (stmt.name.name === '') {
389
+ this.emit(`${a}function(${p}){`);
390
+ this.line();
391
+ this.indent();
392
+ this.genBlock(stmt.body);
393
+ this.dedent();
394
+ this.line('}');
395
+ break;
396
+ }
397
+ this.line(`${a}function ${stmt.name.name}(${p}){`);
398
+ this.indent();
399
+ this.genBlock(stmt.body);
400
+ this.dedent();
401
+ this.line('}');
402
+ this.line();
403
+ break;
404
+ }
405
+ case 'ReturnStatement':
406
+ this.line(`return${stmt.value ? ' ' + this.genExpr(stmt.value) : ''};`);
407
+ break;
408
+ case 'IfStatement': {
409
+ this.line(`if(${this.genExpr(stmt.condition)}){`);
410
+ this.indent();
411
+ this.genBlock(stmt.consequent);
412
+ this.dedent();
413
+ if (stmt.alternate) {
414
+ const inner = stmt.alternate.body;
415
+ if (inner.length === 1 && inner[0].kind === 'IfStatement') {
416
+ this.emit('}else ');
417
+ this.genStmt(inner[0]);
418
+ break;
419
+ }
420
+ this.line('}else{');
421
+ this.indent();
422
+ this.genBlock(stmt.alternate);
423
+ this.dedent();
424
+ }
425
+ this.line('}');
426
+ break;
427
+ }
428
+ case 'SwitchStatement': {
429
+ this.line(`switch(${this.genExpr(stmt.discriminant)}){`);
430
+ this.indent();
431
+ for (const c of stmt.cases) {
432
+ this.line(`case ${this.genExpr(c.test)}:`);
433
+ this.indent();
434
+ this.genBlock(c.body);
435
+ this.line('break;');
436
+ this.dedent();
437
+ }
438
+ if (stmt.defaultCase) {
439
+ this.line('default:');
440
+ this.indent();
441
+ this.genBlock(stmt.defaultCase);
442
+ this.dedent();
443
+ }
444
+ this.dedent();
445
+ this.line('}');
446
+ break;
447
+ }
448
+ case 'RepeatStatement': {
449
+ let init = '';
450
+ if (stmt.init?.kind === 'VariableDeclaration')
451
+ init = `${KW[stmt.init.keyword]} ${stmt.init.name.name}${stmt.init.value ? ' = ' + this.genExpr(stmt.init.value) : ''}`;
452
+ else if (stmt.init?.kind === 'ExpressionStatement')
453
+ init = this.genExpr(stmt.init.expression);
454
+ this.line(`for(${init}; ${stmt.condition ? this.genExpr(stmt.condition) : ''}; ${stmt.update ? this.genExpr(stmt.update) : ''}){`);
455
+ this.indent();
456
+ this.genBlock(stmt.body);
457
+ this.dedent();
458
+ this.line('}');
459
+ break;
460
+ }
461
+ case 'UntilStatement':
462
+ this.line(`while(${this.genExpr(stmt.condition)}){`);
463
+ this.indent();
464
+ this.genBlock(stmt.body);
465
+ this.dedent();
466
+ this.line('}');
467
+ break;
468
+ case 'BreakStatement':
469
+ this.line('break;');
470
+ break;
471
+ case 'ContinueStatement':
472
+ this.line('continue;');
473
+ break;
474
+ case 'ClassDeclaration': {
475
+ const ext = stmt.superClass ? ` extends ${stmt.superClass.name}` : '';
476
+ this.line(`class ${stmt.name.name}${ext}{`);
477
+ this.indent();
478
+ for (const m of stmt.body.members) {
479
+ const p = m.params.map(x => x.name).join(', ');
480
+ if (m.kind === 'ConstructorDeclaration') {
481
+ this.line(`constructor(${p}){`);
482
+ this.indent();
483
+ this.genBlock(m.body);
484
+ this.dedent();
485
+ this.line('}');
486
+ }
487
+ else {
488
+ this.line(`${m.isStatic ? 'static ' : ''}${m.isAsync ? 'async ' : ''}${m.name.name}(${p}){`);
489
+ this.indent();
490
+ this.genBlock(m.body);
491
+ this.dedent();
492
+ this.line('}');
493
+ }
494
+ }
495
+ this.dedent();
496
+ this.line('}');
497
+ this.line();
498
+ break;
499
+ }
500
+ case 'ImportDeclaration': {
501
+ const src = stmt.source.replace('.code', '.js');
502
+ this.line(stmt.specifiers.length === 0 ? `import "${src}";` : `import { ${stmt.specifiers.map(s => s.name).join(', ')} } from "${src}";`);
503
+ break;
504
+ }
505
+ case 'ExportDeclaration':
506
+ this.line(`export { ${stmt.specifiers.map(s => s.name).join(', ')} };`);
507
+ break;
508
+ case 'TryStatement': {
509
+ this.line('try{');
510
+ this.indent();
511
+ this.genBlock(stmt.body);
512
+ this.dedent();
513
+ this.emit('}');
514
+ if (stmt.handler) {
515
+ this.emit(`catch(${stmt.handler.param.name}){`);
516
+ this.line();
517
+ this.indent();
518
+ this.genBlock(stmt.handler.body);
519
+ this.dedent();
520
+ this.emit('}');
521
+ }
522
+ if (stmt.finalizer) {
523
+ this.emit('finally{');
524
+ this.line();
525
+ this.indent();
526
+ this.genBlock(stmt.finalizer);
527
+ this.dedent();
528
+ this.emit('}');
529
+ }
530
+ this.line();
531
+ break;
532
+ }
533
+ case 'ThrowStatement':
534
+ this.line(`throw ${this.genExpr(stmt.value)};`);
535
+ break;
536
+ case 'ExpressionStatement':
537
+ this.line(`${this.genExpr(stmt.expression)};`);
538
+ break;
539
+ }
540
+ }
541
+ genBlock(block) { for (const s of block.body)
542
+ this.genStmt(s); }
543
+ genExpr(expr) {
544
+ switch (expr.kind) {
545
+ case 'Identifier': return KW[expr.name] ?? expr.name;
546
+ case 'Literal': return expr.value === null ? 'null' : expr.value === undefined ? 'undefined' : typeof expr.value === 'string' ? `"${expr.value}"` : String(expr.value);
547
+ case 'TemplateLiteral': return `\`${expr.raw}\``;
548
+ case 'BinaryExpression': return `${this.genExpr(expr.left)} ${expr.operator} ${this.genExpr(expr.right)}`;
549
+ case 'LogicalExpression': return `${this.genExpr(expr.left)} ${expr.operator} ${this.genExpr(expr.right)}`;
550
+ case 'UnaryExpression': {
551
+ if (expr.operator === 'post++')
552
+ return `${this.genExpr(expr.operand)}++`;
553
+ if (expr.operator === 'post--')
554
+ return `${this.genExpr(expr.operand)}--`;
555
+ return `${expr.operator} ${this.genExpr(expr.operand)}`;
556
+ }
557
+ case 'AssignmentExpression': return `${this.genExpr(expr.left)} ${expr.operator} ${this.genExpr(expr.right)}`;
558
+ case 'CallExpression': {
559
+ const callee = this.genExpr(expr.callee);
560
+ return `${KW[callee] ?? callee}(${expr.args.map(a => this.genExpr(a)).join(', ')})`;
561
+ }
562
+ case 'MemberExpression': return expr.computed ? `${this.genExpr(expr.object)}[${this.genExpr(expr.property)}]` : `${this.genExpr(expr.object)}.${this.genExpr(expr.property)}`;
563
+ case 'ArrayExpression': return `[${expr.elements.map(e => this.genExpr(e)).join(', ')}]`;
564
+ case 'ObjectExpression': return expr.properties.length === 0 ? '{}' : `{ ${expr.properties.map(p => `${p.key.name}: ${this.genExpr(p.value)}`).join(', ')} }`;
565
+ case 'NewExpression': return `new ${expr.callee.name}(${expr.args.map(a => this.genExpr(a)).join(', ')})`;
566
+ case 'FunctionExpression': {
567
+ const a = expr.isAsync ? 'async ' : '';
568
+ const p = expr.params.map(x => x.name).join(', ');
569
+ const sub = new CodeGenerator();
570
+ for (const s of expr.body.body)
571
+ sub.genStmt(s);
572
+ return `${a}function(${p}){ ${sub.out.trim()} }`;
573
+ }
574
+ }
575
+ }
576
+ }
577
+ //# sourceMappingURL=compiler-core.js.map