naider 1.14.0 → 1.16.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.
@@ -0,0 +1,1014 @@
1
+ export class CGenerator {
2
+ constructor(options = {}) {
3
+ this.indent = 0;
4
+ this.output = [];
5
+ this.models = new Map();
6
+ this.schemas = new Map();
7
+ this.includes = new Set();
8
+ this.typedefs = [];
9
+ this.functions = [];
10
+ this.mainBody = [];
11
+ this.sourceMap = [];
12
+ this.currentSourceLine = 0;
13
+ this.sourceFile = options.sourceFile || null;
14
+ this.inFunction = false;
15
+ this.inMain = false;
16
+ }
17
+
18
+ generate(ast) {
19
+ this.includes.add('<stdio.h>');
20
+ this.includes.add('<stdlib.h>');
21
+
22
+ this.visitProgram(ast);
23
+
24
+ const out = [];
25
+
26
+ // Preamble: #includes
27
+ for (const inc of [...this.includes].sort()) {
28
+ out.push(`#include ${inc}`);
29
+ }
30
+ out.push('');
31
+
32
+ // Typedefs / structs
33
+ if (this.typedefs.length > 0) {
34
+ out.push(...this.typedefs);
35
+ out.push('');
36
+ }
37
+
38
+ // Function declarations
39
+ if (this.functions.length > 0) {
40
+ out.push(...this.functions);
41
+ out.push('');
42
+ }
43
+
44
+ // Main function wrapping top-level statements
45
+ if (this.mainBody.length > 0) {
46
+ out.push('int main() {');
47
+ out.push(...this.mainBody);
48
+ out.push(' return 0;');
49
+ out.push('}');
50
+ }
51
+
52
+ return out.join('\n');
53
+ }
54
+
55
+ emit(line) {
56
+ const indented = ' '.repeat(this.indent) + line;
57
+ if (this.inFunction) {
58
+ this.functions.push(indented);
59
+ } else {
60
+ this.mainBody.push(indented);
61
+ }
62
+ this.sourceMap.push(this.currentSourceLine);
63
+ }
64
+
65
+ emitRaw(line) {
66
+ if (this.inFunction) {
67
+ this.functions.push(line);
68
+ } else {
69
+ this.mainBody.push(line);
70
+ }
71
+ this.sourceMap.push(this.currentSourceLine);
72
+ }
73
+
74
+ emitTypedef(line) {
75
+ this.typedefs.push(line);
76
+ }
77
+
78
+ visitProgram(node) {
79
+ for (const stmt of node.body) {
80
+ this.visitStatement(stmt);
81
+ }
82
+ }
83
+
84
+ // ===== Type mapping =====
85
+
86
+ mapType(naideType) {
87
+ const map = {
88
+ 'str': 'const char*',
89
+ 'string': 'const char*',
90
+ 'int': 'int',
91
+ 'integer': 'int',
92
+ 'num': 'double',
93
+ 'number': 'double',
94
+ 'float': 'double',
95
+ 'bool': 'int',
96
+ 'boolean': 'int',
97
+ 'list': 'void**',
98
+ 'map': '/* map */ void*',
99
+ 'any': 'void*',
100
+ 'void': 'void',
101
+ 'json': 'const char*',
102
+ 'auto': 'int',
103
+ 'timestamp': 'long',
104
+ };
105
+ return map[naideType] || 'void*';
106
+ }
107
+
108
+ // ===== Statement dispatcher =====
109
+
110
+ visitStatement(node) {
111
+ if (node._line) this.currentSourceLine = node._line;
112
+ switch (node.type) {
113
+ case 'Use': return this.visitUse(node);
114
+ case 'UseDestructured': return this.visitUseDestructured(node);
115
+ case 'Function': return this.visitFunction(node);
116
+ case 'Return': return this.visitReturn(node);
117
+ case 'ReturnStatus': return this.visitReturnStatus(node);
118
+ case 'ReturnMethod': return this.visitReturnMethod(node);
119
+ case 'TypedVar': return this.visitTypedVar(node);
120
+ case 'If': return this.visitIf(node);
121
+ case 'Each': return this.visitEach(node);
122
+ case 'For': return this.visitFor(node);
123
+ case 'While': return this.visitWhile(node);
124
+ case 'Match': return this.visitMatch(node);
125
+ case 'Try': return this.visitTry(node);
126
+ case 'Server': return this.visitServer(node);
127
+ case 'Bot': return this.visitBot(node);
128
+ case 'Model': return this.visitModel(node);
129
+ case 'On': return this.visitOn(node);
130
+ case 'Log': return this.visitLog(node);
131
+ case 'Throw': return this.visitThrow(node);
132
+ case 'Break': this.emit('break;'); return;
133
+ case 'Continue': this.emit('continue;'); return;
134
+ case 'Assignment': return this.visitAssignment(node);
135
+ case 'CompoundAssign': return this.visitCompoundAssign(node);
136
+ case 'ExprStatement': this.emit(this.expr(node.expression) + ';'); return;
137
+ case 'DbConnect': return this.visitDbConnect(node);
138
+ case 'DbDir': return this.visitDbDir(node);
139
+ case 'DbSql': return this.visitDbSql(node);
140
+ case 'AwaitAll': return this.visitAwaitAll(node);
141
+ case 'SchemaDecl': return this.visitSchema(node);
142
+ case 'CrudDecl': return this.visitCrud(node);
143
+ case 'AuthDecl': return this.visitAuth(node);
144
+ case 'CorsDecl': return this.visitCors(node);
145
+ case 'LimitDecl': return this.visitLimit(node);
146
+ case 'EnvDecl': return this.visitEnv(node);
147
+ case 'EveryDecl': return this.visitEvery(node);
148
+ case 'WatchDecl': return this.visitWatch(node);
149
+ case 'StaticDecl': return this.visitStatic(node);
150
+ case 'WsDecl': return this.visitWs(node);
151
+ case 'GroupDecl': return this.visitGroup(node);
152
+ case 'ErrorHandler': return this.visitErrorHandler(node);
153
+ case 'CookieDecl': return this.visitCookie(node);
154
+ case 'UploadDecl': return this.visitUpload(node);
155
+ case 'SessionDecl': return this.visitSession(node);
156
+ case 'ViewDecl': return this.visitView(node);
157
+ case 'SseDecl': return this.visitSse(node);
158
+ case 'CacheDecl': return this.visitCache(node);
159
+ case 'MiddlewareRef': return this.visitMiddlewareRef(node);
160
+ case 'ReturnRender': return this.visitReturnRender(node);
161
+ case 'ValidateDecl': return this.visitValidate(node);
162
+ case 'TestDecl': return this.visitTest(node);
163
+ case 'AssertStmt': return this.visitAssert(node);
164
+ case 'QueueDecl': return this.visitQueue(node);
165
+ case 'OpenapiDecl': return this.visitOpenapi(node);
166
+ case 'ReturnRedirect': return this.visitReturnRedirect(node);
167
+ case 'ReturnDownload': return this.visitReturnDownload(node);
168
+ case 'PromptDecl': return this.visitPrompt(node);
169
+ case 'Page': return this.visitPage(node);
170
+ case 'CliApp': return this.visitCli(node);
171
+ case 'MailConfig': return this.visitMail(node);
172
+ case 'DesktopApp': return this.visitDesktop(node);
173
+ case 'Screen': return this.visitScreen(node);
174
+ case 'OauthDecl': return this.visitOauth(node);
175
+ case 'PayDecl': return this.visitPay(node);
176
+ case 'StorageDecl': return this.visitStorage(node);
177
+ case 'PdfDecl': return this.visitPdf(node);
178
+ case 'I18nDecl': return this.visitI18n(node);
179
+ case 'PushDecl': return this.visitPush(node);
180
+ case 'SearchDecl': return this.visitSearch(node);
181
+ case 'ImageDecl': return this.visitImage(node);
182
+ case 'CsvDecl': return this.visitCsv(node);
183
+ case 'LoggingDecl': return this.visitLogging(node);
184
+ case 'MigrateDecl': return this.visitMigrate(node);
185
+ case 'GrpcDecl': return this.visitGrpc(node);
186
+ case 'WebrtcDecl': return this.visitWebrtc(node);
187
+ case 'BlockchainDecl': return this.visitBlockchain(node);
188
+ default:
189
+ this.emit(`/* unknown: ${node.type} */`);
190
+ }
191
+ }
192
+
193
+ // ===== Imports / Use =====
194
+
195
+ visitUse(node) {
196
+ const raw = node.source ? this.rawString(node.source) : node.name;
197
+ this.emit(`/* use ${raw} */`);
198
+ }
199
+
200
+ visitUseDestructured(node) {
201
+ const raw = this.rawString(node.source);
202
+ const names = node.names.map(n => n.name).join(', ');
203
+ this.emit(`/* use { ${names} } from ${raw} */`);
204
+ }
205
+
206
+ // ===== Functions =====
207
+
208
+ visitFunction(node) {
209
+ const retType = node.returnType ? this.mapType(node.returnType) : 'void';
210
+ const params = node.params.map(p => {
211
+ const type = p.type ? this.mapType(p.type) : 'void*';
212
+ return `${type} ${p.name}`;
213
+ }).join(', ');
214
+
215
+ const savedInFunction = this.inFunction;
216
+ this.inFunction = true;
217
+
218
+ this.emit(`${retType} ${node.name}(${params || 'void'}) {`);
219
+ this.indent++;
220
+ for (const stmt of node.body) {
221
+ this.visitStatement(stmt);
222
+ }
223
+ this.indent--;
224
+ this.emit('}');
225
+ this.emitRaw('');
226
+
227
+ this.inFunction = savedInFunction;
228
+ }
229
+
230
+ visitReturn(node) {
231
+ if (node.value === null) {
232
+ this.emit('return;');
233
+ } else {
234
+ this.emit(`return ${this.expr(node.value)};`);
235
+ }
236
+ }
237
+
238
+ visitReturnStatus(node) {
239
+ this.emit(`/* return status ${this.expr(node.statusCode)} with body */`);
240
+ this.emit(`printf("Status: %s\\n", ${this.expr(node.body)});`);
241
+ }
242
+
243
+ visitReturnMethod(node) {
244
+ this.emit(`/* return ${node.method}: ${this.expr(node.value)} */`);
245
+ }
246
+
247
+ // ===== Variables =====
248
+
249
+ visitTypedVar(node) {
250
+ const type = node.varType ? this.mapType(node.varType) : this.inferCType(node.value);
251
+ this.emit(`${type} ${node.name} = ${this.expr(node.value)};`);
252
+ }
253
+
254
+ inferCType(valueNode) {
255
+ if (!valueNode) return 'void*';
256
+ switch (valueNode.type) {
257
+ case 'Number':
258
+ return valueNode.value.includes('.') ? 'double' : 'int';
259
+ case 'String': return 'const char*';
260
+ case 'Bool': return 'int';
261
+ case 'Null': return 'void*';
262
+ case 'Array': return 'void**';
263
+ default: return 'void*';
264
+ }
265
+ }
266
+
267
+ visitAssignment(node) {
268
+ const value = this.expr(node.value);
269
+ if (node.target.type === 'Array') {
270
+ this.emit(`/* destructuring not supported in C */`);
271
+ this.emit(`/* ${this.expr(node.target)} = ${value} */`);
272
+ } else if (node.target.type === 'Object') {
273
+ this.emit(`/* object destructuring not supported in C */`);
274
+ } else {
275
+ this.emit(`${this.expr(node.target)} = ${value};`);
276
+ }
277
+ }
278
+
279
+ visitCompoundAssign(node) {
280
+ this.emit(`${this.expr(node.target)} ${node.op} ${this.expr(node.value)};`);
281
+ }
282
+
283
+ // ===== Control flow =====
284
+
285
+ visitIf(node) {
286
+ this.emit(`if (${this.expr(node.condition)}) {`);
287
+ this.indent++;
288
+ for (const stmt of node.body) this.visitStatement(stmt);
289
+ this.indent--;
290
+
291
+ for (const elif of node.elifs) {
292
+ this.emit(`} else if (${this.expr(elif.condition)}) {`);
293
+ this.indent++;
294
+ for (const stmt of elif.body) this.visitStatement(stmt);
295
+ this.indent--;
296
+ }
297
+
298
+ if (node.elseBody) {
299
+ this.emit('} else {');
300
+ this.indent++;
301
+ for (const stmt of node.elseBody) this.visitStatement(stmt);
302
+ this.indent--;
303
+ }
304
+ this.emit('}');
305
+ }
306
+
307
+ visitEach(node) {
308
+ const collection = this.expr(node.collection);
309
+ this.emit(`/* each: iterate over ${collection} */`);
310
+ this.emit(`/* C requires manual iteration with known size */`);
311
+ this.emit(`for (int __i = 0; /* __i < length */; __i++) {`);
312
+ this.indent++;
313
+ if (node.key) {
314
+ this.emit(`int ${node.key} = __i;`);
315
+ }
316
+ this.emit(`void* ${node.value} = ${collection}[__i];`);
317
+ for (const stmt of node.body) this.visitStatement(stmt);
318
+ this.indent--;
319
+ this.emit('}');
320
+ }
321
+
322
+ visitFor(node) {
323
+ const varName = node.varName;
324
+ const start = this.expr(node.start);
325
+ const end = this.expr(node.end);
326
+ this.emit(`for (int ${varName} = ${start}; ${varName} < ${end}; ${varName}++) {`);
327
+ this.indent++;
328
+ for (const stmt of node.body) this.visitStatement(stmt);
329
+ this.indent--;
330
+ this.emit('}');
331
+ }
332
+
333
+ visitWhile(node) {
334
+ this.emit(`while (${this.expr(node.condition)}) {`);
335
+ this.indent++;
336
+ for (const stmt of node.body) this.visitStatement(stmt);
337
+ this.indent--;
338
+ this.emit('}');
339
+ }
340
+
341
+ visitMatch(node) {
342
+ this.emit(`switch (${this.expr(node.value)}) {`);
343
+ this.indent++;
344
+ for (const c of node.cases) {
345
+ if (c.pattern.type === 'DefaultPattern') {
346
+ this.emit('default: {');
347
+ } else {
348
+ this.emit(`case ${this.expr(c.pattern)}: {`);
349
+ }
350
+ this.indent++;
351
+ for (const stmt of c.body) this.visitStatement(stmt);
352
+ this.emit('break;');
353
+ this.indent--;
354
+ this.emit('}');
355
+ }
356
+ this.indent--;
357
+ this.emit('}');
358
+ }
359
+
360
+ visitTry(node) {
361
+ this.emit('/* C has no try/catch - use error codes or setjmp/longjmp */');
362
+ this.emit('/* try { */');
363
+ for (const stmt of node.body) this.visitStatement(stmt);
364
+ if (node.catchBody) {
365
+ const catchParam = node.catchVar || 'err';
366
+ this.emit(`/* } catch (${catchParam}) { */`);
367
+ for (const stmt of node.catchBody) this.visitStatement(stmt);
368
+ }
369
+ if (node.ensureBody) {
370
+ this.emit('/* } finally { */');
371
+ for (const stmt of node.ensureBody) this.visitStatement(stmt);
372
+ }
373
+ this.emit('/* } */');
374
+ }
375
+
376
+ // ===== Model (struct) =====
377
+
378
+ visitModel(node) {
379
+ this.models.set(node.name, node);
380
+
381
+ let structDef = `typedef struct {\n`;
382
+ for (const f of node.fields) {
383
+ const type = f.type ? this.mapType(f.type) : 'void*';
384
+ structDef += ` ${type} ${f.name};\n`;
385
+ }
386
+ structDef += `} ${node.name};`;
387
+ this.emitTypedef(structDef);
388
+ this.emitTypedef('');
389
+
390
+ // Generate method stubs as standalone functions
391
+ for (const method of node.methods) {
392
+ const retType = method.returnType ? this.mapType(method.returnType) : 'void';
393
+ const params = method.params.map(p => {
394
+ const type = p.type ? this.mapType(p.type) : 'void*';
395
+ return `${type} ${p.name}`;
396
+ });
397
+ params.unshift(`${node.name}* self`);
398
+
399
+ const savedInFunction = this.inFunction;
400
+ this.inFunction = true;
401
+
402
+ this.emit(`${retType} ${node.name}_${method.name}(${params.join(', ')}) {`);
403
+ this.indent++;
404
+ for (const stmt of method.body) {
405
+ this.visitStatement(stmt);
406
+ }
407
+ this.indent--;
408
+ this.emit('}');
409
+ this.emitRaw('');
410
+
411
+ this.inFunction = savedInFunction;
412
+ }
413
+ }
414
+
415
+ // ===== Log =====
416
+
417
+ visitLog(node) {
418
+ this.includes.add('<stdio.h>');
419
+ const args = node.args.map(a => this.expr(a));
420
+ if (args.length === 1) {
421
+ const arg = args[0];
422
+ if (node.args[0] && node.args[0].type === 'String') {
423
+ this.emit(`printf(${arg});`);
424
+ this.emit(`printf("\\n");`);
425
+ } else {
426
+ this.emit(`printf("%s\\n", ${arg});`);
427
+ }
428
+ } else {
429
+ // Multiple args: print each separated by space
430
+ const fmtParts = args.map(() => '%s').join(' ');
431
+ this.emit(`printf("${fmtParts}\\n", ${args.join(', ')});`);
432
+ }
433
+ }
434
+
435
+ visitThrow(node) {
436
+ this.includes.add('<stdio.h>');
437
+ this.includes.add('<stdlib.h>');
438
+ this.emit(`fprintf(stderr, "Error: %s\\n", ${this.expr(node.value)});`);
439
+ this.emit('exit(1);');
440
+ }
441
+
442
+ // ===== Events =====
443
+
444
+ visitOn(node) {
445
+ this.emit(`/* on event: ${this.expr(node.event)} */`);
446
+ this.emit(`/* C has no built-in event system - use callbacks or signal handlers */`);
447
+ }
448
+
449
+ // ===== Server =====
450
+
451
+ visitServer(node) {
452
+ this.emit('/* HTTP server: use libmicrohttpd or libevent */');
453
+ this.emit(`/* server "${node.name}" */`);
454
+ const port = node.port ? this.expr(node.port) : '3000';
455
+ this.emit(`/* port: ${port} */`);
456
+
457
+ for (const child of node.routes) {
458
+ if (child.type === 'Route') {
459
+ const method = child.method.toUpperCase();
460
+ const path = this.rawString(child.path);
461
+ this.emit(`/* ${method} ${path} */`);
462
+ this.emit(`/* { */`);
463
+ this.indent++;
464
+ for (const stmt of child.body) this.visitStatement(stmt);
465
+ this.indent--;
466
+ this.emit(`/* } */`);
467
+ this.emitRaw('');
468
+ } else {
469
+ this.visitStatement(child);
470
+ }
471
+ }
472
+
473
+ this.emit(`printf("Server ${node.name} would run on port %s\\n", "${port}");`);
474
+ this.emitRaw('');
475
+ }
476
+
477
+ // ===== Bot =====
478
+
479
+ visitBot(node) {
480
+ this.emit('/* Bot: C has no built-in bot framework */');
481
+ this.emit(`/* TODO: bot "${node.name}" - implement with libcurl for API calls */`);
482
+ this.emitRaw('');
483
+ }
484
+
485
+ // ===== Database =====
486
+
487
+ visitDbConnect(node) {
488
+ this.emit(`/* db connect: ${this.expr(node.connectionString)} */`);
489
+ this.emit('/* TODO: use libpq (PostgreSQL) or sqlite3 C API */');
490
+ }
491
+
492
+ visitDbDir(node) {
493
+ const raw = node.path.raw || node.path.parts?.map(p => p.value).join('') || 'data/';
494
+ this.emit(`/* db dir: ${raw} */`);
495
+ }
496
+
497
+ visitDbSql(node) {
498
+ this.emit('/* db sql: use sqlite3 C API */');
499
+ this.emit('/* #include <sqlite3.h> */');
500
+ this.emit('/* sqlite3 *__db; */');
501
+ this.emit('/* sqlite3_open("data.db", &__db); */');
502
+ }
503
+
504
+ visitAwaitAll(node) {
505
+ this.emit('/* await all: C has no async/await - use pthreads */');
506
+ for (const e of node.expressions) {
507
+ this.emit(`${this.expr(e)};`);
508
+ }
509
+ }
510
+
511
+ // ===== Domain features (comment stubs) =====
512
+
513
+ visitSchema(node) {
514
+ this.schemas.set(node.name, node);
515
+ let structDef = `typedef struct {\n`;
516
+ for (const f of node.fields) {
517
+ const type = this.mapType(f.type);
518
+ structDef += ` ${type} ${f.name};\n`;
519
+ }
520
+ structDef += `} ${node.name};`;
521
+ this.emitTypedef(structDef);
522
+ this.emitTypedef('');
523
+ }
524
+
525
+ visitCrud(node) {
526
+ this.emit(`/* TODO: CRUD for "${node.schemaName}" - implement with HTTP library */`);
527
+ }
528
+
529
+ visitAuth(node) {
530
+ this.emit('/* TODO: auth - use libcurl + JWT C library (libjwt) */');
531
+ }
532
+
533
+ visitCors(node) {
534
+ this.emit('/* TODO: CORS - set headers in HTTP response */');
535
+ }
536
+
537
+ visitLimit(node) {
538
+ this.emit('/* TODO: rate limiting - implement with token bucket algorithm */');
539
+ }
540
+
541
+ visitEnv(node) {
542
+ this.includes.add('<stdlib.h>');
543
+ for (const v of node.vars) {
544
+ this.emit(`const char* ${v.name} = getenv("${v.name}");`);
545
+ }
546
+ this.emitRaw('');
547
+ }
548
+
549
+ visitEvery(node) {
550
+ this.emit('/* TODO: scheduled task - use timer_create or sleep loop */');
551
+ this.includes.add('<unistd.h>');
552
+ }
553
+
554
+ visitWatch(node) {
555
+ this.emit(`/* TODO: watch event "${node.eventName}" - use callback pattern */`);
556
+ }
557
+
558
+ visitStatic(node) {
559
+ this.emit('/* TODO: static files - use HTTP library to serve files */');
560
+ }
561
+
562
+ visitWs(node) {
563
+ this.emit('/* TODO: WebSocket - use libwebsockets */');
564
+ }
565
+
566
+ visitGroup(node) {
567
+ this.emit('/* TODO: route group - implement with HTTP library */');
568
+ }
569
+
570
+ visitErrorHandler(node) {
571
+ this.emit('/* TODO: error handler - use errno and custom error codes */');
572
+ }
573
+
574
+ visitCookie(node) {
575
+ this.emit('/* TODO: cookies - set via HTTP headers */');
576
+ }
577
+
578
+ visitUpload(node) {
579
+ this.emit('/* TODO: file upload - use multipart form parser */');
580
+ }
581
+
582
+ visitSession(node) {
583
+ this.emit('/* TODO: sessions - implement with in-memory hash map */');
584
+ }
585
+
586
+ visitView(node) {
587
+ this.emit('/* TODO: view engine - use string templates */');
588
+ }
589
+
590
+ visitSse(node) {
591
+ this.emit('/* TODO: Server-Sent Events - use chunked HTTP response */');
592
+ }
593
+
594
+ visitCache(node) {
595
+ this.emit('/* TODO: caching - use in-memory hash map or memcached C client */');
596
+ }
597
+
598
+ visitMiddlewareRef(node) {
599
+ this.emit(`/* TODO: middleware "${node.name}" */`);
600
+ }
601
+
602
+ visitReturnRender(node) {
603
+ this.emit(`/* TODO: render template ${this.expr(node.template)} */`);
604
+ }
605
+
606
+ visitValidate(node) {
607
+ this.emit('/* TODO: validation - implement manually */');
608
+ }
609
+
610
+ visitTest(node) {
611
+ this.includes.add('<assert.h>');
612
+ const name = this.rawString(node.name);
613
+ const funcName = `test_${name.replace(/[^a-zA-Z0-9]/g, '_')}`;
614
+
615
+ const savedInFunction = this.inFunction;
616
+ this.inFunction = true;
617
+
618
+ this.emit(`void ${funcName}(void) {`);
619
+ this.indent++;
620
+ for (const stmt of node.body) this.visitStatement(stmt);
621
+ this.indent--;
622
+ this.emit('}');
623
+ this.emitRaw('');
624
+
625
+ this.inFunction = savedInFunction;
626
+ }
627
+
628
+ visitAssert(node) {
629
+ this.includes.add('<assert.h>');
630
+ const exprNode = node.expr;
631
+ if (exprNode.type === 'Binary' && (exprNode.op === '===' || exprNode.op === '==')) {
632
+ this.emit(`assert(${this.expr(exprNode.left)} == ${this.expr(exprNode.right)});`);
633
+ } else if (exprNode.type === 'Binary' && (exprNode.op === '!==' || exprNode.op === '!=')) {
634
+ this.emit(`assert(${this.expr(exprNode.left)} != ${this.expr(exprNode.right)});`);
635
+ } else {
636
+ this.emit(`assert(${this.expr(exprNode)});`);
637
+ }
638
+ }
639
+
640
+ visitQueue(node) {
641
+ this.emit(`/* TODO: queue "${node.name}" - use POSIX message queues or custom implementation */`);
642
+ }
643
+
644
+ visitOpenapi(node) {
645
+ this.emit('/* TODO: OpenAPI spec - generate JSON manually */');
646
+ }
647
+
648
+ visitReturnRedirect(node) {
649
+ this.emit(`/* TODO: redirect to ${this.expr(node.url)} */`);
650
+ }
651
+
652
+ visitReturnDownload(node) {
653
+ this.emit(`/* TODO: download file ${this.expr(node.filePath)} */`);
654
+ }
655
+
656
+ visitPrompt(node) {
657
+ this.emit(`/* TODO: prompt template "${node.name}" - use printf with format strings */`);
658
+ }
659
+
660
+ visitPage(node) {
661
+ this.emit('/* TODO: page generation - use fprintf to write HTML file */');
662
+ }
663
+
664
+ visitCli(node) {
665
+ this.includes.add('<string.h>');
666
+ this.emit('/* CLI argument parsing */');
667
+ this.emit('/* argc and argv available in main() */');
668
+
669
+ for (const arg of node.args) {
670
+ const argName = this.rawString(arg.name);
671
+ this.emit(`/* --${argName}: ${arg.type} */`);
672
+ }
673
+ for (const flag of node.flags) {
674
+ const s = this.rawString(flag.short);
675
+ const l = this.rawString(flag.long);
676
+ this.emit(`/* -${s}, --${l} */`);
677
+ }
678
+ }
679
+
680
+ visitMail(node) {
681
+ this.emit('/* TODO: mail - use libcurl for SMTP */');
682
+ }
683
+
684
+ visitDesktop(node) {
685
+ this.emit(`/* TODO: desktop app "${node.name}" - use GTK or SDL2 */`);
686
+ }
687
+
688
+ visitScreen(node) {
689
+ this.emit(`/* TODO: mobile screen "${node.name}" - not applicable in C */`);
690
+ }
691
+
692
+ visitOauth(node) {
693
+ this.emit('/* TODO: OAuth - use libcurl for HTTP requests + libjwt */');
694
+ }
695
+
696
+ visitPay(node) {
697
+ this.emit('/* TODO: payment - use libcurl for Stripe API */');
698
+ }
699
+
700
+ visitStorage(node) {
701
+ this.emit('/* TODO: cloud storage - use AWS SDK for C or libcurl */');
702
+ }
703
+
704
+ visitPdf(node) {
705
+ this.emit('/* TODO: PDF generation - use libharu (libHPDF) */');
706
+ }
707
+
708
+ visitI18n(node) {
709
+ this.emit('/* TODO: i18n - use gettext or custom key-value lookup */');
710
+ }
711
+
712
+ visitPush(node) {
713
+ this.emit('/* TODO: push notifications - use libcurl for web push API */');
714
+ }
715
+
716
+ visitSearch(node) {
717
+ this.emit('/* TODO: search - use libcurl for Elasticsearch/Meilisearch API */');
718
+ }
719
+
720
+ visitImage(node) {
721
+ this.emit('/* TODO: image processing - use stb_image or ImageMagick C API */');
722
+ }
723
+
724
+ visitCsv(node) {
725
+ this.emit('/* TODO: CSV - use fprintf for writing, custom parser for reading */');
726
+ }
727
+
728
+ visitLogging(node) {
729
+ this.emit('/* TODO: logging - use syslog or custom file logger */');
730
+ }
731
+
732
+ visitMigrate(node) {
733
+ this.emit('/* TODO: DB migration - use sqlite3 C API */');
734
+ }
735
+
736
+ visitGrpc(node) {
737
+ this.emit('/* TODO: gRPC - use grpc-c library */');
738
+ }
739
+
740
+ visitWebrtc(node) {
741
+ this.emit('/* TODO: WebRTC - use libdatachannel */');
742
+ }
743
+
744
+ visitBlockchain(node) {
745
+ this.emit('/* TODO: blockchain - use libcurl for JSON-RPC */');
746
+ }
747
+
748
+ // ===== Expression generation =====
749
+
750
+ expr(node) {
751
+ if (!node) return 'NULL';
752
+
753
+ switch (node.type) {
754
+ case 'Number': return node.value;
755
+
756
+ case 'String': return this.generateString(node.value);
757
+
758
+ case 'Bool': return node.value ? '1' : '0';
759
+
760
+ case 'Null': return 'NULL';
761
+
762
+ case 'Self': return 'self';
763
+
764
+ case 'Identifier': return this.mapIdentifier(node.name);
765
+
766
+ case 'Binary': {
767
+ const op = this.mapBinaryOp(node.op);
768
+ const l = this.expr(node.left);
769
+ const r = this.expr(node.right);
770
+ const simple = node.left.type !== 'Binary' && node.right.type !== 'Binary';
771
+ return simple ? `${l} ${op} ${r}` : `(${l} ${op} ${r})`;
772
+ }
773
+
774
+ case 'Unary':
775
+ return `${this.mapUnaryOp(node.op)}${this.expr(node.expr)}`;
776
+
777
+ case 'Await':
778
+ return `/* await */ ${this.expr(node.expr)}`;
779
+
780
+ case 'AwaitAllExpr':
781
+ return `/* await all */ ${this.expr(node.expr)}`;
782
+
783
+ case 'Spread':
784
+ return `/* spread */ ${this.expr(node.expr)}`;
785
+
786
+ case 'New': {
787
+ // In C, allocate with malloc
788
+ this.includes.add('<stdlib.h>');
789
+ return `/* new */ malloc(sizeof(${this.expr(node.expr)}))`;
790
+ }
791
+
792
+ case 'TypeOf':
793
+ return `/* typeof */ "unknown"`;
794
+
795
+ case 'MemberAccess':
796
+ return this.generateMemberAccess(node);
797
+
798
+ case 'OptionalAccess':
799
+ return `(${this.expr(node.object)} ? ${this.expr(node.object)}->${node.property} : NULL)`;
800
+
801
+ case 'Call':
802
+ return this.generateCall(node);
803
+
804
+ case 'IndexAccess':
805
+ return `${this.expr(node.object)}[${this.expr(node.index)}]`;
806
+
807
+ case 'Array':
808
+ // C doesn't have array literals in expressions easily
809
+ return `/* array */ NULL`;
810
+
811
+ case 'Object':
812
+ return `/* object literal */ NULL`;
813
+
814
+ case 'ArrowFn':
815
+ return `/* function pointer */ NULL`;
816
+
817
+ case 'Lambda':
818
+ return `/* lambda */ NULL`;
819
+
820
+ case 'Ternary':
821
+ return `(${this.expr(node.condition)} ? ${this.expr(node.consequent)} : ${this.expr(node.alternate)})`;
822
+
823
+ case 'Pipe':
824
+ return this.generatePipe(node);
825
+
826
+ default:
827
+ return `/* expr:${node.type} */ 0`;
828
+ }
829
+ }
830
+
831
+ mapIdentifier(name) {
832
+ const map = {
833
+ 'null': 'NULL',
834
+ 'undefined': 'NULL',
835
+ 'true': '1',
836
+ 'false': '0',
837
+ 'this': 'self',
838
+ };
839
+ return map[name] || name;
840
+ }
841
+
842
+ mapBinaryOp(op) {
843
+ const map = {
844
+ '===': '==',
845
+ '!==': '!=',
846
+ '&&': '&&',
847
+ '||': '||',
848
+ 'and': '&&',
849
+ 'or': '||',
850
+ };
851
+ return map[op] || op;
852
+ }
853
+
854
+ mapUnaryOp(op) {
855
+ if (op === 'not' || op === '!') return '!';
856
+ return op;
857
+ }
858
+
859
+ generateMemberAccess(node) {
860
+ const obj = this.expr(node.object);
861
+ const prop = node.property;
862
+
863
+ // Map common patterns
864
+ if (prop === 'length') {
865
+ this.includes.add('<string.h>');
866
+ return `strlen(${obj})`;
867
+ }
868
+
869
+ // Struct member access: use -> for pointers, . for values
870
+ return `${obj}.${prop}`;
871
+ }
872
+
873
+ generateCall(node) {
874
+ const args = node.args.map(a => this.expr(a)).join(', ');
875
+
876
+ if (node.callee.type === 'Identifier') {
877
+ const name = node.callee.name;
878
+ if (name === 'parseInt') return `atoi(${args})`;
879
+ if (name === 'parseFloat') return `atof(${args})`;
880
+ if (name === 'toString') { this.includes.add('<stdio.h>'); return `/* toString */ ${args}`; }
881
+ }
882
+
883
+ if (node.callee.type === 'MemberAccess') {
884
+ const obj = this.expr(node.callee.object);
885
+ const prop = node.callee.property;
886
+
887
+ // String methods
888
+ if (prop === 'split') { this.includes.add('<string.h>'); return `strtok(${obj}, ${args})`; }
889
+ if (prop === 'indexOf') { this.includes.add('<string.h>'); return `strstr(${obj}, ${args})`; }
890
+ if (prop === 'includes') { this.includes.add('<string.h>'); return `(strstr(${obj}, ${args}) != NULL)`; }
891
+ if (prop === 'toUpperCase') { return `/* toUpperCase: iterate and toupper */ ${obj}`; }
892
+ if (prop === 'toLowerCase') { return `/* toLowerCase: iterate and tolower */ ${obj}`; }
893
+ if (prop === 'trim') { return `/* trim: custom implementation */ ${obj}`; }
894
+ if (prop === 'replace') { return `/* replace: custom implementation */ ${obj}`; }
895
+ if (prop === 'substring') { return `/* substring: pointer arithmetic */ ${obj}`; }
896
+
897
+ // Console methods
898
+ if (obj === 'console' && prop === 'log') {
899
+ this.includes.add('<stdio.h>');
900
+ return `printf("%s\\n", ${args})`;
901
+ }
902
+ if (obj === 'console' && prop === 'error') {
903
+ this.includes.add('<stdio.h>');
904
+ return `fprintf(stderr, "%s\\n", ${args})`;
905
+ }
906
+
907
+ // Math methods
908
+ if (obj === 'Math' && prop === 'floor') { this.includes.add('<math.h>'); return `floor(${args})`; }
909
+ if (obj === 'Math' && prop === 'ceil') { this.includes.add('<math.h>'); return `ceil(${args})`; }
910
+ if (obj === 'Math' && prop === 'round') { this.includes.add('<math.h>'); return `round(${args})`; }
911
+ if (obj === 'Math' && prop === 'abs') { this.includes.add('<stdlib.h>'); return `abs(${args})`; }
912
+ if (obj === 'Math' && prop === 'sqrt') { this.includes.add('<math.h>'); return `sqrt(${args})`; }
913
+ if (obj === 'Math' && prop === 'pow') { this.includes.add('<math.h>'); return `pow(${args})`; }
914
+ if (obj === 'Math' && prop === 'random') { this.includes.add('<stdlib.h>'); return `((double)rand() / RAND_MAX)`; }
915
+ }
916
+
917
+ const callee = this.expr(node.callee);
918
+ return `${callee}(${args})`;
919
+ }
920
+
921
+ generateString(strData) {
922
+ if (!strData || !strData.parts) return '""';
923
+
924
+ const hasInterpolation = strData.parts.some(p => p.type === 'expr');
925
+
926
+ if (!hasInterpolation) {
927
+ const raw = strData.parts.map(p => p.value).join('');
928
+ return JSON.stringify(raw);
929
+ }
930
+
931
+ // C has no string interpolation; emit printf-style format
932
+ // Return the format string part only; caller must handle arguments
933
+ let fmt = '"';
934
+ const fmtArgs = [];
935
+ for (const part of strData.parts) {
936
+ if (part.type === 'text') {
937
+ fmt += part.value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
938
+ } else {
939
+ fmt += '%s';
940
+ fmtArgs.push(part.value);
941
+ }
942
+ }
943
+ fmt += '"';
944
+
945
+ if (fmtArgs.length > 0) {
946
+ // Return as a comment-annotated format; for printf usage
947
+ return `${fmt} /* args: ${fmtArgs.join(', ')} */`;
948
+ }
949
+ return fmt;
950
+ }
951
+
952
+ generatePipe(node) {
953
+ const steps = [];
954
+ let current = node;
955
+ while (current.type === 'Pipe') {
956
+ steps.unshift(current.right);
957
+ current = current.left;
958
+ }
959
+ steps.unshift(current);
960
+
961
+ let result = this.expr(steps[0]);
962
+ for (let i = 1; i < steps.length; i++) {
963
+ const step = steps[i];
964
+ if (step.type === 'Call') {
965
+ const callee = this.expr(step.callee);
966
+ const args = step.args.map(a => this.expr(a)).join(', ');
967
+ result = `${callee}(${result}${args ? ', ' + args : ''})`;
968
+ } else if (step.type === 'Identifier') {
969
+ result = `${step.name}(${result})`;
970
+ } else {
971
+ result = `/* pipe */ ${this.expr(step)}`;
972
+ }
973
+ }
974
+ return result;
975
+ }
976
+
977
+ rawString(strData) {
978
+ if (!strData) return '';
979
+ if (strData.raw !== null && strData.raw !== undefined) return strData.raw;
980
+ if (strData.parts) return strData.parts.map(p => p.value).join('');
981
+ return '';
982
+ }
983
+
984
+ bodyUsesAwait(body) {
985
+ for (const stmt of body) {
986
+ if (this.stmtUsesAwait(stmt)) return true;
987
+ }
988
+ return false;
989
+ }
990
+
991
+ stmtUsesAwait(node) {
992
+ if (!node) return false;
993
+ const json = JSON.stringify(node);
994
+ return json.includes('"Await"') || json.includes('"AwaitAll"');
995
+ }
996
+
997
+ statementToString(stmt) {
998
+ const saved = this.inFunction;
999
+ const savedFunctions = this.functions;
1000
+ const savedMain = this.mainBody;
1001
+ const savedIndent = this.indent;
1002
+ this.functions = [];
1003
+ this.mainBody = [];
1004
+ this.indent = 0;
1005
+ this.inFunction = false;
1006
+ this.visitStatement(stmt);
1007
+ const result = this.mainBody.join('\n');
1008
+ this.functions = savedFunctions;
1009
+ this.mainBody = savedMain;
1010
+ this.indent = savedIndent;
1011
+ this.inFunction = saved;
1012
+ return result;
1013
+ }
1014
+ }