@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.
- package/LICENSE +25 -25
- package/README.md +20 -12
- package/dist/cli/args.js +22 -0
- package/dist/cli/compiler.js +53 -0
- package/dist/cli/index.js +43 -107
- 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 +59 -0
- package/dist/cli/wasm.js +70 -0
- package/dist/index.js +17 -6
- package/dist/{analysis → interpreter/analysis}/scope.js +38 -3
- package/dist/{analysis → interpreter/analysis}/typeAnalyzer.js +563 -28
- package/dist/{core → interpreter/core}/codegen/class-handlers.js +1 -1
- package/dist/{core → interpreter/core}/codegen/control-flow-handlers.js +12 -11
- package/dist/{core → interpreter/core}/codegen/declaration-handlers.js +28 -9
- package/dist/{core → interpreter/core}/codegen/destructuring-handlers.js +9 -4
- package/dist/{core → interpreter/core}/codegen/expression-handlers.js +82 -88
- package/dist/{core → interpreter/core}/codegen/function-handlers.js +159 -46
- package/dist/{core → interpreter/core}/codegen/helpers.js +170 -25
- 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 +47 -7
- package/package.json +6 -4
- package/scripts/precompile-headers.ts +293 -50
- package/scripts/setup-compiler.ts +63 -63
- package/scripts/setup-emsdk.ts +114 -0
- package/src/prelude/any_value.cpp +888 -0
- package/src/prelude/any_value.hpp +29 -24
- package/src/prelude/{exception_helpers.hpp → exception.cpp} +53 -53
- package/src/prelude/exception.hpp +27 -27
- package/src/prelude/iterator_instantiations.hpp +10 -0
- package/src/prelude/{index.hpp → jspp.hpp} +13 -17
- package/src/prelude/library/array.cpp +191 -0
- package/src/prelude/library/array.hpp +5 -178
- package/src/prelude/library/boolean.cpp +30 -0
- package/src/prelude/library/boolean.hpp +14 -0
- package/src/prelude/library/console.cpp +125 -0
- package/src/prelude/library/console.hpp +9 -97
- package/src/prelude/library/error.cpp +100 -0
- package/src/prelude/library/error.hpp +8 -108
- package/src/prelude/library/function.cpp +69 -0
- package/src/prelude/library/function.hpp +6 -5
- package/src/prelude/library/global.cpp +98 -0
- package/src/prelude/library/global.hpp +12 -28
- package/src/prelude/library/global_usings.hpp +15 -0
- package/src/prelude/library/math.cpp +261 -0
- package/src/prelude/library/math.hpp +8 -288
- package/src/prelude/library/object.cpp +379 -0
- package/src/prelude/library/object.hpp +5 -267
- package/src/prelude/library/performance.cpp +21 -0
- package/src/prelude/library/performance.hpp +5 -20
- package/src/prelude/library/process.cpp +38 -0
- package/src/prelude/library/process.hpp +3 -31
- package/src/prelude/library/promise.cpp +131 -0
- package/src/prelude/library/promise.hpp +5 -116
- package/src/prelude/library/symbol.cpp +56 -0
- package/src/prelude/library/symbol.hpp +5 -46
- package/src/prelude/library/timer.cpp +88 -0
- package/src/prelude/library/timer.hpp +11 -87
- package/src/prelude/runtime.cpp +19 -0
- package/src/prelude/types.hpp +26 -20
- package/src/prelude/utils/access.hpp +123 -32
- package/src/prelude/utils/assignment_operators.hpp +119 -99
- package/src/prelude/utils/log_any_value/array.hpp +61 -40
- package/src/prelude/utils/log_any_value/function.hpp +39 -39
- package/src/prelude/utils/log_any_value/log_any_value.hpp +1 -1
- package/src/prelude/utils/log_any_value/object.hpp +60 -3
- package/src/prelude/utils/log_any_value/primitives.hpp +1 -1
- package/src/prelude/utils/operators.hpp +109 -94
- package/src/prelude/utils/operators_native.hpp +349 -0
- package/src/prelude/utils/well_known_symbols.hpp +24 -24
- package/src/prelude/values/array.cpp +1399 -0
- package/src/prelude/values/array.hpp +4 -0
- package/src/prelude/values/async_iterator.cpp +251 -0
- package/src/prelude/values/async_iterator.hpp +60 -32
- package/src/prelude/values/boolean.cpp +64 -0
- package/src/prelude/values/function.cpp +262 -0
- package/src/prelude/values/function.hpp +10 -30
- package/src/prelude/values/iterator.cpp +309 -0
- package/src/prelude/values/iterator.hpp +33 -64
- package/src/prelude/values/number.cpp +221 -0
- package/src/prelude/values/object.cpp +200 -0
- package/src/prelude/values/object.hpp +4 -0
- package/src/prelude/values/promise.cpp +479 -0
- package/src/prelude/values/promise.hpp +9 -2
- package/src/prelude/values/prototypes/array.hpp +46 -1348
- package/src/prelude/values/prototypes/async_iterator.hpp +19 -61
- package/src/prelude/values/prototypes/boolean.hpp +24 -0
- package/src/prelude/values/prototypes/function.hpp +7 -46
- package/src/prelude/values/prototypes/iterator.hpp +15 -191
- package/src/prelude/values/prototypes/number.hpp +30 -210
- package/src/prelude/values/prototypes/object.hpp +7 -23
- package/src/prelude/values/prototypes/promise.hpp +8 -186
- package/src/prelude/values/prototypes/string.hpp +28 -553
- package/src/prelude/values/prototypes/symbol.hpp +9 -70
- package/src/prelude/values/shape.hpp +52 -52
- package/src/prelude/values/string.cpp +485 -0
- package/src/prelude/values/symbol.cpp +89 -0
- package/src/prelude/values/symbol.hpp +101 -101
- 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 -86
- package/src/prelude/any_value_access.hpp +0 -170
- package/src/prelude/any_value_defines.hpp +0 -190
- package/src/prelude/any_value_helpers.hpp +0 -374
- package/src/prelude/utils/operators_primitive.hpp +0 -337
- package/src/prelude/values/helpers/array.hpp +0 -199
- package/src/prelude/values/helpers/async_iterator.hpp +0 -275
- package/src/prelude/values/helpers/function.hpp +0 -109
- package/src/prelude/values/helpers/iterator.hpp +0 -145
- package/src/prelude/values/helpers/object.hpp +0 -104
- package/src/prelude/values/helpers/promise.hpp +0 -254
- package/src/prelude/values/helpers/string.hpp +0 -37
- package/src/prelude/values/helpers/symbol.hpp +0 -21
- /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/wasm.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { spawn } from "child_process";
|
|
2
|
+
import fs from "fs/promises";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { Spinner } from "./spinner.js";
|
|
5
|
+
export async function setupEmsdk(pkgDir, spinner) {
|
|
6
|
+
spinner.text = "Checking Emscripten SDK...";
|
|
7
|
+
spinner.start();
|
|
8
|
+
// Ensure emsdk is set up
|
|
9
|
+
const setupEmsdk = spawn("bun", ["run", "scripts/setup-emsdk.ts"], {
|
|
10
|
+
cwd: pkgDir,
|
|
11
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
12
|
+
});
|
|
13
|
+
const setupExitCode = await new Promise((resolve) => {
|
|
14
|
+
setupEmsdk.on("close", (code) => resolve(code ?? 1));
|
|
15
|
+
});
|
|
16
|
+
if (setupExitCode !== 0) {
|
|
17
|
+
spinner.fail("Emscripten SDK setup failed");
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
spinner.stop();
|
|
21
|
+
}
|
|
22
|
+
export async function postProcessWasm(exeFilePath, wasmExports) {
|
|
23
|
+
const outputDir = path.dirname(exeFilePath);
|
|
24
|
+
const outputBaseName = path.basename(exeFilePath, ".js");
|
|
25
|
+
// Generate .d.ts
|
|
26
|
+
let dtsContent = "";
|
|
27
|
+
for (const exp of wasmExports) {
|
|
28
|
+
const params = exp.params.map((p) => `${p.name}: ${p.type}`)
|
|
29
|
+
.join(", ");
|
|
30
|
+
dtsContent +=
|
|
31
|
+
`export declare function wasm_export_${exp.jsName}(${params}): ${exp.returnType};\n`;
|
|
32
|
+
}
|
|
33
|
+
dtsContent += `export declare const Module: Promise<any>;\n`;
|
|
34
|
+
dtsContent += `export declare const load: () => typeof Module;\n`;
|
|
35
|
+
dtsContent +=
|
|
36
|
+
`declare const jsppModule: (options?: any) => Promise<any>;\n`;
|
|
37
|
+
dtsContent += `export default jsppModule;\n`;
|
|
38
|
+
const dtsPath = path.join(outputDir, `${outputBaseName}.d.ts`);
|
|
39
|
+
await fs.writeFile(dtsPath, dtsContent);
|
|
40
|
+
// Append exports to .js glue code
|
|
41
|
+
let jsGlue = await fs.readFile(exeFilePath, "utf-8");
|
|
42
|
+
// Emscripten with -sEXPORT_ES6=1 adds this at the end
|
|
43
|
+
const defaultExportStr = "export default jsppModule;";
|
|
44
|
+
if (jsGlue.trim().endsWith(defaultExportStr)) {
|
|
45
|
+
jsGlue = jsGlue.trim().substring(0, jsGlue.trim().length - defaultExportStr.length);
|
|
46
|
+
}
|
|
47
|
+
jsGlue += `\n\n// JSPP Named Exports\n`;
|
|
48
|
+
jsGlue += `let _notLoaded = true;\n`;
|
|
49
|
+
jsGlue += `let _resolve = () => {};\n`;
|
|
50
|
+
jsGlue += `let _reject = () => {};\n`;
|
|
51
|
+
jsGlue += `let _instance;\n`;
|
|
52
|
+
jsGlue +=
|
|
53
|
+
`const _getinstance=()=>{if(!_instance)throw new Error("Module not loaded");return _instance}\n`;
|
|
54
|
+
jsGlue +=
|
|
55
|
+
`export const Module = new Promise((res,rej)=>{_resolve=res;_reject=rej});\n`;
|
|
56
|
+
jsGlue += `export const load = async () => {\n`;
|
|
57
|
+
jsGlue += ` if (_notLoaded) {\n`;
|
|
58
|
+
jsGlue += ` _notLoaded = false;\n`;
|
|
59
|
+
jsGlue +=
|
|
60
|
+
` jsppModule().then(m=>{_instance=m;_resolve(m)}).catch(e=>{_notLoaded=true;_reject(e)});\n`;
|
|
61
|
+
jsGlue += ` }\n`;
|
|
62
|
+
jsGlue += ` return Module;\n`;
|
|
63
|
+
jsGlue += `};\n`;
|
|
64
|
+
for (const exp of wasmExports) {
|
|
65
|
+
jsGlue +=
|
|
66
|
+
`export const wasm_export_${exp.jsName} = (...args) => _getinstance()._wasm_export_${exp.jsName}(...args);\n`;
|
|
67
|
+
}
|
|
68
|
+
jsGlue += `export default jsppModule;\n`;
|
|
69
|
+
await fs.writeFile(exeFilePath, jsGlue);
|
|
70
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1,19 +1,30 @@
|
|
|
1
1
|
import path from "path";
|
|
2
|
-
import { TypeAnalyzer } from "./analysis/typeAnalyzer.js";
|
|
3
|
-
import { CodeGenerator } from "./core/codegen/index.js";
|
|
4
|
-
import { Parser } from "./core/parser.js";
|
|
2
|
+
import { TypeAnalyzer } from "./interpreter/analysis/typeAnalyzer.js";
|
|
3
|
+
import { CodeGenerator } from "./interpreter/core/codegen/index.js";
|
|
4
|
+
import { Parser } from "./interpreter/core/parser.js";
|
|
5
5
|
export class Interpreter {
|
|
6
6
|
parser = new Parser();
|
|
7
7
|
analyzer = new TypeAnalyzer();
|
|
8
8
|
generator = new CodeGenerator();
|
|
9
|
-
interpret(code, fileName) {
|
|
9
|
+
interpret(code, fileName, target = "native") {
|
|
10
10
|
const ast = this.parser.parse(code, fileName);
|
|
11
11
|
this.analyzer.analyze(ast);
|
|
12
12
|
const isTypescript = fileName
|
|
13
13
|
? path.extname(fileName) === ".ts"
|
|
14
14
|
: false;
|
|
15
|
-
const cppCode = this.generator.generate(ast, this.analyzer, isTypescript);
|
|
15
|
+
const cppCode = this.generator.generate(ast, this.analyzer, isTypescript, target === "wasm");
|
|
16
16
|
const preludePath = path.resolve(import.meta.dirname, "..", "src", "prelude");
|
|
17
|
-
return {
|
|
17
|
+
return {
|
|
18
|
+
cppCode,
|
|
19
|
+
preludePath,
|
|
20
|
+
wasmExports: this.generator.wasmExports.map((e) => ({
|
|
21
|
+
jsName: e.jsName,
|
|
22
|
+
params: e.params.map((p) => ({
|
|
23
|
+
name: p.name.getText(),
|
|
24
|
+
type: this.analyzer.inferNodeReturnType(p),
|
|
25
|
+
})),
|
|
26
|
+
returnType: "number", // Currently always number as wrappers use double
|
|
27
|
+
})),
|
|
28
|
+
};
|
|
18
29
|
}
|
|
19
30
|
}
|
|
@@ -7,6 +7,41 @@ export const RESERVED_KEYWORDS = new Set([
|
|
|
7
7
|
"co_return",
|
|
8
8
|
"co_await",
|
|
9
9
|
]);
|
|
10
|
+
export const RESERVED_VAR_NAMES = new Set([
|
|
11
|
+
"arguments",
|
|
12
|
+
"class",
|
|
13
|
+
"const",
|
|
14
|
+
"let",
|
|
15
|
+
"var",
|
|
16
|
+
"enum",
|
|
17
|
+
"false",
|
|
18
|
+
"true",
|
|
19
|
+
"continue",
|
|
20
|
+
"debugger",
|
|
21
|
+
"default",
|
|
22
|
+
"delete",
|
|
23
|
+
"do",
|
|
24
|
+
"else",
|
|
25
|
+
"export",
|
|
26
|
+
"extends",
|
|
27
|
+
"finally",
|
|
28
|
+
"for",
|
|
29
|
+
"function",
|
|
30
|
+
"if",
|
|
31
|
+
"import",
|
|
32
|
+
"in",
|
|
33
|
+
"instanceof",
|
|
34
|
+
"new",
|
|
35
|
+
"return",
|
|
36
|
+
"super",
|
|
37
|
+
"switch",
|
|
38
|
+
"this",
|
|
39
|
+
"throw",
|
|
40
|
+
"try",
|
|
41
|
+
"catch",
|
|
42
|
+
"typeof",
|
|
43
|
+
"void",
|
|
44
|
+
]);
|
|
10
45
|
export const BUILTIN_OBJECTS = new Set([
|
|
11
46
|
{ name: "undefined", isConst: true },
|
|
12
47
|
{ name: "null", isConst: true },
|
|
@@ -25,6 +60,7 @@ export const BUILTIN_OBJECTS = new Set([
|
|
|
25
60
|
{ name: "clearInterval", isConst: false },
|
|
26
61
|
{ name: "Array", isConst: false },
|
|
27
62
|
{ name: "Object", isConst: false },
|
|
63
|
+
{ name: "Boolean", isConst: false },
|
|
28
64
|
{ name: "Math", isConst: false },
|
|
29
65
|
]);
|
|
30
66
|
// Represents a single scope (e.g., a function body or a block statement)
|
|
@@ -57,7 +93,6 @@ export class Scope {
|
|
|
57
93
|
export class ScopeManager {
|
|
58
94
|
currentScope;
|
|
59
95
|
allScopes = []; // Array to store all created scopes
|
|
60
|
-
reservedKeywords = new Set(RESERVED_KEYWORDS);
|
|
61
96
|
constructor() {
|
|
62
97
|
const rootScope = new Scope(null, null); // The global scope
|
|
63
98
|
this.currentScope = rootScope;
|
|
@@ -86,7 +121,7 @@ export class ScopeManager {
|
|
|
86
121
|
// Defines a variable in the current scope.
|
|
87
122
|
define(name, type) {
|
|
88
123
|
// if (name === "named" || name === "letVal") console.log("Defining", name, "in scope. isBuiltin:", type.isBuiltin, " type:", type.type);
|
|
89
|
-
if (
|
|
124
|
+
if (RESERVED_KEYWORDS.has(name) && !type.isBuiltin) {
|
|
90
125
|
if (type.declaration) {
|
|
91
126
|
throw new CompilerError(`Unexpected reserved word "${name}"`, type.declaration, "SyntaxError");
|
|
92
127
|
}
|
|
@@ -96,7 +131,7 @@ export class ScopeManager {
|
|
|
96
131
|
}
|
|
97
132
|
// Defines a `var` variable (hoisted to function or global scope).
|
|
98
133
|
defineVar(name, type) {
|
|
99
|
-
if (
|
|
134
|
+
if (RESERVED_KEYWORDS.has(name) && !type.isBuiltin) {
|
|
100
135
|
if (type.declaration) {
|
|
101
136
|
throw new CompilerError(`Unexpected reserved word "${name}"`, type.declaration, "SyntaxError");
|
|
102
137
|
}
|