@ugo-studio/jspp 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/args.js +22 -0
- package/dist/cli/compiler.js +53 -0
- package/dist/cli/index.js +43 -117
- package/dist/cli/pch.js +71 -0
- package/dist/cli/runner.js +23 -0
- package/dist/cli/spinner.js +27 -11
- package/dist/cli/transpiler.js +20 -0
- package/dist/cli/utils.js +25 -27
- package/dist/cli/wasm.js +70 -0
- package/dist/index.js +17 -6
- package/dist/{analysis → interpreter/analysis}/scope.js +34 -1
- package/dist/{analysis → interpreter/analysis}/typeAnalyzer.js +542 -3
- package/dist/{core → interpreter/core}/codegen/class-handlers.js +1 -1
- package/dist/{core → interpreter/core}/codegen/control-flow-handlers.js +2 -2
- package/dist/{core → interpreter/core}/codegen/declaration-handlers.js +21 -9
- package/dist/{core → interpreter/core}/codegen/destructuring-handlers.js +3 -3
- package/dist/{core → interpreter/core}/codegen/expression-handlers.js +136 -82
- package/dist/{core → interpreter/core}/codegen/function-handlers.js +108 -61
- package/dist/{core → interpreter/core}/codegen/helpers.js +79 -11
- package/dist/interpreter/core/codegen/index.js +156 -0
- package/dist/{core → interpreter/core}/codegen/literal-handlers.js +9 -0
- package/dist/{core → interpreter/core}/codegen/statement-handlers.js +39 -1
- package/package.json +6 -4
- package/scripts/precompile-headers.ts +71 -19
- package/scripts/setup-emsdk.ts +114 -0
- package/src/prelude/any_value.cpp +851 -599
- package/src/prelude/any_value.hpp +28 -30
- package/src/prelude/jspp.hpp +3 -1
- package/src/prelude/library/boolean.cpp +30 -0
- package/src/prelude/library/boolean.hpp +14 -0
- package/src/prelude/library/error.cpp +2 -2
- package/src/prelude/library/global.cpp +2 -0
- package/src/prelude/library/math.cpp +46 -43
- package/src/prelude/library/math.hpp +2 -0
- package/src/prelude/library/object.cpp +1 -1
- package/src/prelude/types.hpp +10 -9
- package/src/prelude/utils/access.hpp +2 -36
- package/src/prelude/utils/assignment_operators.hpp +136 -20
- package/src/prelude/utils/log_any_value/log_any_value.hpp +1 -1
- package/src/prelude/utils/log_any_value/primitives.hpp +1 -1
- package/src/prelude/utils/operators.hpp +123 -88
- package/src/prelude/utils/operators_native.hpp +360 -0
- package/src/prelude/utils/well_known_symbols.hpp +13 -13
- package/src/prelude/values/array.cpp +3 -3
- package/src/prelude/values/boolean.cpp +64 -0
- package/src/prelude/values/iterator.cpp +262 -210
- package/src/prelude/values/number.cpp +137 -92
- package/src/prelude/values/object.cpp +163 -122
- package/src/prelude/values/prototypes/boolean.hpp +24 -0
- package/src/prelude/values/prototypes/number.hpp +8 -1
- package/dist/cli/file-utils.js +0 -20
- package/dist/cli-utils/args.js +0 -59
- package/dist/cli-utils/colors.js +0 -9
- package/dist/cli-utils/file-utils.js +0 -20
- package/dist/cli-utils/spinner.js +0 -55
- package/dist/cli.js +0 -153
- package/dist/core/codegen/index.js +0 -88
- package/src/prelude/utils/operators_primitive.hpp +0 -337
- /package/dist/{ast → interpreter/ast}/symbols.js +0 -0
- /package/dist/{ast → interpreter/ast}/types.js +0 -0
- /package/dist/{core → interpreter/core}/codegen/visitor.js +0 -0
- /package/dist/{core → interpreter/core}/constants.js +0 -0
- /package/dist/{core → interpreter/core}/error.js +0 -0
- /package/dist/{core → interpreter/core}/parser.js +0 -0
- /package/dist/{core → interpreter/core}/traverser.js +0 -0
package/dist/cli-utils/args.js
DELETED
|
@@ -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
|
-
}
|
package/dist/cli-utils/colors.js
DELETED
|
@@ -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,88 +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, isVariableUsedWithoutDeclaration, 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
|
-
isVariableUsedWithoutDeclaration = isVariableUsedWithoutDeclaration;
|
|
35
|
-
validateFunctionParams = validateFunctionParams;
|
|
36
|
-
generateDestructuring = generateDestructuring;
|
|
37
|
-
// function handlers
|
|
38
|
-
generateLambdaComponents = generateLambdaComponents;
|
|
39
|
-
generateNativeLambda = generateNativeLambda;
|
|
40
|
-
generateWrappedLambda = generateWrappedLambda;
|
|
41
|
-
/**
|
|
42
|
-
* Main entry point for the code generation process.
|
|
43
|
-
*/
|
|
44
|
-
generate(ast, analyzer, isTypescript) {
|
|
45
|
-
this.typeAnalyzer = analyzer;
|
|
46
|
-
this.isTypescript = isTypescript;
|
|
47
|
-
this.globalThisVar = this.generateUniqueName("__this_val__", this.getDeclaredSymbols(ast));
|
|
48
|
-
const declarations = `#include "jspp.hpp"\n#include "library/global_usings.hpp"\n\n`;
|
|
49
|
-
let containerCode = `jspp::JsPromise ${MODULE_NAME}() {\n`;
|
|
50
|
-
this.indentationLevel++;
|
|
51
|
-
containerCode +=
|
|
52
|
-
`${this.indent()}jspp::AnyValue ${this.globalThisVar} = global;\n`;
|
|
53
|
-
containerCode += this.visit(ast, {
|
|
54
|
-
currentScopeNode: ast,
|
|
55
|
-
isMainContext: true,
|
|
56
|
-
isInsideFunction: true,
|
|
57
|
-
isFunctionBody: true,
|
|
58
|
-
isInsideAsyncFunction: true,
|
|
59
|
-
globalScopeSymbols: new DeclaredSymbols(),
|
|
60
|
-
localScopeSymbols: new DeclaredSymbols(),
|
|
61
|
-
});
|
|
62
|
-
this.indentationLevel--;
|
|
63
|
-
containerCode += " co_return jspp::Constants::UNDEFINED;\n";
|
|
64
|
-
containerCode += "}\n\n";
|
|
65
|
-
let mainCode = "int main(int argc, char** argv) {\n";
|
|
66
|
-
mainCode += ` try {\n`;
|
|
67
|
-
mainCode += ` jspp::initialize_runtime();\n`;
|
|
68
|
-
mainCode += ` jspp::setup_process_argv(argc, argv);\n`;
|
|
69
|
-
mainCode += ` auto p = ${MODULE_NAME}();\n`;
|
|
70
|
-
mainCode += ` p.then(nullptr, [](jspp::AnyValue err) {\n`;
|
|
71
|
-
mainCode +=
|
|
72
|
-
` auto error = std::make_shared<jspp::AnyValue>(err);\n`;
|
|
73
|
-
mainCode +=
|
|
74
|
-
` console.call_own_property("error", std::span<const jspp::AnyValue>((const jspp::AnyValue[]){*error}, 1));\n`;
|
|
75
|
-
mainCode += ` std::exit(1);\n`;
|
|
76
|
-
mainCode += ` });\n`;
|
|
77
|
-
mainCode += ` jspp::Scheduler::instance().run();\n`;
|
|
78
|
-
mainCode += ` } catch (const std::exception& ex) {\n`;
|
|
79
|
-
mainCode +=
|
|
80
|
-
" auto error = std::make_shared<jspp::AnyValue>(jspp::Exception::exception_to_any_value(ex));\n";
|
|
81
|
-
mainCode +=
|
|
82
|
-
` console.call_own_property("error", std::span<const jspp::AnyValue>((const jspp::AnyValue[]){*error}, 1));\n`;
|
|
83
|
-
mainCode += ` return 1;\n`;
|
|
84
|
-
mainCode += ` }\n`;
|
|
85
|
-
mainCode += " return 0;\n}";
|
|
86
|
-
return declarations + containerCode + mainCode;
|
|
87
|
-
}
|
|
88
|
-
}
|