strata-lang 2.7.5

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 (5) hide show
  1. package/LICENSE +339 -0
  2. package/README.md +968 -0
  3. package/bun.lock +283 -0
  4. package/dist/index.js +1866 -0
  5. package/package.json +50 -0
package/dist/index.js ADDED
@@ -0,0 +1,1866 @@
1
+ // ============================================================================
2
+ // STRATA ARCHITECTURE & MODULE SYSTEM SPECIFICATION
3
+ // ============================================================================
4
+ //
5
+ // This file documents the core architecture design for Strata, including:
6
+ // - Module & Import System
7
+ // - Standard Library Boundary
8
+ // - Deterministic Builds
9
+ // - Package Manager Integration
10
+ //
11
+ // ============================================================================
12
+ // 1. MODULE & IMPORT SYSTEM
13
+ // ============================================================================
14
+ //
15
+ // DESIGN PRINCIPLES:
16
+ // - Explicit over implicit: all imports must be explicit, no implicit exports
17
+ // - File-based modules: each .str file is a module with a single public namespace
18
+ // - Deterministic resolution: no magic path resolution or environment variables
19
+ // - Portable: works identically on Windows, macOS, Linux
20
+ // - Compiler-agnostic: same import semantics for interpreter and C/JS generators
21
+ //
22
+ // IMPORT SYNTAX:
23
+ //
24
+ // import <name> from <module_path>
25
+ // import <name> from <"relative_path">
26
+ // import <name> from <"absolute_path">
27
+ //
28
+ // Examples:
29
+ //
30
+ // import io from std::io // Standard library (always available)
31
+ // import math from std::math // Standard library math
32
+ // import util from ./util // Relative path (sibling)
33
+ // import config from ../config // Parent directory
34
+ // import http from myapp::http // Package: myapp/modules/http.str
35
+ //
36
+ // MODULE PATH RESOLUTION:
37
+ //
38
+ // 1. STANDARD LIBRARY (std::*)
39
+ // - Always available, shipped with Strata compiler
40
+ // - Location: <compiler_root>/stdlib/
41
+ // - Files: std::io → stdlib/io.str, std::math → stdlib/math.str
42
+ // - Immutable, pinned to compiler version
43
+ // - Cannot be overridden by user code
44
+ //
45
+ // 2. ABSOLUTE PATHS (<"path">)
46
+ // - Explicit file-system paths relative to project root
47
+ // - Format: <"./file">, <"../parent/file">, <"/absolute/to/root">
48
+ // - Always interpreted relative to strata.toml location
49
+ // - Extension (.str) optional but recommended for clarity
50
+ //
51
+ // 3. RELATIVE PATHS (./path)
52
+ // - Relative to the importing file's directory
53
+ // - Format: ./sibling.str, ../parent.str, ../../ancestor.str
54
+ // - Must start with ./ or ../
55
+ // - No bare imports (no "util" without package context)
56
+ //
57
+ // 4. PACKAGE IMPORTS (package::module)
58
+ // - Format: <package_name>::<module_path>
59
+ // - Maps to: <project_root>/.strata/packages/<package_name>/<module_path>.str
60
+ // - Resolved via strata.lock for exact versions
61
+ // - Cannot shadow stdlib
62
+ //
63
+ // MODULE DEFINITION:
64
+ //
65
+ // A module is a .str file that exports a namespace. All top-level bindings
66
+ // (functions, types, constants) are part of the module's public API.
67
+ //
68
+ // Example module: myapp/util.str
69
+ //
70
+ // func add(a: int, b: int) => int {
71
+ // return a + b
72
+ // }
73
+ //
74
+ // const VERSION: string = "1.0"
75
+ //
76
+ // Usage:
77
+ //
78
+ // import util from myapp::util
79
+ // let x: int = util.add(1, 2) // Access via namespace
80
+ // io.print(util.VERSION)
81
+ //
82
+ // PRIVATE (INTERNAL) MODULES:
83
+ //
84
+ // Module names starting with _ are internal and should not be imported by
85
+ // external packages. Example: myapp::_internal
86
+ // This is a convention, not enforced by the compiler (for simplicity).
87
+ //
88
+ // IMPORT BEHAVIOR:
89
+ //
90
+ // - Imports are evaluated at compile time (static)
91
+ // - Circular imports are errors (detected during compilation)
92
+ // - Each module is evaluated exactly once per compilation
93
+ // - Import creates a namespace binding in the importing module's scope
94
+ // - Imported names do NOT leak to code that imports the importing module
95
+ // (i.e., imports are not transitive)
96
+ //
97
+ // ============================================================================
98
+ // 2. STANDARD LIBRARY BOUNDARY
99
+ // ============================================================================
100
+ //
101
+ // STDLIB MODULES:
102
+ //
103
+ // The standard library is the minimal set of modules shipped with Strata.
104
+ // All stdlib imports use the std:: namespace prefix.
105
+ //
106
+ // Current stdlib (v1.0):
107
+ //
108
+ // std::io → input/output, print, read, file operations
109
+ // std::math → arithmetic functions, sin, cos, sqrt, etc.
110
+ // std::text → string operations, split, join, trim
111
+ // std::util → misc utilities (later expansion point)
112
+ // std::time → time/date operations (future)
113
+ //
114
+ // Each stdlib module is versioned with the compiler.
115
+ // Compiler version 1.5.2 includes stdlib version 1.5.2 (locked together).
116
+ //
117
+ // PREVENTION OF SHADOWING:
118
+ //
119
+ // Strata's import system prevents accidental shadowing:
120
+ //
121
+ // 1. User code cannot create a module named "std" (reserved)
122
+ // 2. Import resolution checks stdlib first
123
+ // 3. If a file is imported via both std:: and package::, compilation error
124
+ // 4. No $ variables or _ prefixes that could collide with stdlib internals
125
+ //
126
+ // EXTERNAL PACKAGES:
127
+ //
128
+ // Packages are modules not in stdlib. They must:
129
+ // - Be declared in strata.toml
130
+ // - Be explicitly versioned in strata.lock
131
+ // - Be imported via package::module syntax
132
+ // - Cannot use std:: namespace
133
+ // - Cannot override stdlib modules
134
+ //
135
+ // ============================================================================
136
+ // 3. DETERMINISTIC BUILDS
137
+ // ============================================================================
138
+ //
139
+ // REPRODUCIBILITY GUARANTEES:
140
+ //
141
+ // The same source code compiled with the same environment produces
142
+ // identical output across machines.
143
+ //
144
+ // Components that affect output:
145
+ // 1. Compiler version (strata 1.5.2)
146
+ // 2. Stdlib version (locked to compiler version)
147
+ // 3. Package versions (locked in strata.lock)
148
+ // 4. Source code (of course)
149
+ // 5. Target platform (x86-64-linux, arm64-macos, x86-64-windows)
150
+ // 6. Optimization flags (specified in strata.toml)
151
+ //
152
+ // Components that do NOT affect determinism:
153
+ // - File system order (all files processed in sorted order)
154
+ // - Build machine (Windows, macOS, Linux produce identical bytecode)
155
+ // - System environment variables
156
+ // - System time
157
+ // - Cache state (rebuild from scratch = same result)
158
+ //
159
+ // STRATA.TOML (Project Configuration):
160
+ //
161
+ // [project]
162
+ // name = "my-app"
163
+ // version = "1.0.0"
164
+ // strata = "1.5.2" # Compiler version (exact)
165
+ //
166
+ // [build]
167
+ // target = "c" # or "js", "bytecode"
168
+ // optimization = "O2" # or "O0", "O1", "O3"
169
+ // output = "./dist/my-app"
170
+ //
171
+ // [dependencies]
172
+ // http = "1.2.0" # Package name = version
173
+ // crypto = ">=2.0.0,<3.0.0" # Version range (resolved at lock-time)
174
+ // utils = { path = "./vendor/utils" } # Local package (development)
175
+ // git-lib = "git+https://github.com/org/lib#v1.2.0" # Git dependency
176
+ //
177
+ // [[warnings]]
178
+ // level = "strict" # or "warn", "allow"
179
+ //
180
+ // STRATA.LOCK (Dependency Lock File):
181
+ //
182
+ // [metadata]
183
+ // strata = "1.5.2" # Compiler version that created lock
184
+ // generated = 2024-01-15T10:30:00Z
185
+ //
186
+ // [[packages]]
187
+ // name = "http"
188
+ // requested = "1.2.0"
189
+ // resolved = "1.2.0"
190
+ // source = "registry" # or "git", "path"
191
+ // hash = "sha256:abc123..." # Content hash for verification
192
+ //
193
+ // [[packages]]
194
+ // name = "crypto"
195
+ // requested = ">=2.0.0,<3.0.0"
196
+ // resolved = "2.5.1"
197
+ // source = "registry"
198
+ // hash = "sha256:def456..."
199
+ //
200
+ // [[packages]]
201
+ // name = "utils"
202
+ // requested = "path:./vendor/utils"
203
+ // resolved = "./vendor/utils"
204
+ // source = "path"
205
+ //
206
+ // COMPILER VERSION PINNING:
207
+ //
208
+ // If strata.toml specifies strata = "1.5.2", only that version may be used.
209
+ // Attempting to compile with 1.5.3 or 1.6.0 fails with clear error:
210
+ //
211
+ // Error: Project requires Strata 1.5.2, but you have 1.6.0
212
+ // Use: strata update-compiler 1.5.2
213
+ //
214
+ // This prevents subtle differences in compiler behavior from silently
215
+ // affecting builds.
216
+ //
217
+ // ============================================================================
218
+ // 4. PACKAGE MANAGER DESIGN
219
+ // ============================================================================
220
+ //
221
+ // PHILOSOPHY:
222
+ // - Explicit over implicit (no magic)
223
+ // - Deterministic (same input → same output)
224
+ // - Offline-first (local cache, no network unless needed)
225
+ // - Simple (avoid npm-style complexity)
226
+ // - Future-proof (allow centralized registry, but don't require it)
227
+ //
228
+ // PACKAGE MANAGER COMMANDS:
229
+ //
230
+ // strata init # Create new project (generates strata.toml)
231
+ // strata build # Compile to target (uses strata.lock)
232
+ // strata run [args...] # Compile and execute
233
+ // strata add <package> [version] # Add dependency (updates strata.toml + lock)
234
+ // strata remove <package> # Remove dependency
235
+ // strata update [package] # Update packages to latest allowed version
236
+ // strata lock # Regenerate strata.lock from strata.toml
237
+ // strata verify # Verify all packages match lock file hashes
238
+ // strata doctor # Diagnose environment and dependencies
239
+ // strata publish # (Future) publish to registry
240
+ //
241
+ // PACKAGE STORAGE:
242
+ //
243
+ // All packages stored in:
244
+ // <project_root>/.strata/packages/<package_name>/
245
+ //
246
+ // Lock file location:
247
+ // <project_root>/strata.lock
248
+ //
249
+ // Cache location:
250
+ // <home>/.strata/cache/
251
+ // registry/ # Downloaded from registry
252
+ // git/ # Cloned from git
253
+ //
254
+ // PROJECT LAYOUT EXAMPLE:
255
+ //
256
+ // my-app/
257
+ // ├── strata.toml # Project manifest
258
+ // ├── strata.lock # Locked dependencies
259
+ // ├── .gitignore # Excludes .strata/ and dist/
260
+ // ├── src/
261
+ // │ ├── main.str
262
+ // │ ├── util.str
263
+ // │ └── _internal.str # Private module
264
+ // ├── .strata/ # Generated by package manager (gitignored)
265
+ // │ ├── packages/
266
+ // │ │ ├── http/
267
+ // │ │ │ ├── client.str
268
+ // │ │ │ ├── server.str
269
+ // │ │ │ └── _utils.str
270
+ // │ │ └── crypto/
271
+ // │ │ └── aes.str
272
+ // │ └── metadata/ # Package metadata, not needed at runtime
273
+ // └── dist/
274
+ // └── my-app.c # Generated C code
275
+ //
276
+ // DEPENDENCY RESOLUTION:
277
+ //
278
+ // 1. User runs: strata add http 1.2.0
279
+ // 2. strata checks cache, finds http@1.2.0, downloads if needed
280
+ // 3. strata verifies hash matches (if in lock file)
281
+ // 4. strata extracts to .strata/packages/http/
282
+ // 5. strata.toml updated: http = "1.2.0"
283
+ // 6. strata.lock updated with exact version and hash
284
+ // 7. No script execution, no post-install hooks
285
+ //
286
+ // VERSION RESOLUTION:
287
+ //
288
+ // When strata.toml has: http = ">=1.2.0,<2.0.0"
289
+ // strata lock command finds highest version matching range in registry
290
+ // and locks it in strata.lock.
291
+ // Next developer runs strata build → uses exact version from lock.
292
+ //
293
+ // OFFLINE MODE:
294
+ //
295
+ // If a package is in cache and hash matches lock file, use it.
296
+ // If not in cache or hash mismatch:
297
+ // - If offline flag set: error (fail fast)
298
+ // - If online: fetch and verify
299
+ //
300
+ // strata build --offline # Only use cached packages
301
+ // strata build # Fetch if needed
302
+ //
303
+ // GIT DEPENDENCIES:
304
+ //
305
+ // strata.toml:
306
+ // git-lib = "git+https://github.com/org/lib#v1.2.0"
307
+ //
308
+ // strata.lock resolves to:
309
+ // resolved = "git+https://github.com/org/lib@abc123def456..."
310
+ // source = "git"
311
+ // ref = "v1.2.0" # Original tag/branch
312
+ // commit = "abc123def456" # Resolved commit hash
313
+ //
314
+ // Path dependencies (for development):
315
+ //
316
+ // strata.toml:
317
+ // my-utils = { path = "./vendor/my-utils" }
318
+ //
319
+ // strata.lock:
320
+ // source = "path"
321
+ // resolved = "./vendor/my-utils"
322
+ //
323
+ // Path deps are NOT versioned but DO include hash for change detection.
324
+ //
325
+ // REGISTRY INTERFACE (Future):
326
+ //
327
+ // When a centralized registry exists, it must support:
328
+ //
329
+ // GET /api/v1/package/<name>/<version>
330
+ // Returns: { name, version, hash, size, dependencies, ... }
331
+ //
332
+ // GET /api/v1/package/<name>/latest
333
+ // Returns: latest version metadata
334
+ //
335
+ // GET /api/v1/search?q=<term>
336
+ // Returns: matching packages
337
+ //
338
+ // Authentication: API keys in ~/.strata/credentials (not in repo)
339
+ //
340
+ // SECURITY CONSIDERATIONS:
341
+ //
342
+ // 1. Hash verification: All packages verified against strata.lock hash
343
+ // 2. No code execution: Package manager never runs user code
344
+ // 3. Lockfile in git: strata.lock MUST be committed to version control
345
+ // 4. Isolation: Each package in isolated directory, cannot modify others
346
+ // 5. No transitive trust: Package B cannot modify what Package A sees
347
+ //
348
+ // EDGE CASES:
349
+ //
350
+ // Q: What if two packages export conflicting names?
351
+ // A: Each is namespaced: import http from pkg1::http, import text from pkg2::text
352
+ //
353
+ // Q: What if a package depends on another package?
354
+ // A: Not allowed in v1.0 (flat dependency model). Packages are self-contained.
355
+ // Future: transitive dependencies with flattening algorithm.
356
+ //
357
+ // Q: What if strata.lock gets corrupted?
358
+ // A: strata verify reports issues. strata lock --force regenerates.
359
+ //
360
+ // Q: Offline development without registry?
361
+ // A: Use path dependencies (point to local directories). Works without registry.
362
+ //
363
+ // ============================================================================
364
+ // 5. IMPORT EXAMPLES IN PRACTICE
365
+ // ============================================================================
366
+ //
367
+ // Project: web-server
368
+ // strata.toml:
369
+ // [project]
370
+ // name = "web-server"
371
+ // version = "2.1.0"
372
+ // strata = "1.5.2"
373
+ //
374
+ // [dependencies]
375
+ // http = "1.2.0"
376
+ // crypto = ">=2.0.0,<3.0.0"
377
+ //
378
+ // Directory structure:
379
+ // web-server/
380
+ // ├── strata.toml
381
+ // ├── strata.lock
382
+ // ├── src/
383
+ // │ ├── main.str
384
+ // │ ├── handlers.str
385
+ // │ └── _crypto_utils.str
386
+ // └── .strata/packages/
387
+ // ├── http/
388
+ // │ ├── client.str
389
+ // │ ├── server.str
390
+ // │ └── _utils.str
391
+ // └── crypto/
392
+ // └── aes.str
393
+ //
394
+ // main.str:
395
+ //
396
+ // import io from std::io
397
+ // import math from std::math
398
+ // import server from http::server # From http package
399
+ // import aes from crypto::aes # From crypto package
400
+ // import handlers from ./handlers # Relative import
401
+ //
402
+ // func main() => int {
403
+ // let port: int = 8080
404
+ // server.listen(port)
405
+ // return 0
406
+ // }
407
+ //
408
+ // handlers.str:
409
+ //
410
+ // import io from std::io
411
+ // import utils from http::_utils # Can import private modules
412
+ // import crypto from ./_crypto_utils # Local private module
413
+ //
414
+ // func handleRequest(path: string) => string {
415
+ // io.print(path)
416
+ // return "OK"
417
+ // }
418
+ //
419
+ // ============================================================================
420
+ // 6. COMPILER INTEGRATION
421
+ // ============================================================================
422
+ //
423
+ // INTERPRETER (strata run main.str):
424
+ // 1. Read strata.toml and strata.lock
425
+ // 2. Load stdlib modules (std::*)
426
+ // 3. Load package modules from .strata/packages/
427
+ // 4. Parse and type-check main.str (resolves imports)
428
+ // 5. Execute AST in interpreter
429
+ //
430
+ // COMPILER TO C (strata build --target c):
431
+ // 1. Same as interpreter but generates C code instead of interpreting
432
+ // 2. Include all referenced modules in output
433
+ // 3. Generate C with proper namespacing to avoid symbol collisions
434
+ // 4. Output: dist/my-app.c
435
+ //
436
+ // COMPILER TO JS (strata build --target js):
437
+ // 1. Generate JavaScript modules
438
+ // 2. Output: dist/my-app.js
439
+ // 3. Each Strata module → JavaScript module with namespace
440
+ //
441
+ // ============================================================================
442
+ // 7. DESIGN RATIONALE
443
+ // ============================================================================
444
+ //
445
+ // WHY explicit imports over implicit?
446
+ // → Avoids magic, makes dependencies visible, easier to understand code
447
+ // → Enables dead code elimination and dependency tracking
448
+ //
449
+ // WHY file-based modules?
450
+ // → Simple, no complex registry or export syntax
451
+ // → 1 file = 1 module = 1 namespace = easy mental model
452
+ // → Matches most developers' expectations
453
+ //
454
+ // WHY no bare imports?
455
+ // → "import util" is ambiguous (local? stdlib? package?)
456
+ // → Force explicit: ./util (relative) or pkg::util (package)
457
+ // → Prevents mistakes, makes refactoring safe
458
+ //
459
+ // WHY strata.toml + strata.lock?
460
+ // → Similar to Cargo.toml + Cargo.lock, proven model
461
+ // → Separates intent (toml) from reality (lock)
462
+ // → Lock file enables reproducible builds
463
+ // → Both committed to git for team consistency
464
+ //
465
+ // WHY no transitive dependencies in v1.0?
466
+ // → Eliminates dependency hell and version conflicts
467
+ // → Simpler resolver, easier to understand
468
+ // → Can upgrade to transitive later with flattening
469
+ //
470
+ // WHY hash verification?
471
+ // → Detects tampering, corrupted downloads, cache invalidation
472
+ // → Essential for security and reliability
473
+ //
474
+ // WHY no post-install scripts?
475
+ // → Unsafe (arbitrary code execution from untrusted sources)
476
+ // → Slow (requires toolchain to be installed)
477
+ // → Unpredictable (system-dependent)
478
+ // → Instead: packages must be pre-built, fully portable
479
+ //
480
+ // ============================================================================
481
+ import * as fs from "fs";
482
+ import * as process from "process";
483
+ const TYPE_REGISTRY = {
484
+ // Core Primitive Types
485
+ int: { kind: "primitive", primitive: "int" },
486
+ float: { kind: "primitive", primitive: "float" },
487
+ bool: { kind: "primitive", primitive: "bool" },
488
+ char: { kind: "primitive", primitive: "char" },
489
+ string: { kind: "primitive", primitive: "string" },
490
+ any: { kind: "primitive", primitive: "any" },
491
+ // Rust-style Signed Integers
492
+ i8: { kind: "primitive", primitive: "i8" },
493
+ i16: { kind: "primitive", primitive: "i16" },
494
+ i32: { kind: "primitive", primitive: "i32" },
495
+ i64: { kind: "primitive", primitive: "i64" },
496
+ // Rust-style Unsigned Integers
497
+ u8: { kind: "primitive", primitive: "u8" },
498
+ u16: { kind: "primitive", primitive: "u16" },
499
+ u32: { kind: "primitive", primitive: "u32" },
500
+ u64: { kind: "primitive", primitive: "u64" },
501
+ // Floating Point Types
502
+ f32: { kind: "primitive", primitive: "f32" },
503
+ f64: { kind: "primitive", primitive: "f64" },
504
+ // Collection Types (Python, Go, Ruby, JavaScript)
505
+ array: { kind: "primitive", primitive: "array" },
506
+ list: { kind: "primitive", primitive: "list" },
507
+ map: { kind: "primitive", primitive: "map" },
508
+ dict: { kind: "primitive", primitive: "dict" },
509
+ set: { kind: "primitive", primitive: "set" },
510
+ tuple: { kind: "primitive", primitive: "tuple" },
511
+ // Advanced Types (TypeScript, Rust, Go)
512
+ option: { kind: "primitive", primitive: "option" },
513
+ result: { kind: "primitive", primitive: "result" },
514
+ promise: { kind: "primitive", primitive: "promise" },
515
+ void: { kind: "primitive", primitive: "void" },
516
+ null: { kind: "primitive", primitive: "null" },
517
+ undefined: { kind: "primitive", primitive: "undefined" },
518
+ // Regular Expression Support (Python, Ruby, JavaScript, Go)
519
+ regex: { kind: "primitive", primitive: "regex" },
520
+ pattern: { kind: "primitive", primitive: "pattern" },
521
+ // R/NumPy Scientific Computing Types
522
+ complex: { kind: "primitive", primitive: "complex" },
523
+ matrix: { kind: "primitive", primitive: "matrix" },
524
+ dataframe: { kind: "primitive", primitive: "dataframe" },
525
+ // Function Types (JavaScript, TypeScript, Python, Ruby, Rust)
526
+ callable: { kind: "primitive", primitive: "callable" },
527
+ lambda: { kind: "primitive", primitive: "lambda" },
528
+ closure: { kind: "primitive", primitive: "closure" },
529
+ };
530
+ // ============================================================================
531
+ // EXTENDED BUILT-IN FUNCTIONS - Multi-Language Features
532
+ // ============================================================================
533
+ // This registry provides language features from: Ruby, Python, JavaScript,
534
+ // TypeScript, Go, Rust, C++, C#, R, and C while maintaining Strata syntax
535
+ const BUILTIN_FUNCTIONS = {
536
+ // STRING OPERATIONS (Python, Ruby, JavaScript)
537
+ strlen: (args) => args[0]?.length ?? 0,
538
+ substr: (args) => args[0]?.substring(args[1], args[2]) ?? "",
539
+ toUpperCase: (args) => args[0]?.toUpperCase?.() ?? "",
540
+ toLowerCase: (args) => args[0]?.toLowerCase?.() ?? "",
541
+ trim: (args) => args[0]?.trim?.() ?? "",
542
+ split: (args) => (args[0]?.split?.(args[1]) ?? []).join(","),
543
+ join: (args) => args[0]?.join?.(args[1]) ?? "",
544
+ startsWith: (args) => args[0]?.startsWith?.(args[1]) ?? false,
545
+ endsWith: (args) => args[0]?.endsWith?.(args[1]) ?? false,
546
+ includes: (args) => args[0]?.includes?.(args[1]) ?? false,
547
+ indexOf: (args) => args[0]?.indexOf?.(args[1]) ?? -1,
548
+ replace: (args) => args[0]?.replace?.(args[1], args[2]) ?? "",
549
+ replaceAll: (args) => args[0]?.replaceAll?.(args[1], args[2]) ?? "",
550
+ repeat: (args) => args[0]?.repeat?.(args[1]) ?? "",
551
+ slice: (args) => args[0]?.slice?.(args[1], args[2]) ?? "",
552
+ // ARRAY/LIST OPERATIONS (Python, JavaScript, Go, Rust)
553
+ push: (args) => { args[0]?.push?.(args[1]); return args[0]; },
554
+ pop: (args) => args[0]?.pop?.(),
555
+ shift: (args) => args[0]?.shift?.(),
556
+ unshift: (args) => { args[0]?.unshift?.(args[1]); return args[0]; },
557
+ splice: (args) => args[0]?.splice?.(args[1], args[2]) ?? [],
558
+ map: (args) => args[0]?.map?.(args[1]) ?? [],
559
+ filter: (args) => args[0]?.filter?.(args[1]) ?? [],
560
+ reduce: (args) => args[0]?.reduce?.(args[1], args[2]),
561
+ forEach: (args) => { args[0]?.forEach?.(args[1]); },
562
+ find: (args) => args[0]?.find?.(args[1]),
563
+ findIndex: (args) => args[0]?.findIndex?.(args[1]) ?? -1,
564
+ some: (args) => args[0]?.some?.(args[1]) ?? false,
565
+ every: (args) => args[0]?.every?.(args[1]) ?? false,
566
+ reverse: (args) => { args[0]?.reverse?.(); return args[0]; },
567
+ sort: (args) => { args[0]?.sort?.(args[1]); return args[0]; },
568
+ concat: (args) => args[0]?.concat?.(args[1]) ?? [],
569
+ flat: (args) => args[0]?.flat?.(args[1] ?? 1) ?? [],
570
+ flatMap: (args) => args[0]?.flatMap?.(args[1]) ?? [],
571
+ includes_arr: (args) => args[0]?.includes?.(args[1]) ?? false,
572
+ lastIndexOf: (args) => args[0]?.lastIndexOf?.(args[1]) ?? -1,
573
+ // DICTIONARY/MAP OPERATIONS (Python, JavaScript, Go, Rust)
574
+ keys: (args) => Object.keys(args[0] ?? {}) ?? [],
575
+ values: (args) => Object.values(args[0] ?? {}) ?? [],
576
+ entries: (args) => Object.entries(args[0] ?? {}) ?? [],
577
+ has: (args) => (args[0] ?? {})?.[args[1]] !== undefined,
578
+ delete: (args) => { delete (args[0] ?? {})[args[1]]; return args[0]; },
579
+ clear: (args) => { for (let k in args[0])
580
+ delete args[0][k]; return args[0]; },
581
+ get: (args) => (args[0] ?? {})[args[1]],
582
+ set: (args) => { (args[0] ?? {})[args[1]] = args[2]; return args[0]; },
583
+ // SET OPERATIONS (Python, Go, Rust)
584
+ add: (args) => { args[0]?.add?.(args[1]); return args[0]; },
585
+ remove: (args) => { args[0]?.delete?.(args[1]); return args[0]; },
586
+ union: (args) => new Set([...(args[0] ?? []), ...(args[1] ?? [])]),
587
+ intersection: (args) => new Set([...(args[0] ?? [])].filter(x => args[1]?.has?.(x))),
588
+ difference: (args) => new Set([...(args[0] ?? [])].filter(x => !args[1]?.has?.(x))),
589
+ // MATH OPERATIONS (R, Python, C, C++)
590
+ abs: (args) => Math.abs(args[0]),
591
+ sqrt: (args) => Math.sqrt(args[0]),
592
+ pow: (args) => Math.pow(args[0], args[1]),
593
+ sin: (args) => Math.sin(args[0]),
594
+ cos: (args) => Math.cos(args[0]),
595
+ tan: (args) => Math.tan(args[0]),
596
+ asin: (args) => Math.asin(args[0]),
597
+ acos: (args) => Math.acos(args[0]),
598
+ atan: (args) => Math.atan(args[0]),
599
+ atan2: (args) => Math.atan2(args[0], args[1]),
600
+ exp: (args) => Math.exp(args[0]),
601
+ log: (args) => Math.log(args[0]),
602
+ log10: (args) => Math.log10(args[0]),
603
+ log2: (args) => Math.log2(args[0]),
604
+ ceil: (args) => Math.ceil(args[0]),
605
+ floor: (args) => Math.floor(args[0]),
606
+ round: (args) => Math.round(args[0]),
607
+ trunc: (args) => Math.trunc(args[0]),
608
+ max: (args) => Math.max(...args),
609
+ min: (args) => Math.min(...args),
610
+ gcd: (args) => {
611
+ let a = Math.abs(args[0]), b = Math.abs(args[1]);
612
+ while (b)
613
+ [a, b] = [b, a % b];
614
+ return a;
615
+ },
616
+ lcm: (args) => Math.abs(args[0] * args[1]) / BUILTIN_FUNCTIONS.gcd([args[0], args[1]]),
617
+ // RANDOM OPERATIONS (Python, Go, JavaScript, Ruby)
618
+ random: (args) => Math.random(),
619
+ randomInt: (args) => Math.floor(Math.random() * (args[1] - args[0] + 1)) + args[0],
620
+ randomFloat: (args) => Math.random() * (args[1] - args[0]) + args[0],
621
+ // TYPE CHECKING/CONVERSION (Python, JavaScript, TypeScript)
622
+ typeof: (args) => typeof args[0],
623
+ parseInt: (args) => parseInt(args[0], args[1] ?? 10),
624
+ parseFloat: (args) => parseFloat(args[0]),
625
+ toString: (args) => String(args[0]),
626
+ toBoolean: (args) => Boolean(args[0]),
627
+ toNumber: (args) => Number(args[0]),
628
+ isNaN: (args) => isNaN(args[0]),
629
+ isFinite: (args) => isFinite(args[0]),
630
+ isInteger: (args) => Number.isInteger(args[0]),
631
+ isArray: (args) => Array.isArray(args[0]),
632
+ isObject: (args) => args[0] !== null && typeof args[0] === "object",
633
+ isNull: (args) => args[0] === null,
634
+ isUndefined: (args) => args[0] === undefined,
635
+ // ERROR HANDLING (Go, Rust, C++)
636
+ try: (args) => { try {
637
+ return args[0]?.();
638
+ }
639
+ catch (e) {
640
+ return e;
641
+ } },
642
+ catch: (args) => args[0] instanceof Error ? args[1]?.(args[0]) : args[0],
643
+ panic: (args) => { throw new Error(args[0]); },
644
+ defer: (args) => { /* deferred execution placeholder */ return args[0]; },
645
+ // FILE OPERATIONS (Python, Go, C, C++)
646
+ readFile: (args) => { try {
647
+ return fs.readFileSync(args[0], "utf-8");
648
+ }
649
+ catch {
650
+ return null;
651
+ } },
652
+ writeFile: (args) => { try {
653
+ fs.writeFileSync(args[0], args[1]);
654
+ return true;
655
+ }
656
+ catch {
657
+ return false;
658
+ } },
659
+ appendFile: (args) => { try {
660
+ fs.appendFileSync(args[0], args[1]);
661
+ return true;
662
+ }
663
+ catch {
664
+ return false;
665
+ } },
666
+ deleteFile: (args) => { try {
667
+ fs.unlinkSync(args[0]);
668
+ return true;
669
+ }
670
+ catch {
671
+ return false;
672
+ } },
673
+ exists: (args) => fs.existsSync(args[0]),
674
+ isFile: (args) => { try {
675
+ return fs.statSync(args[0]).isFile();
676
+ }
677
+ catch {
678
+ return false;
679
+ } },
680
+ isDirectory: (args) => { try {
681
+ return fs.statSync(args[0]).isDirectory();
682
+ }
683
+ catch {
684
+ return false;
685
+ } },
686
+ mkdir: (args) => { try {
687
+ fs.mkdirSync(args[0], { recursive: true });
688
+ return true;
689
+ }
690
+ catch {
691
+ return false;
692
+ } },
693
+ // REGEX OPERATIONS (Python, Ruby, JavaScript, Go)
694
+ match: (args) => {
695
+ try {
696
+ const m = args[0]?.match?.(new RegExp(args[1], args[2] ?? ""));
697
+ return m ?? null;
698
+ }
699
+ catch {
700
+ return null;
701
+ }
702
+ },
703
+ test: (args) => {
704
+ try {
705
+ return new RegExp(args[1], args[2] ?? "").test(args[0]);
706
+ }
707
+ catch {
708
+ return false;
709
+ }
710
+ },
711
+ search: (args) => {
712
+ try {
713
+ return args[0]?.search?.(new RegExp(args[1], args[2] ?? ""));
714
+ }
715
+ catch {
716
+ return -1;
717
+ }
718
+ },
719
+ matchAll: (args) => {
720
+ try {
721
+ return [...args[0]?.matchAll?.(new RegExp(args[1], "g")) ?? []];
722
+ }
723
+ catch {
724
+ return [];
725
+ }
726
+ },
727
+ // DATETIME OPERATIONS (Python, Go, JavaScript, Ruby)
728
+ now: (args) => new Date().getTime(),
729
+ timestamp: (args) => Math.floor(new Date().getTime() / 1000),
730
+ getDate: (args) => new Date(args[0]).getDate(),
731
+ getMonth: (args) => new Date(args[0]).getMonth() + 1,
732
+ getYear: (args) => new Date(args[0]).getFullYear(),
733
+ getHours: (args) => new Date(args[0]).getHours(),
734
+ getMinutes: (args) => new Date(args[0]).getMinutes(),
735
+ getSeconds: (args) => new Date(args[0]).getSeconds(),
736
+ // PROMISE/ASYNC OPERATIONS (JavaScript, TypeScript, Python async)
737
+ Promise: (args) => new Promise(args[0]),
738
+ resolve: (args) => Promise.resolve(args[0]),
739
+ reject: (args) => Promise.reject(args[0]),
740
+ // TUPLES (Python, Go, Rust)
741
+ tuple: (args) => Object.freeze(Array.from(args)),
742
+ untuple: (args) => Array.from(args[0] ?? []),
743
+ // OPTIONAL/NULL HANDLING (Rust, TypeScript, Go)
744
+ Some: (args) => ({ type: "some", value: args[0] }),
745
+ None: (args) => ({ type: "none" }),
746
+ unwrap: (args) => args[0]?.type === "some" ? args[0].value : (() => { throw new Error("unwrap of None"); })(),
747
+ unwrapOr: (args) => args[0]?.type === "some" ? args[0].value : args[1],
748
+ isSome: (args) => args[0]?.type === "some",
749
+ isNone: (args) => args[0]?.type === "none",
750
+ // RESULT OPERATIONS (Rust, Go)
751
+ Ok: (args) => ({ type: "ok", value: args[0] }),
752
+ Err: (args) => ({ type: "err", error: args[0] }),
753
+ isOk: (args) => args[0]?.type === "ok",
754
+ isErr: (args) => args[0]?.type === "err",
755
+ // ITERATOR/GENERATOR OPERATIONS (Python, JavaScript, Go)
756
+ range: (args) => Array.from({ length: args[1] - args[0] }, (_, i) => i + args[0]),
757
+ enumerate: (args) => args[0]?.map?.((v, i) => [i, v]) ?? [],
758
+ zip: (args) => args[0]?.map?.((v, i) => [v, args[1]?.[i]]) ?? [],
759
+ reversed: (args) => [...args[0] ?? []].reverse(),
760
+ sorted: (args) => [...args[0] ?? []].sort(args[1]),
761
+ iter: (args) => (args[0] ?? [])[Symbol.iterator]?.(),
762
+ next: (args) => args[0]?.next?.(),
763
+ // HASH/DIGEST OPERATIONS (Python, Go, C++)
764
+ hash: (args) => {
765
+ let hash = 0;
766
+ const str = String(args[0]);
767
+ for (let i = 0; i < str.length; i++)
768
+ hash = ((hash << 5) - hash) + str.charCodeAt(i), hash |= 0;
769
+ return hash;
770
+ },
771
+ // REFLECTION (Python, JavaScript, TypeScript)
772
+ hasProperty: (args) => args[1] in args[0],
773
+ getProperty: (args) => args[0][args[1]],
774
+ setProperty: (args) => { args[0][args[1]] = args[2]; return args[0]; },
775
+ deleteProperty: (args) => { delete args[0][args[1]]; return args[0]; },
776
+ getPrototype: (args) => Object.getPrototypeOf(args[0]),
777
+ setPrototype: (args) => { Object.setPrototypeOf(args[0], args[1]); return args[0]; },
778
+ // DEEP OPERATIONS
779
+ clone: (args) => JSON.parse(JSON.stringify(args[0])),
780
+ deepEqual: (args) => JSON.stringify(args[0]) === JSON.stringify(args[1]),
781
+ assign: (args) => Object.assign(args[0], ...args.slice(1)),
782
+ // TYPE ALIASES FOR COMPATIBILITY
783
+ uint: (args) => Math.abs(Math.floor(args[0])),
784
+ sint: (args) => Math.floor(args[0]),
785
+ byte: (args) => Math.floor(args[0]) & 0xFF,
786
+ rune: (args) => String.fromCharCode(args[0]),
787
+ // FUNCTIONAL PROGRAMMING (JavaScript, Python, Rust)
788
+ compose: (args) => (x) => args.reduceRight((v, f) => f(v), x),
789
+ pipe: (args) => (x) => args.reduce((v, f) => f(v), x),
790
+ curry: (args) => {
791
+ const fn = args[0];
792
+ const arity = args[1] ?? fn.length;
793
+ return function curried(...args) {
794
+ return args.length >= arity ? fn(...args) : (...more) => curried(...args, ...more);
795
+ };
796
+ },
797
+ partial: (args) => args[0].bind(null, ...args.slice(1)),
798
+ memoize: (args) => {
799
+ const cache = new Map();
800
+ return (...args) => {
801
+ const key = JSON.stringify(args);
802
+ return cache.has(key) ? cache.get(key) : (cache.set(key, args[0](...args)), cache.get(key));
803
+ };
804
+ },
805
+ // SYMBOL/ENUM OPERATIONS
806
+ symbol: (args) => Symbol(args[0]),
807
+ // GENERIC/TEMPLATE OPERATIONS (C++, C#, TypeScript)
808
+ generic: (args) => args[0],
809
+ // BITWISE OPERATIONS (C, C++, Rust, Go)
810
+ bitwiseAnd: (args) => args[0] & args[1],
811
+ bitwiseOr: (args) => args[0] | args[1],
812
+ bitwiseXor: (args) => args[0] ^ args[1],
813
+ bitwiseNot: (args) => ~args[0],
814
+ leftShift: (args) => args[0] << args[1],
815
+ rightShift: (args) => args[0] >> args[1],
816
+ unsignedRightShift: (args) => args[0] >>> args[1],
817
+ };
818
+ function parseTypeAnnotation(token) {
819
+ if (token in TYPE_REGISTRY)
820
+ return TYPE_REGISTRY[token];
821
+ if (token.endsWith("?"))
822
+ return {
823
+ kind: "optional",
824
+ innerType: parseTypeAnnotation(token.slice(0, -1)) ||
825
+ { kind: "primitive", primitive: "any" },
826
+ };
827
+ if (token in TYPE_REGISTRY)
828
+ return TYPE_REGISTRY[token];
829
+ return { kind: "primitive", primitive: "any" };
830
+ }
831
+ function typeCompatible(actual, expected) {
832
+ if (expected.primitive === "any" || actual.primitive === "any")
833
+ return true;
834
+ if (actual.kind === "primitive" && expected.kind === "primitive") {
835
+ if (actual.primitive === expected.primitive)
836
+ return true;
837
+ // Allow numeric conversions: int → float
838
+ if (actual.primitive === "int" &&
839
+ expected.primitive === "float")
840
+ return true;
841
+ // Allow char → string
842
+ if (actual.primitive === "char" &&
843
+ expected.primitive === "string")
844
+ return true;
845
+ return false;
846
+ }
847
+ if (actual.kind === "union" && expected.kind === "union") {
848
+ return ((actual.types
849
+ ?.every((t) => expected.types?.some((e) => typeCompatible(t, e))) ?? false));
850
+ }
851
+ return false;
852
+ }
853
+ class Lexer {
854
+ constructor(input) {
855
+ this.input = input;
856
+ this.pos = 0;
857
+ this.line = 1;
858
+ this.column = 1;
859
+ this.lineStart = 0;
860
+ }
861
+ peek() {
862
+ return this.input[this.pos];
863
+ }
864
+ advance() {
865
+ const ch = this.input[this.pos++];
866
+ if (ch === "\n") {
867
+ this.line++;
868
+ this.column = 1;
869
+ this.lineStart = this.pos;
870
+ }
871
+ else {
872
+ this.column++;
873
+ }
874
+ return ch;
875
+ }
876
+ getLocation() {
877
+ return {
878
+ line: this.line,
879
+ column: this.column,
880
+ source: this.input.substring(this.lineStart, this.pos),
881
+ };
882
+ }
883
+ nextToken() {
884
+ // Skip whitespace
885
+ while (this.peek() === " " ||
886
+ this.peek() === "\n" ||
887
+ this.peek() === "\r" ||
888
+ this.peek() === "\t") {
889
+ this.advance();
890
+ }
891
+ // Skip comments
892
+ if (this.peek() === "/" &&
893
+ this.input[this.pos + 1] === "/") {
894
+ while (this.peek() && this.peek() !== "\n")
895
+ this.advance();
896
+ return this.nextToken();
897
+ }
898
+ if (!this.peek())
899
+ return null;
900
+ const loc = this.getLocation();
901
+ // Multi-character operators
902
+ const twoCharOps = [
903
+ "==",
904
+ "!=",
905
+ "<=",
906
+ ">=",
907
+ "=>",
908
+ "||",
909
+ "&&",
910
+ "++",
911
+ "--",
912
+ ];
913
+ const twoChar = this.input.substring(this.pos, this.pos + 2);
914
+ if (twoCharOps.includes(twoChar)) {
915
+ this.advance();
916
+ this.advance();
917
+ return { token: twoChar, location: loc };
918
+ }
919
+ // Identifiers / keywords
920
+ if (/[a-zA-Z_]/.test(this.peek() || "")) {
921
+ let word = "";
922
+ while (/[a-zA-Z0-9_]/.test(this.peek() || ""))
923
+ word += this.advance();
924
+ return { token: word, location: loc };
925
+ }
926
+ // Strings
927
+ if (this.peek() === '"') {
928
+ this.advance(); // Skip opening quote
929
+ let str = "";
930
+ while (this.peek() && this.peek() !== '"') {
931
+ if (this.peek() === "\\") {
932
+ this.advance();
933
+ const escaped = this.advance();
934
+ str += escaped === "n" ? "\n" : escaped;
935
+ }
936
+ else {
937
+ str += this.advance();
938
+ }
939
+ }
940
+ if (this.peek() === '"')
941
+ this.advance(); // Skip closing quote
942
+ return { token: `"${str}"`, location: loc };
943
+ }
944
+ // Numbers
945
+ if (/[0-9]/.test(this.peek() || "")) {
946
+ let num = "";
947
+ while (/[0-9.]/.test(this.peek() || ""))
948
+ num += this.advance();
949
+ return { token: num, location: loc };
950
+ }
951
+ // Single character tokens
952
+ const ch = this.advance();
953
+ return { token: ch, location: loc };
954
+ }
955
+ }
956
+ // ============================================================================
957
+ // PARSER
958
+ // ============================================================================
959
+ class Parser {
960
+ constructor(input) {
961
+ this.tokens = [];
962
+ this.pos = 0;
963
+ const lexer = new Lexer(input);
964
+ let token;
965
+ while ((token = lexer.nextToken())) {
966
+ this.tokens.push(token);
967
+ }
968
+ }
969
+ current() {
970
+ return this.tokens[this.pos];
971
+ }
972
+ advance() {
973
+ this.pos++;
974
+ }
975
+ expect(token) {
976
+ if (!this.current() || this.current().token !== token) {
977
+ throw new Error(`Expected ${token} at line ${this.current()?.location.line}`);
978
+ }
979
+ this.advance();
980
+ }
981
+ precedence(op) {
982
+ const precs = {
983
+ "||": 1,
984
+ "&&": 2,
985
+ "==": 3,
986
+ "!=": 3,
987
+ "<": 4,
988
+ ">": 4,
989
+ "<=": 4,
990
+ ">=": 4,
991
+ "+": 5,
992
+ "-": 5,
993
+ "*": 6,
994
+ "/": 6,
995
+ "%": 6,
996
+ };
997
+ return precs[op] ?? 0;
998
+ }
999
+ parseUnary() {
1000
+ if (this.current() &&
1001
+ ["!", "-", "+", "~"].includes(this.current().token)) {
1002
+ const op = this.current().token;
1003
+ this.advance();
1004
+ return { kind: "unary", op, operand: this.parseUnary() };
1005
+ }
1006
+ return this.parsePrimary();
1007
+ }
1008
+ parsePrimary() {
1009
+ if (!this.current())
1010
+ throw new Error("Unexpected end of input");
1011
+ const token = this.current().token;
1012
+ if (/^[0-9]/.test(token)) {
1013
+ this.advance();
1014
+ return {
1015
+ kind: "literal",
1016
+ value: token.includes(".") ? parseFloat(token) : parseInt(token),
1017
+ type: token.includes(".") ? { kind: "primitive", primitive: "float" } : { kind: "primitive", primitive: "int" },
1018
+ };
1019
+ }
1020
+ if (token.startsWith('"')) {
1021
+ this.advance();
1022
+ return {
1023
+ kind: "literal",
1024
+ value: token.slice(1, -1),
1025
+ type: { kind: "primitive", primitive: "string" },
1026
+ };
1027
+ }
1028
+ if (token === "true" || token === "false") {
1029
+ this.advance();
1030
+ return {
1031
+ kind: "literal",
1032
+ value: token === "true",
1033
+ type: { kind: "primitive", primitive: "bool" },
1034
+ };
1035
+ }
1036
+ if (/[a-zA-Z_]/.test(token)) {
1037
+ let expr = { kind: "identifier", name: token };
1038
+ this.advance();
1039
+ // Handle member access and calls: io.print(...), obj.method(...), etc.
1040
+ while (this.current()?.token === ".") {
1041
+ this.advance();
1042
+ const property = this.current()?.token;
1043
+ if (!property)
1044
+ throw new Error("Expected property name after .");
1045
+ this.advance();
1046
+ // Check for function call
1047
+ if (this.current()?.token === "(") {
1048
+ this.advance();
1049
+ const args = [];
1050
+ while (this.current()?.token !== ")") {
1051
+ args.push(this.parseUnary());
1052
+ if (this.current()?.token === ",")
1053
+ this.advance();
1054
+ }
1055
+ this.expect(")");
1056
+ expr = {
1057
+ kind: "call",
1058
+ func: { kind: "member", object: expr, property },
1059
+ args,
1060
+ };
1061
+ }
1062
+ else {
1063
+ // Property access without call
1064
+ expr = { kind: "member", object: expr, property };
1065
+ }
1066
+ }
1067
+ return expr;
1068
+ }
1069
+ if (token === "(") {
1070
+ this.advance();
1071
+ const expr = this.parseBinary();
1072
+ this.expect(")");
1073
+ return expr;
1074
+ }
1075
+ throw new Error(`Unexpected token: ${token}`);
1076
+ }
1077
+ parseBinary(minPrec = 0) {
1078
+ let left = this.parseUnary();
1079
+ while (this.current() &&
1080
+ this.precedence(this.current().token) >= minPrec) {
1081
+ const op = this.current().token;
1082
+ const prec = this.precedence(op);
1083
+ this.advance();
1084
+ const right = this.parseBinary(prec + 1);
1085
+ left = { kind: "binary", op, left, right };
1086
+ }
1087
+ return left;
1088
+ }
1089
+ parse() {
1090
+ const statements = [];
1091
+ while (this.current()) {
1092
+ statements.push(this.parseStatement());
1093
+ }
1094
+ return statements;
1095
+ }
1096
+ parseStatement() {
1097
+ const token = this.current()?.token;
1098
+ if (token === "import") {
1099
+ this.advance();
1100
+ const name = this.current().token;
1101
+ this.advance();
1102
+ this.expect("from");
1103
+ const module = this.current().token;
1104
+ this.advance();
1105
+ return { kind: "import", name, module };
1106
+ }
1107
+ if (token === "let" || token === "const" || token === "var") {
1108
+ const mutable = token === "var";
1109
+ this.advance();
1110
+ const name = this.current().token;
1111
+ this.advance();
1112
+ this.expect(":");
1113
+ const typeStr = this.current().token;
1114
+ this.advance();
1115
+ this.expect("=");
1116
+ const value = this.parseBinary();
1117
+ return {
1118
+ kind: "let",
1119
+ name,
1120
+ type: parseTypeAnnotation(typeStr) || { kind: "primitive", primitive: "any" },
1121
+ value,
1122
+ mutable,
1123
+ };
1124
+ }
1125
+ if (token === "func") {
1126
+ this.advance();
1127
+ const name = this.current().token;
1128
+ this.advance();
1129
+ this.expect("(");
1130
+ const params = [];
1131
+ while (this.current()?.token !== ")") {
1132
+ const pname = this.current().token;
1133
+ this.advance();
1134
+ this.expect(":");
1135
+ const ptype = this.current().token;
1136
+ this.advance();
1137
+ params.push({
1138
+ name: pname,
1139
+ type: parseTypeAnnotation(ptype) || { kind: "primitive", primitive: "any" },
1140
+ });
1141
+ if (this.current()?.token === ",")
1142
+ this.advance();
1143
+ }
1144
+ this.expect(")");
1145
+ this.expect("=>");
1146
+ const returnTypeStr = this.current().token;
1147
+ this.advance();
1148
+ this.expect("{");
1149
+ const body = [];
1150
+ while (this.current()?.token !== "}") {
1151
+ body.push(this.parseStatement());
1152
+ }
1153
+ this.expect("}");
1154
+ return {
1155
+ kind: "function",
1156
+ name,
1157
+ params,
1158
+ returnType: parseTypeAnnotation(returnTypeStr) || { kind: "primitive", primitive: "any" },
1159
+ body,
1160
+ };
1161
+ }
1162
+ if (token === "return") {
1163
+ this.advance();
1164
+ const value = this.current() ? this.parseBinary() : undefined;
1165
+ return { kind: "return", value };
1166
+ }
1167
+ if (token === "if") {
1168
+ this.advance();
1169
+ this.expect("(");
1170
+ const condition = this.parseBinary();
1171
+ this.expect(")");
1172
+ this.expect("{");
1173
+ const then = [];
1174
+ while (this.current()?.token !== "}") {
1175
+ then.push(this.parseStatement());
1176
+ }
1177
+ this.expect("}");
1178
+ return { kind: "if", condition, then };
1179
+ }
1180
+ if (token === "while") {
1181
+ this.advance();
1182
+ this.expect("(");
1183
+ const condition = this.parseBinary();
1184
+ this.expect(")");
1185
+ this.expect("{");
1186
+ const body = [];
1187
+ while (this.current()?.token !== "}") {
1188
+ body.push(this.parseStatement());
1189
+ }
1190
+ this.expect("}");
1191
+ return { kind: "while", condition, body };
1192
+ }
1193
+ if (token === "break") {
1194
+ this.advance();
1195
+ return { kind: "break" };
1196
+ }
1197
+ if (token === "continue") {
1198
+ this.advance();
1199
+ return { kind: "continue" };
1200
+ }
1201
+ const expr = this.parseBinary();
1202
+ // Check for assignment: identifier = value
1203
+ if (this.current()?.token === "=" && expr.kind === "identifier") {
1204
+ const target = expr.name;
1205
+ this.advance();
1206
+ const value = this.parseBinary();
1207
+ return { kind: "assignment", target, value };
1208
+ }
1209
+ return { kind: "expression", expr };
1210
+ }
1211
+ }
1212
+ class TypeChecker {
1213
+ constructor() {
1214
+ this.env = {
1215
+ vars: new Map(),
1216
+ functions: new Map(),
1217
+ };
1218
+ this.modules = new Map();
1219
+ }
1220
+ check(statements) {
1221
+ for (const stmt of statements) {
1222
+ this.checkStatement(stmt);
1223
+ }
1224
+ }
1225
+ checkStatement(stmt) {
1226
+ switch (stmt.kind) {
1227
+ case "let":
1228
+ this.env.vars.set(stmt.name, {
1229
+ type: stmt.type,
1230
+ mutable: stmt.mutable,
1231
+ });
1232
+ this.checkExpression(stmt.value, stmt.type);
1233
+ break;
1234
+ case "function":
1235
+ this.env.functions.set(stmt.name, {
1236
+ params: stmt.params.map((p) => p.type),
1237
+ returnType: stmt.returnType,
1238
+ });
1239
+ const oldEnv = this.env;
1240
+ this.env = { vars: new Map(), functions: new Map(), parent: oldEnv };
1241
+ for (const param of stmt.params) {
1242
+ this.env.vars.set(param.name, {
1243
+ type: param.type,
1244
+ mutable: false,
1245
+ });
1246
+ }
1247
+ for (const s of stmt.body) {
1248
+ this.checkStatement(s);
1249
+ }
1250
+ this.env = oldEnv;
1251
+ break;
1252
+ case "if":
1253
+ this.checkExpression(stmt.condition, { kind: "primitive", primitive: "bool" });
1254
+ for (const s of stmt.then) {
1255
+ this.checkStatement(s);
1256
+ }
1257
+ if (stmt.else) {
1258
+ for (const s of stmt.else) {
1259
+ this.checkStatement(s);
1260
+ }
1261
+ }
1262
+ break;
1263
+ case "while":
1264
+ this.checkExpression(stmt.condition, { kind: "primitive", primitive: "bool" });
1265
+ for (const s of stmt.body) {
1266
+ this.checkStatement(s);
1267
+ }
1268
+ break;
1269
+ case "expression":
1270
+ this.checkExpression(stmt.expr, { kind: "primitive", primitive: "any" });
1271
+ break;
1272
+ case "import":
1273
+ break;
1274
+ }
1275
+ }
1276
+ checkExpression(expr, expectedType) {
1277
+ const actualType = this.inferType(expr);
1278
+ if (!typeCompatible(actualType, expectedType)) {
1279
+ throw new Error(`Type mismatch: expected ${JSON.stringify(expectedType)}, got ${JSON.stringify(actualType)}`);
1280
+ }
1281
+ }
1282
+ inferType(expr) {
1283
+ switch (expr.kind) {
1284
+ case "literal":
1285
+ return expr.type;
1286
+ case "identifier":
1287
+ return this.env.vars.get(expr.name)?.type || { kind: "primitive", primitive: "any" };
1288
+ case "binary":
1289
+ if (["==", "!=", "<", ">", "<=", ">=", "&&", "||"].includes(expr.op)) {
1290
+ return { kind: "primitive", primitive: "bool" };
1291
+ }
1292
+ return this.inferType(expr.left);
1293
+ case "unary":
1294
+ if (expr.op === "!")
1295
+ return { kind: "primitive", primitive: "bool" };
1296
+ return this.inferType(expr.operand);
1297
+ default:
1298
+ return { kind: "primitive", primitive: "any" };
1299
+ }
1300
+ }
1301
+ }
1302
+ class Environment {
1303
+ constructor() {
1304
+ this.vars = new Map();
1305
+ this.functions = new Map();
1306
+ this.modules = new Map();
1307
+ this.parent = null;
1308
+ }
1309
+ set(name, value, mutable = false) {
1310
+ this.vars.set(name, { value, mutable });
1311
+ }
1312
+ get(name) {
1313
+ if (this.vars.has(name)) {
1314
+ return this.vars.get(name).value;
1315
+ }
1316
+ if (this.parent)
1317
+ return this.parent.get(name);
1318
+ throw new Error(`Undefined variable: ${name}`);
1319
+ }
1320
+ update(name, value) {
1321
+ if (this.vars.has(name)) {
1322
+ const entry = this.vars.get(name);
1323
+ if (!entry.mutable) {
1324
+ throw new Error(`Cannot reassign immutable variable: ${name}`);
1325
+ }
1326
+ entry.value = value;
1327
+ return;
1328
+ }
1329
+ if (this.parent) {
1330
+ this.parent.update(name, value);
1331
+ return;
1332
+ }
1333
+ throw new Error(`Undefined variable: ${name}`);
1334
+ }
1335
+ setFunction(name, params, body) {
1336
+ this.functions.set(name, { params, body });
1337
+ }
1338
+ getFunction(name) {
1339
+ if (this.functions.has(name)) {
1340
+ return this.functions.get(name);
1341
+ }
1342
+ if (this.parent)
1343
+ return this.parent.getFunction(name);
1344
+ return null;
1345
+ }
1346
+ setModule(name, module) {
1347
+ this.modules.set(name, module);
1348
+ }
1349
+ getModule(name) {
1350
+ if (this.modules.has(name)) {
1351
+ return this.modules.get(name);
1352
+ }
1353
+ if (this.parent)
1354
+ return this.parent.getModule(name);
1355
+ return null;
1356
+ }
1357
+ }
1358
+ class Interpreter {
1359
+ constructor() {
1360
+ this.env = new Environment();
1361
+ this.controlFlow = { type: null };
1362
+ this.setupStdlib();
1363
+ }
1364
+ setupStdlib() {
1365
+ // I/O Module
1366
+ const ioModule = {
1367
+ print: (value) => { console.log(value); return null; },
1368
+ println: (value) => { console.log(value); return null; },
1369
+ };
1370
+ this.env.setModule("std::io", ioModule);
1371
+ this.env.setModule("str", ioModule); // Alias for std::io
1372
+ // Math Module (Python, R, C, C++)
1373
+ this.env.setModule("std::math", {
1374
+ sqrt: (x) => Math.sqrt(x),
1375
+ sin: (x) => Math.sin(x),
1376
+ cos: (x) => Math.cos(x),
1377
+ tan: (x) => Math.tan(x),
1378
+ asin: (x) => Math.asin(x),
1379
+ acos: (x) => Math.acos(x),
1380
+ atan: (x) => Math.atan(x),
1381
+ exp: (x) => Math.exp(x),
1382
+ log: (x) => Math.log(x),
1383
+ log10: (x) => Math.log10(x),
1384
+ log2: (x) => Math.log2(x),
1385
+ floor: (x) => Math.floor(x),
1386
+ ceil: (x) => Math.ceil(x),
1387
+ round: (x) => Math.round(x),
1388
+ abs: (x) => Math.abs(x),
1389
+ pow: (x, y) => Math.pow(x, y),
1390
+ max: (...args) => Math.max(...args),
1391
+ min: (...args) => Math.min(...args),
1392
+ gcd: (a, b) => { let x = Math.abs(a), y = Math.abs(b); while (y)
1393
+ [x, y] = [y, x % y]; return x; },
1394
+ PI: Math.PI,
1395
+ E: Math.E,
1396
+ });
1397
+ // String/Text Module (Python, Ruby, JavaScript)
1398
+ this.env.setModule("std::text", {
1399
+ split: (s, sep) => s.split(sep),
1400
+ join: (arr, sep) => arr.join(sep),
1401
+ trim: (s) => s.trim(),
1402
+ toUpperCase: (s) => s.toUpperCase(),
1403
+ toLowerCase: (s) => s.toLowerCase(),
1404
+ startsWith: (s, prefix) => s.startsWith(prefix),
1405
+ endsWith: (s, suffix) => s.endsWith(suffix),
1406
+ includes: (s, substr) => s.includes(substr),
1407
+ indexOf: (s, substr) => s.indexOf(substr),
1408
+ replace: (s, old, newStr) => s.replace(old, newStr),
1409
+ replaceAll: (s, old, newStr) => s.replaceAll(old, newStr),
1410
+ substring: (s, start, end) => s.substring(start, end),
1411
+ substr: (s, start, length) => s.substr(start, length),
1412
+ slice: (s, start, end) => s.slice(start, end),
1413
+ repeat: (s, count) => s.repeat(count),
1414
+ length: (s) => s.length,
1415
+ charAt: (s, index) => s.charAt(index),
1416
+ charCodeAt: (s, index) => s.charCodeAt(index),
1417
+ });
1418
+ // Array/List Module (Python, JavaScript, Go, Rust)
1419
+ this.env.setModule("std::list", {
1420
+ map: (arr, fn) => arr.map(fn),
1421
+ filter: (arr, fn) => arr.filter(fn),
1422
+ reduce: (arr, fn, init) => arr.reduce(fn, init),
1423
+ forEach: (arr, fn) => { arr.forEach(fn); },
1424
+ find: (arr, fn) => arr.find(fn),
1425
+ findIndex: (arr, fn) => arr.findIndex(fn),
1426
+ some: (arr, fn) => arr.some(fn),
1427
+ every: (arr, fn) => arr.every(fn),
1428
+ includes: (arr, item) => arr.includes(item),
1429
+ indexOf: (arr, item) => arr.indexOf(item),
1430
+ push: (arr, item) => { arr.push(item); return arr; },
1431
+ pop: (arr) => arr.pop(),
1432
+ shift: (arr) => arr.shift(),
1433
+ unshift: (arr, item) => { arr.unshift(item); return arr; },
1434
+ reverse: (arr) => { arr.reverse(); return arr; },
1435
+ sort: (arr, fn) => { arr.sort(fn); return arr; },
1436
+ concat: (arr, ...others) => arr.concat(...others),
1437
+ flat: (arr, depth) => arr.flat(depth),
1438
+ length: (arr) => arr.length,
1439
+ });
1440
+ // Dictionary/Map Module (Python, JavaScript, Go, Rust)
1441
+ this.env.setModule("std::map", {
1442
+ keys: (obj) => Object.keys(obj),
1443
+ values: (obj) => Object.values(obj),
1444
+ entries: (obj) => Object.entries(obj),
1445
+ has: (obj, key) => key in obj,
1446
+ get: (obj, key) => obj[key],
1447
+ set: (obj, key, value) => { obj[key] = value; return obj; },
1448
+ delete: (obj, key) => { delete obj[key]; return obj; },
1449
+ clear: (obj) => { for (let k in obj)
1450
+ delete obj[k]; return obj; },
1451
+ length: (obj) => Object.keys(obj).length,
1452
+ assign: (target, ...sources) => Object.assign(target, ...sources),
1453
+ });
1454
+ // Type Module (Python, JavaScript, TypeScript, Go)
1455
+ this.env.setModule("std::type", {
1456
+ typeof: (x) => typeof x,
1457
+ isArray: (x) => Array.isArray(x),
1458
+ isObject: (x) => x !== null && typeof x === "object",
1459
+ isNull: (x) => x === null,
1460
+ isUndefined: (x) => x === undefined,
1461
+ isNumber: (x) => typeof x === "number",
1462
+ isString: (x) => typeof x === "string",
1463
+ isBoolean: (x) => typeof x === "boolean",
1464
+ isNaN: (x) => isNaN(x),
1465
+ isFinite: (x) => isFinite(x),
1466
+ isInteger: (x) => Number.isInteger(x),
1467
+ toNumber: (x) => Number(x),
1468
+ toString: (x) => String(x),
1469
+ toBoolean: (x) => Boolean(x),
1470
+ toInt: (x) => Math.floor(Number(x)),
1471
+ toFloat: (x) => parseFloat(String(x)),
1472
+ });
1473
+ // File Module (Python, Go, C, C++)
1474
+ this.env.setModule("std::file", {
1475
+ read: (path) => { try {
1476
+ return fs.readFileSync(path, "utf-8");
1477
+ }
1478
+ catch {
1479
+ return null;
1480
+ } },
1481
+ write: (path, content) => { try {
1482
+ fs.writeFileSync(path, content);
1483
+ return true;
1484
+ }
1485
+ catch {
1486
+ return false;
1487
+ } },
1488
+ append: (path, content) => { try {
1489
+ fs.appendFileSync(path, content);
1490
+ return true;
1491
+ }
1492
+ catch {
1493
+ return false;
1494
+ } },
1495
+ exists: (path) => fs.existsSync(path),
1496
+ delete: (path) => { try {
1497
+ fs.unlinkSync(path);
1498
+ return true;
1499
+ }
1500
+ catch {
1501
+ return false;
1502
+ } },
1503
+ isFile: (path) => { try {
1504
+ return fs.statSync(path).isFile();
1505
+ }
1506
+ catch {
1507
+ return false;
1508
+ } },
1509
+ isDirectory: (path) => { try {
1510
+ return fs.statSync(path).isDirectory();
1511
+ }
1512
+ catch {
1513
+ return false;
1514
+ } },
1515
+ mkdir: (path) => { try {
1516
+ fs.mkdirSync(path, { recursive: true });
1517
+ return true;
1518
+ }
1519
+ catch {
1520
+ return false;
1521
+ } },
1522
+ });
1523
+ // Regex Module (Python, Ruby, JavaScript, Go)
1524
+ this.env.setModule("std::regex", {
1525
+ match: (str, pattern, flags) => { try {
1526
+ const m = str.match(new RegExp(pattern, flags ?? ""));
1527
+ return m ?? null;
1528
+ }
1529
+ catch {
1530
+ return null;
1531
+ } },
1532
+ test: (str, pattern, flags) => { try {
1533
+ return new RegExp(pattern, flags ?? "").test(str);
1534
+ }
1535
+ catch {
1536
+ return false;
1537
+ } },
1538
+ search: (str, pattern, flags) => { try {
1539
+ return str.search(new RegExp(pattern, flags ?? ""));
1540
+ }
1541
+ catch {
1542
+ return -1;
1543
+ } },
1544
+ replace: (str, pattern, replacement, flags) => { try {
1545
+ return str.replace(new RegExp(pattern, flags ?? "g"), replacement);
1546
+ }
1547
+ catch {
1548
+ return str;
1549
+ } },
1550
+ });
1551
+ // DateTime Module (Python, Go, JavaScript, Ruby)
1552
+ this.env.setModule("std::time", {
1553
+ now: () => new Date().getTime(),
1554
+ timestamp: () => Math.floor(new Date().getTime() / 1000),
1555
+ getDate: (ms) => new Date(ms).getDate(),
1556
+ getMonth: (ms) => new Date(ms).getMonth() + 1,
1557
+ getYear: (ms) => new Date(ms).getFullYear(),
1558
+ getHours: (ms) => new Date(ms).getHours(),
1559
+ getMinutes: (ms) => new Date(ms).getMinutes(),
1560
+ getSeconds: (ms) => new Date(ms).getSeconds(),
1561
+ });
1562
+ // Set Module (Python, Go, Rust)
1563
+ this.env.setModule("std::set", {
1564
+ create: () => new Set(),
1565
+ add: (set, item) => { set.add(item); return set; },
1566
+ remove: (set, item) => { set.delete(item); return set; },
1567
+ has: (set, item) => set.has(item),
1568
+ size: (set) => set.size,
1569
+ clear: (set) => { set.clear(); return set; },
1570
+ union: (set1, set2) => new Set([...set1, ...set2]),
1571
+ intersection: (set1, set2) => new Set([...set1].filter(x => set2.has(x))),
1572
+ difference: (set1, set2) => new Set([...set1].filter(x => !set2.has(x))),
1573
+ });
1574
+ }
1575
+ interpret(statements) {
1576
+ for (const stmt of statements) {
1577
+ this.interpretStatement(stmt);
1578
+ if (this.controlFlow.type)
1579
+ break;
1580
+ }
1581
+ }
1582
+ interpretStatement(stmt) {
1583
+ switch (stmt.kind) {
1584
+ case "let":
1585
+ const value = this.evaluateExpression(stmt.value);
1586
+ this.env.set(stmt.name, value, stmt.mutable);
1587
+ break;
1588
+ case "assignment":
1589
+ const newValue = this.evaluateExpression(stmt.value);
1590
+ this.env.update(stmt.target, newValue);
1591
+ break;
1592
+ case "expression":
1593
+ this.evaluateExpression(stmt.expr);
1594
+ break;
1595
+ case "if":
1596
+ const condition = this.evaluateExpression(stmt.condition);
1597
+ if (condition) {
1598
+ for (const s of stmt.then) {
1599
+ this.interpretStatement(s);
1600
+ if (this.controlFlow.type)
1601
+ return;
1602
+ }
1603
+ }
1604
+ else if (stmt.else) {
1605
+ for (const s of stmt.else) {
1606
+ this.interpretStatement(s);
1607
+ if (this.controlFlow.type)
1608
+ return;
1609
+ }
1610
+ }
1611
+ break;
1612
+ case "while":
1613
+ while (this.evaluateExpression(stmt.condition)) {
1614
+ for (const s of stmt.body) {
1615
+ this.interpretStatement(s);
1616
+ if (this.controlFlow.type === "break") {
1617
+ this.controlFlow.type = null;
1618
+ return;
1619
+ }
1620
+ if (this.controlFlow.type === "continue") {
1621
+ this.controlFlow.type = null;
1622
+ break;
1623
+ }
1624
+ if (this.controlFlow.type === "return")
1625
+ return;
1626
+ }
1627
+ }
1628
+ break;
1629
+ case "for":
1630
+ this.interpretStatement(stmt.init);
1631
+ while (this.evaluateExpression(stmt.condition)) {
1632
+ for (const s of stmt.body) {
1633
+ this.interpretStatement(s);
1634
+ if (this.controlFlow.type === "break") {
1635
+ this.controlFlow.type = null;
1636
+ return;
1637
+ }
1638
+ if (this.controlFlow.type === "continue") {
1639
+ this.controlFlow.type = null;
1640
+ break;
1641
+ }
1642
+ if (this.controlFlow.type === "return")
1643
+ return;
1644
+ }
1645
+ this.interpretStatement(stmt.update);
1646
+ }
1647
+ break;
1648
+ case "return":
1649
+ this.controlFlow.value = stmt.value
1650
+ ? this.evaluateExpression(stmt.value)
1651
+ : null;
1652
+ this.controlFlow.type = "return";
1653
+ break;
1654
+ case "break":
1655
+ this.controlFlow.type = "break";
1656
+ break;
1657
+ case "continue":
1658
+ this.controlFlow.type = "continue";
1659
+ break;
1660
+ case "function":
1661
+ this.env.setFunction(stmt.name, [
1662
+ ...stmt.params.map((p) => p.name),
1663
+ ], stmt.body);
1664
+ break;
1665
+ case "import":
1666
+ // Bind module to variable name
1667
+ const module = this.env.getModule(stmt.module);
1668
+ if (!module) {
1669
+ throw new Error(`Module not found: ${stmt.module}`);
1670
+ }
1671
+ this.env.set(stmt.name, module, false);
1672
+ break;
1673
+ }
1674
+ }
1675
+ evaluateExpression(expr) {
1676
+ switch (expr.kind) {
1677
+ case "literal":
1678
+ return expr.value;
1679
+ case "identifier":
1680
+ return this.env.get(expr.name);
1681
+ case "binary":
1682
+ const left = this.evaluateExpression(expr.left);
1683
+ const right = this.evaluateExpression(expr.right);
1684
+ switch (expr.op) {
1685
+ case "+":
1686
+ return left + right;
1687
+ case "-":
1688
+ return left - right;
1689
+ case "*":
1690
+ return left * right;
1691
+ case "/":
1692
+ return left / right;
1693
+ case "%":
1694
+ return left % right;
1695
+ case "==":
1696
+ return left === right;
1697
+ case "!=":
1698
+ return left !== right;
1699
+ case "<":
1700
+ return left < right;
1701
+ case ">":
1702
+ return left > right;
1703
+ case "<=":
1704
+ return left <= right;
1705
+ case ">=":
1706
+ return left >= right;
1707
+ case "&&":
1708
+ return left && right;
1709
+ case "||":
1710
+ return left || right;
1711
+ default:
1712
+ return null;
1713
+ }
1714
+ case "unary":
1715
+ const operand = this.evaluateExpression(expr.operand);
1716
+ switch (expr.op) {
1717
+ case "-":
1718
+ return -operand;
1719
+ case "+":
1720
+ return +operand;
1721
+ case "!":
1722
+ return !operand;
1723
+ case "~":
1724
+ return ~operand;
1725
+ default:
1726
+ return null;
1727
+ }
1728
+ case "call":
1729
+ const func = this.evaluateExpression(expr.func);
1730
+ const args = expr.args.map((a) => this.evaluateExpression(a));
1731
+ // Check for built-in functions from extended language features
1732
+ if (expr.func.kind === "identifier" && expr.func.name in BUILTIN_FUNCTIONS) {
1733
+ return BUILTIN_FUNCTIONS[expr.func.name](args);
1734
+ }
1735
+ if (typeof func === "function") {
1736
+ return func(...args);
1737
+ }
1738
+ throw new Error("Not a function");
1739
+ case "member":
1740
+ const obj = this.evaluateExpression(expr.object);
1741
+ return obj?.[expr.property];
1742
+ }
1743
+ }
1744
+ }
1745
+ // ============================================================================
1746
+ // C CODE GENERATOR
1747
+ // ============================================================================
1748
+ class CGenerator {
1749
+ constructor() {
1750
+ this.code = [];
1751
+ }
1752
+ generate(statements) {
1753
+ this.code = [];
1754
+ this.code.push("#include <stdio.h>");
1755
+ this.code.push("#include <math.h>");
1756
+ this.code.push("int main() {");
1757
+ for (const stmt of statements) {
1758
+ this.generateStatement(stmt);
1759
+ }
1760
+ this.code.push("return 0;");
1761
+ this.code.push("}");
1762
+ return this.code.join("\n");
1763
+ }
1764
+ generateStatement(stmt) {
1765
+ switch (stmt.kind) {
1766
+ case "let":
1767
+ const ctype = this.typeToCString(stmt.type);
1768
+ const value = this.generateExpression(stmt.value);
1769
+ this.code.push(`${ctype} ${stmt.name} = ${value};`);
1770
+ break;
1771
+ case "expression":
1772
+ const expr = this.generateExpression(stmt.expr);
1773
+ this.code.push(`${expr};`);
1774
+ break;
1775
+ case "if":
1776
+ const condition = this.generateExpression(stmt.condition);
1777
+ this.code.push(`if (${condition}) {`);
1778
+ for (const s of stmt.then) {
1779
+ this.generateStatement(s);
1780
+ }
1781
+ this.code.push("}");
1782
+ break;
1783
+ case "return":
1784
+ const value2 = stmt.value
1785
+ ? this.generateExpression(stmt.value)
1786
+ : "0";
1787
+ this.code.push(`return ${value2};`);
1788
+ break;
1789
+ }
1790
+ }
1791
+ generateExpression(expr) {
1792
+ switch (expr.kind) {
1793
+ case "literal":
1794
+ if (typeof expr.value === "string") {
1795
+ return `"${expr.value}"`;
1796
+ }
1797
+ return String(expr.value);
1798
+ case "identifier":
1799
+ return expr.name;
1800
+ case "binary":
1801
+ const left = this.generateExpression(expr.left);
1802
+ const right = this.generateExpression(expr.right);
1803
+ return `(${left} ${expr.op} ${right})`;
1804
+ case "unary":
1805
+ const operand = this.generateExpression(expr.operand);
1806
+ return `(${expr.op}${operand})`;
1807
+ case "call":
1808
+ const func = this.generateExpression(expr.func);
1809
+ const args = expr.args.map((a) => this.generateExpression(a));
1810
+ return `${func}(${args.join(", ")})`;
1811
+ case "member":
1812
+ const obj = this.generateExpression(expr.object);
1813
+ return `${obj}.${expr.property}`;
1814
+ default:
1815
+ return "";
1816
+ }
1817
+ }
1818
+ typeToCString(type) {
1819
+ if (type.kind === "primitive") {
1820
+ switch (type.primitive) {
1821
+ case "int":
1822
+ return "int";
1823
+ case "float":
1824
+ return "double";
1825
+ case "bool":
1826
+ return "int";
1827
+ case "char":
1828
+ return "char";
1829
+ case "string":
1830
+ return "char*";
1831
+ default:
1832
+ return "int";
1833
+ }
1834
+ }
1835
+ return "int";
1836
+ }
1837
+ }
1838
+ // ============================================================================
1839
+ // MAIN
1840
+ // ============================================================================
1841
+ const args = process.argv.slice(2);
1842
+ if (args.length === 0) {
1843
+ console.error("Usage: strata <file.str>");
1844
+ process.exit(1);
1845
+ }
1846
+ const startTime = performance.now();
1847
+ const filePath = args[0];
1848
+ const source = fs.readFileSync(filePath, "utf-8");
1849
+ try {
1850
+ const parser = new Parser(source);
1851
+ const statements = parser.parse();
1852
+ const typeChecker = new TypeChecker();
1853
+ typeChecker.check(statements);
1854
+ const interpreter = new Interpreter();
1855
+ interpreter.interpret(statements);
1856
+ const generator = new CGenerator();
1857
+ const cCode = generator.generate(statements);
1858
+ fs.writeFileSync("out.c", cCode);
1859
+ const endTime = performance.now();
1860
+ const elapsed = (endTime - startTime).toFixed(2);
1861
+ console.error(`Executed in ${elapsed}ms`);
1862
+ }
1863
+ catch (error) {
1864
+ console.error("Error:", error instanceof Error ? error.message : String(error));
1865
+ process.exit(1);
1866
+ }