functionalscript 0.6.11 → 0.8.0
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/LICENSE +21 -661
- package/README.md +3 -2
- package/bnf/data/module.f.d.ts +45 -2
- package/bnf/data/module.f.js +134 -12
- package/bnf/data/test.f.d.ts +4 -0
- package/bnf/data/test.f.js +366 -9
- package/bnf/module.f.d.ts +5 -4
- package/bnf/module.f.js +1 -1
- package/bnf/testlib.f.js +1 -1
- package/dev/test.f.js +1 -1
- package/dev/tf/all.test.js +43 -0
- package/dev/{test → tf}/module.f.d.ts +4 -1
- package/dev/{test → tf}/module.f.js +56 -34
- package/dev/tf/test.f.d.ts +4 -0
- package/dev/tf/test.f.js +5 -0
- package/fsc/test.f.d.ts +5 -0
- package/fsc/test.f.js +65 -1
- package/io/module.f.d.ts +2 -1
- package/issues/test.f.d.ts +6 -1
- package/issues/test.f.js +5 -13
- package/nanvm-lib/tests/vm/test.f.d.ts +25 -0
- package/nanvm-lib/tests/vm/test.f.js +105 -0
- package/package.json +10 -9
- package/text/module.f.d.ts +0 -1
- package/text/module.f.js +4 -4
- package/bnf/djs/module.f.d.ts +0 -77
- package/bnf/djs/module.f.js +0 -207
- package/bnf/djs/test.f.d.ts +0 -8
- package/bnf/djs/test.f.js +0 -277
- package/deno/module.d.ts +0 -8
- package/deno/module.js +0 -53
- package/deno/test.js +0 -2
- /package/{deno/test.d.ts → dev/tf/all.test.d.ts} +0 -0
- /package/dev/{test → tf}/module.d.ts +0 -0
- /package/dev/{test → tf}/module.js +0 -0
- /package/djs/{test → examples}/input.f.d.ts +0 -0
- /package/djs/{test → examples}/input.f.js +0 -0
- /package/djs/{test → examples}/m.f.d.ts +0 -0
- /package/djs/{test → examples}/m.f.js +0 -0
- /package/issues/demo/{test → sample}/test.f.js +0 -0
package/bnf/module.f.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { type Array2 } from '../types/array/module.f.ts';
|
|
2
2
|
/**
|
|
3
|
-
* A range of symbols (48 bits)
|
|
3
|
+
* A range of symbols. Two 24-bit numbers are stored in one JS number (48 bits).
|
|
4
|
+
*
|
|
4
5
|
* For example: 0xBBBBBB_EEEEEE
|
|
5
|
-
* - 0xBBBBBB is the first symbol
|
|
6
|
-
* - 0xEEEEEE is the last symbol
|
|
6
|
+
* - 0xBBBBBB is the first symbol (24 bits)
|
|
7
|
+
* - 0xEEEEEE is the last symbol (24 bits)
|
|
7
8
|
*/
|
|
8
9
|
export type TerminalRange = number;
|
|
9
10
|
/** A sequence of rules. */
|
|
@@ -34,8 +35,8 @@ export declare const remove: (range: TerminalRange, removeSet: RangeVariant) =>
|
|
|
34
35
|
export type None = readonly [];
|
|
35
36
|
export declare const none: None;
|
|
36
37
|
export type Option<S> = {
|
|
37
|
-
none: None;
|
|
38
38
|
some: S;
|
|
39
|
+
none: None;
|
|
39
40
|
};
|
|
40
41
|
export declare const option: <S extends Rule>(some: S) => Option<S>;
|
|
41
42
|
export type Repeat0Plus<T> = () => Option<readonly [T, Repeat0Plus<T>]>;
|
package/bnf/module.f.js
CHANGED
package/bnf/testlib.f.js
CHANGED
|
@@ -130,8 +130,8 @@ export const deterministic = () => {
|
|
|
130
130
|
close,
|
|
131
131
|
];
|
|
132
132
|
const value = () => ({
|
|
133
|
-
object: commaJoin0Plus('{}', [string, ws, ':', ws, value]),
|
|
134
133
|
array: commaJoin0Plus('[]', value),
|
|
134
|
+
object: commaJoin0Plus('{}', [string, ws, ':', ws, value]),
|
|
135
135
|
string,
|
|
136
136
|
number,
|
|
137
137
|
true: 'true',
|
package/dev/test.f.js
CHANGED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { io } from "../../io/module.js";
|
|
2
|
+
import { loadModuleMap } from "../module.f.js";
|
|
3
|
+
import { isTest, parseTestSet } from "./module.f.js";
|
|
4
|
+
import * as nodeTest from 'node:test';
|
|
5
|
+
const isBun = typeof Bun !== 'undefined';
|
|
6
|
+
const createFramework = (fw) => (prefix, f) => fw.test(prefix, t => f((name, v) => t.test(name, v)));
|
|
7
|
+
const createBunFramework = (fw) => (prefix, f) => f((name, v) => fw.test(`${prefix}: ${name}`, v));
|
|
8
|
+
const framework = isBun ? createBunFramework(nodeTest) : createFramework(nodeTest);
|
|
9
|
+
const parse = parseTestSet(io.tryCatch);
|
|
10
|
+
const scanModule = (x) => async (subTestRunner) => {
|
|
11
|
+
let subTests = [x];
|
|
12
|
+
while (true) {
|
|
13
|
+
const [first, ...rest] = subTests;
|
|
14
|
+
if (first === undefined) {
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
17
|
+
subTests = rest;
|
|
18
|
+
//
|
|
19
|
+
const [name, value] = first;
|
|
20
|
+
const set = parse(value);
|
|
21
|
+
if (typeof set === 'function') {
|
|
22
|
+
await subTestRunner(name, () => {
|
|
23
|
+
const r = set();
|
|
24
|
+
subTests = [...subTests, [`${name}()`, r]];
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
for (const [j, y] of set) {
|
|
29
|
+
const pr = `${name}/${j}`;
|
|
30
|
+
subTests = [...subTests, [pr, y]];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const run = async () => {
|
|
36
|
+
const x = await loadModuleMap(io);
|
|
37
|
+
for (const [i, v] of Object.entries(x)) {
|
|
38
|
+
if (isTest(i)) {
|
|
39
|
+
framework(i, scanModule(['', v.default]));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
await run();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type CsiConsole } from '../../text/sgr/module.f.ts';
|
|
2
2
|
import type * as Result from '../../types/result/module.f.ts';
|
|
3
|
-
import type { Io, Performance } from '../../io/module.f.ts';
|
|
3
|
+
import type { Io, Performance, TryCatch } from '../../io/module.f.ts';
|
|
4
4
|
import { type ModuleMap } from '../module.f.ts';
|
|
5
5
|
type Log<T> = CsiConsole;
|
|
6
6
|
type Measure<T> = <R>(f: () => R) => (state: T) => readonly [R, number, T];
|
|
@@ -14,6 +14,9 @@ type Input<T> = {
|
|
|
14
14
|
readonly env: (n: string) => string | undefined;
|
|
15
15
|
};
|
|
16
16
|
export declare const isTest: (s: string) => boolean;
|
|
17
|
+
export type Test = () => unknown;
|
|
18
|
+
export type TestSet = Test | readonly (readonly [string, unknown])[];
|
|
19
|
+
export declare const parseTestSet: (t: TryCatch) => (x: unknown) => TestSet;
|
|
17
20
|
export declare const test: <T>(input: Input<T>) => readonly [number, T];
|
|
18
21
|
export declare const anyLog: (f: (s: string) => void) => (s: string) => <T>(state: T) => T;
|
|
19
22
|
export declare const measure: (p: Performance) => <R>(f: () => R) => <T>(state: T) => readonly [R, number, T];
|
|
@@ -13,49 +13,71 @@ const timeFormat = (a) => {
|
|
|
13
13
|
const e = x.substring(s);
|
|
14
14
|
return `${b}.${e} ms`;
|
|
15
15
|
};
|
|
16
|
+
export const parseTestSet = (t) => (x) => {
|
|
17
|
+
switch (typeof x) {
|
|
18
|
+
case 'function': {
|
|
19
|
+
if (x.length === 0) {
|
|
20
|
+
const xt = x;
|
|
21
|
+
if (xt.name !== 'throw') {
|
|
22
|
+
return xt;
|
|
23
|
+
}
|
|
24
|
+
// Usual tests throw on error, but if the function name is 'throw',
|
|
25
|
+
// then the test passes if it throws.
|
|
26
|
+
return () => {
|
|
27
|
+
const [tag, value] = t(xt);
|
|
28
|
+
if (tag === 'ok') {
|
|
29
|
+
throw value;
|
|
30
|
+
}
|
|
31
|
+
return value;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
case 'object': {
|
|
37
|
+
if (x !== null) {
|
|
38
|
+
return Object.entries(x);
|
|
39
|
+
}
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return [];
|
|
44
|
+
};
|
|
16
45
|
export const test = (input) => {
|
|
17
46
|
let { moduleMap, log, error, measure, tryCatch, env, state } = input;
|
|
18
47
|
const isGitHub = env('GITHUB_ACTION') !== undefined;
|
|
48
|
+
const parse = parseTestSet(tryCatch);
|
|
19
49
|
const f = ([k, v]) => {
|
|
20
50
|
const test = i => v => ([ts, state]) => {
|
|
21
51
|
const next = test(`${i}| `);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
// https://github.com/OndraM/ci-detector/blob/main/src/Ci/GitHubActions.php
|
|
33
|
-
error(`::error file=${k},line=1,title=[3]['a']()::${r}`);
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
error(`${i}() ${fgRed}error${reset}, ${timeFormat(delta)}`);
|
|
37
|
-
error(`${fgRed}${r}${reset}`);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
ts = addPass(delta)(ts);
|
|
42
|
-
log(`${i}() ${fgGreen}ok${reset}, ${timeFormat(delta)}`);
|
|
43
|
-
}
|
|
44
|
-
[ts, state] = next(r)([ts, state]);
|
|
52
|
+
const set = parse(v);
|
|
53
|
+
if (typeof set === 'function') {
|
|
54
|
+
const [[s, r], delta, state0] = measure(() => tryCatch(set))(state);
|
|
55
|
+
state = state0;
|
|
56
|
+
if (s !== 'ok') {
|
|
57
|
+
ts = addFail(delta)(ts);
|
|
58
|
+
if (isGitHub) {
|
|
59
|
+
// https://docs.github.com/en/actions/learn-github-actions/workflow-commands-for-github-actions
|
|
60
|
+
// https://github.com/OndraM/ci-detector/blob/main/src/Ci/GitHubActions.php
|
|
61
|
+
error(`::error file=${k},line=1,title=[3]['a']()::${r}`);
|
|
45
62
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (v !== null) {
|
|
50
|
-
const f = ([k, v]) => ([time, state]) => {
|
|
51
|
-
log(`${i}${k}:`);
|
|
52
|
-
[time, state] = next(v)([time, state]);
|
|
53
|
-
return [time, state];
|
|
54
|
-
};
|
|
55
|
-
[ts, state] = fold(f)([ts, state])(v instanceof Array ? entries(v) : Object.entries(v));
|
|
63
|
+
else {
|
|
64
|
+
error(`${i}() ${fgRed}error${reset}, ${timeFormat(delta)}`);
|
|
65
|
+
error(`${fgRed}${r}${reset}`);
|
|
56
66
|
}
|
|
57
|
-
break;
|
|
58
67
|
}
|
|
68
|
+
else {
|
|
69
|
+
ts = addPass(delta)(ts);
|
|
70
|
+
log(`${i}() ${fgGreen}ok${reset}, ${timeFormat(delta)}`);
|
|
71
|
+
[ts, state] = next(r)([ts, state]);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
const f = ([k, v]) => ([time, state]) => {
|
|
76
|
+
log(`${i}${k}:`);
|
|
77
|
+
[time, state] = next(v)([time, state]);
|
|
78
|
+
return [time, state];
|
|
79
|
+
};
|
|
80
|
+
[ts, state] = fold(f)([ts, state])(set);
|
|
59
81
|
}
|
|
60
82
|
return [ts, state];
|
|
61
83
|
};
|
package/dev/tf/test.f.js
ADDED
package/fsc/test.f.d.ts
CHANGED
package/fsc/test.f.js
CHANGED
|
@@ -8,11 +8,75 @@ const f = v => {
|
|
|
8
8
|
const n = one(v);
|
|
9
9
|
return s(_.init(n)[0]);
|
|
10
10
|
};
|
|
11
|
+
// this doesn't change a name of the function
|
|
12
|
+
const fn = (f, name) => ({ [name]: f }[name]);
|
|
13
|
+
const withName = (name) =>
|
|
14
|
+
// translated into one command: define a `function [name]() { return undefined }`
|
|
15
|
+
Object.getOwnPropertyDescriptor({ [name]: () => undefined }, name).value;
|
|
11
16
|
export default {
|
|
12
17
|
a: () => {
|
|
13
18
|
const x = f('1');
|
|
14
|
-
if (x
|
|
19
|
+
if (x !== '["1"]') {
|
|
15
20
|
throw x;
|
|
16
21
|
}
|
|
22
|
+
},
|
|
23
|
+
fn: () => {
|
|
24
|
+
const o = {
|
|
25
|
+
["hello world!"]: () => undefined
|
|
26
|
+
};
|
|
27
|
+
const f = o["hello world!"];
|
|
28
|
+
const { name } = f;
|
|
29
|
+
if (name !== "hello world!") {
|
|
30
|
+
throw name;
|
|
31
|
+
}
|
|
32
|
+
//
|
|
33
|
+
const f1 = { ["boring"]: () => undefined }["boring"];
|
|
34
|
+
if (f1.name !== "boring") {
|
|
35
|
+
throw f1.name;
|
|
36
|
+
}
|
|
37
|
+
//
|
|
38
|
+
const x = fn(() => undefined, "hello").name;
|
|
39
|
+
if (x !== "") {
|
|
40
|
+
throw x;
|
|
41
|
+
}
|
|
42
|
+
//
|
|
43
|
+
const m = withName("boring2").name;
|
|
44
|
+
if (m !== "boring2") {
|
|
45
|
+
throw m;
|
|
46
|
+
}
|
|
47
|
+
//
|
|
48
|
+
const a = function x() { return undefined; };
|
|
49
|
+
if (a.name !== "x") {
|
|
50
|
+
throw a.name;
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
//
|
|
54
|
+
f1: () => {
|
|
55
|
+
const m1 = () => undefined;
|
|
56
|
+
if (m1.name !== "m1") {
|
|
57
|
+
throw m1.name;
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
//
|
|
61
|
+
f2: () => {
|
|
62
|
+
const m11 = (() => undefined);
|
|
63
|
+
if (m11.name !== "m11") {
|
|
64
|
+
throw m11.name;
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
//
|
|
68
|
+
f3: () => {
|
|
69
|
+
const m2 = true ? () => undefined : () => undefined;
|
|
70
|
+
// for `bun` it is `m2`:
|
|
71
|
+
// if (m2.name !== "") { throw m2.name }
|
|
72
|
+
// see also https://github.com/oven-sh/bun/issues/20398
|
|
73
|
+
},
|
|
74
|
+
f4: () => {
|
|
75
|
+
const id = (i) => i;
|
|
76
|
+
const f = id(() => undefined);
|
|
77
|
+
// for `bun` it is `m2`:
|
|
78
|
+
if (f.name !== "") {
|
|
79
|
+
throw f.name;
|
|
80
|
+
}
|
|
17
81
|
}
|
|
18
82
|
};
|
package/io/module.f.d.ts
CHANGED
|
@@ -77,6 +77,7 @@ export type Process = {
|
|
|
77
77
|
readonly stdout: Writable;
|
|
78
78
|
readonly stderr: Writable;
|
|
79
79
|
};
|
|
80
|
+
export type TryCatch = <T>(f: () => T) => Result<T, unknown>;
|
|
80
81
|
/**
|
|
81
82
|
* Core IO operations interface providing access to system resources
|
|
82
83
|
*/
|
|
@@ -87,7 +88,7 @@ export type Io = {
|
|
|
87
88
|
readonly asyncImport: (s: string) => Promise<Module>;
|
|
88
89
|
readonly performance: Performance;
|
|
89
90
|
readonly fetch: (url: string) => Promise<Response>;
|
|
90
|
-
readonly tryCatch:
|
|
91
|
+
readonly tryCatch: TryCatch;
|
|
91
92
|
readonly asyncTryCatch: <T>(f: () => Promise<T>) => Promise<Result<T, unknown>>;
|
|
92
93
|
};
|
|
93
94
|
/**
|
package/issues/test.f.d.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
declare const _default: {
|
|
2
2
|
literal: () => void;
|
|
3
3
|
ownProperty: {
|
|
4
|
-
|
|
4
|
+
null: {
|
|
5
|
+
throw: () => PropertyDescriptor | undefined;
|
|
6
|
+
};
|
|
7
|
+
undefined: {
|
|
8
|
+
throw: () => PropertyDescriptor | undefined;
|
|
9
|
+
};
|
|
5
10
|
bool: () => void;
|
|
6
11
|
array: () => void;
|
|
7
12
|
object: {
|
package/issues/test.f.js
CHANGED
|
@@ -6,19 +6,11 @@ export default {
|
|
|
6
6
|
const m = '<html>Hello</html>';
|
|
7
7
|
},
|
|
8
8
|
ownProperty: {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
*/
|
|
16
|
-
/* // panic
|
|
17
|
-
const v = Object.getOwnPropertyDescriptor(undefined, 0)
|
|
18
|
-
if (v !== undefined) {
|
|
19
|
-
throw v
|
|
20
|
-
}
|
|
21
|
-
*/
|
|
9
|
+
null: {
|
|
10
|
+
throw: () => Object.getOwnPropertyDescriptor(null, 0),
|
|
11
|
+
},
|
|
12
|
+
undefined: {
|
|
13
|
+
throw: () => Object.getOwnPropertyDescriptor(undefined, 0),
|
|
22
14
|
},
|
|
23
15
|
bool: () => {
|
|
24
16
|
const v = at(true)('x');
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
stringCoercion: {
|
|
3
|
+
number: () => void;
|
|
4
|
+
bool: () => void;
|
|
5
|
+
null: () => void;
|
|
6
|
+
undefined: () => void;
|
|
7
|
+
bigint: () => void;
|
|
8
|
+
array: () => void;
|
|
9
|
+
func: () => void;
|
|
10
|
+
object: {
|
|
11
|
+
norm: () => void;
|
|
12
|
+
toString: () => void;
|
|
13
|
+
toStringThrow: {
|
|
14
|
+
throw: () => void;
|
|
15
|
+
};
|
|
16
|
+
toStringNotFunc: {
|
|
17
|
+
throw: () => void;
|
|
18
|
+
};
|
|
19
|
+
toStringNonPrimitive: {
|
|
20
|
+
throw: () => void;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
export default _default;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
const stringCoercion = (a) => a + '';
|
|
2
|
+
export default {
|
|
3
|
+
stringCoercion: {
|
|
4
|
+
number: () => {
|
|
5
|
+
if (stringCoercion(123) !== '123') {
|
|
6
|
+
throw [123, 'toString', '123'];
|
|
7
|
+
}
|
|
8
|
+
if (stringCoercion(-456) !== '-456') {
|
|
9
|
+
throw [-456, 'toString', '-456'];
|
|
10
|
+
}
|
|
11
|
+
if (stringCoercion(0) !== '0') {
|
|
12
|
+
throw [0, 'toString', '0'];
|
|
13
|
+
}
|
|
14
|
+
if (stringCoercion(-0) !== '0') {
|
|
15
|
+
throw [0, 'toString', '0'];
|
|
16
|
+
}
|
|
17
|
+
if (stringCoercion(1 / (-0)) !== '-Infinity') {
|
|
18
|
+
throw [0, 'toString', '-Infinity'];
|
|
19
|
+
}
|
|
20
|
+
if (stringCoercion(Infinity) !== 'Infinity') {
|
|
21
|
+
throw [Infinity, 'toString', 'Infinity'];
|
|
22
|
+
}
|
|
23
|
+
if (stringCoercion(-Infinity) !== '-Infinity') {
|
|
24
|
+
throw [-Infinity, 'toString', '-Infinity'];
|
|
25
|
+
}
|
|
26
|
+
if (stringCoercion(1 / -Infinity) !== '0') {
|
|
27
|
+
throw [-Infinity, 'toString', '0'];
|
|
28
|
+
}
|
|
29
|
+
if (stringCoercion(NaN) !== 'NaN') {
|
|
30
|
+
throw [NaN, 'toString', 'NaN'];
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
bool: () => {
|
|
34
|
+
if (stringCoercion(true) !== 'true') {
|
|
35
|
+
throw [true, 'toString', 'true'];
|
|
36
|
+
}
|
|
37
|
+
if (stringCoercion(false) !== 'false') {
|
|
38
|
+
throw [false, 'toString', 'false'];
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
null: () => {
|
|
42
|
+
if (stringCoercion(null) !== 'null') {
|
|
43
|
+
throw [null, 'toString', 'null'];
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
undefined: () => {
|
|
47
|
+
if (stringCoercion(undefined) !== 'undefined') {
|
|
48
|
+
throw [undefined, 'toString', 'undefined'];
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
bigint: () => {
|
|
52
|
+
if (stringCoercion(123n) !== '123') {
|
|
53
|
+
throw [123n, 'toString', '123'];
|
|
54
|
+
}
|
|
55
|
+
if (stringCoercion(-456n) !== '-456') {
|
|
56
|
+
throw [-456n, 'toString', '-456'];
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
array: () => {
|
|
60
|
+
const arr = [1, 2, 3];
|
|
61
|
+
if (stringCoercion(arr) !== '1,2,3') {
|
|
62
|
+
throw [arr, 'toString', '1,2,3'];
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
func: () => {
|
|
66
|
+
const func = () => 5;
|
|
67
|
+
if (typeof stringCoercion(func) !== 'string') {
|
|
68
|
+
throw [func, 'toString'];
|
|
69
|
+
}
|
|
70
|
+
// if (stringCoercion(func) !== '() => 5') { throw [func, 'toString', 'function result'] }
|
|
71
|
+
},
|
|
72
|
+
object: {
|
|
73
|
+
norm: () => {
|
|
74
|
+
const obj = { a: 1, b: 2 };
|
|
75
|
+
if (stringCoercion(obj) !== '[object Object]') {
|
|
76
|
+
throw [obj, 'toString', '[object Object]'];
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
toString: () => {
|
|
80
|
+
const x = { toString: () => 'custom string' };
|
|
81
|
+
if (stringCoercion(x) !== 'custom string') {
|
|
82
|
+
throw [x, 'toString', 'custom string'];
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
toStringThrow: {
|
|
86
|
+
throw: () => {
|
|
87
|
+
const x = { toString: () => { throw new Error('Custom error'); } };
|
|
88
|
+
stringCoercion(x);
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
toStringNotFunc: {
|
|
92
|
+
throw: () => {
|
|
93
|
+
const x = { toString: 'hello' };
|
|
94
|
+
stringCoercion(x);
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
toStringNonPrimitive: {
|
|
98
|
+
throw: () => {
|
|
99
|
+
const x = { toString: () => [] };
|
|
100
|
+
stringCoercion(x);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "functionalscript",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"**/*.js",
|
|
@@ -10,11 +10,12 @@
|
|
|
10
10
|
"scripts": {
|
|
11
11
|
"prepack": "tsc --NoEmit false",
|
|
12
12
|
"git-clean": "git clean -xf",
|
|
13
|
-
"test20": "npm run prepack && node
|
|
14
|
-
"test22": "tsc && node --experimental-strip-types
|
|
15
|
-
"test": "tsc && node
|
|
13
|
+
"test20": "npm run prepack && node --test",
|
|
14
|
+
"test22": "tsc && node --test --experimental-strip-types",
|
|
15
|
+
"test": "tsc && node --test --experimental-test-coverage --test-coverage-include=**/module.f.ts",
|
|
16
16
|
"index": "node ./dev/index/module.ts",
|
|
17
17
|
"fsc": "node ./fsc/module.ts",
|
|
18
|
+
"fst": "node ./dev/tf/module.ts",
|
|
18
19
|
"update": "npm run index && npm install"
|
|
19
20
|
},
|
|
20
21
|
"engines": {
|
|
@@ -22,14 +23,14 @@
|
|
|
22
23
|
},
|
|
23
24
|
"bin": {
|
|
24
25
|
"fsc": "fsc/module.js",
|
|
25
|
-
"fst": "dev/
|
|
26
|
+
"fst": "dev/tf/module.js"
|
|
26
27
|
},
|
|
27
28
|
"repository": {
|
|
28
29
|
"type": "git",
|
|
29
30
|
"url": "git+https://github.com/functionalscript/functionalscript.git"
|
|
30
31
|
},
|
|
31
32
|
"author": "Sergey Shandar",
|
|
32
|
-
"license": "
|
|
33
|
+
"license": "MIT",
|
|
33
34
|
"keywords": [
|
|
34
35
|
"lambda",
|
|
35
36
|
"functional-programming",
|
|
@@ -44,8 +45,8 @@
|
|
|
44
45
|
},
|
|
45
46
|
"homepage": "https://github.com/functionalscript/functionalscript#readme",
|
|
46
47
|
"devDependencies": {
|
|
47
|
-
"@types/node": "
|
|
48
|
-
"@typescript/native-preview": "
|
|
49
|
-
"typescript": "
|
|
48
|
+
"@types/node": "*",
|
|
49
|
+
"@typescript/native-preview": "*",
|
|
50
|
+
"typescript": "*"
|
|
50
51
|
}
|
|
51
52
|
}
|
package/text/module.f.d.ts
CHANGED
|
@@ -5,7 +5,6 @@ type ItemArray = readonly Item[];
|
|
|
5
5
|
type ItemThunk = () => List<Item>;
|
|
6
6
|
export type Item = string | ItemArray | ItemThunk;
|
|
7
7
|
export declare const flat: (indent: string) => (text: Block) => List<string>;
|
|
8
|
-
export declare const curly: (type: string) => (name: string) => (body: Block) => Block;
|
|
9
8
|
/**
|
|
10
9
|
* Converts a string to an UTF-8, represented as an MSB first bit vector.
|
|
11
10
|
*
|
package/text/module.f.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { msb, u8List, u8ListToVec } from "../types/bit_vec/module.f.js";
|
|
2
2
|
import { flatMap } from "../types/list/module.f.js";
|
|
3
|
-
import
|
|
3
|
+
import { fromCodePointList, toCodePointList } from "./utf8/module.f.js";
|
|
4
4
|
import { stringToCodePointList, codePointListToString } from "./utf16/module.f.js";
|
|
5
5
|
export const flat = (indent) => {
|
|
6
6
|
const f = (prefix) => {
|
|
@@ -9,18 +9,18 @@ export const flat = (indent) => {
|
|
|
9
9
|
};
|
|
10
10
|
return f('');
|
|
11
11
|
};
|
|
12
|
-
|
|
12
|
+
const u8ListToVecMsb = u8ListToVec(msb);
|
|
13
13
|
/**
|
|
14
14
|
* Converts a string to an UTF-8, represented as an MSB first bit vector.
|
|
15
15
|
*
|
|
16
16
|
* @param s The input string to be converted.
|
|
17
17
|
* @returns The resulting UTF-8 bit vector, MSB first.
|
|
18
18
|
*/
|
|
19
|
-
export const msbUtf8 = (s) =>
|
|
19
|
+
export const msbUtf8 = (s) => u8ListToVecMsb(fromCodePointList(stringToCodePointList(s)));
|
|
20
20
|
/**
|
|
21
21
|
* Converts a UTF-8 bit vector with MSB first encoding to a string.
|
|
22
22
|
*
|
|
23
23
|
* @param msbV - The UTF-8 bit vector with MSB first encoding.
|
|
24
24
|
* @returns The resulting string.
|
|
25
25
|
*/
|
|
26
|
-
export const msbUtf8ToString = (msbV) => codePointListToString(
|
|
26
|
+
export const msbUtf8ToString = (msbV) => codePointListToString(toCodePointList(u8List(msb)(msbV)));
|