functionalscript 0.6.11 → 0.7.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/bnf/data/module.f.d.ts +39 -0
- package/bnf/data/module.f.js +85 -2
- package/bnf/data/test.f.d.ts +1 -0
- package/bnf/data/test.f.js +49 -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/io/module.f.d.ts +2 -1
- package/issues/test.f.d.ts +6 -1
- package/issues/test.f.js +5 -13
- package/package.json +9 -8
- package/text/module.f.d.ts +0 -1
- package/text/module.f.js +4 -4
- 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/data/module.f.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { type CodePoint } from '../../text/utf16/module.f.ts';
|
|
2
|
+
import { type RangeMapArray } from '../../types/range_map/module.f.ts';
|
|
1
3
|
import { type Rule as FRule } from '../module.f.ts';
|
|
2
4
|
export type TerminalRange = number;
|
|
3
5
|
export type Sequence = readonly string[];
|
|
@@ -8,7 +10,44 @@ export type Variant = {
|
|
|
8
10
|
export type Rule = Variant | Sequence | TerminalRange;
|
|
9
11
|
/** The full grammar */
|
|
10
12
|
export type RuleSet = Readonly<Record<string, Rule>>;
|
|
13
|
+
type EmptyTag = string | true | undefined;
|
|
14
|
+
type DispatchRule = {
|
|
15
|
+
readonly emptyTag: EmptyTag;
|
|
16
|
+
readonly rangeMap: Dispatch;
|
|
17
|
+
};
|
|
18
|
+
type Dispatch = RangeMapArray<DispatchResult>;
|
|
19
|
+
type DispatchResult = DispatchRuleCollection | null;
|
|
20
|
+
type DispatchRuleCollection = {
|
|
21
|
+
readonly tag: string | undefined;
|
|
22
|
+
readonly rules: DispatchRule[];
|
|
23
|
+
};
|
|
24
|
+
type DispatchMap = {
|
|
25
|
+
readonly [id in string]: DispatchRule;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Represents a parsed Abstract Syntax Tree (AST) sequence.
|
|
29
|
+
*/
|
|
30
|
+
export type AstSequence = readonly (AstRule | CodePoint)[];
|
|
31
|
+
/**
|
|
32
|
+
* Represents a parsed AST rule, consisting of a rule name and its parsed sequence.
|
|
33
|
+
*/
|
|
34
|
+
export type AstRule = readonly [string, AstSequence];
|
|
35
|
+
/**
|
|
36
|
+
* Represents the remaining input after a match attempt, or `null` if no match is possible.
|
|
37
|
+
*/
|
|
38
|
+
export type Remainder = readonly CodePoint[] | null;
|
|
39
|
+
/**
|
|
40
|
+
* Represents the result of a match operation, including the parsed AST rule and the remainder of the input.
|
|
41
|
+
*/
|
|
42
|
+
export type MatchResult = readonly [AstRule, Remainder];
|
|
43
|
+
/**
|
|
44
|
+
* Represents an LL(1) parser function for matching input against grammar rules.
|
|
45
|
+
*/
|
|
46
|
+
export type Match = (name: string, s: readonly CodePoint[]) => MatchResult;
|
|
11
47
|
export declare const toData: (fr: FRule) => readonly [RuleSet, string];
|
|
48
|
+
export declare const dispatchMap: (ruleSet: RuleSet) => DispatchMap;
|
|
49
|
+
export declare const parser: (fr: FRule) => Match;
|
|
50
|
+
export {};
|
|
12
51
|
/**
|
|
13
52
|
* Either `{ variantItem: id }` or `id`.
|
|
14
53
|
*/
|
package/bnf/data/module.f.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { todo } from "../../dev/module.f.js";
|
|
1
2
|
import { stringToCodePointList } from "../../text/utf16/module.f.js";
|
|
3
|
+
import { strictEqual } from "../../types/function/operator/module.f.js";
|
|
2
4
|
import { map, toArray } from "../../types/list/module.f.js";
|
|
3
|
-
import {
|
|
5
|
+
import { rangeMap } from "../../types/range_map/module.f.js";
|
|
6
|
+
import { oneEncode, rangeDecode, } from "../module.f.js";
|
|
4
7
|
const { entries } = Object;
|
|
5
8
|
const find = (map) => (fr) => {
|
|
6
9
|
for (const [k, v] of entries(map)) {
|
|
@@ -74,7 +77,87 @@ export const toData = (fr) => {
|
|
|
74
77
|
const [, ruleSet, id] = toDataAdd({})(fr);
|
|
75
78
|
return [ruleSet, id];
|
|
76
79
|
};
|
|
77
|
-
|
|
80
|
+
const dispatchOp = rangeMap({
|
|
81
|
+
union: a => b => {
|
|
82
|
+
if (a === null) {
|
|
83
|
+
return b;
|
|
84
|
+
}
|
|
85
|
+
if (b === null) {
|
|
86
|
+
return a;
|
|
87
|
+
}
|
|
88
|
+
throw ['can not merge [', a, '][', b, ']'];
|
|
89
|
+
},
|
|
90
|
+
equal: strictEqual,
|
|
91
|
+
def: null,
|
|
92
|
+
});
|
|
93
|
+
export const dispatchMap = (ruleSet) => {
|
|
94
|
+
const addRuleToDispatch = (dr, rule) => {
|
|
95
|
+
if (dr === null)
|
|
96
|
+
return null;
|
|
97
|
+
return { tag: dr.tag, rules: [...dr.rules, rule] };
|
|
98
|
+
};
|
|
99
|
+
const addTagToDispatch = (dr, tag) => {
|
|
100
|
+
if (dr === null)
|
|
101
|
+
return null;
|
|
102
|
+
return { tag, rules: dr.rules };
|
|
103
|
+
};
|
|
104
|
+
const dispatchRule = (dm, name) => {
|
|
105
|
+
if (name in dm) {
|
|
106
|
+
return dm;
|
|
107
|
+
}
|
|
108
|
+
const rule = ruleSet[name];
|
|
109
|
+
if (typeof rule === 'number') {
|
|
110
|
+
const range = rangeDecode(rule);
|
|
111
|
+
const dispatch = dispatchOp.fromRange(range)({ tag: undefined, rules: [] });
|
|
112
|
+
const dr = { emptyTag: undefined, rangeMap: dispatch };
|
|
113
|
+
return { ...dm, [name]: dr };
|
|
114
|
+
}
|
|
115
|
+
else if (rule instanceof Array) {
|
|
116
|
+
let emptyTag = true;
|
|
117
|
+
let result = [];
|
|
118
|
+
for (const item of rule) {
|
|
119
|
+
dm = dispatchRule(dm, item);
|
|
120
|
+
const dr = dm[item];
|
|
121
|
+
if (emptyTag === true) {
|
|
122
|
+
result = toArray(dispatchOp.merge(result)(dr.rangeMap));
|
|
123
|
+
emptyTag = dr.emptyTag !== undefined ? true : undefined;
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
result = result.map(x => [addRuleToDispatch(x[0], dr), x[1]]);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const dr = { emptyTag, rangeMap: result };
|
|
130
|
+
return { ...dm, [name]: dr };
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
const entries = Object.entries(rule);
|
|
134
|
+
let result = [];
|
|
135
|
+
let emptyTag = undefined;
|
|
136
|
+
for (const [tag, item] of entries) {
|
|
137
|
+
dm = dispatchRule(dm, item);
|
|
138
|
+
const dr = dm[item];
|
|
139
|
+
if (dr.emptyTag !== undefined) {
|
|
140
|
+
emptyTag = tag;
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
const d = dr.rangeMap.map(x => [addTagToDispatch(x[0], tag), x[1]]);
|
|
144
|
+
result = toArray(dispatchOp.merge(result)(d));
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
const dr = { emptyTag, rangeMap: result };
|
|
148
|
+
return { ...dm, [name]: dr };
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
let result = {};
|
|
152
|
+
for (const k in ruleSet) {
|
|
153
|
+
result = dispatchRule(result, k);
|
|
154
|
+
}
|
|
155
|
+
return result;
|
|
156
|
+
};
|
|
157
|
+
export const parser = (fr) => {
|
|
158
|
+
const data = toData(fr);
|
|
159
|
+
return todo();
|
|
160
|
+
};
|
|
78
161
|
/**
|
|
79
162
|
* Either `{ variantItem: id }` or `id`.
|
|
80
163
|
*/
|
package/bnf/data/test.f.d.ts
CHANGED
package/bnf/data/test.f.js
CHANGED
|
@@ -2,7 +2,7 @@ import { stringify } from "../../json/module.f.js";
|
|
|
2
2
|
import { sort } from "../../types/object/module.f.js";
|
|
3
3
|
import { range } from "../module.f.js";
|
|
4
4
|
import { classic, deterministic } from "../testlib.f.js";
|
|
5
|
-
import { toData } from "./module.f.js";
|
|
5
|
+
import { dispatchMap, toData } from "./module.f.js";
|
|
6
6
|
export default {
|
|
7
7
|
toData: [
|
|
8
8
|
() => {
|
|
@@ -62,6 +62,54 @@ export default {
|
|
|
62
62
|
throw result;
|
|
63
63
|
}
|
|
64
64
|
},
|
|
65
|
+
dispatch: [
|
|
66
|
+
() => {
|
|
67
|
+
const terminalRangeRule = range('AF');
|
|
68
|
+
const data = toData(terminalRangeRule);
|
|
69
|
+
const dm = dispatchMap(data[0]);
|
|
70
|
+
const result = JSON.stringify(dm);
|
|
71
|
+
if (result != '{"":{"rangeMap":[[null,64],[{"rules":[]},70]]}}') {
|
|
72
|
+
throw result;
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
() => {
|
|
76
|
+
const stringRule = 'AB';
|
|
77
|
+
const data = toData(stringRule);
|
|
78
|
+
const dm = dispatchMap(data[0]);
|
|
79
|
+
const result = JSON.stringify(dm);
|
|
80
|
+
if (result != '{"0":{"rangeMap":[[null,64],[{"rules":[]},65]]},"1":{"rangeMap":[[null,65],[{"rules":[]},66]]},"":{"rangeMap":[[null,64],[{"rules":[{"rangeMap":[[null,65],[{"rules":[]},66]]}]},65]]}}') {
|
|
81
|
+
throw result;
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
() => {
|
|
85
|
+
const emptyRule = '';
|
|
86
|
+
const data = toData(emptyRule);
|
|
87
|
+
const dm = dispatchMap(data[0]);
|
|
88
|
+
const result = JSON.stringify(dm);
|
|
89
|
+
if (result != '{"":{"emptyTag":true,"rangeMap":[]}}') {
|
|
90
|
+
throw result;
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
() => {
|
|
94
|
+
const variantRule = { 'a': range('AA'), 'b': range('BB') };
|
|
95
|
+
const data = toData(variantRule);
|
|
96
|
+
const dm = dispatchMap(data[0]);
|
|
97
|
+
const result = JSON.stringify(dm);
|
|
98
|
+
if (result != '{"0":{"rangeMap":[[null,64],[{"rules":[]},65]]},"1":{"rangeMap":[[null,65],[{"rules":[]},66]]},"":{"rangeMap":[[null,64],[{"tag":"a","rules":[]},65],[{"tag":"b","rules":[]},66]]}}') {
|
|
99
|
+
throw result;
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
() => {
|
|
103
|
+
const emptyRule = '';
|
|
104
|
+
const variantRule = { 'e': emptyRule, 'a': range('AA') };
|
|
105
|
+
const data = toData(variantRule);
|
|
106
|
+
const dm = dispatchMap(data[0]);
|
|
107
|
+
const result = JSON.stringify(dm);
|
|
108
|
+
if (result != '{"0":{"emptyTag":true,"rangeMap":[]},"1":{"rangeMap":[[null,64],[{"rules":[]},65]]},"":{"emptyTag":"e","rangeMap":[[null,64],[{"tag":"a","rules":[]},65]]}}') {
|
|
109
|
+
throw result;
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
],
|
|
65
113
|
example: () => {
|
|
66
114
|
const grammar = {
|
|
67
115
|
space: 0x000020_000020,
|
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/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');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "functionalscript",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.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",
|
|
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,7 +23,7 @@
|
|
|
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",
|
|
@@ -44,8 +45,8 @@
|
|
|
44
45
|
},
|
|
45
46
|
"homepage": "https://github.com/functionalscript/functionalscript#readme",
|
|
46
47
|
"devDependencies": {
|
|
47
|
-
"@types/node": "^24.0
|
|
48
|
-
"@typescript/native-preview": "^7.0.0-dev.
|
|
49
|
-
"typescript": "^5.
|
|
48
|
+
"@types/node": "^24.2.0",
|
|
49
|
+
"@typescript/native-preview": "^7.0.0-dev.20250805.1",
|
|
50
|
+
"typescript": "^5.9.2"
|
|
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)));
|
package/deno/module.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
type DenoTestStep = {
|
|
2
|
-
readonly step: (name: string, f: () => void | Promise<void>) => Promise<void>;
|
|
3
|
-
};
|
|
4
|
-
type DenoFunc = (t: DenoTestStep) => void | Promise<void>;
|
|
5
|
-
type DenoArg = readonly [string, DenoFunc];
|
|
6
|
-
export type DenoTest = (...arg: DenoArg) => void;
|
|
7
|
-
declare const _default: () => Promise<void>;
|
|
8
|
-
export default _default;
|
package/deno/module.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { io } from "../io/module.js";
|
|
2
|
-
import { loadModuleMap } from "../dev/module.f.js";
|
|
3
|
-
import { isTest } from "../dev/test/module.f.js";
|
|
4
|
-
const denoTest = (x) => async (t) => {
|
|
5
|
-
let subTests = [x];
|
|
6
|
-
while (true) {
|
|
7
|
-
const [first, ...rest] = subTests;
|
|
8
|
-
if (first === undefined) {
|
|
9
|
-
break;
|
|
10
|
-
}
|
|
11
|
-
subTests = rest;
|
|
12
|
-
//
|
|
13
|
-
const [name, value] = first;
|
|
14
|
-
if (value === null) {
|
|
15
|
-
continue;
|
|
16
|
-
}
|
|
17
|
-
switch (typeof value) {
|
|
18
|
-
case "function": {
|
|
19
|
-
if (value.length === 0) {
|
|
20
|
-
const g = value.name === 'throw'
|
|
21
|
-
? () => {
|
|
22
|
-
try {
|
|
23
|
-
value();
|
|
24
|
-
throw new Error(`Expected ${name} to throw, but it did not.`);
|
|
25
|
-
}
|
|
26
|
-
catch { }
|
|
27
|
-
}
|
|
28
|
-
: () => {
|
|
29
|
-
const r = value();
|
|
30
|
-
subTests = [...subTests, [`${name}()`, r]];
|
|
31
|
-
};
|
|
32
|
-
await t.step(name, g);
|
|
33
|
-
}
|
|
34
|
-
break;
|
|
35
|
-
}
|
|
36
|
-
case "object": {
|
|
37
|
-
for (const [j, y] of Object.entries(value)) {
|
|
38
|
-
const pr = `${name}/${j}`;
|
|
39
|
-
subTests = [...subTests, [pr, y]];
|
|
40
|
-
}
|
|
41
|
-
break;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
export default async () => {
|
|
47
|
-
const x = await loadModuleMap(io);
|
|
48
|
-
for (const [i, v] of Object.entries(x)) {
|
|
49
|
-
if (isTest(i)) {
|
|
50
|
-
Deno.test(i, denoTest(['', v.default]));
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
};
|
package/deno/test.js
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|