@ugo-studio/jspp 0.3.0 → 0.3.2

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 (127) hide show
  1. package/LICENSE +25 -25
  2. package/README.md +20 -12
  3. package/dist/cli/args.js +22 -0
  4. package/dist/cli/compiler.js +53 -0
  5. package/dist/cli/index.js +43 -107
  6. package/dist/cli/pch.js +71 -0
  7. package/dist/cli/runner.js +23 -0
  8. package/dist/cli/spinner.js +27 -11
  9. package/dist/cli/transpiler.js +20 -0
  10. package/dist/cli/utils.js +59 -0
  11. package/dist/cli/wasm.js +70 -0
  12. package/dist/index.js +17 -6
  13. package/dist/{analysis → interpreter/analysis}/scope.js +38 -3
  14. package/dist/{analysis → interpreter/analysis}/typeAnalyzer.js +563 -28
  15. package/dist/{core → interpreter/core}/codegen/class-handlers.js +1 -1
  16. package/dist/{core → interpreter/core}/codegen/control-flow-handlers.js +12 -11
  17. package/dist/{core → interpreter/core}/codegen/declaration-handlers.js +28 -9
  18. package/dist/{core → interpreter/core}/codegen/destructuring-handlers.js +9 -4
  19. package/dist/{core → interpreter/core}/codegen/expression-handlers.js +82 -88
  20. package/dist/{core → interpreter/core}/codegen/function-handlers.js +159 -46
  21. package/dist/{core → interpreter/core}/codegen/helpers.js +170 -25
  22. package/dist/interpreter/core/codegen/index.js +156 -0
  23. package/dist/{core → interpreter/core}/codegen/literal-handlers.js +9 -0
  24. package/dist/{core → interpreter/core}/codegen/statement-handlers.js +47 -7
  25. package/package.json +6 -4
  26. package/scripts/precompile-headers.ts +293 -50
  27. package/scripts/setup-compiler.ts +63 -63
  28. package/scripts/setup-emsdk.ts +114 -0
  29. package/src/prelude/any_value.cpp +888 -0
  30. package/src/prelude/any_value.hpp +29 -24
  31. package/src/prelude/{exception_helpers.hpp → exception.cpp} +53 -53
  32. package/src/prelude/exception.hpp +27 -27
  33. package/src/prelude/iterator_instantiations.hpp +10 -0
  34. package/src/prelude/{index.hpp → jspp.hpp} +13 -17
  35. package/src/prelude/library/array.cpp +191 -0
  36. package/src/prelude/library/array.hpp +5 -178
  37. package/src/prelude/library/boolean.cpp +30 -0
  38. package/src/prelude/library/boolean.hpp +14 -0
  39. package/src/prelude/library/console.cpp +125 -0
  40. package/src/prelude/library/console.hpp +9 -97
  41. package/src/prelude/library/error.cpp +100 -0
  42. package/src/prelude/library/error.hpp +8 -108
  43. package/src/prelude/library/function.cpp +69 -0
  44. package/src/prelude/library/function.hpp +6 -5
  45. package/src/prelude/library/global.cpp +98 -0
  46. package/src/prelude/library/global.hpp +12 -28
  47. package/src/prelude/library/global_usings.hpp +15 -0
  48. package/src/prelude/library/math.cpp +261 -0
  49. package/src/prelude/library/math.hpp +8 -288
  50. package/src/prelude/library/object.cpp +379 -0
  51. package/src/prelude/library/object.hpp +5 -267
  52. package/src/prelude/library/performance.cpp +21 -0
  53. package/src/prelude/library/performance.hpp +5 -20
  54. package/src/prelude/library/process.cpp +38 -0
  55. package/src/prelude/library/process.hpp +3 -31
  56. package/src/prelude/library/promise.cpp +131 -0
  57. package/src/prelude/library/promise.hpp +5 -116
  58. package/src/prelude/library/symbol.cpp +56 -0
  59. package/src/prelude/library/symbol.hpp +5 -46
  60. package/src/prelude/library/timer.cpp +88 -0
  61. package/src/prelude/library/timer.hpp +11 -87
  62. package/src/prelude/runtime.cpp +19 -0
  63. package/src/prelude/types.hpp +26 -20
  64. package/src/prelude/utils/access.hpp +123 -32
  65. package/src/prelude/utils/assignment_operators.hpp +119 -99
  66. package/src/prelude/utils/log_any_value/array.hpp +61 -40
  67. package/src/prelude/utils/log_any_value/function.hpp +39 -39
  68. package/src/prelude/utils/log_any_value/log_any_value.hpp +1 -1
  69. package/src/prelude/utils/log_any_value/object.hpp +60 -3
  70. package/src/prelude/utils/log_any_value/primitives.hpp +1 -1
  71. package/src/prelude/utils/operators.hpp +109 -94
  72. package/src/prelude/utils/operators_native.hpp +349 -0
  73. package/src/prelude/utils/well_known_symbols.hpp +24 -24
  74. package/src/prelude/values/array.cpp +1399 -0
  75. package/src/prelude/values/array.hpp +4 -0
  76. package/src/prelude/values/async_iterator.cpp +251 -0
  77. package/src/prelude/values/async_iterator.hpp +60 -32
  78. package/src/prelude/values/boolean.cpp +64 -0
  79. package/src/prelude/values/function.cpp +262 -0
  80. package/src/prelude/values/function.hpp +10 -30
  81. package/src/prelude/values/iterator.cpp +309 -0
  82. package/src/prelude/values/iterator.hpp +33 -64
  83. package/src/prelude/values/number.cpp +221 -0
  84. package/src/prelude/values/object.cpp +200 -0
  85. package/src/prelude/values/object.hpp +4 -0
  86. package/src/prelude/values/promise.cpp +479 -0
  87. package/src/prelude/values/promise.hpp +9 -2
  88. package/src/prelude/values/prototypes/array.hpp +46 -1348
  89. package/src/prelude/values/prototypes/async_iterator.hpp +19 -61
  90. package/src/prelude/values/prototypes/boolean.hpp +24 -0
  91. package/src/prelude/values/prototypes/function.hpp +7 -46
  92. package/src/prelude/values/prototypes/iterator.hpp +15 -191
  93. package/src/prelude/values/prototypes/number.hpp +30 -210
  94. package/src/prelude/values/prototypes/object.hpp +7 -23
  95. package/src/prelude/values/prototypes/promise.hpp +8 -186
  96. package/src/prelude/values/prototypes/string.hpp +28 -553
  97. package/src/prelude/values/prototypes/symbol.hpp +9 -70
  98. package/src/prelude/values/shape.hpp +52 -52
  99. package/src/prelude/values/string.cpp +485 -0
  100. package/src/prelude/values/symbol.cpp +89 -0
  101. package/src/prelude/values/symbol.hpp +101 -101
  102. package/dist/cli/file-utils.js +0 -20
  103. package/dist/cli-utils/args.js +0 -59
  104. package/dist/cli-utils/colors.js +0 -9
  105. package/dist/cli-utils/file-utils.js +0 -20
  106. package/dist/cli-utils/spinner.js +0 -55
  107. package/dist/cli.js +0 -153
  108. package/dist/core/codegen/index.js +0 -86
  109. package/src/prelude/any_value_access.hpp +0 -170
  110. package/src/prelude/any_value_defines.hpp +0 -190
  111. package/src/prelude/any_value_helpers.hpp +0 -374
  112. package/src/prelude/utils/operators_primitive.hpp +0 -337
  113. package/src/prelude/values/helpers/array.hpp +0 -199
  114. package/src/prelude/values/helpers/async_iterator.hpp +0 -275
  115. package/src/prelude/values/helpers/function.hpp +0 -109
  116. package/src/prelude/values/helpers/iterator.hpp +0 -145
  117. package/src/prelude/values/helpers/object.hpp +0 -104
  118. package/src/prelude/values/helpers/promise.hpp +0 -254
  119. package/src/prelude/values/helpers/string.hpp +0 -37
  120. package/src/prelude/values/helpers/symbol.hpp +0 -21
  121. /package/dist/{ast → interpreter/ast}/symbols.js +0 -0
  122. /package/dist/{ast → interpreter/ast}/types.js +0 -0
  123. /package/dist/{core → interpreter/core}/codegen/visitor.js +0 -0
  124. /package/dist/{core → interpreter/core}/constants.js +0 -0
  125. /package/dist/{core → interpreter/core}/error.js +0 -0
  126. /package/dist/{core → interpreter/core}/parser.js +0 -0
  127. /package/dist/{core → interpreter/core}/traverser.js +0 -0
