@ugo-studio/jspp 0.1.4 → 0.1.6
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/analysis/scope.js +17 -0
- package/dist/analysis/typeAnalyzer.js +7 -1
- package/dist/ast/symbols.js +32 -0
- package/dist/ast/types.js +0 -6
- package/dist/cli-utils/args.js +57 -0
- package/dist/cli-utils/colors.js +9 -0
- package/dist/cli-utils/file-utils.js +20 -0
- package/dist/cli-utils/spinner.js +55 -0
- package/dist/cli.js +105 -30
- package/dist/core/codegen/class-handlers.js +10 -6
- package/dist/core/codegen/control-flow-handlers.js +57 -28
- package/dist/core/codegen/declaration-handlers.js +10 -6
- package/dist/core/codegen/expression-handlers.js +206 -61
- package/dist/core/codegen/function-handlers.js +203 -76
- package/dist/core/codegen/helpers.js +125 -28
- package/dist/core/codegen/index.js +23 -15
- package/dist/core/codegen/literal-handlers.js +15 -6
- package/dist/core/codegen/statement-handlers.js +282 -84
- package/dist/core/codegen/visitor.js +3 -1
- package/package.json +1 -1
- package/src/prelude/any_value.hpp +221 -342
- package/src/prelude/any_value_access.hpp +168 -81
- package/src/prelude/any_value_defines.hpp +74 -35
- package/src/prelude/any_value_helpers.hpp +75 -180
- package/src/prelude/exception.hpp +1 -0
- package/src/prelude/exception_helpers.hpp +4 -4
- package/src/prelude/index.hpp +12 -2
- package/src/prelude/library/array.hpp +190 -0
- package/src/prelude/library/console.hpp +6 -5
- package/src/prelude/library/error.hpp +10 -8
- package/src/prelude/library/function.hpp +10 -0
- package/src/prelude/library/global.hpp +20 -0
- package/src/prelude/library/math.hpp +308 -0
- package/src/prelude/library/object.hpp +288 -0
- package/src/prelude/library/performance.hpp +1 -1
- package/src/prelude/library/process.hpp +39 -0
- package/src/prelude/library/promise.hpp +57 -55
- package/src/prelude/library/symbol.hpp +45 -57
- package/src/prelude/library/timer.hpp +6 -6
- package/src/prelude/types.hpp +54 -0
- package/src/prelude/utils/access.hpp +215 -11
- package/src/prelude/utils/assignment_operators.hpp +99 -0
- package/src/prelude/utils/log_any_value/array.hpp +8 -8
- package/src/prelude/utils/log_any_value/function.hpp +6 -4
- package/src/prelude/utils/log_any_value/object.hpp +41 -24
- package/src/prelude/utils/log_any_value/primitives.hpp +3 -1
- package/src/prelude/utils/operators.hpp +750 -274
- package/src/prelude/utils/well_known_symbols.hpp +12 -0
- package/src/prelude/values/array.hpp +8 -6
- package/src/prelude/values/async_iterator.hpp +79 -0
- package/src/prelude/values/descriptors.hpp +2 -2
- package/src/prelude/values/function.hpp +72 -62
- package/src/prelude/values/helpers/array.hpp +64 -28
- package/src/prelude/values/helpers/async_iterator.hpp +275 -0
- package/src/prelude/values/helpers/function.hpp +81 -92
- package/src/prelude/values/helpers/iterator.hpp +3 -3
- package/src/prelude/values/helpers/object.hpp +54 -9
- package/src/prelude/values/helpers/promise.hpp +13 -6
- package/src/prelude/values/iterator.hpp +1 -1
- package/src/prelude/values/object.hpp +10 -3
- package/src/prelude/values/promise.hpp +7 -11
- package/src/prelude/values/prototypes/array.hpp +851 -12
- package/src/prelude/values/prototypes/async_iterator.hpp +50 -0
- package/src/prelude/values/prototypes/function.hpp +2 -2
- package/src/prelude/values/prototypes/iterator.hpp +5 -5
- package/src/prelude/values/prototypes/number.hpp +153 -0
- package/src/prelude/values/prototypes/object.hpp +2 -2
- package/src/prelude/values/prototypes/promise.hpp +40 -30
- package/src/prelude/values/prototypes/string.hpp +28 -28
- package/src/prelude/values/prototypes/symbol.hpp +20 -3
- package/src/prelude/values/shape.hpp +52 -0
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
inline jspp::AnyValue Error;
|
|
8
8
|
|
|
9
9
|
// Constructor logic
|
|
10
|
-
inline auto errorConstructor = [](const jspp::AnyValue &thisVal,
|
|
10
|
+
inline auto errorConstructor = [](const jspp::AnyValue &thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
|
|
11
11
|
{
|
|
12
12
|
// Access global Error to get prototype
|
|
13
13
|
jspp::AnyValue proto = Error.get_own_property("prototype");
|
|
@@ -18,7 +18,7 @@ inline auto errorConstructor = [](const jspp::AnyValue &thisVal, const std::vect
|
|
|
18
18
|
if (target.is_object())
|
|
19
19
|
{
|
|
20
20
|
auto obj = target.as_object();
|
|
21
|
-
if (obj->proto && (*obj->proto)
|
|
21
|
+
if (obj->proto && is_strictly_equal_to_primitive((*obj->proto), proto))
|
|
22
22
|
{
|
|
23
23
|
is_construct_call = true;
|
|
24
24
|
}
|
|
@@ -29,6 +29,7 @@ inline auto errorConstructor = [](const jspp::AnyValue &thisVal, const std::vect
|
|
|
29
29
|
target = jspp::AnyValue::make_object_with_proto({}, proto);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
std::string name = "Error";
|
|
32
33
|
std::string message = "";
|
|
33
34
|
if (!args.empty() && !args[0].is_undefined())
|
|
34
35
|
{
|
|
@@ -36,8 +37,8 @@ inline auto errorConstructor = [](const jspp::AnyValue &thisVal, const std::vect
|
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
target.define_data_property("message", jspp::AnyValue::make_string(message), true, false, true);
|
|
39
|
-
target.define_data_property("name", jspp::AnyValue::make_string(
|
|
40
|
-
target.define_data_property("stack", jspp::AnyValue::make_string("
|
|
40
|
+
target.define_data_property("name", jspp::AnyValue::make_string(name), true, false, true);
|
|
41
|
+
target.define_data_property("stack", jspp::AnyValue::make_string(name + ": " + message + "\n at <unknown>"), true, false, true);
|
|
41
42
|
|
|
42
43
|
if (args.size() > 1 && args[1].is_object())
|
|
43
44
|
{
|
|
@@ -52,7 +53,7 @@ inline auto errorConstructor = [](const jspp::AnyValue &thisVal, const std::vect
|
|
|
52
53
|
};
|
|
53
54
|
|
|
54
55
|
// Static Error.isError(val) implementation
|
|
55
|
-
inline auto isErrorFn = jspp::AnyValue::make_function([](const jspp::AnyValue &thisVal,
|
|
56
|
+
inline auto isErrorFn = jspp::AnyValue::make_function([](const jspp::AnyValue &thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
|
|
56
57
|
{
|
|
57
58
|
if (args.empty()) return jspp::AnyValue::make_boolean(false);
|
|
58
59
|
|
|
@@ -67,7 +68,7 @@ inline auto isErrorFn = jspp::AnyValue::make_function([](const jspp::AnyValue &t
|
|
|
67
68
|
if (val.is_object()) {
|
|
68
69
|
auto current = val.as_object()->proto;
|
|
69
70
|
while (current && !(*current).is_null()) {
|
|
70
|
-
if ((*current)
|
|
71
|
+
if (is_strictly_equal_to_primitive((*current),proto)) return jspp::AnyValue::make_boolean(true);
|
|
71
72
|
if ((*current).is_object()) current = (*current).as_object()->proto;
|
|
72
73
|
else break;
|
|
73
74
|
}
|
|
@@ -76,7 +77,7 @@ inline auto isErrorFn = jspp::AnyValue::make_function([](const jspp::AnyValue &t
|
|
|
76
77
|
return jspp::AnyValue::make_boolean(false); }, "isError");
|
|
77
78
|
|
|
78
79
|
// toString method for Error.prototype
|
|
79
|
-
inline auto errorToStringFn = jspp::AnyValue::make_function([](const jspp::AnyValue &thisVal,
|
|
80
|
+
inline auto errorToStringFn = jspp::AnyValue::make_function([](const jspp::AnyValue &thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
|
|
80
81
|
{
|
|
81
82
|
std::string name = "Error";
|
|
82
83
|
std::string msg = "";
|
|
@@ -104,8 +105,9 @@ struct ErrorInit
|
|
|
104
105
|
// Define Error.prototype.toString
|
|
105
106
|
auto proto = Error.get_own_property("prototype");
|
|
106
107
|
proto.define_data_property("toString", errorToStringFn, true, false, true);
|
|
108
|
+
proto.define_data_property(jspp::WellKnownSymbols::toStringTag->key, errorToStringFn, true, false, true);
|
|
107
109
|
|
|
108
110
|
// Define static Error.isError
|
|
109
|
-
Error.define_data_property("isError", isErrorFn,true
|
|
111
|
+
Error.define_data_property("isError", isErrorFn, true, false, true);
|
|
110
112
|
}
|
|
111
113
|
} errorInit;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "types.hpp"
|
|
4
|
+
#include "any_value.hpp"
|
|
5
|
+
|
|
6
|
+
// Define Function constructor
|
|
7
|
+
// In a full implementation, this would support 'new Function(args, body)'
|
|
8
|
+
inline auto Function = jspp::AnyValue::make_class([](const jspp::AnyValue& thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue {
|
|
9
|
+
return jspp::Constants::UNDEFINED;
|
|
10
|
+
}, "Function");
|
|
@@ -8,8 +8,12 @@
|
|
|
8
8
|
|
|
9
9
|
#include "library/promise.hpp"
|
|
10
10
|
#include "library/timer.hpp"
|
|
11
|
+
#include "library/math.hpp"
|
|
11
12
|
|
|
12
13
|
inline auto global = jspp::AnyValue::make_object({
|
|
14
|
+
{"Symbol", Symbol},
|
|
15
|
+
{"process", process},
|
|
16
|
+
{"Function", Function},
|
|
13
17
|
{"console", console},
|
|
14
18
|
{"performance", performance},
|
|
15
19
|
{"Error", Error},
|
|
@@ -18,4 +22,20 @@ inline auto global = jspp::AnyValue::make_object({
|
|
|
18
22
|
{"clearTimeout", clearTimeout},
|
|
19
23
|
{"setInterval", setInterval},
|
|
20
24
|
{"clearInterval", clearInterval},
|
|
25
|
+
{"Math", Math},
|
|
26
|
+
{"Object", Object},
|
|
27
|
+
{"Array", Array},
|
|
21
28
|
});
|
|
29
|
+
|
|
30
|
+
struct GlobalInit {
|
|
31
|
+
GlobalInit() {
|
|
32
|
+
auto objectProto = ::Object.get_own_property("prototype");
|
|
33
|
+
|
|
34
|
+
// Tie built-in prototypes to Object.prototype
|
|
35
|
+
::Array.get_own_property("prototype").set_prototype(objectProto);
|
|
36
|
+
::Function.get_own_property("prototype").set_prototype(objectProto);
|
|
37
|
+
::Error.get_own_property("prototype").set_prototype(objectProto);
|
|
38
|
+
::Promise.get_own_property("prototype").set_prototype(objectProto);
|
|
39
|
+
::Symbol.get_own_property("prototype").set_prototype(objectProto);
|
|
40
|
+
}
|
|
41
|
+
} globalInit;
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <cmath>
|
|
4
|
+
#include <limits>
|
|
5
|
+
#include <random>
|
|
6
|
+
#include <algorithm>
|
|
7
|
+
#include <bit>
|
|
8
|
+
#include <numbers>
|
|
9
|
+
#include <stdfloat>
|
|
10
|
+
|
|
11
|
+
#include "types.hpp"
|
|
12
|
+
#include "any_value.hpp"
|
|
13
|
+
#include "utils/operators.hpp"
|
|
14
|
+
#include "utils/access.hpp"
|
|
15
|
+
|
|
16
|
+
namespace jspp {
|
|
17
|
+
namespace Library {
|
|
18
|
+
// --- Random Number Generator ---
|
|
19
|
+
static std::random_device rd;
|
|
20
|
+
static std::mt19937 gen(rd());
|
|
21
|
+
static std::uniform_real_distribution<> dis(0.0, 1.0);
|
|
22
|
+
|
|
23
|
+
// --- Helpers ---
|
|
24
|
+
inline double GetArgAsDouble(std::span<const jspp::AnyValue> args, size_t index) {
|
|
25
|
+
if (index >= args.size()) return std::numeric_limits<double>::quiet_NaN();
|
|
26
|
+
return Operators_Private::ToNumber(args[index]);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
inline jspp::AnyValue MathFunc1(std::span<const jspp::AnyValue> args, double (*func)(double)) {
|
|
30
|
+
return jspp::AnyValue::make_number(func(GetArgAsDouble(args, 0)));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
inline jspp::AnyValue MathFunc2(std::span<const jspp::AnyValue> args, double (*func)(double, double)) {
|
|
34
|
+
return jspp::AnyValue::make_number(func(GetArgAsDouble(args, 0), GetArgAsDouble(args, 1)));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
inline auto Math = jspp::AnyValue::make_object({});
|
|
40
|
+
|
|
41
|
+
struct MathInit {
|
|
42
|
+
MathInit() {
|
|
43
|
+
using namespace jspp;
|
|
44
|
+
using namespace jspp::Library;
|
|
45
|
+
|
|
46
|
+
// --- Constants ---
|
|
47
|
+
auto defConst = [](const std::string& key, double val) {
|
|
48
|
+
Math.define_data_property(key, AnyValue::make_number(val), false, false, false);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
defConst("E", std::numbers::e);
|
|
52
|
+
defConst("LN10", std::numbers::ln10);
|
|
53
|
+
defConst("LN2", std::numbers::ln2);
|
|
54
|
+
defConst("LOG10E", std::numbers::log10e);
|
|
55
|
+
defConst("LOG2E", std::numbers::log2e);
|
|
56
|
+
defConst("PI", std::numbers::pi);
|
|
57
|
+
defConst("SQRT1_2", std::numbers::sqrt2 / 2.0);
|
|
58
|
+
defConst("SQRT2", std::numbers::sqrt2);
|
|
59
|
+
|
|
60
|
+
// --- Methods ---
|
|
61
|
+
|
|
62
|
+
// Math.abs(x)
|
|
63
|
+
Math.define_data_property("abs", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
64
|
+
return AnyValue::make_number(std::abs(GetArgAsDouble(args, 0)));
|
|
65
|
+
}, "abs"));
|
|
66
|
+
|
|
67
|
+
// Math.acos(x)
|
|
68
|
+
Math.define_data_property("acos", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
69
|
+
return MathFunc1(args, std::acos);
|
|
70
|
+
}, "acos"));
|
|
71
|
+
|
|
72
|
+
// Math.acosh(x)
|
|
73
|
+
Math.define_data_property("acosh", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
74
|
+
return MathFunc1(args, std::acosh);
|
|
75
|
+
}, "acosh"));
|
|
76
|
+
|
|
77
|
+
// Math.asin(x)
|
|
78
|
+
Math.define_data_property("asin", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
79
|
+
return MathFunc1(args, std::asin);
|
|
80
|
+
}, "asin"));
|
|
81
|
+
|
|
82
|
+
// Math.asinh(x)
|
|
83
|
+
Math.define_data_property("asinh", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
84
|
+
return MathFunc1(args, std::asinh);
|
|
85
|
+
}, "asinh"));
|
|
86
|
+
|
|
87
|
+
// Math.atan(x)
|
|
88
|
+
Math.define_data_property("atan", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
89
|
+
return MathFunc1(args, std::atan);
|
|
90
|
+
}, "atan"));
|
|
91
|
+
|
|
92
|
+
// Math.atan2(y, x)
|
|
93
|
+
Math.define_data_property("atan2", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
94
|
+
return MathFunc2(args, std::atan2);
|
|
95
|
+
}, "atan2"));
|
|
96
|
+
|
|
97
|
+
// Math.atanh(x)
|
|
98
|
+
Math.define_data_property("atanh", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
99
|
+
return MathFunc1(args, std::atanh);
|
|
100
|
+
}, "atanh"));
|
|
101
|
+
|
|
102
|
+
// Math.cbrt(x)
|
|
103
|
+
Math.define_data_property("cbrt", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
104
|
+
return MathFunc1(args, std::cbrt);
|
|
105
|
+
}, "cbrt"));
|
|
106
|
+
|
|
107
|
+
// Math.ceil(x)
|
|
108
|
+
Math.define_data_property("ceil", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
109
|
+
return MathFunc1(args, std::ceil);
|
|
110
|
+
}, "ceil"));
|
|
111
|
+
|
|
112
|
+
// Math.clz32(x)
|
|
113
|
+
Math.define_data_property("clz32", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
114
|
+
uint32_t val = Operators_Private::ToInt32(args.empty() ? AnyValue::make_undefined() : args[0]);
|
|
115
|
+
if (val == 0) return AnyValue::make_number(32);
|
|
116
|
+
return AnyValue::make_number(std::countl_zero(val));
|
|
117
|
+
}, "clz32"));
|
|
118
|
+
|
|
119
|
+
// Math.cos(x)
|
|
120
|
+
Math.define_data_property("cos", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
121
|
+
return MathFunc1(args, std::cos);
|
|
122
|
+
}, "cos"));
|
|
123
|
+
|
|
124
|
+
// Math.cosh(x)
|
|
125
|
+
Math.define_data_property("cosh", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
126
|
+
return MathFunc1(args, std::cosh);
|
|
127
|
+
}, "cosh"));
|
|
128
|
+
|
|
129
|
+
// Math.exp(x)
|
|
130
|
+
Math.define_data_property("exp", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
131
|
+
return MathFunc1(args, std::exp);
|
|
132
|
+
}, "exp"));
|
|
133
|
+
|
|
134
|
+
// Math.expm1(x)
|
|
135
|
+
Math.define_data_property("expm1", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
136
|
+
return MathFunc1(args, std::expm1);
|
|
137
|
+
}, "expm1"));
|
|
138
|
+
|
|
139
|
+
// Math.f16round(x)
|
|
140
|
+
Math.define_data_property("f16round", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
141
|
+
double d = GetArgAsDouble(args, 0);
|
|
142
|
+
#if defined(__STDCPP_FLOAT16_T__)
|
|
143
|
+
return AnyValue::make_number(static_cast<double>(static_cast<std::float16_t>(d)));
|
|
144
|
+
#else
|
|
145
|
+
// Manual fallback if float16_t is not available
|
|
146
|
+
// This is a very rough approximation, actual f16round is more complex
|
|
147
|
+
float f = static_cast<float>(d);
|
|
148
|
+
return AnyValue::make_number(static_cast<double>(f));
|
|
149
|
+
#endif
|
|
150
|
+
}, "f16round"));
|
|
151
|
+
|
|
152
|
+
// Math.floor(x)
|
|
153
|
+
Math.define_data_property("floor", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
154
|
+
return MathFunc1(args, std::floor);
|
|
155
|
+
}, "floor"));
|
|
156
|
+
|
|
157
|
+
// Math.fround(x)
|
|
158
|
+
Math.define_data_property("fround", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
159
|
+
double d = GetArgAsDouble(args, 0);
|
|
160
|
+
return AnyValue::make_number(static_cast<double>(static_cast<float>(d)));
|
|
161
|
+
}, "fround"));
|
|
162
|
+
|
|
163
|
+
// Math.hypot(...args)
|
|
164
|
+
Math.define_data_property("hypot", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
165
|
+
double result = 0;
|
|
166
|
+
for (const auto& arg : args) {
|
|
167
|
+
double val = Operators_Private::ToNumber(arg);
|
|
168
|
+
if (std::isinf(val)) return AnyValue::make_number(std::numeric_limits<double>::infinity());
|
|
169
|
+
result = std::hypot(result, val);
|
|
170
|
+
}
|
|
171
|
+
return AnyValue::make_number(result);
|
|
172
|
+
}, "hypot"));
|
|
173
|
+
|
|
174
|
+
// Math.imul(x, y)
|
|
175
|
+
Math.define_data_property("imul", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
176
|
+
int32_t a = Operators_Private::ToInt32(args.empty() ? AnyValue::make_undefined() : args[0]);
|
|
177
|
+
int32_t b = Operators_Private::ToInt32(args.size() < 2 ? AnyValue::make_undefined() : args[1]);
|
|
178
|
+
return AnyValue::make_number(a * b);
|
|
179
|
+
}, "imul"));
|
|
180
|
+
|
|
181
|
+
// Math.log(x)
|
|
182
|
+
Math.define_data_property("log", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
183
|
+
return MathFunc1(args, std::log);
|
|
184
|
+
}, "log"));
|
|
185
|
+
|
|
186
|
+
// Math.log10(x)
|
|
187
|
+
Math.define_data_property("log10", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
188
|
+
return MathFunc1(args, std::log10);
|
|
189
|
+
}, "log10"));
|
|
190
|
+
|
|
191
|
+
// Math.log1p(x)
|
|
192
|
+
Math.define_data_property("log1p", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
193
|
+
return MathFunc1(args, std::log1p);
|
|
194
|
+
}, "log1p"));
|
|
195
|
+
|
|
196
|
+
// Math.log2(x)
|
|
197
|
+
Math.define_data_property("log2", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
198
|
+
return MathFunc1(args, std::log2);
|
|
199
|
+
}, "log2"));
|
|
200
|
+
|
|
201
|
+
// Math.max(...args)
|
|
202
|
+
Math.define_data_property("max", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
203
|
+
double maxVal = -std::numeric_limits<double>::infinity();
|
|
204
|
+
for (const auto& arg : args) {
|
|
205
|
+
double val = Operators_Private::ToNumber(arg);
|
|
206
|
+
if (std::isnan(val)) return AnyValue::make_nan();
|
|
207
|
+
if (val > maxVal) maxVal = val;
|
|
208
|
+
}
|
|
209
|
+
return AnyValue::make_number(maxVal);
|
|
210
|
+
}, "max"));
|
|
211
|
+
|
|
212
|
+
// Math.min(...args)
|
|
213
|
+
Math.define_data_property("min", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
214
|
+
double minVal = std::numeric_limits<double>::infinity();
|
|
215
|
+
for (const auto& arg : args) {
|
|
216
|
+
double val = Operators_Private::ToNumber(arg);
|
|
217
|
+
if (std::isnan(val)) return AnyValue::make_nan();
|
|
218
|
+
if (val < minVal) minVal = val;
|
|
219
|
+
}
|
|
220
|
+
return AnyValue::make_number(minVal);
|
|
221
|
+
}, "min"));
|
|
222
|
+
|
|
223
|
+
// Math.pow(base, exponent)
|
|
224
|
+
Math.define_data_property("pow", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
225
|
+
return MathFunc2(args, std::pow);
|
|
226
|
+
}, "pow"));
|
|
227
|
+
|
|
228
|
+
// Math.random()
|
|
229
|
+
Math.define_data_property("random", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
230
|
+
return AnyValue::make_number(dis(gen));
|
|
231
|
+
}, "random"));
|
|
232
|
+
|
|
233
|
+
// Math.round(x)
|
|
234
|
+
Math.define_data_property("round", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
235
|
+
double d = GetArgAsDouble(args, 0);
|
|
236
|
+
if (std::isnan(d)) return AnyValue::make_nan();
|
|
237
|
+
return AnyValue::make_number(std::floor(d + 0.5));
|
|
238
|
+
}, "round"));
|
|
239
|
+
|
|
240
|
+
// Math.sign(x)
|
|
241
|
+
Math.define_data_property("sign", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
242
|
+
double d = GetArgAsDouble(args, 0);
|
|
243
|
+
if (std::isnan(d)) return AnyValue::make_nan();
|
|
244
|
+
if (d == 0) return AnyValue::make_number(d);
|
|
245
|
+
return AnyValue::make_number(d > 0 ? 1.0 : -1.0);
|
|
246
|
+
}, "sign"));
|
|
247
|
+
|
|
248
|
+
// Math.sin(x)
|
|
249
|
+
Math.define_data_property("sin", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
250
|
+
return MathFunc1(args, std::sin);
|
|
251
|
+
}, "sin"));
|
|
252
|
+
|
|
253
|
+
// Math.sinh(x)
|
|
254
|
+
Math.define_data_property("sinh", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
255
|
+
return MathFunc1(args, std::sinh);
|
|
256
|
+
}, "sinh"));
|
|
257
|
+
|
|
258
|
+
// Math.sqrt(x)
|
|
259
|
+
Math.define_data_property("sqrt", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
260
|
+
return MathFunc1(args, std::sqrt);
|
|
261
|
+
}, "sqrt"));
|
|
262
|
+
|
|
263
|
+
// Math.sumPrecise(iterable)
|
|
264
|
+
Math.define_data_property("sumPrecise", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
265
|
+
if (args.empty()) throw Exception::make_exception("Math.sumPrecise requires an iterable", "TypeError");
|
|
266
|
+
|
|
267
|
+
auto iterObj = jspp::Access::get_object_value_iterator(args[0], "iterable");
|
|
268
|
+
auto nextFunc = iterObj.get_own_property("next");
|
|
269
|
+
|
|
270
|
+
double sum = 0;
|
|
271
|
+
// Kahan summation algorithm for better precision
|
|
272
|
+
double c = 0;
|
|
273
|
+
|
|
274
|
+
while (true) {
|
|
275
|
+
auto nextRes = nextFunc.call(iterObj, std::span<const jspp::AnyValue>{}, "next");
|
|
276
|
+
if (is_truthy(nextRes.get_own_property("done"))) break;
|
|
277
|
+
|
|
278
|
+
double val = Operators_Private::ToNumber(nextRes.get_own_property("value"));
|
|
279
|
+
if (std::isnan(val)) {
|
|
280
|
+
sum = std::numeric_limits<double>::quiet_NaN();
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
double y = val - c;
|
|
285
|
+
double t = sum + y;
|
|
286
|
+
c = (t - sum) - y;
|
|
287
|
+
sum = t;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return AnyValue::make_number(sum);
|
|
291
|
+
}, "sumPrecise"));
|
|
292
|
+
|
|
293
|
+
// Math.tan(x)
|
|
294
|
+
Math.define_data_property("tan", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
295
|
+
return MathFunc1(args, std::tan);
|
|
296
|
+
}, "tan"));
|
|
297
|
+
|
|
298
|
+
// Math.tanh(x)
|
|
299
|
+
Math.define_data_property("tanh", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
300
|
+
return MathFunc1(args, std::tanh);
|
|
301
|
+
}, "tanh"));
|
|
302
|
+
|
|
303
|
+
// Math.trunc(x)
|
|
304
|
+
Math.define_data_property("trunc", AnyValue::make_function([](const AnyValue&, std::span<const AnyValue> args) -> AnyValue {
|
|
305
|
+
return MathFunc1(args, std::trunc);
|
|
306
|
+
}, "trunc"));
|
|
307
|
+
}
|
|
308
|
+
} mathInit;
|