xbintsc 0.3.15 → 0.3.16
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/src/cli/main.js +4 -4
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/codegen/generator/state.js +8 -0
- package/dist/src/codegen/generator/state.js.map +1 -1
- package/dist/src/codegen/generator/tables.js +8 -0
- package/dist/src/codegen/generator/tables.js.map +1 -1
- package/dist/src/driver/bundler/graph.d.ts +8 -0
- package/dist/src/driver/bundler/graph.js +85 -0
- package/dist/src/driver/bundler/graph.js.map +1 -0
- package/dist/src/driver/bundler/merge.d.ts +11 -0
- package/dist/src/driver/bundler/merge.js +288 -0
- package/dist/src/driver/bundler/merge.js.map +1 -0
- package/dist/src/driver/bundler/resolve.d.ts +12 -0
- package/dist/src/driver/bundler/resolve.js +246 -0
- package/dist/src/driver/bundler/resolve.js.map +1 -0
- package/dist/src/driver/bundler/symbols.d.ts +15 -0
- package/dist/src/driver/bundler/symbols.js +51 -0
- package/dist/src/driver/bundler/symbols.js.map +1 -0
- package/dist/src/driver/bundler/types.d.ts +36 -0
- package/dist/src/driver/bundler/types.js +5 -0
- package/dist/src/driver/bundler/types.js.map +1 -0
- package/dist/src/driver/modules.d.ts +9 -16
- package/dist/src/driver/modules.js +8 -644
- package/dist/src/driver/modules.js.map +1 -1
- package/dist/src/extensions/catalog.js +2 -1
- package/dist/src/extensions/catalog.js.map +1 -1
- package/dist/src/extensions/gui/index.d.ts +24 -0
- package/dist/src/extensions/gui/index.js +101 -0
- package/dist/src/extensions/gui/index.js.map +1 -0
- package/dist/tests/e2e/compile-basics.test.d.ts +4 -0
- package/dist/tests/e2e/compile-basics.test.js +134 -0
- package/dist/tests/e2e/compile-basics.test.js.map +1 -0
- package/dist/tests/e2e/compile-builtins.test.d.ts +4 -0
- package/dist/tests/e2e/compile-builtins.test.js +191 -0
- package/dist/tests/e2e/compile-builtins.test.js.map +1 -0
- package/dist/tests/e2e/compile-control-flow.test.d.ts +4 -0
- package/dist/tests/e2e/compile-control-flow.test.js +190 -0
- package/dist/tests/e2e/compile-control-flow.test.js.map +1 -0
- package/dist/tests/e2e/compile-modules.test.d.ts +4 -0
- package/dist/tests/e2e/compile-modules.test.js +48 -0
- package/dist/tests/e2e/compile-modules.test.js.map +1 -0
- package/dist/tests/e2e/compile-objects-classes.test.d.ts +4 -0
- package/dist/tests/e2e/compile-objects-classes.test.js +362 -0
- package/dist/tests/e2e/compile-objects-classes.test.js.map +1 -0
- package/dist/tests/e2e/differential-helpers.d.ts +12 -0
- package/dist/tests/e2e/differential-helpers.js +16 -0
- package/dist/tests/e2e/differential-helpers.js.map +1 -0
- package/dist/tests/e2e/differential-language.test.d.ts +4 -0
- package/dist/tests/e2e/{differential.test.js → differential-language.test.js} +5 -287
- package/dist/tests/e2e/differential-language.test.js.map +1 -0
- package/dist/tests/e2e/differential-symbols.test.d.ts +4 -0
- package/dist/tests/e2e/differential-symbols.test.js +92 -0
- package/dist/tests/e2e/differential-symbols.test.js.map +1 -0
- package/dist/tests/e2e/differential-values.test.d.ts +4 -0
- package/dist/tests/e2e/differential-values.test.js +197 -0
- package/dist/tests/e2e/differential-values.test.js.map +1 -0
- package/dist/tests/e2e/gui.test.d.ts +12 -0
- package/dist/tests/e2e/gui.test.js +493 -0
- package/dist/tests/e2e/gui.test.js.map +1 -0
- package/dist/tests/e2e/runtime-coverage-buffer.test.d.ts +4 -0
- package/dist/tests/e2e/runtime-coverage-buffer.test.js +97 -0
- package/dist/tests/e2e/runtime-coverage-buffer.test.js.map +1 -0
- package/dist/tests/e2e/runtime-coverage-globals.test.d.ts +4 -0
- package/dist/tests/e2e/runtime-coverage-globals.test.js +149 -0
- package/dist/tests/e2e/runtime-coverage-globals.test.js.map +1 -0
- package/dist/tests/e2e/runtime-coverage-node-modules.test.d.ts +4 -0
- package/dist/tests/e2e/runtime-coverage-node-modules.test.js +177 -0
- package/dist/tests/e2e/runtime-coverage-node-modules.test.js.map +1 -0
- package/dist/tests/e2e/runtime-coverage-streams.test.d.ts +4 -0
- package/dist/tests/e2e/runtime-coverage-streams.test.js +161 -0
- package/dist/tests/e2e/runtime-coverage-streams.test.js.map +1 -0
- package/dist/tests/e2e/runtime-coverage-system.test.d.ts +4 -0
- package/dist/tests/e2e/runtime-coverage-system.test.js +91 -0
- package/dist/tests/e2e/runtime-coverage-system.test.js.map +1 -0
- package/dist/tests/e2e/timers.test.d.ts +7 -0
- package/dist/tests/e2e/timers.test.js +63 -0
- package/dist/tests/e2e/timers.test.js.map +1 -0
- package/package.json +2 -1
- package/runtime/ext_gui/css.cpp +743 -0
- package/runtime/ext_gui/css.h +98 -0
- package/runtime/ext_gui/document.cpp +264 -0
- package/runtime/ext_gui/document.h +89 -0
- package/runtime/ext_gui/dom.cpp +472 -0
- package/runtime/ext_gui/dom.h +71 -0
- package/runtime/ext_gui/gui.cpp +457 -0
- package/runtime/ext_gui/gui_engine.h +81 -0
- package/runtime/ext_gui/image.cpp +125 -0
- package/runtime/ext_gui/image.h +42 -0
- package/runtime/ext_gui/layout.cpp +748 -0
- package/runtime/ext_gui/layout.h +93 -0
- package/runtime/ext_gui/paint.cpp +137 -0
- package/runtime/ext_gui/paint.h +75 -0
- package/runtime/ext_gui/renderer.cpp +959 -0
- package/runtime/ext_gui/renderer.h +68 -0
- package/runtime/ext_gui/stb_image.h +7988 -0
- package/runtime/ext_gui/style.cpp +771 -0
- package/runtime/ext_gui/style.h +117 -0
- package/runtime/ext_gui/text.cpp +378 -0
- package/runtime/ext_gui/text.h +78 -0
- package/runtime/ext_gui/window.cpp +405 -0
- package/runtime/ext_node/fs/fs_common.h +13 -527
- package/runtime/ext_node/fs/parts/buffer-bridge.inc +6 -0
- package/runtime/ext_node/fs/parts/builtins.inc +69 -0
- package/runtime/ext_node/fs/parts/dir.inc +47 -0
- package/runtime/ext_node/fs/parts/encoding.inc +186 -0
- package/runtime/ext_node/fs/parts/errors.inc +66 -0
- package/runtime/ext_node/fs/parts/flags.inc +39 -0
- package/runtime/ext_node/fs/parts/platform.inc +86 -0
- package/runtime/ext_node/fs/parts/promisify.inc +15 -0
- package/runtime/ext_node/fs/parts/time.inc +9 -0
- package/runtime/rt.h +33 -0
- package/runtime/xt_builtins.c +4 -0
- package/runtime/xt_containers/access.inc +168 -0
- package/runtime/xt_containers/arrays.inc +108 -0
- package/runtime/xt_containers/boxes.inc +11 -0
- package/runtime/xt_containers/objects.inc +326 -0
- package/runtime/xt_containers.c +8 -618
- package/runtime/xt_io/base64.inc +87 -0
- package/runtime/xt_io/console.inc +119 -0
- package/runtime/xt_io/exception.inc +142 -0
- package/runtime/xt_io/inspect.inc +212 -0
- package/runtime/xt_io.c +8 -553
- package/runtime/xt_loop.c +262 -24
- package/runtime/xt_regex/api.inc +58 -0
- package/runtime/xt_regex/helpers.inc +68 -0
- package/runtime/xt_regex/matcher.inc +248 -0
- package/runtime/xt_regex/parser.inc +236 -0
- package/runtime/xt_regex/types.inc +58 -0
- package/runtime/xt_regex.h +9 -672
- package/runtime/xt_values/arithmetic.inc +150 -0
- package/runtime/xt_values/comparison.inc +112 -0
- package/runtime/xt_values/constructors.inc +41 -0
- package/runtime/xt_values/conversions.inc +115 -0
- package/runtime/xt_values/number-format.inc +180 -0
- package/runtime/xt_values/strings.inc +22 -0
- package/runtime/xt_values.c +10 -626
- package/scripts/build-gui.ts +317 -0
- package/src/cli/main.ts +4 -3
- package/src/codegen/generator/state.ts +8 -0
- package/src/codegen/generator/tables.ts +8 -0
- package/src/driver/bundler/graph.ts +95 -0
- package/src/driver/bundler/merge.ts +312 -0
- package/src/driver/bundler/resolve.ts +240 -0
- package/src/driver/bundler/symbols.ts +55 -0
- package/src/driver/bundler/types.ts +37 -0
- package/src/driver/modules.ts +9 -693
- package/src/extensions/catalog.ts +2 -1
- package/src/extensions/gui/index.ts +107 -0
- package/dist/tests/e2e/compile.test.d.ts +0 -8
- package/dist/tests/e2e/compile.test.js +0 -893
- package/dist/tests/e2e/compile.test.js.map +0 -1
- package/dist/tests/e2e/differential.test.d.ts +0 -7
- package/dist/tests/e2e/differential.test.js.map +0 -1
- package/dist/tests/e2e/runtime-coverage.test.d.ts +0 -11
- package/dist/tests/e2e/runtime-coverage.test.js +0 -646
- package/dist/tests/e2e/runtime-coverage.test.js.map +0 -1
package/runtime/xt_values.c
CHANGED
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Constructors, the string representation, JS conversions, arithmetic and
|
|
5
5
|
* comparison operators. All of these operate on the NaN-boxed `xt_value`.
|
|
6
|
+
*
|
|
7
|
+
* The implementation is grouped by functional area under `xt_values/` and
|
|
8
|
+
* `#include`d here as a single translation unit, so the internal helpers stay
|
|
9
|
+
* `static` while each file stays focused on one area.
|
|
6
10
|
*/
|
|
7
11
|
|
|
8
12
|
#include "rt_internal.h"
|
|
@@ -13,629 +17,9 @@
|
|
|
13
17
|
#include <stdlib.h>
|
|
14
18
|
#include <string.h>
|
|
15
19
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
xt_value xt_bool(int b) { return b ? XT_TRUE : XT_FALSE; }
|
|
23
|
-
xt_value xt_number(double d) { return xt_from_double(d); }
|
|
24
|
-
|
|
25
|
-
xt_string *xt_string_alloc(size_t length) {
|
|
26
|
-
xt_string *s = (xt_string *)xt_alloc(sizeof(xt_string), XT_OBJECT_KIND_STRING);
|
|
27
|
-
s->length = (uint32_t)length;
|
|
28
|
-
s->capacity = (uint32_t)length + 1;
|
|
29
|
-
s->data = (char *)malloc(s->capacity);
|
|
30
|
-
if (!s->data) {
|
|
31
|
-
fprintf(stderr, "xbintsc: out of memory allocating string\n");
|
|
32
|
-
abort();
|
|
33
|
-
}
|
|
34
|
-
s->data[length] = '\0';
|
|
35
|
-
return s;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
xt_value xt_string_new(const char *data, size_t len) {
|
|
39
|
-
xt_string *s = xt_string_alloc(len);
|
|
40
|
-
if (len > 0) memcpy(s->data, data, len);
|
|
41
|
-
return XT_FROM_PTR(XT_TAG_STRING, s);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
xt_value xt_string_from_cstr(const char *data) { return xt_string_new(data, strlen(data)); }
|
|
45
|
-
|
|
46
|
-
xt_string *xt_as_string(xt_value v);
|
|
47
|
-
|
|
48
|
-
const char *xt_string_data(xt_value value) {
|
|
49
|
-
xt_string *s = xt_as_string(value);
|
|
50
|
-
return s ? s->data : NULL;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
int32_t xt_string_length_value(xt_value value) {
|
|
54
|
-
xt_string *s = xt_as_string(value);
|
|
55
|
-
return s ? (int32_t)s->length : -1;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/* ------------------------------------------------------------------------- */
|
|
59
|
-
/* Strings */
|
|
60
|
-
/* ------------------------------------------------------------------------- */
|
|
61
|
-
|
|
62
|
-
xt_string *xt_as_string(xt_value v) {
|
|
63
|
-
if (XT_IS_STRING(v)) return (xt_string *)XT_GET_PTR(v);
|
|
64
|
-
return NULL;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
int32_t xt_string_length(xt_string *s) { return (int32_t)s->length; }
|
|
68
|
-
|
|
69
|
-
static xt_value xt_string_concat(xt_string *a, xt_string *b) {
|
|
70
|
-
size_t total = (size_t)a->length + (size_t)b->length;
|
|
71
|
-
xt_string *out = xt_string_alloc(total);
|
|
72
|
-
memcpy(out->data, a->data, a->length);
|
|
73
|
-
memcpy(out->data + a->length, b->data, b->length);
|
|
74
|
-
return XT_FROM_PTR(XT_TAG_STRING, out);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
int xt_string_equals(xt_string *a, xt_string *b) {
|
|
78
|
-
return a->length == b->length && memcmp(a->data, b->data, a->length) == 0;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/*
|
|
82
|
-
* ECMAScript number formatting.
|
|
83
|
-
*
|
|
84
|
-
* A double is rendered as the shortest decimal string that round-trips, then
|
|
85
|
-
* laid out with JavaScript's notation rules: fixed notation unless the decimal
|
|
86
|
-
* exponent is < -6 or >= 21, and a bare (unpadded, explicitly signed) exponent.
|
|
87
|
-
* The `toFixed`/`toExponential`/`toPrecision` variants reuse the same renderer.
|
|
88
|
-
*/
|
|
89
|
-
static void xt_render_decimal(int negative, const char *digits, int nd, int exp10, int expo, char *buffer, size_t size) {
|
|
90
|
-
size_t o = 0;
|
|
91
|
-
if (negative && o + 1 < size) buffer[o++] = '-';
|
|
92
|
-
if (expo) {
|
|
93
|
-
if (o + 1 < size) buffer[o++] = digits[0];
|
|
94
|
-
if (nd > 1) {
|
|
95
|
-
if (o + 1 < size) buffer[o++] = '.';
|
|
96
|
-
for (int i = 1; i < nd && o + 1 < size; i++) buffer[o++] = digits[i];
|
|
97
|
-
}
|
|
98
|
-
int written = snprintf(buffer + o, size - o, "e%c%d", exp10 < 0 ? '-' : '+', exp10 < 0 ? -exp10 : exp10);
|
|
99
|
-
if (written > 0) o += (size_t)written;
|
|
100
|
-
} else if (exp10 >= 0) {
|
|
101
|
-
int intDigits = exp10 + 1;
|
|
102
|
-
if (nd <= intDigits) {
|
|
103
|
-
for (int i = 0; i < nd && o + 1 < size; i++) buffer[o++] = digits[i];
|
|
104
|
-
for (int i = nd; i < intDigits && o + 1 < size; i++) buffer[o++] = '0';
|
|
105
|
-
} else {
|
|
106
|
-
for (int i = 0; i < intDigits && o + 1 < size; i++) buffer[o++] = digits[i];
|
|
107
|
-
if (o + 1 < size) buffer[o++] = '.';
|
|
108
|
-
for (int i = intDigits; i < nd && o + 1 < size; i++) buffer[o++] = digits[i];
|
|
109
|
-
}
|
|
110
|
-
} else {
|
|
111
|
-
if (o + 1 < size) buffer[o++] = '0';
|
|
112
|
-
if (o + 1 < size) buffer[o++] = '.';
|
|
113
|
-
for (int i = 0; i < -exp10 - 1 && o + 1 < size; i++) buffer[o++] = '0';
|
|
114
|
-
for (int i = 0; i < nd && o + 1 < size; i++) buffer[o++] = digits[i];
|
|
115
|
-
}
|
|
116
|
-
buffer[o] = '\0';
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/* Split a `%e`-formatted string into its significant digits and exponent. */
|
|
120
|
-
static void xt_parse_scientific(const char *sci, char *digits, int *nd, int *exp10) {
|
|
121
|
-
int n = 0;
|
|
122
|
-
*exp10 = 0;
|
|
123
|
-
const char *q = sci;
|
|
124
|
-
while (*q && *q != 'e' && *q != 'E') {
|
|
125
|
-
if (*q >= '0' && *q <= '9') digits[n++] = *q;
|
|
126
|
-
q++;
|
|
127
|
-
}
|
|
128
|
-
if (*q == 'e' || *q == 'E') *exp10 = atoi(q + 1);
|
|
129
|
-
*nd = n;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
void xt_number_to_js_string(double d, char *buffer, size_t size) {
|
|
133
|
-
if (isnan(d)) {
|
|
134
|
-
snprintf(buffer, size, "NaN");
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
if (isinf(d)) {
|
|
138
|
-
snprintf(buffer, size, d < 0 ? "-Infinity" : "Infinity");
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
if (d == 0.0) {
|
|
142
|
-
snprintf(buffer, size, "0");
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
int negative = d < 0;
|
|
146
|
-
double x = negative ? -d : d;
|
|
147
|
-
char sci[64];
|
|
148
|
-
for (int p = 1; p <= 17; p++) {
|
|
149
|
-
snprintf(sci, sizeof(sci), "%.*e", p - 1, x);
|
|
150
|
-
if (strtod(sci, NULL) == x) break;
|
|
151
|
-
}
|
|
152
|
-
char digits[32];
|
|
153
|
-
int nd = 0;
|
|
154
|
-
int exp10 = 0;
|
|
155
|
-
xt_parse_scientific(sci, digits, &nd, &exp10);
|
|
156
|
-
while (nd > 1 && digits[nd - 1] == '0') nd--;
|
|
157
|
-
xt_render_decimal(negative, digits, nd, exp10, exp10 < -6 || exp10 >= 21, buffer, size);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
void xt_number_to_exponential(double d, int precision, char *buffer, size_t size) {
|
|
161
|
-
if (isnan(d)) {
|
|
162
|
-
snprintf(buffer, size, "NaN");
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
if (isinf(d)) {
|
|
166
|
-
snprintf(buffer, size, d < 0 ? "-Infinity" : "Infinity");
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
int negative = d < 0;
|
|
170
|
-
double x = negative ? -d : d;
|
|
171
|
-
char sci[64];
|
|
172
|
-
if (precision < 0) {
|
|
173
|
-
/* No fractionDigits argument: use the shortest round-tripping form. */
|
|
174
|
-
for (int p = 1; p <= 17; p++) {
|
|
175
|
-
snprintf(sci, sizeof(sci), "%.*e", p - 1, x);
|
|
176
|
-
if (strtod(sci, NULL) == x) break;
|
|
177
|
-
}
|
|
178
|
-
} else {
|
|
179
|
-
snprintf(sci, sizeof(sci), "%.*e", precision, x);
|
|
180
|
-
}
|
|
181
|
-
char digits[64];
|
|
182
|
-
int nd = 0;
|
|
183
|
-
int exp10 = 0;
|
|
184
|
-
xt_parse_scientific(sci, digits, &nd, &exp10);
|
|
185
|
-
if (precision < 0) while (nd > 1 && digits[nd - 1] == '0') nd--;
|
|
186
|
-
xt_render_decimal(negative, digits, nd, exp10, 1, buffer, size);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
void xt_number_to_precision(double d, int precision, char *buffer, size_t size) {
|
|
190
|
-
if (isnan(d)) {
|
|
191
|
-
snprintf(buffer, size, "NaN");
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
if (isinf(d)) {
|
|
195
|
-
snprintf(buffer, size, d < 0 ? "-Infinity" : "Infinity");
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
int negative = d < 0;
|
|
199
|
-
double x = negative ? -d : d;
|
|
200
|
-
char sci[512];
|
|
201
|
-
snprintf(sci, sizeof(sci), "%.*e", precision - 1, x);
|
|
202
|
-
char digits[512];
|
|
203
|
-
int nd = 0;
|
|
204
|
-
int exp10 = 0;
|
|
205
|
-
xt_parse_scientific(sci, digits, &nd, &exp10);
|
|
206
|
-
xt_render_decimal(negative, digits, nd, exp10, exp10 < -6 || exp10 >= precision, buffer, size);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
void xt_number_to_fixed(double d, int precision, char *buffer, size_t size) {
|
|
210
|
-
if (isnan(d)) {
|
|
211
|
-
snprintf(buffer, size, "NaN");
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
if (isinf(d)) {
|
|
215
|
-
snprintf(buffer, size, d < 0 ? "-Infinity" : "Infinity");
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
if (fabs(d) >= 1e21) {
|
|
219
|
-
xt_number_to_js_string(d, buffer, size);
|
|
220
|
-
return;
|
|
221
|
-
}
|
|
222
|
-
int negative = d < 0;
|
|
223
|
-
double x = negative ? -d : d;
|
|
224
|
-
/* 20 guard digits let us round exactly half away from zero, which is what
|
|
225
|
-
ECMAScript specifies and what `printf`'s round-half-to-even does not. */
|
|
226
|
-
char raw[1024];
|
|
227
|
-
snprintf(raw, sizeof(raw), "%.*f", precision + 20, x);
|
|
228
|
-
const char *dot = strchr(raw, '.');
|
|
229
|
-
int intLen = dot ? (int)(dot - raw) : (int)strlen(raw);
|
|
230
|
-
int len = intLen;
|
|
231
|
-
if (precision > 0) len += 1 + precision;
|
|
232
|
-
if (len >= (int)sizeof(raw)) len = (int)sizeof(raw) - 1;
|
|
233
|
-
char work[1024];
|
|
234
|
-
memcpy(work, raw, (size_t)len);
|
|
235
|
-
work[len] = '\0';
|
|
236
|
-
/* The digit that decides rounding is the first one we dropped. With a
|
|
237
|
-
precision of zero that is the character after the decimal point. */
|
|
238
|
-
int firstDropped = precision > 0 ? len : (dot ? intLen + 1 : len);
|
|
239
|
-
if (dot && raw[firstDropped] >= '5') {
|
|
240
|
-
int i = len - 1;
|
|
241
|
-
while (i >= 0) {
|
|
242
|
-
if (work[i] == '.') {
|
|
243
|
-
i--;
|
|
244
|
-
continue;
|
|
245
|
-
}
|
|
246
|
-
if (work[i] < '9') {
|
|
247
|
-
work[i]++;
|
|
248
|
-
break;
|
|
249
|
-
}
|
|
250
|
-
work[i] = '0';
|
|
251
|
-
i--;
|
|
252
|
-
}
|
|
253
|
-
if (i < 0) {
|
|
254
|
-
memmove(work + 1, work, strlen(work) + 1);
|
|
255
|
-
work[0] = '1';
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
if (negative) snprintf(buffer, size, "-%s", work);
|
|
259
|
-
else snprintf(buffer, size, "%s", work);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/* ------------------------------------------------------------------------- */
|
|
263
|
-
/* Conversions */
|
|
264
|
-
/* ------------------------------------------------------------------------- */
|
|
265
|
-
|
|
266
|
-
int xt_truthy(xt_value v) {
|
|
267
|
-
if (XT_IS_NUMBER(v)) {
|
|
268
|
-
double d = xt_to_double(v);
|
|
269
|
-
return d != 0.0 && !isnan(d);
|
|
270
|
-
}
|
|
271
|
-
if (v == XT_UNDEFINED || v == XT_NULL) return 0;
|
|
272
|
-
if (v == XT_FALSE) return 0;
|
|
273
|
-
if (v == XT_TRUE) return 1;
|
|
274
|
-
if (XT_IS_BIGINT(v)) return XT_GET_PTR(v) != NULL && ((xt_bigint *)XT_GET_PTR(v))->sign != 0;
|
|
275
|
-
if (XT_IS_STRING(v)) return xt_as_string(v)->length != 0;
|
|
276
|
-
return 1; /* objects, arrays and functions are truthy */
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
double xt_to_number(xt_value v) {
|
|
280
|
-
if (XT_IS_NUMBER(v)) return xt_to_double(v);
|
|
281
|
-
if (v == XT_TRUE) return 1.0;
|
|
282
|
-
if (v == XT_FALSE) return 0.0;
|
|
283
|
-
if (v == XT_UNDEFINED) return NAN;
|
|
284
|
-
if (v == XT_NULL) return 0.0;
|
|
285
|
-
if (XT_IS_BIGINT(v)) return xt_bigint_to_double_value(v);
|
|
286
|
-
if (XT_IS_STRING(v)) {
|
|
287
|
-
xt_string *s = xt_as_string(v);
|
|
288
|
-
const char *begin = s->data;
|
|
289
|
-
const char *end = s->data + s->length;
|
|
290
|
-
while (begin < end && isspace((unsigned char)*begin)) begin++;
|
|
291
|
-
while (end > begin && isspace((unsigned char)end[-1])) end--;
|
|
292
|
-
size_t length = (size_t)(end - begin);
|
|
293
|
-
if (length == 0) return 0.0;
|
|
294
|
-
char stackbuf[128];
|
|
295
|
-
char *tmp = length < sizeof(stackbuf) ? stackbuf : (char *)malloc(length + 1);
|
|
296
|
-
memcpy(tmp, begin, length);
|
|
297
|
-
tmp[length] = '\0';
|
|
298
|
-
double result;
|
|
299
|
-
int base = 0;
|
|
300
|
-
if (length > 2 && tmp[0] == '0' && (tmp[1] == 'x' || tmp[1] == 'X')) base = 16;
|
|
301
|
-
else if (length > 2 && tmp[0] == '0' && (tmp[1] == 'o' || tmp[1] == 'O')) base = 8;
|
|
302
|
-
else if (length > 2 && tmp[0] == '0' && (tmp[1] == 'b' || tmp[1] == 'B')) base = 2;
|
|
303
|
-
if (base != 0) {
|
|
304
|
-
char *stop = NULL;
|
|
305
|
-
unsigned long long parsed = strtoull(tmp + 2, &stop, base);
|
|
306
|
-
result = (*stop == '\0' && stop != tmp + 2) ? (double)parsed : NAN;
|
|
307
|
-
} else {
|
|
308
|
-
char *stop = NULL;
|
|
309
|
-
result = strtod(tmp, &stop);
|
|
310
|
-
if (stop != tmp + length) result = NAN;
|
|
311
|
-
}
|
|
312
|
-
if (tmp != stackbuf) free(tmp);
|
|
313
|
-
return result;
|
|
314
|
-
}
|
|
315
|
-
return NAN;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
static xt_value xt_number_to_string_value(double d) {
|
|
319
|
-
char buffer[64];
|
|
320
|
-
xt_number_to_js_string(d, buffer, sizeof(buffer));
|
|
321
|
-
return xt_string_from_cstr(buffer);
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
xt_value xt_to_string(xt_value v) {
|
|
325
|
-
if (XT_IS_STRING(v)) return v;
|
|
326
|
-
if (XT_IS_NUMBER(v)) return xt_number_to_string_value(xt_to_double(v));
|
|
327
|
-
if (v == XT_UNDEFINED) return xt_string_from_cstr("undefined");
|
|
328
|
-
if (v == XT_NULL) return xt_string_from_cstr("null");
|
|
329
|
-
if (v == XT_TRUE) return xt_string_from_cstr("true");
|
|
330
|
-
if (v == XT_FALSE) return xt_string_from_cstr("false");
|
|
331
|
-
if (XT_IS_BIGINT(v)) return xt_bigint_to_decimal(v);
|
|
332
|
-
if (XT_IS_ARRAY(v)) {
|
|
333
|
-
xt_array *a = (xt_array *)XT_GET_PTR(v);
|
|
334
|
-
/* Join elements with commas, like Array.prototype.toString. */
|
|
335
|
-
size_t capacity = 32;
|
|
336
|
-
char *out = (char *)malloc(capacity);
|
|
337
|
-
size_t length = 0;
|
|
338
|
-
out[0] = '\0';
|
|
339
|
-
for (uint32_t i = 0; i < a->length; i++) {
|
|
340
|
-
xt_value s = xt_to_string(a->items[i]);
|
|
341
|
-
xt_string *str = xt_as_string(s);
|
|
342
|
-
if (length + str->length + 2 > capacity) {
|
|
343
|
-
capacity = (length + str->length + 2) * 2;
|
|
344
|
-
out = (char *)realloc(out, capacity);
|
|
345
|
-
}
|
|
346
|
-
if (i > 0) out[length++] = ',';
|
|
347
|
-
memcpy(out + length, str->data, str->length);
|
|
348
|
-
length += str->length;
|
|
349
|
-
out[length] = '\0';
|
|
350
|
-
}
|
|
351
|
-
xt_value result = xt_string_new(out, length);
|
|
352
|
-
free(out);
|
|
353
|
-
return result;
|
|
354
|
-
}
|
|
355
|
-
if (XT_IS_FUNCTION(v)) return xt_string_from_cstr("function () { [native code] }");
|
|
356
|
-
if (xt_is_symbol(v)) {
|
|
357
|
-
xt_throw(xt_string_from_cstr("TypeError: Cannot convert a Symbol value to a string"));
|
|
358
|
-
}
|
|
359
|
-
if (XT_IS_OBJECT(v) &&
|
|
360
|
-
((xt_object *)XT_GET_PTR(v))->header.kind == XT_OBJECT_KIND_ERROR) {
|
|
361
|
-
return xt_error_to_string(v);
|
|
362
|
-
}
|
|
363
|
-
return xt_string_from_cstr("[object Object]");
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
xt_value xt_typeof(xt_value v) {
|
|
367
|
-
if (XT_IS_NUMBER(v)) return xt_string_from_cstr("number");
|
|
368
|
-
if (XT_IS_STRING(v)) return xt_string_from_cstr("string");
|
|
369
|
-
if (v == XT_TRUE || v == XT_FALSE) return xt_string_from_cstr("boolean");
|
|
370
|
-
if (XT_IS_BIGINT(v)) return xt_string_from_cstr("bigint");
|
|
371
|
-
if (v == XT_UNDEFINED) return xt_string_from_cstr("undefined");
|
|
372
|
-
if (XT_IS_FUNCTION(v)) return xt_string_from_cstr("function");
|
|
373
|
-
if (v == XT_NULL) return xt_string_from_cstr("object");
|
|
374
|
-
if (xt_is_symbol(v)) return xt_string_from_cstr("symbol");
|
|
375
|
-
return xt_string_from_cstr("object");
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
/* ------------------------------------------------------------------------- */
|
|
379
|
-
/* Arithmetic */
|
|
380
|
-
/* ------------------------------------------------------------------------- */
|
|
381
|
-
|
|
382
|
-
static void xt_throw_mixed_bigint(void) {
|
|
383
|
-
xt_throw(xt_string_from_cstr("TypeError: Cannot mix BigInt and other types, use explicit conversions"));
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
/* ToPrimitive for the operators: arrays/objects/functions stringify (their
|
|
387
|
-
`valueOf` is the object itself, so `toString` decides). */
|
|
388
|
-
static int xt_is_object_like(xt_value v) { return XT_IS_OBJECT(v) || XT_IS_ARRAY(v) || XT_IS_FUNCTION(v); }
|
|
389
|
-
|
|
390
|
-
static xt_value xt_to_primitive(xt_value v) { return xt_is_object_like(v) ? xt_to_string(v) : v; }
|
|
391
|
-
|
|
392
|
-
xt_value xt_add(xt_value a, xt_value b) {
|
|
393
|
-
a = xt_to_primitive(a);
|
|
394
|
-
b = xt_to_primitive(b);
|
|
395
|
-
if (XT_IS_NUMBER(a) && XT_IS_NUMBER(b)) {
|
|
396
|
-
return xt_number(xt_to_double(a) + xt_to_double(b));
|
|
397
|
-
}
|
|
398
|
-
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_add(a, b);
|
|
399
|
-
/* JavaScript's `+` concatenates when either operand is a string. */
|
|
400
|
-
if (XT_IS_STRING(a) || XT_IS_STRING(b)) {
|
|
401
|
-
xt_value sa = xt_to_string(a);
|
|
402
|
-
xt_value sb = xt_to_string(b);
|
|
403
|
-
return xt_string_concat(xt_as_string(sa), xt_as_string(sb));
|
|
404
|
-
}
|
|
405
|
-
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
406
|
-
xt_throw_mixed_bigint();
|
|
407
|
-
return XT_UNDEFINED;
|
|
408
|
-
}
|
|
409
|
-
return xt_number(xt_to_number(a) + xt_to_number(b));
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
xt_value xt_sub(xt_value a, xt_value b) {
|
|
413
|
-
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_sub(a, b);
|
|
414
|
-
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
415
|
-
xt_throw_mixed_bigint();
|
|
416
|
-
return XT_UNDEFINED;
|
|
417
|
-
}
|
|
418
|
-
return xt_number(xt_to_number(a) - xt_to_number(b));
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
xt_value xt_mul(xt_value a, xt_value b) {
|
|
422
|
-
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_mul(a, b);
|
|
423
|
-
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
424
|
-
xt_throw_mixed_bigint();
|
|
425
|
-
return XT_UNDEFINED;
|
|
426
|
-
}
|
|
427
|
-
return xt_number(xt_to_number(a) * xt_to_number(b));
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
xt_value xt_div(xt_value a, xt_value b) {
|
|
431
|
-
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_div(a, b);
|
|
432
|
-
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
433
|
-
xt_throw_mixed_bigint();
|
|
434
|
-
return XT_UNDEFINED;
|
|
435
|
-
}
|
|
436
|
-
return xt_number(xt_to_number(a) / xt_to_number(b));
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
xt_value xt_mod(xt_value a, xt_value b) {
|
|
440
|
-
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_mod(a, b);
|
|
441
|
-
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
442
|
-
xt_throw_mixed_bigint();
|
|
443
|
-
return XT_UNDEFINED;
|
|
444
|
-
}
|
|
445
|
-
double x = xt_to_number(a);
|
|
446
|
-
double y = xt_to_number(b);
|
|
447
|
-
return xt_number(fmod(x, y));
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
xt_value xt_pow(xt_value a, xt_value b) {
|
|
451
|
-
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_pow(a, b);
|
|
452
|
-
return xt_number(pow(xt_to_number(a), xt_to_number(b)));
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
xt_value xt_neg(xt_value a) {
|
|
456
|
-
if (XT_IS_BIGINT(a)) return xt_bigint_neg(a);
|
|
457
|
-
return xt_number(-xt_to_number(a));
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
xt_value xt_pos(xt_value a) {
|
|
461
|
-
if (XT_IS_BIGINT(a)) return a;
|
|
462
|
-
return xt_number(xt_to_number(a));
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
int32_t xt_to_int32(xt_value v) {
|
|
466
|
-
double d = xt_to_number(v);
|
|
467
|
-
if (isnan(d) || isinf(d)) return 0;
|
|
468
|
-
return (int32_t)(uint32_t)(int64_t)d;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
xt_value xt_bit_and(xt_value a, xt_value b) {
|
|
472
|
-
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_bit_and(a, b);
|
|
473
|
-
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
474
|
-
xt_throw_mixed_bigint();
|
|
475
|
-
return XT_UNDEFINED;
|
|
476
|
-
}
|
|
477
|
-
return xt_number((double)(xt_to_int32(a) & xt_to_int32(b)));
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
xt_value xt_bit_or(xt_value a, xt_value b) {
|
|
481
|
-
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_bit_or(a, b);
|
|
482
|
-
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
483
|
-
xt_throw_mixed_bigint();
|
|
484
|
-
return XT_UNDEFINED;
|
|
485
|
-
}
|
|
486
|
-
return xt_number((double)(xt_to_int32(a) | xt_to_int32(b)));
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
xt_value xt_bit_xor(xt_value a, xt_value b) {
|
|
490
|
-
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_bit_xor(a, b);
|
|
491
|
-
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
492
|
-
xt_throw_mixed_bigint();
|
|
493
|
-
return XT_UNDEFINED;
|
|
494
|
-
}
|
|
495
|
-
return xt_number((double)(xt_to_int32(a) ^ xt_to_int32(b)));
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
xt_value xt_bit_not(xt_value a) {
|
|
499
|
-
if (XT_IS_BIGINT(a)) return xt_bigint_bit_not(a);
|
|
500
|
-
return xt_number((double)(~xt_to_int32(a)));
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
xt_value xt_shl(xt_value a, xt_value b) {
|
|
504
|
-
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_shl(a, b);
|
|
505
|
-
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
506
|
-
xt_throw_mixed_bigint();
|
|
507
|
-
return XT_UNDEFINED;
|
|
508
|
-
}
|
|
509
|
-
return xt_number((double)(int32_t)((uint32_t)xt_to_int32(a) << (xt_to_int32(b) & 31)));
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
xt_value xt_shr(xt_value a, xt_value b) {
|
|
513
|
-
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_shr(a, b);
|
|
514
|
-
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
515
|
-
xt_throw_mixed_bigint();
|
|
516
|
-
return XT_UNDEFINED;
|
|
517
|
-
}
|
|
518
|
-
return xt_number((double)(xt_to_int32(a) >> (xt_to_int32(b) & 31)));
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
xt_value xt_ushr(xt_value a, xt_value b) {
|
|
522
|
-
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
523
|
-
xt_throw(xt_string_from_cstr("TypeError: BigInts have no unsigned right shift, use >> instead"));
|
|
524
|
-
return XT_UNDEFINED;
|
|
525
|
-
}
|
|
526
|
-
return xt_number((double)(uint32_t)((uint32_t)xt_to_int32(a) >> (xt_to_int32(b) & 31)));
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
/* ------------------------------------------------------------------------- */
|
|
530
|
-
/* Comparison */
|
|
531
|
-
/* ------------------------------------------------------------------------- */
|
|
532
|
-
|
|
533
|
-
/** Mixed numeric/bigint comparison; returns -1/0/1, or 2 for unordered. */
|
|
534
|
-
static int xt_compare_numeric(xt_value a, xt_value b) {
|
|
535
|
-
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_compare(a, b);
|
|
536
|
-
if (XT_IS_BIGINT(a)) {
|
|
537
|
-
if (XT_IS_NUMBER(b)) return xt_bigint_compare_double(a, xt_to_double(b));
|
|
538
|
-
if (XT_IS_STRING(b)) {
|
|
539
|
-
double n = xt_to_number(b);
|
|
540
|
-
if (isnan(n)) return 2;
|
|
541
|
-
return xt_bigint_compare_double(a, n);
|
|
542
|
-
}
|
|
543
|
-
if (b == XT_TRUE) return xt_bigint_compare_double(a, 1.0);
|
|
544
|
-
if (b == XT_FALSE) return xt_bigint_compare_double(a, 0.0);
|
|
545
|
-
return 2;
|
|
546
|
-
}
|
|
547
|
-
if (XT_IS_BIGINT(b)) {
|
|
548
|
-
int cmp = xt_compare_numeric(b, a);
|
|
549
|
-
return cmp == 2 ? 2 : -cmp;
|
|
550
|
-
}
|
|
551
|
-
double x = xt_to_number(a);
|
|
552
|
-
double y = xt_to_number(b);
|
|
553
|
-
if (isnan(x) || isnan(y)) return 2;
|
|
554
|
-
return x < y ? -1 : (x > y ? 1 : 0);
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
xt_value xt_lt(xt_value a, xt_value b) {
|
|
558
|
-
a = xt_to_primitive(a);
|
|
559
|
-
b = xt_to_primitive(b);
|
|
560
|
-
if (XT_IS_STRING(a) && XT_IS_STRING(b)) {
|
|
561
|
-
xt_string *x = xt_as_string(a);
|
|
562
|
-
xt_string *y = xt_as_string(b);
|
|
563
|
-
size_t n = x->length < y->length ? x->length : y->length;
|
|
564
|
-
int cmp = memcmp(x->data, y->data, n);
|
|
565
|
-
if (cmp == 0) return xt_bool(x->length < y->length);
|
|
566
|
-
return xt_bool(cmp < 0);
|
|
567
|
-
}
|
|
568
|
-
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) return xt_bool(xt_compare_numeric(a, b) == -1);
|
|
569
|
-
return xt_bool(xt_to_number(a) < xt_to_number(b));
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
xt_value xt_le(xt_value a, xt_value b) {
|
|
573
|
-
a = xt_to_primitive(a);
|
|
574
|
-
b = xt_to_primitive(b);
|
|
575
|
-
if (XT_IS_STRING(a) && XT_IS_STRING(b)) {
|
|
576
|
-
xt_string *x = xt_as_string(a);
|
|
577
|
-
xt_string *y = xt_as_string(b);
|
|
578
|
-
size_t n = x->length < y->length ? x->length : y->length;
|
|
579
|
-
int cmp = memcmp(x->data, y->data, n);
|
|
580
|
-
if (cmp == 0) return xt_bool(x->length <= y->length);
|
|
581
|
-
return xt_bool(cmp < 0);
|
|
582
|
-
}
|
|
583
|
-
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
584
|
-
int cmp = xt_compare_numeric(a, b);
|
|
585
|
-
return xt_bool(cmp != 2 && cmp <= 0);
|
|
586
|
-
}
|
|
587
|
-
return xt_bool(xt_to_number(a) <= xt_to_number(b));
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
xt_value xt_gt(xt_value a, xt_value b) { return xt_lt(b, a); }
|
|
591
|
-
xt_value xt_ge(xt_value a, xt_value b) { return xt_le(b, a); }
|
|
592
|
-
|
|
593
|
-
static int xt_loose_equals(xt_value a, xt_value b) {
|
|
594
|
-
if (xt_is_symbol(a) || xt_is_symbol(b)) return a == b;
|
|
595
|
-
if (XT_IS_NUMBER(a) && XT_IS_NUMBER(b)) return xt_to_double(a) == xt_to_double(b);
|
|
596
|
-
if (XT_IS_STRING(a) && XT_IS_STRING(b)) return xt_string_equals(xt_as_string(a), xt_as_string(b));
|
|
597
|
-
if (a == b) return 1;
|
|
598
|
-
if ((a == XT_NULL && b == XT_UNDEFINED) || (a == XT_UNDEFINED && b == XT_NULL)) return 1;
|
|
599
|
-
/* Abstract equality converts an object operand to a primitive (via
|
|
600
|
-
ToPrimitive) before comparing, so `[] == 0`, `[1] == 1` and
|
|
601
|
-
`{} == "[object Object]"` are all true. */
|
|
602
|
-
if (XT_IS_OBJECT(a) || XT_IS_ARRAY(a) || XT_IS_FUNCTION(a)) {
|
|
603
|
-
if (XT_IS_OBJECT(b) || XT_IS_ARRAY(b) || XT_IS_FUNCTION(b)) return 0;
|
|
604
|
-
return xt_loose_equals(xt_to_string(a), b);
|
|
605
|
-
}
|
|
606
|
-
if (XT_IS_OBJECT(b) || XT_IS_ARRAY(b) || XT_IS_FUNCTION(b)) {
|
|
607
|
-
return xt_loose_equals(a, xt_to_string(b));
|
|
608
|
-
}
|
|
609
|
-
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
610
|
-
xt_value big = XT_IS_BIGINT(a) ? a : b;
|
|
611
|
-
xt_value other = XT_IS_BIGINT(a) ? b : a;
|
|
612
|
-
if (XT_IS_BIGINT(other)) return xt_bigint_compare(big, other) == 0;
|
|
613
|
-
if (XT_IS_NUMBER(other)) return xt_bigint_compare_double(big, xt_to_double(other)) == 0;
|
|
614
|
-
if (XT_IS_STRING(other)) {
|
|
615
|
-
int cmp = xt_compare_numeric(big, other);
|
|
616
|
-
return cmp == 0;
|
|
617
|
-
}
|
|
618
|
-
if (other == XT_TRUE) return xt_bigint_compare_double(big, 1.0) == 0;
|
|
619
|
-
if (other == XT_FALSE) return xt_bigint_compare_double(big, 0.0) == 0;
|
|
620
|
-
return 0;
|
|
621
|
-
}
|
|
622
|
-
if (XT_IS_BOOL(a)) return xt_loose_equals(xt_number(xt_to_number(a)), b);
|
|
623
|
-
if (XT_IS_BOOL(b)) return xt_loose_equals(a, xt_number(xt_to_number(b)));
|
|
624
|
-
if (XT_IS_STRING(a) && XT_IS_NUMBER(b)) return xt_to_number(a) == xt_to_double(b);
|
|
625
|
-
if (XT_IS_NUMBER(a) && XT_IS_STRING(b)) return xt_to_double(a) == xt_to_number(b);
|
|
626
|
-
return 0;
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
xt_value xt_eq(xt_value a, xt_value b) { return xt_bool(xt_loose_equals(a, b)); }
|
|
630
|
-
xt_value xt_ne(xt_value a, xt_value b) { return xt_bool(!xt_loose_equals(a, b)); }
|
|
631
|
-
|
|
632
|
-
xt_value xt_seq(xt_value a, xt_value b) {
|
|
633
|
-
if (XT_IS_NUMBER(a) && XT_IS_NUMBER(b)) return xt_bool(xt_to_double(a) == xt_to_double(b));
|
|
634
|
-
if (XT_IS_STRING(a) && XT_IS_STRING(b)) return xt_bool(xt_string_equals(xt_as_string(a), xt_as_string(b)));
|
|
635
|
-
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bool(xt_bigint_compare(a, b) == 0);
|
|
636
|
-
return xt_bool(a == b);
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
xt_value xt_sne(xt_value a, xt_value b) { return xt_bool(!xt_truthy(xt_seq(a, b))); }
|
|
640
|
-
xt_value xt_not(xt_value a) { return xt_bool(!xt_truthy(a)); }
|
|
641
|
-
|
|
20
|
+
#include "xt_values/constructors.inc"
|
|
21
|
+
#include "xt_values/strings.inc"
|
|
22
|
+
#include "xt_values/number-format.inc"
|
|
23
|
+
#include "xt_values/conversions.inc"
|
|
24
|
+
#include "xt_values/arithmetic.inc"
|
|
25
|
+
#include "xt_values/comparison.inc"
|