@@ -1,101 +1,101 @@
1
- #pragma once
2
-
3
- #include "types.hpp"
4
- #include <atomic>
5
- #include <string>
6
- #include <unordered_map>
7
- #include <unordered_set>
8
- #include <optional>
9
-
10
- namespace jspp
11
- {
12
- // Forward declaration of AnyValue
13
- class AnyValue;
14
-
15
- struct JsSymbol : HeapObject
16
- {
17
- std::string description;
18
- std::string key; // Internal unique key used for AnyValue property maps
19
-
20
- JsType get_heap_type() const override { return JsType::Symbol; }
21
-
22
- // --- Registries ---
23
-
24
- // 1. Global Symbol Registry (for Symbol.for/keyFor)
25
- static std::unordered_map<std::string, JsSymbol*> &registry()
26
- {
27
- static std::unordered_map<std::string, JsSymbol*> reg;
28
- return reg;
29
- }
30
-
31
- // 2. All Internal Keys Registry (for robust Object.keys filtering)
32
- static std::unordered_set<std::string> &internal_keys_registry()
33
- {
34
- static std::unordered_set<std::string> keys;
35
- return keys;
36
- }
37
-
38
- static bool is_internal_key(const std::string &k)
39
- {
40
- return internal_keys_registry().count(k) > 0;
41
- }
42
-
43
- // --- Constructors ---
44
-
45
- // Standard Constructor (creates unique symbol)
46
- JsSymbol(const std::string &desc) : description(desc)
47
- {
48
- static std::atomic<uint64_t> id_counter{0};
49
- // Ensure unique internal key for property storage
50
- key = "__Sym" + std::to_string(id_counter++) + "_" + desc;
51
-
52
- // Register this key as a valid symbol key
53
- internal_keys_registry().insert(key);
54
- }
55
-
56
- // Constructor for Well-Known Symbols (fixed keys)
57
- JsSymbol(const std::string &desc, const std::string &fixed_key)
58
- : description(desc), key(fixed_key)
59
- {
60
- // Register this key as a valid symbol key
61
- internal_keys_registry().insert(key);
62
- }
63
-
64
- // --- Global Registry API ---
65
-
66
- // Implements Symbol.for(key)
67
- static JsSymbol* for_global(const std::string &registryKey)
68
- {
69
- auto &reg = registry();
70
- auto it = reg.find(registryKey);
71
- if (it != reg.end())
72
- {
73
- return it->second;
74
- }
75
-
76
- // Create new symbol with description = registryKey
77
- auto newSym = new JsSymbol(registryKey);
78
- newSym->ref(); // Keep it alive in registry
79
- reg[registryKey] = newSym;
80
- return newSym;
81
- }
82
-
83
- // Implements Symbol.keyFor(sym)
84
- static std::optional<std::string> key_for(const JsSymbol *sym)
85
- {
86
- auto &reg = registry();
87
- for (const auto &pair : reg)
88
- {
89
- if (pair.second == sym)
90
- {
91
- return pair.first;
92
- }
93
- }
94
- return std::nullopt;
95
- }
96
-
97
- // --- Methods ---
98
- std::string to_std_string() const;
99
- AnyValue get_property(const std::string &key, const AnyValue &thisVal);
100
- };
101
- }
1
+ #pragma once
2
+
3
+ #include "types.hpp"
4
+ #include <atomic>
5
+ #include <string>
6
+ #include <unordered_map>
7
+ #include <unordered_set>
8
+ #include <optional>
9
+
10
+ namespace jspp
11
+ {
12
+ // Forward declaration of AnyValue
13
+ class AnyValue;
14
+
15
+ struct JsSymbol : HeapObject
16
+ {
17
+ std::string description;
18
+ std::string key; // Internal unique key used for AnyValue property maps
19
+
20
+ JsType get_heap_type() const override { return JsType::Symbol; }
21
+
22
+ // --- Registries ---
23
+
24
+ // 1. Global Symbol Registry (for Symbol.for/keyFor)
25
+ static std::unordered_map<std::string, JsSymbol*> &registry()
26
+ {
27
+ static std::unordered_map<std::string, JsSymbol*> reg;
28
+ return reg;
29
+ }
30
+
31
+ // 2. All Internal Keys Registry (for robust Object.keys filtering)
32
+ static std::unordered_set<std::string> &internal_keys_registry()
33
+ {
34
+ static std::unordered_set<std::string> keys;
35
+ return keys;
36
+ }
37
+
38
+ static bool is_internal_key(const std::string &k)
39
+ {
40
+ return internal_keys_registry().count(k) > 0;
41
+ }
42
+
43
+ // --- Constructors ---
44
+
45
+ // Standard Constructor (creates unique symbol)
46
+ JsSymbol(const std::string &desc) : description(desc)
47
+ {
48
+ static std::atomic<uint64_t> id_counter{0};
49
+ // Ensure unique internal key for property storage
50
+ key = "__Sym" + std::to_string(id_counter++) + "_" + desc;
51
+
52
+ // Register this key as a valid symbol key
53
+ internal_keys_registry().insert(key);
54
+ }
55
+
56
+ // Constructor for Well-Known Symbols (fixed keys)
57
+ JsSymbol(const std::string &desc, const std::string &fixed_key)
58
+ : description(desc), key(fixed_key)
59
+ {
60
+ // Register this key as a valid symbol key
61
+ internal_keys_registry().insert(key);
62
+ }
63
+
64
+ // --- Global Registry API ---
65
+
66
+ // Implements Symbol.for(key)
67
+ static JsSymbol* for_global(const std::string &registryKey)
68
+ {
69
+ auto &reg = registry();
70
+ auto it = reg.find(registryKey);
71
+ if (it != reg.end())
72
+ {
73
+ return it->second;
74
+ }
75
+
76
+ // Create new symbol with description = registryKey
77
+ auto newSym = new JsSymbol(registryKey);
78
+ newSym->ref(); // Keep it alive in registry
79
+ reg[registryKey] = newSym;
80
+ return newSym;
81
+ }
82
+
83
+ // Implements Symbol.keyFor(sym)
84
+ static std::optional<std::string> key_for(const JsSymbol *sym)
85
+ {
86
+ auto &reg = registry();
87
+ for (const auto &pair : reg)
88
+ {
89
+ if (pair.second == sym)
90
+ {
91
+ return pair.first;
92
+ }
93
+ }
94
+ return std::nullopt;
95
+ }
96
+
97
+ // --- Methods ---
98
+ std::string to_std_string() const;
99
+ AnyValue get_property(const std::string &key, const AnyValue &thisVal);
100
+ };
101
+ }
@@ -1,20 +0,0 @@
1
- import fs from "fs/promises";
2
- import path from "path";
3
- export async function getLatestMtime(dirPath) {
4
- let maxMtime = 0;
5
- const entries = await fs.readdir(dirPath, { withFileTypes: true });
6
- for (const entry of entries) {
7
- const fullPath = path.join(dirPath, entry.name);
8
- if (entry.isDirectory()) {
9
- const nestedMtime = await getLatestMtime(fullPath);
10
- if (nestedMtime > maxMtime)
11
- maxMtime = nestedMtime;
12
- }
13
- else {
14
- const stats = await fs.stat(fullPath);
15
- if (stats.mtimeMs > maxMtime)
16
- maxMtime = stats.mtimeMs;
17
- }
18
- }
19
- return maxMtime;
20
- }
@@ -1,59 +0,0 @@
1
- import path from "path";
2
- import pkg from "../../package.json" with { type: "json" };
3
- import { COLORS } from "./colors.js";
4
- export function parseArgs(rawArgs) {
5
- let jsFilePathArg = null;
6
- let isRelease = false;
7
- let keepCpp = false;
8
- let outputExePath = null;
9
- let scriptArgs = [];
10
- for (let i = 0; i < rawArgs.length; i++) {
11
- const arg = rawArgs[i];
12
- if (!arg)
13
- continue;
14
- if (arg === "--") {
15
- scriptArgs = rawArgs.slice(i + 1);
16
- break;
17
- }
18
- if (arg === "--release") {
19
- isRelease = true;
20
- }
21
- else if (arg === "--keep-cpp") {
22
- keepCpp = true;
23
- }
24
- else if (arg === "-o" || arg === "--output") {
25
- if (i + 1 < rawArgs.length) {
26
- outputExePath = rawArgs[i + 1] ?? null;
27
- i++;
28
- }
29
- else {
30
- console.error(`${COLORS.red}Error: --output requires a file path argument.${COLORS.reset}`);
31
- process.exit(1);
32
- }
33
- }
34
- else if (arg.startsWith("-")) {
35
- console.warn(`${COLORS.yellow}Warning: Unknown argument '${arg}'${COLORS.reset}`);
36
- }
37
- else {
38
- if (jsFilePathArg) {
39
- console.error(`${COLORS.red}Error: Multiple input files specified.${COLORS.reset}`);
40
- process.exit(1);
41
- }
42
- jsFilePathArg = arg;
43
- }
44
- }
45
- if (!jsFilePathArg) {
46
- console.log(`${COLORS.bold}JSPP Compiler${COLORS.reset} ${COLORS.dim}v${pkg.version}${COLORS.reset}`);
47
- console.log(`${COLORS.bold}Usage:${COLORS.reset} jspp <path-to-js-file> [--release] [--keep-cpp] [-o <output-path>] [-- <args...>]`);
48
- process.exit(1);
49
- }
50
- return {
51
- jsFilePath: path.resolve(process.cwd(), jsFilePathArg),
52
- isRelease,
53
- keepCpp,
54
- outputExePath: outputExePath
55
- ? path.resolve(process.cwd(), outputExePath)
56
- : null,
57
- scriptArgs,
58
- };
59
- }
@@ -1,9 +0,0 @@
1
- export const COLORS = {
2
- reset: "\x1b[0m",
3
- cyan: "\x1b[36m",
4
- green: "\x1b[32m",
5
- yellow: "\x1b[33m",
6
- red: "\x1b[31m",
7
- dim: "\x1b[2m",
8
- bold: "\x1b[1m",
9
- };
@@ -1,20 +0,0 @@
1
- import fs from "fs/promises";
2
- import path from "path";
3
- export async function getLatestMtime(dirPath) {
4
- let maxMtime = 0;
5
- const entries = await fs.readdir(dirPath, { withFileTypes: true });
6
- for (const entry of entries) {
7
- const fullPath = path.join(dirPath, entry.name);
8
- if (entry.isDirectory()) {
9
- const nestedMtime = await getLatestMtime(fullPath);
10
- if (nestedMtime > maxMtime)
11
- maxMtime = nestedMtime;
12
- }
13
- else {
14
- const stats = await fs.stat(fullPath);
15
- if (stats.mtimeMs > maxMtime)
16
- maxMtime = stats.mtimeMs;
17
- }
18
- }
19
- return maxMtime;
20
- }
@@ -1,55 +0,0 @@
1
- import { COLORS } from "./colors.js";
2
- export class Spinner {
3
- frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
4
- interval = null;
5
- frameIndex = 0;
6
- text;
7
- constructor(text) {
8
- this.text = text;
9
- }
10
- start() {
11
- process.stdout.write("\x1b[?25l"); // Hide cursor
12
- this.frameIndex = 0;
13
- this.render();
14
- this.interval = setInterval(() => {
15
- this.frameIndex = (this.frameIndex + 1) % this.frames.length;
16
- this.render();
17
- }, 80);
18
- }
19
- update(text) {
20
- this.text = text;
21
- this.render();
22
- }
23
- stop(symbol = "", color = COLORS.reset) {
24
- if (this.interval) {
25
- clearInterval(this.interval);
26
- this.interval = null;
27
- }
28
- this.clearLine();
29
- process.stdout.write(`${color}${symbol} ${COLORS.reset} ${this.text}\n`);
30
- process.stdout.write("\x1b[?25h"); // Show cursor
31
- }
32
- succeed(text) {
33
- if (text)
34
- this.text = text;
35
- this.stop("✔", COLORS.green);
36
- }
37
- fail(text) {
38
- if (text)
39
- this.text = text;
40
- this.stop("✖", COLORS.red);
41
- }
42
- info(text) {
43
- if (text)
44
- this.text = text;
45
- this.stop("ℹ", COLORS.cyan);
46
- }
47
- render() {
48
- this.clearLine();
49
- const frame = this.frames[this.frameIndex];
50
- process.stdout.write(`${COLORS.cyan}${frame} ${COLORS.reset} ${this.text}`);
51
- }
52
- clearLine() {
53
- process.stdout.write("\r\x1b[K");
54
- }
55
- }
package/dist/cli.js DELETED
@@ -1,153 +0,0 @@
1
- #!/usr/bin/env node
2
- import { spawn } from "child_process";
3
- import fs from "fs/promises";
4
- import path from "path";
5
- import pkg from "../package.json" with { type: "json" };
6
- import { parseArgs } from "./cli-utils/args.js";
7
- import { COLORS } from "./cli-utils/colors.js";
8
- import { getLatestMtime } from "./cli-utils/file-utils.js";
9
- import { Spinner } from "./cli-utils/spinner.js";
10
- import { Interpreter } from "./index.js";
11
- const pkgDir = path.dirname(import.meta.dirname);
12
- async function main() {
13
- const { jsFilePath, isRelease, keepCpp, outputExePath, scriptArgs } = parseArgs(process.argv.slice(2));
14
- const jsFileName = path.basename(jsFilePath, ".js");
15
- const sourceDir = path.dirname(jsFilePath);
16
- // Intermediate C++ file goes alongside the source JS file
17
- const cppFilePath = path.join(sourceDir, `${jsFileName}.cpp`);
18
- // Determine output executable path
19
- let exeFilePath;
20
- if (outputExePath) {
21
- exeFilePath = outputExePath;
22
- }
23
- else {
24
- const ext = process.platform === "win32" ? ".exe" : "";
25
- exeFilePath = path.join(sourceDir, `${jsFileName}${ext}`);
26
- }
27
- // Mode Configuration
28
- const mode = isRelease ? "release" : "debug";
29
- console.log(`${COLORS.bold}JSPP Compiler${COLORS.reset} ${COLORS.dim}v${pkg.version}${COLORS.reset}`);
30
- console.log(`Mode: ${isRelease ? COLORS.green : COLORS.yellow}${mode.toUpperCase()}${COLORS.reset}\n`);
31
- const flags = isRelease ? ["-O3", "-DNDEBUG"] : ["-O0"];
32
- if (process.platform === "win32") {
33
- flags.push("-Wa,-mbig-obj");
34
- }
35
- const pchDir = path.resolve(pkgDir, "prelude-build", mode);
36
- const spinner = new Spinner("Initializing...");
37
- try {
38
- spinner.start();
39
- // 1. Interpreter Phase
40
- spinner.update(`Reading ${path.basename(jsFilePath)}...`);
41
- const jsCode = await fs.readFile(jsFilePath, "utf-8");
42
- spinner.update("Transpiling to C++...");
43
- const interpreter = new Interpreter();
44
- const { cppCode, preludePath } = interpreter.interpret(jsCode, jsFilePath);
45
- // Ensure directory for cpp file exists (should exist as it's source dir, but for safety if we change logic)
46
- await fs.mkdir(path.dirname(cppFilePath), { recursive: true });
47
- await fs.writeFile(cppFilePath, cppCode);
48
- spinner.succeed(`Generated cpp`);
49
- // 2. Precompiled Header Check
50
- spinner.text = "Checking precompiled headers...";
51
- spinner.start();
52
- const pchFile = path.join(pchDir, "index.hpp.gch");
53
- let shouldRebuild = false;
54
- try {
55
- const pchStats = await fs.stat(pchFile);
56
- const sourceMtime = await getLatestMtime(preludePath);
57
- if (sourceMtime > pchStats.mtimeMs) {
58
- shouldRebuild = true;
59
- }
60
- }
61
- catch (e) {
62
- shouldRebuild = true;
63
- }
64
- if (shouldRebuild) {
65
- spinner.update("Rebuilding precompiled headers (this may take a while)...");
66
- // Use spawn (async) instead of spawnSync to keep spinner alive
67
- const rebuild = spawn("bun", [
68
- "run",
69
- "scripts/precompile-headers.ts",
70
- ], {
71
- cwd: pkgDir,
72
- stdio: ["ignore", "pipe", "pipe"],
73
- });
74
- const stderrChunks = [];
75
- if (rebuild.stderr) {
76
- rebuild.stderr.on("data", (chunk) => stderrChunks.push(chunk));
77
- }
78
- const exitCode = await new Promise((resolve) => {
79
- rebuild.on("close", (code) => resolve(code ?? 1));
80
- });
81
- if (exitCode !== 0) {
82
- const stderr = Buffer.concat(stderrChunks).toString();
83
- spinner.fail("Failed to rebuild precompiled headers");
84
- console.error(stderr);
85
- process.exit(1);
86
- }
87
- spinner.succeed("Precompiled headers updated");
88
- }
89
- else {
90
- spinner.succeed("Precompiled headers");
91
- }
92
- // 3. Compilation Phase
93
- spinner.text = `Compiling binary...`;
94
- spinner.start();
95
- // Ensure output directory exists
96
- await fs.mkdir(path.dirname(exeFilePath), { recursive: true });
97
- const compile = spawn("g++", [
98
- "-std=c++23",
99
- ...flags,
100
- cppFilePath,
101
- "-o",
102
- exeFilePath,
103
- "-I",
104
- pchDir,
105
- "-I",
106
- preludePath,
107
- ], {
108
- stdio: ["ignore", "pipe", "pipe"],
109
- });
110
- const compileStderrChunks = [];
111
- if (compile.stderr) {
112
- compile.stderr.on("data", (chunk) => compileStderrChunks.push(chunk));
113
- }
114
- const compileExitCode = await new Promise((resolve) => {
115
- compile.on("close", (code) => resolve(code ?? 1));
116
- });
117
- if (compileExitCode !== 0) {
118
- const stderr = Buffer.concat(compileStderrChunks).toString();
119
- spinner.fail(`Compilation failed`);
120
- console.error(stderr);
121
- process.exit(1);
122
- }
123
- spinner.succeed(`Compiled to ${COLORS.green}${COLORS.bold}${path.basename(exeFilePath)}${COLORS.reset}`);
124
- // Clean up C++ file if not requested to keep
125
- if (!keepCpp) {
126
- try {
127
- await fs.unlink(cppFilePath);
128
- }
129
- catch (e) {
130
- // Ignore error if file cannot be deleted
131
- }
132
- }
133
- // 4. Execution Phase
134
- console.log(`\n${COLORS.cyan}--- Running Output ---${COLORS.reset}`);
135
- const run = spawn(exeFilePath, scriptArgs, {
136
- stdio: "inherit",
137
- });
138
- const runExitCode = await new Promise((resolve) => {
139
- run.on("close", (code) => resolve(code ?? 1));
140
- });
141
- console.log(`${COLORS.cyan}----------------------${COLORS.reset}\n`);
142
- if (runExitCode !== 0) {
143
- console.error(`${COLORS.red}Execution failed with exit code ${runExitCode}${COLORS.reset}`);
144
- process.exit(1);
145
- }
146
- }
147
- catch (error) {
148
- spinner.fail("An unexpected error occurred");
149
- console.error(error);
150
- process.exit(1);
151
- }
152
- }
153
- main();
@@ -1,86 +0,0 @@
1
- import { DeclaredSymbols } from "../../ast/symbols.js";
2
- import { generateLambdaComponents, generateNativeLambda, generateWrappedLambda, } from "./function-handlers.js";
3
- import { escapeString, generateUniqueExceptionName, generateUniqueName, getDeclaredSymbols, getDerefCode, getJsVarName, getReturnCommand, getScopeForNode, hoistDeclaration, indent, isAsyncFunction, isBuiltinObject, isDeclarationCalledAsFunction, isDeclarationUsedAsValue, isDeclarationUsedBeforeInitialization, isGeneratorFunction, markSymbolAsInitialized, prepareScopeSymbolsForVisit, validateFunctionParams, } from "./helpers.js";
4
- import { generateDestructuring } from "./destructuring-handlers.js";
5
- import { visit } from "./visitor.js";
6
- const MODULE_NAME = "__entry_point__";
7
- export class CodeGenerator {
8
- indentationLevel = 0;
9
- typeAnalyzer;
10
- isTypescript = false;
11
- globalThisVar;
12
- uniqueNameCounter = 0;
13
- // visitor
14
- visit = visit;
15
- // helpers
16
- getDeclaredSymbols = getDeclaredSymbols;
17
- generateUniqueName = generateUniqueName;
18
- generateUniqueExceptionName = generateUniqueExceptionName;
19
- hoistDeclaration = hoistDeclaration;
20
- getScopeForNode = getScopeForNode;
21
- indent = indent;
22
- escapeString = escapeString;
23
- getJsVarName = getJsVarName;
24
- getDerefCode = getDerefCode;
25
- getReturnCommand = getReturnCommand;
26
- isBuiltinObject = isBuiltinObject;
27
- isGeneratorFunction = isGeneratorFunction;
28
- isAsyncFunction = isAsyncFunction;
29
- prepareScopeSymbolsForVisit = prepareScopeSymbolsForVisit;
30
- markSymbolAsInitialized = markSymbolAsInitialized;
31
- isDeclarationCalledAsFunction = isDeclarationCalledAsFunction;
32
- isDeclarationUsedAsValue = isDeclarationUsedAsValue;
33
- isDeclarationUsedBeforeInitialization = isDeclarationUsedBeforeInitialization;
34
- validateFunctionParams = validateFunctionParams;
35
- generateDestructuring = generateDestructuring;
36
- // function handlers
37
- generateLambdaComponents = generateLambdaComponents;
38
- generateNativeLambda = generateNativeLambda;
39
- generateWrappedLambda = generateWrappedLambda;
40
- /**
41
- * Main entry point for the code generation process.
42
- */
43
- generate(ast, analyzer, isTypescript) {
44
- this.typeAnalyzer = analyzer;
45
- this.isTypescript = isTypescript;
46
- this.globalThisVar = this.generateUniqueName("__this_val__", this.getDeclaredSymbols(ast));
47
- const declarations = `#include "index.hpp"\n\n`;
48
- let containerCode = `jspp::JsPromise ${MODULE_NAME}() {\n`;
49
- this.indentationLevel++;
50
- containerCode +=
51
- `${this.indent()}jspp::AnyValue ${this.globalThisVar} = global;\n`;
52
- containerCode += this.visit(ast, {
53
- currentScopeNode: ast,
54
- isMainContext: true,
55
- isInsideFunction: true,
56
- isFunctionBody: true,
57
- isInsideAsyncFunction: true,
58
- globalScopeSymbols: new DeclaredSymbols(),
59
- localScopeSymbols: new DeclaredSymbols(),
60
- });
61
- this.indentationLevel--;
62
- containerCode += " co_return jspp::Constants::UNDEFINED;\n";
63
- containerCode += "}\n\n";
64
- let mainCode = "int main(int argc, char** argv) {\n";
65
- mainCode += ` try {\n`;
66
- mainCode += ` jspp::setup_process_argv(argc, argv);\n`;
67
- mainCode += ` auto p = ${MODULE_NAME}();\n`;
68
- mainCode += ` p.then(nullptr, [](jspp::AnyValue err) {\n`;
69
- mainCode +=
70
- ` auto error = std::make_shared<jspp::AnyValue>(err);\n`;
71
- mainCode +=
72
- ` console.call_own_property("error", std::span<const jspp::AnyValue>((const jspp::AnyValue[]){*error}, 1));\n`;
73
- mainCode += ` std::exit(1);\n`;
74
- mainCode += ` });\n`;
75
- mainCode += ` jspp::Scheduler::instance().run();\n`;
76
- mainCode += ` } catch (const std::exception& ex) {\n`;
77
- mainCode +=
78
- " auto error = std::make_shared<jspp::AnyValue>(jspp::Exception::exception_to_any_value(ex));\n";
79
- mainCode +=
80
- ` console.call_own_property("error", std::span<const jspp::AnyValue>((const jspp::AnyValue[]){*error}, 1));\n`;
81
- mainCode += ` return 1;\n`;
82
- mainCode += ` }\n`;
83
- mainCode += " return 0;\n}";
84
- return declarations + containerCode + mainCode;
85
- }
86
- }