@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.
Files changed (71) hide show
  1. package/dist/analysis/scope.js +17 -0
  2. package/dist/analysis/typeAnalyzer.js +7 -1
  3. package/dist/ast/symbols.js +32 -0
  4. package/dist/ast/types.js +0 -6
  5. package/dist/cli-utils/args.js +57 -0
  6. package/dist/cli-utils/colors.js +9 -0
  7. package/dist/cli-utils/file-utils.js +20 -0
  8. package/dist/cli-utils/spinner.js +55 -0
  9. package/dist/cli.js +105 -30
  10. package/dist/core/codegen/class-handlers.js +10 -6
  11. package/dist/core/codegen/control-flow-handlers.js +57 -28
  12. package/dist/core/codegen/declaration-handlers.js +10 -6
  13. package/dist/core/codegen/expression-handlers.js +206 -61
  14. package/dist/core/codegen/function-handlers.js +203 -76
  15. package/dist/core/codegen/helpers.js +125 -28
  16. package/dist/core/codegen/index.js +23 -15
  17. package/dist/core/codegen/literal-handlers.js +15 -6
  18. package/dist/core/codegen/statement-handlers.js +282 -84
  19. package/dist/core/codegen/visitor.js +3 -1
  20. package/package.json +1 -1
  21. package/src/prelude/any_value.hpp +221 -342
  22. package/src/prelude/any_value_access.hpp +168 -81
  23. package/src/prelude/any_value_defines.hpp +74 -35
  24. package/src/prelude/any_value_helpers.hpp +75 -180
  25. package/src/prelude/exception.hpp +1 -0
  26. package/src/prelude/exception_helpers.hpp +4 -4
  27. package/src/prelude/index.hpp +12 -2
  28. package/src/prelude/library/array.hpp +190 -0
  29. package/src/prelude/library/console.hpp +6 -5
  30. package/src/prelude/library/error.hpp +10 -8
  31. package/src/prelude/library/function.hpp +10 -0
  32. package/src/prelude/library/global.hpp +20 -0
  33. package/src/prelude/library/math.hpp +308 -0
  34. package/src/prelude/library/object.hpp +288 -0
  35. package/src/prelude/library/performance.hpp +1 -1
  36. package/src/prelude/library/process.hpp +39 -0
  37. package/src/prelude/library/promise.hpp +57 -55
  38. package/src/prelude/library/symbol.hpp +45 -57
  39. package/src/prelude/library/timer.hpp +6 -6
  40. package/src/prelude/types.hpp +54 -0
  41. package/src/prelude/utils/access.hpp +215 -11
  42. package/src/prelude/utils/assignment_operators.hpp +99 -0
  43. package/src/prelude/utils/log_any_value/array.hpp +8 -8
  44. package/src/prelude/utils/log_any_value/function.hpp +6 -4
  45. package/src/prelude/utils/log_any_value/object.hpp +41 -24
  46. package/src/prelude/utils/log_any_value/primitives.hpp +3 -1
  47. package/src/prelude/utils/operators.hpp +750 -274
  48. package/src/prelude/utils/well_known_symbols.hpp +12 -0
  49. package/src/prelude/values/array.hpp +8 -6
  50. package/src/prelude/values/async_iterator.hpp +79 -0
  51. package/src/prelude/values/descriptors.hpp +2 -2
  52. package/src/prelude/values/function.hpp +72 -62
  53. package/src/prelude/values/helpers/array.hpp +64 -28
  54. package/src/prelude/values/helpers/async_iterator.hpp +275 -0
  55. package/src/prelude/values/helpers/function.hpp +81 -92
  56. package/src/prelude/values/helpers/iterator.hpp +3 -3
  57. package/src/prelude/values/helpers/object.hpp +54 -9
  58. package/src/prelude/values/helpers/promise.hpp +13 -6
  59. package/src/prelude/values/iterator.hpp +1 -1
  60. package/src/prelude/values/object.hpp +10 -3
  61. package/src/prelude/values/promise.hpp +7 -11
  62. package/src/prelude/values/prototypes/array.hpp +851 -12
  63. package/src/prelude/values/prototypes/async_iterator.hpp +50 -0
  64. package/src/prelude/values/prototypes/function.hpp +2 -2
  65. package/src/prelude/values/prototypes/iterator.hpp +5 -5
  66. package/src/prelude/values/prototypes/number.hpp +153 -0
  67. package/src/prelude/values/prototypes/object.hpp +2 -2
  68. package/src/prelude/values/prototypes/promise.hpp +40 -30
  69. package/src/prelude/values/prototypes/string.hpp +28 -28
  70. package/src/prelude/values/prototypes/symbol.hpp +20 -3
  71. 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, const std::vector<jspp::AnyValue> &args) -> jspp::AnyValue
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).is_strictly_equal_to_primitive(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("Error"), true, false, true);
40
- target.define_data_property("stack", jspp::AnyValue::make_string("Error: " + message + "\n at <unknown>"), true, false, true);
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, const std::vector<jspp::AnyValue> &args) -> jspp::AnyValue
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).is_strictly_equal_to_primitive(proto)) return jspp::AnyValue::make_boolean(true);
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, const std::vector<jspp::AnyValue> &args) -> jspp::AnyValue
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 ,false,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;