@ugo-studio/jspp 0.3.2 → 0.3.4
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/README.md +2 -6
- package/dist/cli/args.js +5 -0
- package/dist/cli/compiler.js +1 -1
- package/dist/cli/index.js +4 -2
- package/dist/interpreter/analysis/typeAnalyzer.js +62 -25
- package/dist/interpreter/core/codegen/control-flow-handlers.js +34 -10
- package/dist/interpreter/core/codegen/expression-handlers.js +92 -21
- package/dist/interpreter/core/codegen/function-handlers.js +16 -11
- package/dist/interpreter/core/codegen/helpers.js +5 -1
- package/dist/interpreter/core/codegen/index.js +1 -1
- package/dist/interpreter/core/codegen/statement-handlers.js +15 -11
- package/dist/interpreter/core/traverser.js +1 -2
- package/package.json +2 -2
- package/scripts/precompile-headers.ts +9 -1
- package/src/prelude/library/array.cpp +2 -2
- package/src/prelude/library/math.cpp +8 -8
- package/src/prelude/utils/access.hpp +0 -34
- package/src/prelude/utils/assignment_operators.hpp +96 -0
- package/src/prelude/utils/operators.hpp +39 -4
- package/src/prelude/utils/operators_native.hpp +73 -62
- package/src/prelude/values/array.cpp +17 -17
- package/src/prelude/values/iterator.cpp +262 -210
- package/src/prelude/values/number.cpp +4 -4
- package/src/prelude/values/string.cpp +13 -13
|
@@ -106,7 +106,7 @@ export class CodeGenerator {
|
|
|
106
106
|
wasmWrappers +=
|
|
107
107
|
` auto res = ${pointerName}(global${callArgs});\n`;
|
|
108
108
|
wasmWrappers +=
|
|
109
|
-
` return jspp::
|
|
109
|
+
` return jspp::NumberOperators::ToDouble(res);\n`;
|
|
110
110
|
wasmWrappers += `}\n\n`;
|
|
111
111
|
}
|
|
112
112
|
}
|
|
@@ -819,22 +819,26 @@ export function visitReturnStatement(node, context) {
|
|
|
819
819
|
return `${this.indent()}jspp::Exception::throw_unresolved_reference(${this.getJsVarName(expr)});\n`; // THROWS, not returns
|
|
820
820
|
}
|
|
821
821
|
if (typeInfo &&
|
|
822
|
-
!typeInfo.isParameter &&
|
|
823
822
|
!typeInfo.isBuiltin) {
|
|
824
823
|
finalExpr = this.getDerefCode(exprText, this.getJsVarName(expr), context, typeInfo);
|
|
825
824
|
}
|
|
826
|
-
const
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
825
|
+
const funcDecl = this
|
|
826
|
+
.findEnclosingFunctionDeclarationFromReturnStatement(expr);
|
|
827
|
+
if (funcDecl) {
|
|
828
|
+
const funcReturnType = this.typeAnalyzer
|
|
829
|
+
.inferFunctionReturnType(funcDecl);
|
|
830
|
+
if (funcReturnType === "number" &&
|
|
831
|
+
context.isInsideNativeLambda &&
|
|
832
|
+
context.isInsideFunction) {
|
|
833
|
+
const exprReturnType = this.typeAnalyzer
|
|
834
|
+
.inferNodeReturnType(expr);
|
|
835
|
+
if (exprReturnType === "number") {
|
|
836
836
|
finalExpr = `${finalExpr}.as_double()`;
|
|
837
837
|
}
|
|
838
|
+
else {
|
|
839
|
+
finalExpr =
|
|
840
|
+
`jspp::NumberOperators::ToDouble(${finalExpr})`;
|
|
841
|
+
}
|
|
838
842
|
}
|
|
839
843
|
}
|
|
840
844
|
}
|
|
@@ -4,8 +4,7 @@ export class Traverser {
|
|
|
4
4
|
this.traverseNode(node, null, visitor);
|
|
5
5
|
}
|
|
6
6
|
traverseNode(node, parent, visitor) {
|
|
7
|
-
const
|
|
8
|
-
const visitorActions = visitor[nodeKind];
|
|
7
|
+
const visitorActions = visitor[node.kind];
|
|
9
8
|
if (visitorActions && visitorActions.enter) {
|
|
10
9
|
visitorActions.enter(node, parent);
|
|
11
10
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ugo-studio/jspp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"description": "A modern transpiler that converts JavaScript code into high-performance, standard C++23.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "src/index.ts",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"scripts"
|
|
15
15
|
],
|
|
16
16
|
"scripts": {
|
|
17
|
-
"postinstall": "bun run scripts/setup-compiler.ts && bun run scripts/setup-emsdk.ts
|
|
17
|
+
"postinstall": "bun run scripts/setup-compiler.ts && bun run scripts/setup-emsdk.ts",
|
|
18
18
|
"dev": "bun run src/cli/index.ts",
|
|
19
19
|
"typecheck": "tsc --noEmit",
|
|
20
20
|
"test": "bun test",
|
|
@@ -112,6 +112,14 @@ if (process.platform === "win32") {
|
|
|
112
112
|
MODES[1].flags.push("-Wa,-mbig-obj");
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
+
const pkgDir = path.dirname(import.meta.dirname);
|
|
116
|
+
const emsdkEnv = {
|
|
117
|
+
...process.env,
|
|
118
|
+
PATH: `${path.join(pkgDir, ".emsdk")}${path.delimiter}${
|
|
119
|
+
path.join(pkgDir, ".emsdk", "upstream", "emscripten")
|
|
120
|
+
}${path.delimiter}${process.env.PATH}`,
|
|
121
|
+
};
|
|
122
|
+
|
|
115
123
|
async function getLatestMtime(
|
|
116
124
|
dirPath: string,
|
|
117
125
|
filter?: (name: string) => boolean,
|
|
@@ -146,11 +154,11 @@ async function findCppFiles(dir: string): Promise<string[]> {
|
|
|
146
154
|
}
|
|
147
155
|
|
|
148
156
|
async function runCommand(cmd: string, args: string[]): Promise<boolean> {
|
|
149
|
-
// console.log(`${COLORS.dim}> ${cmd} ${args.join(" ")}${COLORS.reset}`);
|
|
150
157
|
return new Promise((resolve) => {
|
|
151
158
|
const proc = spawn(cmd, args, {
|
|
152
159
|
stdio: "inherit",
|
|
153
160
|
shell: process.platform === "win32",
|
|
161
|
+
env: emsdkEnv,
|
|
154
162
|
});
|
|
155
163
|
proc.on("close", (code) => resolve(code === 0));
|
|
156
164
|
});
|
|
@@ -78,7 +78,7 @@ namespace jspp {
|
|
|
78
78
|
}
|
|
79
79
|
} else {
|
|
80
80
|
auto lenVal = items.get_property_with_receiver("length", items);
|
|
81
|
-
size_t len = static_cast<size_t>(jspp::
|
|
81
|
+
size_t len = static_cast<size_t>(jspp::NumberOperators::ToUint32(lenVal));
|
|
82
82
|
|
|
83
83
|
for (size_t k = 0; k < len; ++k) {
|
|
84
84
|
auto kVal = items.get_property_with_receiver(std::to_string(k), items);
|
|
@@ -149,7 +149,7 @@ namespace jspp {
|
|
|
149
149
|
}
|
|
150
150
|
} else {
|
|
151
151
|
auto lenVal = items.get_property_with_receiver("length", items);
|
|
152
|
-
size_t len = static_cast<size_t>(jspp::
|
|
152
|
+
size_t len = static_cast<size_t>(jspp::NumberOperators::ToUint32(lenVal));
|
|
153
153
|
for (size_t k = 0; k < len; ++k) {
|
|
154
154
|
auto kVal = items.get_property_with_receiver(std::to_string(k), items);
|
|
155
155
|
if (kVal.is_promise()) kVal = co_await kVal;
|
|
@@ -11,7 +11,7 @@ namespace jspp {
|
|
|
11
11
|
|
|
12
12
|
double GetArgAsDouble(std::span<const jspp::AnyValue> args, size_t index) {
|
|
13
13
|
if (index >= args.size()) return std::numeric_limits<double>::quiet_NaN();
|
|
14
|
-
return
|
|
14
|
+
return NumberOperators::ToDouble(args[index]);
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
jspp::AnyValue MathFunc1(std::span<const jspp::AnyValue> args, double (*func)(double)) {
|
|
@@ -86,7 +86,7 @@ namespace jspp {
|
|
|
86
86
|
}, "ceil"));
|
|
87
87
|
|
|
88
88
|
defMutable("clz32", AnyValue::make_function([](AnyValue, std::span<const AnyValue> args) -> AnyValue {
|
|
89
|
-
uint32_t val =
|
|
89
|
+
uint32_t val = NumberOperators::ToInt32(args.empty() ? Constants::UNDEFINED : args[0]);
|
|
90
90
|
if (val == 0) return AnyValue::make_number(32);
|
|
91
91
|
return AnyValue::make_number(std::countl_zero(val));
|
|
92
92
|
}, "clz32"));
|
|
@@ -119,7 +119,7 @@ namespace jspp {
|
|
|
119
119
|
defMutable("hypot", AnyValue::make_function([](AnyValue, std::span<const AnyValue> args) -> AnyValue {
|
|
120
120
|
double result = 0;
|
|
121
121
|
for (const auto& arg : args) {
|
|
122
|
-
double val =
|
|
122
|
+
double val = NumberOperators::ToDouble(arg);
|
|
123
123
|
if (std::isinf(val)) return AnyValue::make_number(std::numeric_limits<double>::infinity());
|
|
124
124
|
result = std::hypot(result, val);
|
|
125
125
|
}
|
|
@@ -127,8 +127,8 @@ namespace jspp {
|
|
|
127
127
|
}, "hypot"));
|
|
128
128
|
|
|
129
129
|
defMutable("imul", AnyValue::make_function([](AnyValue, std::span<const AnyValue> args) -> AnyValue {
|
|
130
|
-
int32_t a =
|
|
131
|
-
int32_t b =
|
|
130
|
+
int32_t a = NumberOperators::ToInt32(args.empty() ? Constants::UNDEFINED : args[0]);
|
|
131
|
+
int32_t b = NumberOperators::ToInt32(args.size() < 2 ? Constants::UNDEFINED : args[1]);
|
|
132
132
|
return AnyValue::make_number(a * b);
|
|
133
133
|
}, "imul"));
|
|
134
134
|
|
|
@@ -151,7 +151,7 @@ namespace jspp {
|
|
|
151
151
|
defMutable("max", AnyValue::make_function([](AnyValue, std::span<const AnyValue> args) -> AnyValue {
|
|
152
152
|
double maxVal = -std::numeric_limits<double>::infinity();
|
|
153
153
|
for (const auto& arg : args) {
|
|
154
|
-
double val =
|
|
154
|
+
double val = NumberOperators::ToDouble(arg);
|
|
155
155
|
if (std::isnan(val)) return AnyValue::make_nan();
|
|
156
156
|
if (val > maxVal) maxVal = val;
|
|
157
157
|
}
|
|
@@ -161,7 +161,7 @@ namespace jspp {
|
|
|
161
161
|
defMutable("min", AnyValue::make_function([](AnyValue, std::span<const AnyValue> args) -> AnyValue {
|
|
162
162
|
double minVal = std::numeric_limits<double>::infinity();
|
|
163
163
|
for (const auto& arg : args) {
|
|
164
|
-
double val =
|
|
164
|
+
double val = NumberOperators::ToDouble(arg);
|
|
165
165
|
if (std::isnan(val)) return AnyValue::make_nan();
|
|
166
166
|
if (val < minVal) minVal = val;
|
|
167
167
|
}
|
|
@@ -238,7 +238,7 @@ namespace jspp {
|
|
|
238
238
|
auto nextRes = nextFunc.call(iterObj, std::span<const jspp::AnyValue>{}, "next");
|
|
239
239
|
if (is_truthy(nextRes.get_own_property("done"))) break;
|
|
240
240
|
|
|
241
|
-
double val =
|
|
241
|
+
double val = NumberOperators::ToDouble(nextRes.get_own_property("value"));
|
|
242
242
|
if (std::isnan(val)) {
|
|
243
243
|
sum = std::numeric_limits<double>::quiet_NaN();
|
|
244
244
|
break;
|
|
@@ -48,40 +48,6 @@ namespace jspp
|
|
|
48
48
|
return var;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
inline AnyValue type_of(const std::optional<AnyValue> &val = std::nullopt)
|
|
52
|
-
{
|
|
53
|
-
if (!val.has_value())
|
|
54
|
-
return AnyValue::make_string("undefined");
|
|
55
|
-
|
|
56
|
-
switch (val.value().get_type())
|
|
57
|
-
{
|
|
58
|
-
case JsType::Undefined:
|
|
59
|
-
return AnyValue::make_string("undefined");
|
|
60
|
-
case JsType::Null:
|
|
61
|
-
return AnyValue::make_string("object");
|
|
62
|
-
case JsType::Boolean:
|
|
63
|
-
return AnyValue::make_string("boolean");
|
|
64
|
-
case JsType::Number:
|
|
65
|
-
return AnyValue::make_string("number");
|
|
66
|
-
case JsType::String:
|
|
67
|
-
return AnyValue::make_string("string");
|
|
68
|
-
case JsType::Symbol:
|
|
69
|
-
return AnyValue::make_string("symbol");
|
|
70
|
-
case JsType::Function:
|
|
71
|
-
return AnyValue::make_string("function");
|
|
72
|
-
case JsType::Object:
|
|
73
|
-
return AnyValue::make_string("object");
|
|
74
|
-
case JsType::Array:
|
|
75
|
-
return AnyValue::make_string("object");
|
|
76
|
-
case JsType::Iterator:
|
|
77
|
-
return AnyValue::make_string("object");
|
|
78
|
-
case JsType::AsyncIterator:
|
|
79
|
-
return AnyValue::make_string("object");
|
|
80
|
-
default:
|
|
81
|
-
return AnyValue::make_string("undefined");
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
51
|
// Helper function to get enumerable own property keys/values of an object
|
|
86
52
|
inline std::vector<AnyValue> get_object_keys(const AnyValue &obj, bool include_symbols = false)
|
|
87
53
|
{
|
|
@@ -39,6 +39,42 @@ namespace jspp
|
|
|
39
39
|
return lhs;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
inline AnyValue &operator&=(AnyValue &lhs, const AnyValue &rhs)
|
|
43
|
+
{
|
|
44
|
+
lhs = jspp::bitwise_and(lhs, rhs);
|
|
45
|
+
return lhs;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
inline AnyValue &operator|=(AnyValue &lhs, const AnyValue &rhs)
|
|
49
|
+
{
|
|
50
|
+
lhs = jspp::bitwise_or(lhs, rhs);
|
|
51
|
+
return lhs;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
inline AnyValue &operator^=(AnyValue &lhs, const AnyValue &rhs)
|
|
55
|
+
{
|
|
56
|
+
lhs = jspp::bitwise_xor(lhs, rhs);
|
|
57
|
+
return lhs;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
inline AnyValue &operator<<=(AnyValue &lhs, const AnyValue &rhs)
|
|
61
|
+
{
|
|
62
|
+
lhs = jspp::left_shift(lhs, rhs);
|
|
63
|
+
return lhs;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
inline AnyValue &operator>>=(AnyValue &lhs, const AnyValue &rhs)
|
|
67
|
+
{
|
|
68
|
+
lhs = jspp::right_shift(lhs, rhs);
|
|
69
|
+
return lhs;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
inline AnyValue &unsigned_right_shift_assign(AnyValue &lhs, const AnyValue &rhs)
|
|
73
|
+
{
|
|
74
|
+
lhs = jspp::unsigned_right_shift(lhs, rhs);
|
|
75
|
+
return lhs;
|
|
76
|
+
}
|
|
77
|
+
|
|
42
78
|
inline AnyValue &operator++(AnyValue &val)
|
|
43
79
|
{
|
|
44
80
|
val = jspp::add(val, 1.0);
|
|
@@ -116,4 +152,64 @@ namespace jspp
|
|
|
116
152
|
{
|
|
117
153
|
return lhs %= static_cast<double>(rhs);
|
|
118
154
|
}
|
|
155
|
+
|
|
156
|
+
inline AnyValue &operator&=(AnyValue &lhs, const double &rhs)
|
|
157
|
+
{
|
|
158
|
+
lhs = jspp::bitwise_and(lhs, rhs);
|
|
159
|
+
return lhs;
|
|
160
|
+
}
|
|
161
|
+
inline AnyValue &operator&=(AnyValue &lhs, const int &rhs)
|
|
162
|
+
{
|
|
163
|
+
return lhs &= static_cast<double>(rhs);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
inline AnyValue &operator|=(AnyValue &lhs, const double &rhs)
|
|
167
|
+
{
|
|
168
|
+
lhs = jspp::bitwise_or(lhs, rhs);
|
|
169
|
+
return lhs;
|
|
170
|
+
}
|
|
171
|
+
inline AnyValue &operator|=(AnyValue &lhs, const int &rhs)
|
|
172
|
+
{
|
|
173
|
+
return lhs |= static_cast<double>(rhs);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
inline AnyValue &operator^=(AnyValue &lhs, const double &rhs)
|
|
177
|
+
{
|
|
178
|
+
lhs = jspp::bitwise_xor(lhs, rhs);
|
|
179
|
+
return lhs;
|
|
180
|
+
}
|
|
181
|
+
inline AnyValue &operator^=(AnyValue &lhs, const int &rhs)
|
|
182
|
+
{
|
|
183
|
+
return lhs ^= static_cast<double>(rhs);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
inline AnyValue &operator<<=(AnyValue &lhs, const double &rhs)
|
|
187
|
+
{
|
|
188
|
+
lhs = jspp::left_shift(lhs, rhs);
|
|
189
|
+
return lhs;
|
|
190
|
+
}
|
|
191
|
+
inline AnyValue &operator<<=(AnyValue &lhs, const int &rhs)
|
|
192
|
+
{
|
|
193
|
+
return lhs <<= static_cast<double>(rhs);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
inline AnyValue &operator>>=(AnyValue &lhs, const double &rhs)
|
|
197
|
+
{
|
|
198
|
+
lhs = jspp::right_shift(lhs, rhs);
|
|
199
|
+
return lhs;
|
|
200
|
+
}
|
|
201
|
+
inline AnyValue &operator>>=(AnyValue &lhs, const int &rhs)
|
|
202
|
+
{
|
|
203
|
+
return lhs >>= static_cast<double>(rhs);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
inline AnyValue &unsigned_right_shift_assign(AnyValue &lhs, const double &rhs)
|
|
207
|
+
{
|
|
208
|
+
lhs = jspp::unsigned_right_shift(lhs, rhs);
|
|
209
|
+
return lhs;
|
|
210
|
+
}
|
|
211
|
+
inline AnyValue &unsigned_right_shift_assign(AnyValue &lhs, const int &rhs)
|
|
212
|
+
{
|
|
213
|
+
return unsigned_right_shift_assign(lhs, static_cast<double>(rhs));
|
|
214
|
+
}
|
|
119
215
|
}
|
|
@@ -11,6 +11,41 @@
|
|
|
11
11
|
|
|
12
12
|
namespace jspp
|
|
13
13
|
{
|
|
14
|
+
// --- TYPE OF ---
|
|
15
|
+
inline AnyValue type_of(const std::optional<AnyValue> &val = std::nullopt)
|
|
16
|
+
{
|
|
17
|
+
if (!val.has_value())
|
|
18
|
+
return AnyValue::make_string("undefined");
|
|
19
|
+
|
|
20
|
+
switch (val.value().get_type())
|
|
21
|
+
{
|
|
22
|
+
case JsType::Undefined:
|
|
23
|
+
return AnyValue::make_string("undefined");
|
|
24
|
+
case JsType::Null:
|
|
25
|
+
return AnyValue::make_string("object");
|
|
26
|
+
case JsType::Boolean:
|
|
27
|
+
return AnyValue::make_string("boolean");
|
|
28
|
+
case JsType::Number:
|
|
29
|
+
return AnyValue::make_string("number");
|
|
30
|
+
case JsType::String:
|
|
31
|
+
return AnyValue::make_string("string");
|
|
32
|
+
case JsType::Symbol:
|
|
33
|
+
return AnyValue::make_string("symbol");
|
|
34
|
+
case JsType::Function:
|
|
35
|
+
return AnyValue::make_string("function");
|
|
36
|
+
case JsType::Object:
|
|
37
|
+
return AnyValue::make_string("object");
|
|
38
|
+
case JsType::Array:
|
|
39
|
+
return AnyValue::make_string("object");
|
|
40
|
+
case JsType::Iterator:
|
|
41
|
+
return AnyValue::make_string("object");
|
|
42
|
+
case JsType::AsyncIterator:
|
|
43
|
+
return AnyValue::make_string("object");
|
|
44
|
+
default:
|
|
45
|
+
return AnyValue::make_string("undefined");
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
14
49
|
// Operator === (returns boolean wrapped in AnyValue)
|
|
15
50
|
inline const AnyValue is_strictly_equal_to(const AnyValue &lhs, const double &rhs) noexcept
|
|
16
51
|
{
|
|
@@ -157,15 +192,15 @@ namespace jspp
|
|
|
157
192
|
// --- UNARY OPERATORS ---
|
|
158
193
|
inline AnyValue plus(const AnyValue &val)
|
|
159
194
|
{
|
|
160
|
-
return AnyValue::make_number(
|
|
195
|
+
return AnyValue::make_number(NumberOperators::ToDouble(val));
|
|
161
196
|
}
|
|
162
197
|
inline AnyValue negate(const AnyValue &val)
|
|
163
198
|
{
|
|
164
|
-
return AnyValue::make_number(-
|
|
199
|
+
return AnyValue::make_number(-NumberOperators::ToDouble(val));
|
|
165
200
|
}
|
|
166
201
|
inline AnyValue bitwise_not(const AnyValue &val)
|
|
167
202
|
{
|
|
168
|
-
return AnyValue::make_number(~
|
|
203
|
+
return AnyValue::make_number(~NumberOperators::ToInt32(val));
|
|
169
204
|
}
|
|
170
205
|
inline AnyValue logical_not(const AnyValue &val)
|
|
171
206
|
{
|
|
@@ -349,4 +384,4 @@ namespace jspp
|
|
|
349
384
|
return lhs;
|
|
350
385
|
return rhs;
|
|
351
386
|
}
|
|
352
|
-
}
|
|
387
|
+
}
|