@fable-org/fable-library-ts 2.0.0-beta.1 → 2.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Async.ts +13 -14
- package/BigInt.ts +48 -22
- package/CHANGELOG.md +14 -1
- package/Date.ts +47 -41
- package/Decimal.ts +29 -1
- package/List.ts +2 -2
- package/MapUtil.ts +3 -0
- package/Numeric.ts +8 -3
- package/Random.ts +3 -3
- package/Range.ts +6 -6
- package/String.ts +81 -10
- package/package.json +1 -1
package/Async.ts
CHANGED
|
@@ -159,12 +159,14 @@ export function sleep(millisecondsDueTime: number) {
|
|
|
159
159
|
});
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
-
export function runSynchronously(): never {
|
|
163
|
-
throw new Error("Asynchronous code cannot be run synchronously in JS");
|
|
164
|
-
}
|
|
165
|
-
|
|
166
162
|
export function start<T>(computation: Async<T>, cancellationToken?: CancellationToken) {
|
|
167
|
-
return startWithContinuations(
|
|
163
|
+
return startWithContinuations(
|
|
164
|
+
computation,
|
|
165
|
+
emptyContinuation,
|
|
166
|
+
function (err) { throw err },
|
|
167
|
+
emptyContinuation,
|
|
168
|
+
cancellationToken
|
|
169
|
+
);
|
|
168
170
|
}
|
|
169
171
|
|
|
170
172
|
export function startImmediate<T>(computation: Async<T>, cancellationToken?: CancellationToken) {
|
|
@@ -173,19 +175,16 @@ export function startImmediate<T>(computation: Async<T>, cancellationToken?: Can
|
|
|
173
175
|
|
|
174
176
|
export function startWithContinuations<T>(
|
|
175
177
|
computation: Async<T>,
|
|
176
|
-
continuation
|
|
177
|
-
exceptionContinuation
|
|
178
|
-
cancellationContinuation
|
|
178
|
+
continuation: Continuation<T>,
|
|
179
|
+
exceptionContinuation: Continuation<any>,
|
|
180
|
+
cancellationContinuation: Continuation<any>,
|
|
179
181
|
cancelToken?: CancellationToken) {
|
|
180
|
-
|
|
181
|
-
cancelToken = continuation as CancellationToken;
|
|
182
|
-
continuation = undefined;
|
|
183
|
-
}
|
|
182
|
+
|
|
184
183
|
const trampoline = new Trampoline();
|
|
185
184
|
computation({
|
|
186
185
|
onSuccess: continuation ? continuation as Continuation<T> : emptyContinuation,
|
|
187
|
-
onError: exceptionContinuation
|
|
188
|
-
onCancel: cancellationContinuation
|
|
186
|
+
onError: exceptionContinuation,
|
|
187
|
+
onCancel: cancellationContinuation,
|
|
189
188
|
cancelToken: cancelToken ? cancelToken : defaultCancellationToken,
|
|
190
189
|
trampoline,
|
|
191
190
|
});
|
package/BigInt.ts
CHANGED
|
@@ -130,20 +130,46 @@ export function toByteArray(value: bigint): number[] {
|
|
|
130
130
|
return toSignedBytes(value, isBigEndian) as any as number[];
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
export function
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
export function
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
export function
|
|
133
|
+
export function toIntN_unchecked(bits: number, x: bigint, signed: boolean): bigint {
|
|
134
|
+
return signed ? BigInt.asIntN(bits, x) : BigInt.asUintN(bits, x);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function toIntN(bits: number, x: bigint, signed: boolean): bigint {
|
|
138
|
+
let higher_bits = abs(x) >> BigInt(bits);
|
|
139
|
+
if (higher_bits !== 0n) {
|
|
140
|
+
const s = signed ? "a signed" : "an unsigned";
|
|
141
|
+
throw new Error(`Value was either too large or too small for ${s} ${bits}-bit integer.`);
|
|
142
|
+
}
|
|
143
|
+
return signed ? BigInt.asIntN(bits, x) : BigInt.asUintN(bits, x);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function toInt8(x: bigint): int8 { return Number(toIntN(8, x, true)); }
|
|
147
|
+
export function toUInt8(x: bigint): uint8 { return Number(toIntN(8, x, false)); }
|
|
148
|
+
export function toInt16(x: bigint): int16 { return Number(toIntN(16, x, true)); }
|
|
149
|
+
export function toUInt16(x: bigint): uint16 { return Number(toIntN(16, x, false)); }
|
|
150
|
+
export function toInt32(x: bigint): int32 { return Number(toIntN(32, x, true)); }
|
|
151
|
+
export function toUInt32(x: bigint): uint32 { return Number(toIntN(32, x, false)); }
|
|
152
|
+
export function toInt64(x: bigint): int64 { return toIntN(64, x, true); }
|
|
153
|
+
export function toUInt64(x: bigint): uint64 { return toIntN(64, x, false); }
|
|
154
|
+
export function toInt128(x: bigint): int128 { return toIntN(128, x, true); }
|
|
155
|
+
export function toUInt128(x: bigint): uint128 { return toIntN(128, x, false); }
|
|
156
|
+
export function toNativeInt(x: bigint): nativeint { return toIntN(64, x, true); }
|
|
157
|
+
export function toUNativeInt(x: bigint): unativeint { return toIntN(64, x, false); }
|
|
158
|
+
|
|
159
|
+
export function toInt8_unchecked(x: bigint): int8 { return Number(toIntN_unchecked(8, x, true)); }
|
|
160
|
+
export function toUInt8_unchecked(x: bigint): uint8 { return Number(toIntN_unchecked(8, x, false)); }
|
|
161
|
+
export function toInt16_unchecked(x: bigint): int16 { return Number(toIntN_unchecked(16, x, true)); }
|
|
162
|
+
export function toUInt16_unchecked(x: bigint): uint16 { return Number(toIntN_unchecked(16, x, false)); }
|
|
163
|
+
export function toInt32_unchecked(x: bigint): int32 { return Number(toIntN_unchecked(32, x, true)); }
|
|
164
|
+
export function toUInt32_unchecked(x: bigint): uint32 { return Number(toIntN_unchecked(32, x, false)); }
|
|
165
|
+
export function toInt64_unchecked(x: bigint): int64 { return toIntN_unchecked(64, x, true); }
|
|
166
|
+
export function toUInt64_unchecked(x: bigint): uint64 { return toIntN_unchecked(64, x, false); }
|
|
167
|
+
export function toInt128_unchecked(x: bigint): int128 { return toIntN_unchecked(128, x, true); }
|
|
168
|
+
export function toUInt128_unchecked(x: bigint): uint128 { return toIntN_unchecked(128, x, false); }
|
|
169
|
+
export function toNativeInt_unchecked(x: bigint): nativeint { return toIntN_unchecked(64, x, true); }
|
|
170
|
+
export function toUNativeInt_unchecked(x: bigint): unativeint { return toIntN_unchecked(64, x, false); }
|
|
171
|
+
|
|
172
|
+
export function toFloat16(x: bigint): float16 { return Number(x); }
|
|
147
173
|
export function toFloat32(x: bigint): float32 { return Number(x); }
|
|
148
174
|
export function toFloat64(x: bigint): float64 { return Number(x); }
|
|
149
175
|
|
|
@@ -191,14 +217,14 @@ export function modPow(x: bigint, e: bigint, m: bigint): bigint {
|
|
|
191
217
|
export function divRem(x: bigint, y: bigint): [bigint, bigint];
|
|
192
218
|
export function divRem(x: bigint, y: bigint, out: FSharpRef<bigint>): bigint;
|
|
193
219
|
export function divRem(x: bigint, y: bigint, out?: FSharpRef<bigint>): bigint | [bigint, bigint] {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
220
|
+
const div = x / y;
|
|
221
|
+
const rem = x % y;
|
|
222
|
+
if (out === void 0) {
|
|
223
|
+
return [div, rem];
|
|
224
|
+
} else {
|
|
225
|
+
out.contents = rem;
|
|
226
|
+
return div;
|
|
227
|
+
}
|
|
202
228
|
}
|
|
203
229
|
|
|
204
230
|
export function greatestCommonDivisor(x: bigint, y: bigint): bigint {
|
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## Unreleased
|
|
9
9
|
|
|
10
|
+
## 2.0.0-beta.2 - 2025-03-03
|
|
11
|
+
|
|
12
|
+
* [JS/TS] Fix #4049: decimal/bigint to integer conversion checks (by @ncave)
|
|
13
|
+
* [JS/TS] Fix `decimal` to `char` conversion checks (by @ManngelMaxime)
|
|
14
|
+
* [JS/TS] Propagate non-captured exception when running `Async.Start` or `Async.StartImmediate` (by @MangelMaxime)
|
|
15
|
+
* [JS/TS] Remove `Async.RunSynchronously` (by @MangelMaxime)
|
|
16
|
+
* [JS/TS] Change signature of `startWithContinuations` to always require all its arguments (by @MangelMaxime)
|
|
17
|
+
* [JS/TS] Fix short `DateTime` and `DateTimeOffset` short format strings (by @MangelMaxime)
|
|
18
|
+
* [JS/TS] Add `C` and `c` format for numeric types (by @MangelMaxime)
|
|
19
|
+
* [JS/TS] Add `B` and `b` format for numeric types (by @MangelMaxime)
|
|
20
|
+
* [JS/TS] Add `n` format for numeric types (by @MangelMaxime)
|
|
21
|
+
* [JS/TS] Fix numeric formats (by @MangelMaxime)
|
|
22
|
+
|
|
10
23
|
## 2.0.0-beta.1 - 2025-02-16
|
|
11
24
|
|
|
12
25
|
* Compiled with Fable 5.0.0-alpha.10
|
|
@@ -59,7 +72,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
59
72
|
|
|
60
73
|
* [JS/TS] Fix escaping of `{` and `}` in FormattableString (#3890) (by @roboz0r)
|
|
61
74
|
* [JS/TS] Fix `uri.Host` to return the host name without the port (by @MangelMaxime)
|
|
62
|
-
* [JS/TS] Fix TypeScript compilation by resolving type of `jsOptions` (#3894) (by @
|
|
75
|
+
* [JS/TS] Fix TypeScript compilation by resolving type of `jsOptions` (#3894) (by @MangelMaxime)
|
|
63
76
|
|
|
64
77
|
## 1.4.3 - 2024-09-04
|
|
65
78
|
|
package/Date.ts
CHANGED
|
@@ -55,7 +55,7 @@ function parseNextChar(format: string, pos: number) {
|
|
|
55
55
|
return format.charCodeAt(pos + 1);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
function parseQuotedString(format: string, pos: number)
|
|
58
|
+
function parseQuotedString(format: string, pos: number): [string, number] {
|
|
59
59
|
let beginPos = pos;
|
|
60
60
|
// Get the character used to quote the string
|
|
61
61
|
const quoteChar = format[pos];
|
|
@@ -114,9 +114,8 @@ function dateToStringWithCustomFormat(date: Date, format: string, utc: boolean)
|
|
|
114
114
|
result += shortDays[dayOfWeek(localizedDate)];
|
|
115
115
|
break;
|
|
116
116
|
case 4:
|
|
117
|
-
result += longDays[dayOfWeek(localizedDate)];
|
|
118
|
-
break;
|
|
119
117
|
default:
|
|
118
|
+
result += longDays[dayOfWeek(localizedDate)];
|
|
120
119
|
break;
|
|
121
120
|
}
|
|
122
121
|
break;
|
|
@@ -132,7 +131,9 @@ function dateToStringWithCustomFormat(date: Date, format: string, utc: boolean)
|
|
|
132
131
|
// milliseconds provided to it.
|
|
133
132
|
// This is to have the same behavior as .NET when doing:
|
|
134
133
|
// DateTime(1, 2, 3, 4, 5, 6, DateTimeKind.Utc).ToString("fffff") => 00000
|
|
135
|
-
result += (""+millisecond(localizedDate)).padEnd(tokenLength, "0");
|
|
134
|
+
result += ("" + millisecond(localizedDate)).padEnd(tokenLength, "0");
|
|
135
|
+
} else {
|
|
136
|
+
throw "Input string was not in a correct format.";
|
|
136
137
|
}
|
|
137
138
|
break;
|
|
138
139
|
case "F":
|
|
@@ -152,14 +153,14 @@ function dateToStringWithCustomFormat(date: Date, format: string, utc: boolean)
|
|
|
152
153
|
if (value != 0) {
|
|
153
154
|
result += padWithZeros(value, 3);
|
|
154
155
|
}
|
|
156
|
+
} else {
|
|
157
|
+
throw "Input string was not in a correct format.";
|
|
155
158
|
}
|
|
156
159
|
break;
|
|
157
160
|
case "g":
|
|
158
161
|
tokenLength = parseRepeatToken(format, cursorPos, "g");
|
|
159
162
|
cursorPos += tokenLength;
|
|
160
|
-
|
|
161
|
-
result += "A.D.";
|
|
162
|
-
}
|
|
163
|
+
result += "A.D.";
|
|
163
164
|
break;
|
|
164
165
|
case "h":
|
|
165
166
|
tokenLength = parseRepeatToken(format, cursorPos, "h");
|
|
@@ -170,11 +171,10 @@ function dateToStringWithCustomFormat(date: Date, format: string, utc: boolean)
|
|
|
170
171
|
result += h1Value ? h1Value : 12;
|
|
171
172
|
break;
|
|
172
173
|
case 2:
|
|
174
|
+
default:
|
|
173
175
|
const h2Value = hour(localizedDate) % 12;
|
|
174
176
|
result += padWithZeros(h2Value ? h2Value : 12, 2);
|
|
175
177
|
break;
|
|
176
|
-
default:
|
|
177
|
-
break;
|
|
178
178
|
}
|
|
179
179
|
break;
|
|
180
180
|
case "H":
|
|
@@ -185,9 +185,8 @@ function dateToStringWithCustomFormat(date: Date, format: string, utc: boolean)
|
|
|
185
185
|
result += hour(localizedDate);
|
|
186
186
|
break;
|
|
187
187
|
case 2:
|
|
188
|
-
result += padWithZeros(hour(localizedDate), 2);
|
|
189
|
-
break;
|
|
190
188
|
default:
|
|
189
|
+
result += padWithZeros(hour(localizedDate), 2);
|
|
191
190
|
break;
|
|
192
191
|
}
|
|
193
192
|
break;
|
|
@@ -219,9 +218,8 @@ function dateToStringWithCustomFormat(date: Date, format: string, utc: boolean)
|
|
|
219
218
|
result += minute(localizedDate);
|
|
220
219
|
break;
|
|
221
220
|
case 2:
|
|
222
|
-
result += padWithZeros(minute(localizedDate), 2);
|
|
223
|
-
break;
|
|
224
221
|
default:
|
|
222
|
+
result += padWithZeros(minute(localizedDate), 2);
|
|
225
223
|
break;
|
|
226
224
|
}
|
|
227
225
|
break;
|
|
@@ -239,9 +237,8 @@ function dateToStringWithCustomFormat(date: Date, format: string, utc: boolean)
|
|
|
239
237
|
result += shortMonths[month(localizedDate) - 1];
|
|
240
238
|
break;
|
|
241
239
|
case 4:
|
|
242
|
-
result += longMonths[month(localizedDate) - 1];
|
|
243
|
-
break;
|
|
244
240
|
default:
|
|
241
|
+
result += longMonths[month(localizedDate) - 1];
|
|
245
242
|
break;
|
|
246
243
|
}
|
|
247
244
|
break;
|
|
@@ -253,9 +250,8 @@ function dateToStringWithCustomFormat(date: Date, format: string, utc: boolean)
|
|
|
253
250
|
result += second(localizedDate);
|
|
254
251
|
break;
|
|
255
252
|
case 2:
|
|
256
|
-
result += padWithZeros(second(localizedDate), 2);
|
|
257
|
-
break;
|
|
258
253
|
default:
|
|
254
|
+
result += padWithZeros(second(localizedDate), 2);
|
|
259
255
|
break;
|
|
260
256
|
}
|
|
261
257
|
break;
|
|
@@ -267,9 +263,8 @@ function dateToStringWithCustomFormat(date: Date, format: string, utc: boolean)
|
|
|
267
263
|
result += localizedDate.getHours() < 12 ? "A" : "P";
|
|
268
264
|
break;
|
|
269
265
|
case 2:
|
|
270
|
-
result += localizedDate.getHours() < 12 ? "AM" : "PM";
|
|
271
|
-
break;
|
|
272
266
|
default:
|
|
267
|
+
result += localizedDate.getHours() < 12 ? "AM" : "PM";
|
|
273
268
|
break;
|
|
274
269
|
}
|
|
275
270
|
break;
|
|
@@ -283,16 +278,8 @@ function dateToStringWithCustomFormat(date: Date, format: string, utc: boolean)
|
|
|
283
278
|
case 2:
|
|
284
279
|
result += padWithZeros(localizedDate.getFullYear() % 100, 2);
|
|
285
280
|
break;
|
|
286
|
-
case 3:
|
|
287
|
-
result += padWithZeros(localizedDate.getFullYear(), 3);
|
|
288
|
-
break;
|
|
289
|
-
case 4:
|
|
290
|
-
result += padWithZeros(localizedDate.getFullYear(), 4);
|
|
291
|
-
break;
|
|
292
|
-
case 5:
|
|
293
|
-
result += padWithZeros(localizedDate.getFullYear(), 5);
|
|
294
|
-
break;
|
|
295
281
|
default:
|
|
282
|
+
result += padWithZeros(localizedDate.getFullYear(), tokenLength);
|
|
296
283
|
break;
|
|
297
284
|
}
|
|
298
285
|
break;
|
|
@@ -393,13 +380,6 @@ export function dateOffsetToString(offset: number) {
|
|
|
393
380
|
padWithZeros(minutes, 2);
|
|
394
381
|
}
|
|
395
382
|
|
|
396
|
-
export function dateToHalfUTCString(date: IDateTime, half: "first" | "second") {
|
|
397
|
-
const str = date.toISOString();
|
|
398
|
-
return half === "first"
|
|
399
|
-
? str.substring(0, str.indexOf("T"))
|
|
400
|
-
: str.substring(str.indexOf("T") + 1, str.length - 1);
|
|
401
|
-
}
|
|
402
|
-
|
|
403
383
|
function dateToISOString(d: IDateTime, utc: boolean) {
|
|
404
384
|
if (utc) {
|
|
405
385
|
return d.toISOString();
|
|
@@ -428,8 +408,10 @@ function dateToStringWithOffset(date: IDateTimeOffset, format?: string) {
|
|
|
428
408
|
return d.toISOString().replace(/\.\d+/, "").replace(/[A-Z]|\.\d+/g, " ") + dateOffsetToString((date.offset ?? 0));
|
|
429
409
|
} else if (format.length === 1) {
|
|
430
410
|
switch (format) {
|
|
431
|
-
case "D":
|
|
432
|
-
case "
|
|
411
|
+
case "D": return dateToString_D(d);
|
|
412
|
+
case "d": return dateToString_d(d);
|
|
413
|
+
case "T": return dateToString_T(toUniversalTime(d));
|
|
414
|
+
case "t": return dateToString_t(toUniversalTime(d));
|
|
433
415
|
case "O": case "o": return dateToISOStringWithOffset(d, (date.offset ?? 0));
|
|
434
416
|
default: throw new Error("Unrecognized Date print format");
|
|
435
417
|
}
|
|
@@ -438,16 +420,40 @@ function dateToStringWithOffset(date: IDateTimeOffset, format?: string) {
|
|
|
438
420
|
}
|
|
439
421
|
}
|
|
440
422
|
|
|
423
|
+
function dateToString_D(date: IDateTime) {
|
|
424
|
+
return longDays[dayOfWeek(date)]
|
|
425
|
+
+ ", " + padWithZeros(day(date), 2)
|
|
426
|
+
+ " " + longMonths[month(date) - 1]
|
|
427
|
+
+ " " + year(date);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
function dateToString_d(date: IDateTime) {
|
|
431
|
+
return padWithZeros(month(date), 2)
|
|
432
|
+
+ "/" + padWithZeros(day(date), 2)
|
|
433
|
+
+ "/" + year(date);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
function dateToString_T(date: IDateTime) {
|
|
437
|
+
return padWithZeros(hour(date), 2)
|
|
438
|
+
+ ":" + padWithZeros(minute(date), 2)
|
|
439
|
+
+ ":" + padWithZeros(second(date), 2);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
function dateToString_t(date: IDateTime) {
|
|
443
|
+
return padWithZeros(hour(date), 2)
|
|
444
|
+
+ ":" + padWithZeros(minute(date), 2);
|
|
445
|
+
}
|
|
446
|
+
|
|
441
447
|
function dateToStringWithKind(date: IDateTime, format?: string) {
|
|
442
448
|
const utc = date.kind === DateKind.UTC;
|
|
443
449
|
if (typeof format !== "string") {
|
|
444
450
|
return utc ? date.toUTCString() : date.toLocaleString();
|
|
445
451
|
} else if (format.length === 1) {
|
|
446
452
|
switch (format) {
|
|
447
|
-
case "D":
|
|
448
|
-
|
|
449
|
-
case "T":
|
|
450
|
-
|
|
453
|
+
case "D": return dateToString_D(date);
|
|
454
|
+
case "d": return dateToString_d(date);
|
|
455
|
+
case "T": return dateToString_T(date);
|
|
456
|
+
case "t": return dateToString_t(date);
|
|
451
457
|
case "O": case "o":
|
|
452
458
|
return dateToISOString(date, utc);
|
|
453
459
|
default:
|
package/Decimal.ts
CHANGED
|
@@ -2,6 +2,9 @@ import Decimal, { BigSource } from "./lib/big.js";
|
|
|
2
2
|
import { Numeric, symbol } from "./Numeric.js";
|
|
3
3
|
import { FSharpRef } from "./Types.js";
|
|
4
4
|
import { combineHashCodes } from "./Util.js";
|
|
5
|
+
import { int8, uint8, int16, uint16, int32, uint32, float16, float32, float64 } from "./Int32.js";
|
|
6
|
+
import { fromDecimal, int64, uint64, int128, uint128, nativeint, unativeint } from "./BigInt.js";
|
|
7
|
+
import * as bigInt from "./BigInt.js";
|
|
5
8
|
|
|
6
9
|
Decimal.prototype.GetHashCode = function () {
|
|
7
10
|
return combineHashCodes([this.s, this.e].concat(this.c))
|
|
@@ -139,10 +142,35 @@ export function parse(str: string): Decimal {
|
|
|
139
142
|
}
|
|
140
143
|
}
|
|
141
144
|
|
|
142
|
-
export function toNumber(x: Decimal) {
|
|
145
|
+
export function toNumber(x: Decimal): number {
|
|
143
146
|
return +x;
|
|
144
147
|
}
|
|
145
148
|
|
|
149
|
+
export function toChar(x: Decimal): string {
|
|
150
|
+
const n = toNumber(x);
|
|
151
|
+
if (n < 0 || n > 65535 || isNaN(n)) {
|
|
152
|
+
throw new Error("Value was either too large or too small for a character.");
|
|
153
|
+
}
|
|
154
|
+
return String.fromCharCode(n);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function toInt8(x: Decimal): int8 { return bigInt.toInt8(fromDecimal(x)); }
|
|
158
|
+
export function toUInt8(x: Decimal): uint8 { return bigInt.toUInt8(fromDecimal(x)); }
|
|
159
|
+
export function toInt16(x: Decimal): int16 { return bigInt.toInt16(fromDecimal(x)); }
|
|
160
|
+
export function toUInt16(x: Decimal): uint16 { return bigInt.toUInt16(fromDecimal(x)); }
|
|
161
|
+
export function toInt32(x: Decimal): int32 { return bigInt.toInt32(fromDecimal(x)); }
|
|
162
|
+
export function toUInt32(x: Decimal): uint32 { return bigInt.toUInt32(fromDecimal(x)); }
|
|
163
|
+
export function toInt64(x: Decimal): int64 { return bigInt.toInt64(fromDecimal(x)); }
|
|
164
|
+
export function toUInt64(x: Decimal): uint64 { return bigInt.toUInt64(fromDecimal(x)); }
|
|
165
|
+
export function toInt128(x: Decimal): int128 { return bigInt.toInt128(fromDecimal(x)); }
|
|
166
|
+
export function toUInt128(x: Decimal): uint128 { return bigInt.toUInt128(fromDecimal(x)); }
|
|
167
|
+
export function toNativeInt(x: Decimal): nativeint { return bigInt.toNativeInt(fromDecimal(x)); }
|
|
168
|
+
export function toUNativeInt(x: Decimal): unativeint { return bigInt.toUNativeInt(fromDecimal(x)); }
|
|
169
|
+
|
|
170
|
+
export function toFloat16(x: Decimal): float16 { return toNumber(x); }
|
|
171
|
+
export function toFloat32(x: Decimal): float32 { return toNumber(x); }
|
|
172
|
+
export function toFloat64(x: Decimal): float64 { return toNumber(x); }
|
|
173
|
+
|
|
146
174
|
function decimalToHex(dec: Uint8Array, bitSize: number) {
|
|
147
175
|
const hex = new Uint8Array(bitSize / 4 | 0);
|
|
148
176
|
let hexCount = 1;
|
package/List.ts
CHANGED
|
@@ -450,13 +450,13 @@ export function foldBack2<T1, T2, State>(folder: ((arg0: T1, arg1: T2, arg2: Sta
|
|
|
450
450
|
return foldBack2_1<T1, T2, State>(folder, toArray<T1>(xs), toArray<T2>(ys), state);
|
|
451
451
|
}
|
|
452
452
|
|
|
453
|
-
export function unfold<State, T>(
|
|
453
|
+
export function unfold<State, T>(generator: ((arg0: State) => Option<[T, State]>), state: State): FSharpList<T> {
|
|
454
454
|
const loop = (acc_mut: State, node_mut: FSharpList<T>): FSharpList<T> => {
|
|
455
455
|
loop:
|
|
456
456
|
while (true) {
|
|
457
457
|
const acc: State = acc_mut, node: FSharpList<T> = node_mut;
|
|
458
458
|
let t: FSharpList<T>;
|
|
459
|
-
const matchValue: Option<[T, State]> =
|
|
459
|
+
const matchValue: Option<[T, State]> = generator(acc);
|
|
460
460
|
if (matchValue != null) {
|
|
461
461
|
acc_mut = value_1(matchValue)[1];
|
|
462
462
|
node_mut = ((t = (new FSharpList(value_1(matchValue)[0], undefined)), (node.tail = t, t)));
|
package/MapUtil.ts
CHANGED
|
@@ -7,6 +7,7 @@ const CaseRules = {
|
|
|
7
7
|
SnakeCase: 2,
|
|
8
8
|
SnakeCaseAllCaps: 3,
|
|
9
9
|
KebabCase: 4,
|
|
10
|
+
LowerAll: 5,
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
function dashify(str: string, separator: string) {
|
|
@@ -25,6 +26,8 @@ function changeCase(str: string, caseRule: number) {
|
|
|
25
26
|
return dashify(str, "_").toUpperCase();
|
|
26
27
|
case CaseRules.KebabCase:
|
|
27
28
|
return dashify(str, "-");
|
|
29
|
+
case CaseRules.LowerAll:
|
|
30
|
+
return str.toLowerCase();
|
|
28
31
|
case CaseRules.None:
|
|
29
32
|
default:
|
|
30
33
|
return str;
|
package/Numeric.ts
CHANGED
|
@@ -18,6 +18,11 @@ export function isNumeric(x: any) {
|
|
|
18
18
|
return typeof x === "number" || typeof x === "bigint" || x?.[symbol];
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
export function isIntegral(x: Numeric) {
|
|
22
|
+
// Not perfect, because in JS we can't distinguish between 1.0 and 1
|
|
23
|
+
return typeof x === "number" && Number.isInteger(x) || typeof x === "bigint";
|
|
24
|
+
}
|
|
25
|
+
|
|
21
26
|
export function compare(x: Numeric, y: number) {
|
|
22
27
|
if (typeof x === "number") {
|
|
23
28
|
return x < y ? -1 : (x > y ? 1 : 0);
|
|
@@ -42,7 +47,7 @@ export function toFixed(x: Numeric, dp?: number) {
|
|
|
42
47
|
if (typeof x === "number") {
|
|
43
48
|
return x.toFixed(dp);
|
|
44
49
|
} else if (typeof x === "bigint") {
|
|
45
|
-
return x;
|
|
50
|
+
return x.toString();
|
|
46
51
|
} else {
|
|
47
52
|
return x[symbol]().toFixed(dp);
|
|
48
53
|
}
|
|
@@ -52,7 +57,7 @@ export function toPrecision(x: Numeric, sd?: number) {
|
|
|
52
57
|
if (typeof x === "number") {
|
|
53
58
|
return x.toPrecision(sd);
|
|
54
59
|
} else if (typeof x === "bigint") {
|
|
55
|
-
return x;
|
|
60
|
+
return x.toString();
|
|
56
61
|
} else {
|
|
57
62
|
return x[symbol]().toPrecision(sd);
|
|
58
63
|
}
|
|
@@ -77,4 +82,4 @@ export function toHex(x: Numeric) {
|
|
|
77
82
|
} else {
|
|
78
83
|
return x[symbol]().toHex();
|
|
79
84
|
}
|
|
80
|
-
}
|
|
85
|
+
}
|
package/Random.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { uint8, int32, float64 } from "./Int32.js";
|
|
2
2
|
import { class_type, TypeInfo } from "./Reflection.js";
|
|
3
|
-
import { fromFloat64, op_Addition,
|
|
3
|
+
import { fromFloat64, op_Addition, toInt32_unchecked, toFloat64, compare, int64, fromInt32, toInt64_unchecked } from "./BigInt.js";
|
|
4
4
|
import { Operators_IsNull } from "./FSharp.Core.js";
|
|
5
5
|
import { item, fill, setItem } from "./Array.js";
|
|
6
6
|
|
|
@@ -121,8 +121,8 @@ export class Seeded implements IRandom {
|
|
|
121
121
|
if (minValue > maxValue) {
|
|
122
122
|
throw new Error("minValue must be less than maxValue");
|
|
123
123
|
}
|
|
124
|
-
const range: int64 =
|
|
125
|
-
return ((compare(range,
|
|
124
|
+
const range: int64 = toInt64_unchecked(fromInt32(maxValue - minValue));
|
|
125
|
+
return ((compare(range, toInt64_unchecked(fromInt32(2147483647))) <= 0) ? (~~(Seeded__Sample(this$) * toFloat64(range)) + minValue) : ~~toInt32_unchecked(toInt64_unchecked(op_Addition(toInt64_unchecked(fromFloat64(Seeded__GetSampleForLargeRange(this$) * toFloat64(range))), toInt64_unchecked(fromInt32(minValue)))))) | 0;
|
|
126
126
|
}
|
|
127
127
|
NextDouble(): float64 {
|
|
128
128
|
const this$: Seeded = this;
|
package/Range.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { compare } from "./Util.js";
|
|
|
2
2
|
import { float64, int32 } from "./Int32.js";
|
|
3
3
|
import { Option } from "./Option.js";
|
|
4
4
|
import { unfold, delay } from "./Seq.js";
|
|
5
|
-
import { uint64,
|
|
5
|
+
import { uint64, toUInt64_unchecked, int64, toInt64_unchecked, op_Addition, fromZero } from "./BigInt.js";
|
|
6
6
|
import { decimal, op_Addition as op_Addition_1, fromParts } from "./Decimal.js";
|
|
7
7
|
|
|
8
8
|
export function makeRangeStepFunction<T>(step: T, stop: T, zero: T, add: ((arg0: T, arg1: T) => T)): ((arg0: T) => Option<[T, T]>) {
|
|
@@ -35,18 +35,18 @@ export function rangeDouble(start: float64, step: float64, stop: float64): Itera
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
export function rangeInt64(start: int64, step: int64, stop: int64): Iterable<int64> {
|
|
38
|
-
return integralRangeStep<int64>(start, step, stop, 0n, (x: int64, y: int64): int64 =>
|
|
38
|
+
return integralRangeStep<int64>(start, step, stop, 0n, (x: int64, y: int64): int64 => toInt64_unchecked(op_Addition(x, y)));
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
export function rangeUInt64(start: uint64, step: uint64, stop: uint64): Iterable<uint64> {
|
|
42
|
-
return integralRangeStep<uint64>(start, step, stop, 0n, (x: uint64, y: uint64): uint64 =>
|
|
42
|
+
return integralRangeStep<uint64>(start, step, stop, 0n, (x: uint64, y: uint64): uint64 => toUInt64_unchecked(op_Addition(x, y)));
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
export function rangeChar(start: string, stop: string): Iterable<string> {
|
|
46
46
|
const intStop: int32 = ~~stop.charCodeAt(0) | 0;
|
|
47
|
-
return delay<string>((): Iterable<string> => unfold<int32, string>((
|
|
48
|
-
if (
|
|
49
|
-
return [String.fromCharCode(
|
|
47
|
+
return delay<string>((): Iterable<string> => unfold<int32, string>((i: int32): Option<[string, int32]> => {
|
|
48
|
+
if (i <= intStop) {
|
|
49
|
+
return [String.fromCharCode(i & 0xFFFF), i + 1] as [string, int32];
|
|
50
50
|
}
|
|
51
51
|
else {
|
|
52
52
|
return undefined;
|
package/String.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { toString as dateToString } from "./Date.js";
|
|
2
|
-
import { compare as numericCompare, isNumeric, multiply, Numeric, toExponential, toFixed, toHex, toPrecision } from "./Numeric.js";
|
|
2
|
+
import { compare as numericCompare, isNumeric, isIntegral, multiply, Numeric, toExponential, toFixed, toHex, toPrecision } from "./Numeric.js";
|
|
3
3
|
import { escape } from "./RegExp.js";
|
|
4
4
|
import { toString } from "./Types.js";
|
|
5
5
|
|
|
@@ -295,6 +295,19 @@ export function fsFormat(str: string) {
|
|
|
295
295
|
};
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
+
function splitIntAndDecimalPart(value: string) {
|
|
299
|
+
let [repInt, repDecimal] = value.split(".");
|
|
300
|
+
repDecimal === undefined && (repDecimal = "");
|
|
301
|
+
return {
|
|
302
|
+
integral: repInt,
|
|
303
|
+
decimal: repDecimal
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function thousandSeparate(value: string) {
|
|
308
|
+
return value.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
309
|
+
}
|
|
310
|
+
|
|
298
311
|
export function format(str: string | object, ...args: any[]) {
|
|
299
312
|
let str2: string;
|
|
300
313
|
if (typeof str === "object") {
|
|
@@ -310,31 +323,89 @@ export function format(str: string | object, ...args: any[]) {
|
|
|
310
323
|
throw new Error("Index must be greater or equal to zero and less than the arguments' length.")
|
|
311
324
|
}
|
|
312
325
|
let rep = args[idx];
|
|
326
|
+
let parts;
|
|
313
327
|
if (isNumeric(rep)) {
|
|
314
|
-
precision = precision ==
|
|
328
|
+
precision = precision == "" ? null : parseInt(precision, 10);
|
|
315
329
|
switch (format) {
|
|
330
|
+
case "b": case "B":
|
|
331
|
+
if (!isIntegral(rep)) {
|
|
332
|
+
throw new Error("Format specifier was invalid.");
|
|
333
|
+
}
|
|
334
|
+
rep = (rep >>> 0).toString(2).replace(/^0+/, "").padStart(precision || 1, "0");
|
|
335
|
+
break;
|
|
336
|
+
case "c": case "C":
|
|
337
|
+
const isNegative = isLessThan(rep, 0);
|
|
338
|
+
if (isLessThan(rep, 0)) {
|
|
339
|
+
rep = multiply(rep, -1);
|
|
340
|
+
}
|
|
341
|
+
precision = precision == null ? 2 : precision;
|
|
342
|
+
rep = toFixed(rep, precision);
|
|
343
|
+
parts = splitIntAndDecimalPart(rep);
|
|
344
|
+
rep = "¤" + thousandSeparate(parts.integral) + "." + padRight(parts.decimal, precision, "0");
|
|
345
|
+
if (isNegative) {
|
|
346
|
+
rep = "(" + rep + ")";
|
|
347
|
+
}
|
|
348
|
+
break;
|
|
349
|
+
case "d": case "D":
|
|
350
|
+
if (!isIntegral(rep)) {
|
|
351
|
+
throw new Error("Format specifier was invalid.");
|
|
352
|
+
}
|
|
353
|
+
rep = String(rep);
|
|
354
|
+
if (precision != null) {
|
|
355
|
+
if (rep.startsWith("-")) {
|
|
356
|
+
rep = "-" + padLeft(rep.substring(1), precision, "0");
|
|
357
|
+
} else {
|
|
358
|
+
rep = padLeft(rep, precision, "0");
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
break;
|
|
362
|
+
case "e": case "E":
|
|
363
|
+
rep = precision != null ? toExponential(rep, precision) : toExponential(rep);
|
|
364
|
+
break;
|
|
316
365
|
case "f": case "F":
|
|
317
366
|
precision = precision != null ? precision : 2;
|
|
318
367
|
rep = toFixed(rep, precision);
|
|
368
|
+
if (precision > 0) {
|
|
369
|
+
parts = splitIntAndDecimalPart(rep);
|
|
370
|
+
rep = parts.integral + "." + padRight(parts.decimal, precision, "0");
|
|
371
|
+
}
|
|
319
372
|
break;
|
|
320
373
|
case "g": case "G":
|
|
321
374
|
rep = precision != null ? toPrecision(rep, precision) : toPrecision(rep);
|
|
375
|
+
// TODO: Check why some numbers are formatted with decimal part
|
|
376
|
+
rep = trimEnd(trimEnd(rep, "0"), ".");
|
|
322
377
|
break;
|
|
323
|
-
case "
|
|
324
|
-
|
|
378
|
+
case "n": case "N":
|
|
379
|
+
precision = precision != null ? precision : 2;
|
|
380
|
+
rep = toFixed(rep, precision);
|
|
381
|
+
parts = splitIntAndDecimalPart(rep);
|
|
382
|
+
rep = thousandSeparate(parts.integral) + "." + padRight(parts.decimal, precision, "0");
|
|
325
383
|
break;
|
|
326
384
|
case "p": case "P":
|
|
327
385
|
precision = precision != null ? precision : 2;
|
|
328
|
-
rep = toFixed(multiply(rep, 100), precision)
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
rep = precision != null ? padLeft(String(rep), precision, "0") : String(rep);
|
|
386
|
+
rep = toFixed(multiply(rep, 100), precision)
|
|
387
|
+
parts = splitIntAndDecimalPart(rep);
|
|
388
|
+
rep = thousandSeparate(parts.integral) + "." + padRight(parts.decimal, precision, "0") + " %";
|
|
332
389
|
break;
|
|
390
|
+
case "r": case "R":
|
|
391
|
+
throw new Error("The round-trip format is not supported by Fable");
|
|
333
392
|
case "x": case "X":
|
|
334
|
-
|
|
335
|
-
|
|
393
|
+
if (!isIntegral(rep)) {
|
|
394
|
+
throw new Error("Format specifier was invalid.");
|
|
395
|
+
}
|
|
396
|
+
precision = precision != null ? precision : 2;
|
|
397
|
+
rep = padLeft(toHex(rep), precision, "0");
|
|
398
|
+
if (format === "X") {
|
|
399
|
+
rep = rep.toUpperCase();
|
|
400
|
+
}
|
|
336
401
|
break;
|
|
337
402
|
default:
|
|
403
|
+
// If we have format and were not able to handle it throw
|
|
404
|
+
// See: https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings#standard-format-specifiers
|
|
405
|
+
if (format) {
|
|
406
|
+
throw new Error("Format specifier was invalid.");
|
|
407
|
+
}
|
|
408
|
+
|
|
338
409
|
if (pattern) {
|
|
339
410
|
let sign = "";
|
|
340
411
|
rep = (pattern as string).replace(/([0#,]+)(\.[0#]+)?/, (_, intPart: string, decimalPart: string) => {
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"private": false,
|
|
4
4
|
"type": "module",
|
|
5
5
|
"name": "@fable-org/fable-library-ts",
|
|
6
|
-
"version": "2.0.0-beta.
|
|
6
|
+
"version": "2.0.0-beta.2",
|
|
7
7
|
"description": "Core library used by F# projects compiled with fable.io",
|
|
8
8
|
"author": "Fable Contributors",
|
|
9
9
|
"license": "MIT",
|