functionalscript 0.4.3 → 0.5.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/README.md +1 -1
- package/bnf/data/module.f.d.ts +12 -0
- package/bnf/data/module.f.js +85 -0
- package/bnf/data/test.f.d.ts +4 -0
- package/bnf/data/test.f.js +8 -0
- package/bnf/module.f.d.ts +55 -0
- package/bnf/module.f.js +98 -0
- package/bnf/test.f.d.ts +4 -0
- package/bnf/test.f.js +7 -0
- package/bnf/testlib.f.d.ts +3 -0
- package/bnf/{tag/test.f.js → testlib.f.js} +48 -44
- package/crypto/secp/module.f.d.ts +8 -0
- package/crypto/secp/module.f.js +30 -0
- package/crypto/secp/test.f.d.ts +3 -0
- package/crypto/secp/test.f.js +67 -3
- package/djs/ast/module.f.d.ts +10 -0
- package/djs/ast/module.f.js +52 -0
- package/djs/ast/test.f.d.ts +8 -0
- package/djs/ast/test.f.js +41 -0
- package/djs/module.f.d.ts +7 -15
- package/djs/module.f.js +23 -60
- package/djs/parser/module.f.d.ts +9 -9
- package/djs/parser/module.f.js +7 -8
- package/djs/parser/test.f.js +97 -97
- package/djs/serializer/module.f.d.ts +8 -4
- package/djs/serializer/module.f.js +9 -27
- package/djs/{test.f.d.ts → serializer/test.f.d.ts} +3 -3
- package/djs/{test.f.js → serializer/test.f.js} +13 -13
- package/djs/tokenizer/test.f.js +2 -2
- package/djs/transpiler/module.f.d.ts +15 -0
- package/djs/transpiler/module.f.js +58 -0
- package/djs/transpiler/test.f.d.ts +8 -0
- package/djs/transpiler/test.f.js +74 -0
- package/fsc.js +4 -0
- package/io/module.f.d.ts +17 -0
- package/io/node-io.js +7 -0
- package/io/virtual-io.f.d.ts +3 -0
- package/io/virtual-io.f.js +14 -0
- package/js/tokenizer/test.f.js +2 -2
- package/json/module.f.d.ts +2 -1
- package/json/tokenizer/test.f.js +2 -2
- package/nanvm-lib/tests/test.f.js +4 -4
- package/package.json +16 -9
- package/path/module.f.d.ts +2 -0
- package/path/module.f.js +31 -0
- package/path/test.f.d.ts +5 -0
- package/path/test.f.js +49 -0
- package/text/sgr/module.f.d.ts +19 -1
- package/text/sgr/module.f.js +26 -1
- package/text/sgr/test.f.d.ts +2 -0
- package/text/sgr/test.f.js +8 -0
- package/text/utf16/module.f.d.ts +116 -0
- package/text/utf16/module.f.js +285 -0
- package/text/utf16/test.f.d.ts +4 -0
- package/text/utf16/test.f.js +28 -0
- package/types/monoid/module.f.d.ts +3 -1
- package/types/monoid/module.f.js +2 -0
- package/types/object/module.f.d.ts +18 -0
- package/types/object/module.f.js +1 -1
- package/bnf/tag/module.f.d.ts +0 -30
- package/bnf/tag/module.f.js +0 -37
- /package/{bnf/tag/test.f.d.ts → io/module.f.js} +0 -0
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ Learn more about
|
|
|
19
19
|
- [Purely Functional Programming in JavaScript](https://blog.bitsrc.io/purely-functional-programming-in-javascript-91114b1b2dff?sk=5f7132e56902f38fcf4c6164bfa681ed),
|
|
20
20
|
- [FunctionalScript and I/O](https://medium.com/@sergeyshandar/functionalscript-5cf817345376?sk=30b32189a81d1a2dad16c2244f32328d).
|
|
21
21
|
|
|
22
|
-
This repository is a [monorepo](https://en.wikipedia.org/wiki/Monorepo) and distributted under
|
|
22
|
+
This repository is a [monorepo](https://en.wikipedia.org/wiki/Monorepo) and distributted under [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.en.html#license-text). Let us know if you need another license by sending an [email](mailto:sergey.oss@proton.me).
|
|
23
23
|
|
|
24
24
|
## Vision
|
|
25
25
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Rule as FRule } from '../module.f.ts';
|
|
2
|
+
export type TerminalRange = number;
|
|
3
|
+
export type Sequence = readonly string[];
|
|
4
|
+
export type Variant = {
|
|
5
|
+
readonly [k in string]: string;
|
|
6
|
+
};
|
|
7
|
+
export type Rule = Variant | Sequence | TerminalRange;
|
|
8
|
+
export type RuleSet = Readonly<Record<string, Rule>>;
|
|
9
|
+
export declare const toData: (fr: FRule) => readonly [RuleSet, string];
|
|
10
|
+
/**
|
|
11
|
+
* Either `{ variantItem: id }` or `id`.
|
|
12
|
+
*/
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { stringToCodePointList } from "../../text/utf16/module.f.js";
|
|
2
|
+
import { toArray } from "../../types/list/module.f.js";
|
|
3
|
+
const { entries } = Object;
|
|
4
|
+
const find = (map) => (fr) => {
|
|
5
|
+
for (const [k, v] of entries(map)) {
|
|
6
|
+
if (v === fr) {
|
|
7
|
+
return k;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
return undefined;
|
|
11
|
+
};
|
|
12
|
+
const newName = (map, name) => {
|
|
13
|
+
let i = 0;
|
|
14
|
+
let result = name;
|
|
15
|
+
while (result in map) {
|
|
16
|
+
result = name + i;
|
|
17
|
+
++i;
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
const sequence = (list) => map => {
|
|
22
|
+
let result = [];
|
|
23
|
+
let set = {};
|
|
24
|
+
for (const fr of list) {
|
|
25
|
+
const [map1, set1, id] = toDataAdd(map)(fr);
|
|
26
|
+
map = map1;
|
|
27
|
+
set = { ...set, ...set1 };
|
|
28
|
+
result = [...result, id];
|
|
29
|
+
}
|
|
30
|
+
return [map, set, result];
|
|
31
|
+
};
|
|
32
|
+
const variant = (fr) => map => {
|
|
33
|
+
let set = {};
|
|
34
|
+
let rule = {};
|
|
35
|
+
for (const [k, v] of entries(fr)) {
|
|
36
|
+
const [m1, s, id] = toDataAdd(map)(v);
|
|
37
|
+
map = m1;
|
|
38
|
+
set = { ...set, ...s };
|
|
39
|
+
rule = { ...rule, [k]: id };
|
|
40
|
+
}
|
|
41
|
+
return [map, set, rule];
|
|
42
|
+
};
|
|
43
|
+
const data = (dr) => {
|
|
44
|
+
switch (typeof dr) {
|
|
45
|
+
case 'string': {
|
|
46
|
+
return sequence(toArray(stringToCodePointList(dr)));
|
|
47
|
+
}
|
|
48
|
+
case 'number':
|
|
49
|
+
return m => [m, {}, dr];
|
|
50
|
+
default:
|
|
51
|
+
if (dr instanceof Array) {
|
|
52
|
+
return sequence(dr);
|
|
53
|
+
}
|
|
54
|
+
return variant(dr);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
const toDataAdd = (map) => (fr) => {
|
|
58
|
+
{
|
|
59
|
+
const id = find(map)(fr);
|
|
60
|
+
if (id !== undefined) {
|
|
61
|
+
return [map, {}, id];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const [dr, tmpId] = typeof fr === 'function' ? [fr(), fr.name] : [fr, ''];
|
|
65
|
+
const newRule = data(dr);
|
|
66
|
+
const id = newName(map, tmpId);
|
|
67
|
+
const map1 = { ...map, [id]: fr };
|
|
68
|
+
const [map2, set, rule] = newRule(map1);
|
|
69
|
+
return [map2, { ...set, [id]: rule }, id];
|
|
70
|
+
};
|
|
71
|
+
export const toData = (fr) => {
|
|
72
|
+
const [, ruleSet, id] = toDataAdd({})(fr);
|
|
73
|
+
return [ruleSet, id];
|
|
74
|
+
};
|
|
75
|
+
// type Dispatch = RangeMapArray<string>;
|
|
76
|
+
/**
|
|
77
|
+
* Either `{ variantItem: id }` or `id`.
|
|
78
|
+
*/
|
|
79
|
+
/*
|
|
80
|
+
type DispatchRule = SingleProperty<> | string
|
|
81
|
+
|
|
82
|
+
type Dispatch = RangeMapArray<DispatchRule>
|
|
83
|
+
|
|
84
|
+
type DispatchMap = { readonly[id in string]: Dispatch }
|
|
85
|
+
*/
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type Array2 } from '../types/array/module.f.ts';
|
|
2
|
+
export type TerminalRange = number;
|
|
3
|
+
export type Sequence = readonly Rule[];
|
|
4
|
+
export type Variant = {
|
|
5
|
+
readonly [k in string]: Rule;
|
|
6
|
+
};
|
|
7
|
+
export type DataRule = Variant | Sequence | TerminalRange | string;
|
|
8
|
+
export type LazyRule = () => DataRule;
|
|
9
|
+
export type Rule = DataRule | LazyRule;
|
|
10
|
+
export declare const max: string;
|
|
11
|
+
export declare const rangeEncode: (a: number, b: number) => TerminalRange;
|
|
12
|
+
export declare const oneEncode: (a: number) => TerminalRange;
|
|
13
|
+
export declare const rangeDecode: (r: number) => Array2<number>;
|
|
14
|
+
export declare const toSequence: (s: string) => readonly TerminalRange[];
|
|
15
|
+
export declare const str: (s: string) => readonly TerminalRange[] | TerminalRange;
|
|
16
|
+
export declare const set: (s: string) => RangeVariant;
|
|
17
|
+
export declare const range: (ab: string) => TerminalRange;
|
|
18
|
+
/**
|
|
19
|
+
* A set of terminal ranges compatible with the `Variant` rule.
|
|
20
|
+
*/
|
|
21
|
+
export type RangeVariant = {
|
|
22
|
+
readonly [k in string]: TerminalRange;
|
|
23
|
+
};
|
|
24
|
+
export declare const rangeToId: (r: TerminalRange) => string;
|
|
25
|
+
export declare const remove: (range: TerminalRange, removeSet: RangeVariant) => RangeVariant;
|
|
26
|
+
export type None = readonly [];
|
|
27
|
+
export declare const none: None;
|
|
28
|
+
export type Option<S> = {
|
|
29
|
+
none: None;
|
|
30
|
+
some: S;
|
|
31
|
+
};
|
|
32
|
+
export declare const option: <S extends Rule>(some: S) => Option<S>;
|
|
33
|
+
export type Repeat0Plus<T> = () => Option<readonly [T, Repeat0Plus<T>]>;
|
|
34
|
+
/**
|
|
35
|
+
* Repeat zero or more times.
|
|
36
|
+
*
|
|
37
|
+
* https://english.stackexchange.com/questions/506480/single-word-quantifiers-for-zero-or-more-like-cardinalities
|
|
38
|
+
* - zero or more - any, 0Plus
|
|
39
|
+
* - one or more - several, 1Plus
|
|
40
|
+
*
|
|
41
|
+
* Also see: https://arbs.nzcer.org.nz/types-numbers
|
|
42
|
+
*/
|
|
43
|
+
export declare const repeat0Plus: <T extends Rule>(some: T) => Repeat0Plus<T>;
|
|
44
|
+
export type Repeat1Plus<T> = readonly [T, Repeat0Plus<T>];
|
|
45
|
+
/**
|
|
46
|
+
* Repeat one or more times.
|
|
47
|
+
*/
|
|
48
|
+
export declare const repeat1Plus: <T extends Rule>(some: T) => Repeat1Plus<T>;
|
|
49
|
+
export type Join1Plus<T, S> = readonly [T, Repeat0Plus<readonly [S, T]>];
|
|
50
|
+
export declare const join1Plus: <T extends Rule, S extends Rule>(some: T, separator: S) => Join1Plus<T, S>;
|
|
51
|
+
export type Join0Plus<T, S> = Option<readonly [T, Repeat0Plus<readonly [S, T]>]>;
|
|
52
|
+
export declare const join0Plus: <T extends Rule, S extends Rule>(some: T, separator: S) => Rule;
|
|
53
|
+
export type Repeat<T> = readonly T[];
|
|
54
|
+
export declare const repeat: (n: number) => <T extends Rule>(some: T) => Repeat<T>;
|
|
55
|
+
export declare const isEmpty: (rule: Rule) => boolean;
|
package/bnf/module.f.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { codePointListToString, stringToCodePointList } from "../text/utf16/module.f.js";
|
|
2
|
+
import { isArray2 } from "../types/array/module.f.js";
|
|
3
|
+
import { map, toArray, repeat as listRepeat } from "../types/list/module.f.js";
|
|
4
|
+
//
|
|
5
|
+
const { fromEntries, values } = Object;
|
|
6
|
+
const { fromCodePoint } = String;
|
|
7
|
+
/**
|
|
8
|
+
* Two 24 bit numbers can be fit into one JS number (53 bit).
|
|
9
|
+
*/
|
|
10
|
+
const offset = 24;
|
|
11
|
+
const mask = (1 << offset) - 1;
|
|
12
|
+
const isValid = (r) => r >= 0 && r <= mask;
|
|
13
|
+
export const max = codePointListToString([0x10FFFF]);
|
|
14
|
+
export const rangeEncode = (a, b) => {
|
|
15
|
+
if (!isValid(a) || !isValid(b) || a > b) {
|
|
16
|
+
throw `Invalid range ${a} ${b}.`;
|
|
17
|
+
}
|
|
18
|
+
return (a << offset) | b;
|
|
19
|
+
};
|
|
20
|
+
export const oneEncode = (a) => rangeEncode(a, a);
|
|
21
|
+
export const rangeDecode = (r) => [r >> offset, r & mask];
|
|
22
|
+
const mapOneEncode = map(oneEncode);
|
|
23
|
+
export const toSequence = (s) => toArray(mapOneEncode(stringToCodePointList(s)));
|
|
24
|
+
export const str = (s) => {
|
|
25
|
+
const x = toSequence(s);
|
|
26
|
+
return x.length === 1 ? x[0] : x;
|
|
27
|
+
};
|
|
28
|
+
const mapEntry = map((v) => [fromCodePoint(v), oneEncode(v)]);
|
|
29
|
+
export const set = (s) => fromEntries(toArray(mapEntry(stringToCodePointList(s))));
|
|
30
|
+
export const range = (ab) => {
|
|
31
|
+
const a = toArray(stringToCodePointList(ab));
|
|
32
|
+
if (!isArray2(a)) {
|
|
33
|
+
throw `Invalid range ${ab}.`;
|
|
34
|
+
}
|
|
35
|
+
return rangeEncode(...a);
|
|
36
|
+
};
|
|
37
|
+
export const rangeToId = (r) => {
|
|
38
|
+
const ab = rangeDecode(r);
|
|
39
|
+
const [a, b] = ab;
|
|
40
|
+
const cp = a === b ? [a] : ab;
|
|
41
|
+
return fromCodePoint(...cp);
|
|
42
|
+
};
|
|
43
|
+
const rangeToEntry = (r) => [rangeToId(r), r];
|
|
44
|
+
const toVariantRangeSet = (r) => fromEntries(r.map(rangeToEntry));
|
|
45
|
+
const removeOne = (list, ab) => {
|
|
46
|
+
const [a, b] = rangeDecode(ab);
|
|
47
|
+
let result = [];
|
|
48
|
+
for (const ab0 of list) {
|
|
49
|
+
const [a0, b0] = rangeDecode(ab0);
|
|
50
|
+
if (a0 < a) {
|
|
51
|
+
// [a0
|
|
52
|
+
// ]a
|
|
53
|
+
result = [...result, rangeEncode(a0, Math.min(b0, a - 1))];
|
|
54
|
+
}
|
|
55
|
+
if (b < b0) {
|
|
56
|
+
// b0]
|
|
57
|
+
// b[
|
|
58
|
+
result = [...result, rangeEncode(Math.max(b + 1, a0), b0)];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return result;
|
|
62
|
+
};
|
|
63
|
+
export const remove = (range, removeSet) => {
|
|
64
|
+
let result = [range];
|
|
65
|
+
for (const r of values(removeSet)) {
|
|
66
|
+
result = removeOne(result, r);
|
|
67
|
+
}
|
|
68
|
+
return toVariantRangeSet(result);
|
|
69
|
+
};
|
|
70
|
+
export const none = [];
|
|
71
|
+
export const option = (some) => ({
|
|
72
|
+
none,
|
|
73
|
+
some,
|
|
74
|
+
});
|
|
75
|
+
/**
|
|
76
|
+
* Repeat zero or more times.
|
|
77
|
+
*
|
|
78
|
+
* https://english.stackexchange.com/questions/506480/single-word-quantifiers-for-zero-or-more-like-cardinalities
|
|
79
|
+
* - zero or more - any, 0Plus
|
|
80
|
+
* - one or more - several, 1Plus
|
|
81
|
+
*
|
|
82
|
+
* Also see: https://arbs.nzcer.org.nz/types-numbers
|
|
83
|
+
*/
|
|
84
|
+
export const repeat0Plus = (some) => {
|
|
85
|
+
const r = () => option([some, r]);
|
|
86
|
+
return r;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Repeat one or more times.
|
|
90
|
+
*/
|
|
91
|
+
export const repeat1Plus = (some) => [some, repeat0Plus(some)];
|
|
92
|
+
export const join1Plus = (some, separator) => [some, repeat0Plus([separator, some])];
|
|
93
|
+
export const join0Plus = (some, separator) => option(join1Plus(some, separator));
|
|
94
|
+
export const repeat = (n) => (some) => toArray(listRepeat(some)(n));
|
|
95
|
+
export const isEmpty = (rule) => {
|
|
96
|
+
const d = typeof rule === 'function' ? rule() : rule;
|
|
97
|
+
return d === '' || (d instanceof Array && d.length === 0);
|
|
98
|
+
};
|
package/bnf/test.f.d.ts
ADDED
package/bnf/test.f.js
ADDED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
const
|
|
1
|
+
import { join0Plus, max, none, option, range, remove, repeat, repeat0Plus, set } from "./module.f.js";
|
|
2
|
+
export const classic = () => {
|
|
3
3
|
const json = () => [element];
|
|
4
4
|
const value = () => ({
|
|
5
5
|
object,
|
|
@@ -34,9 +34,9 @@ const _classic = () => {
|
|
|
34
34
|
characters: [character, characters],
|
|
35
35
|
});
|
|
36
36
|
const character = () => ({
|
|
37
|
-
0:
|
|
38
|
-
1:
|
|
39
|
-
2:
|
|
37
|
+
0: 0x20_000021,
|
|
38
|
+
1: 0x23_00005B,
|
|
39
|
+
2: 0x5D_10FFFF,
|
|
40
40
|
escape: ['\\', escape],
|
|
41
41
|
});
|
|
42
42
|
const escape = () => ({
|
|
@@ -63,7 +63,7 @@ const _classic = () => {
|
|
|
63
63
|
'0': '0',
|
|
64
64
|
onenine,
|
|
65
65
|
});
|
|
66
|
-
const onenine = range('
|
|
66
|
+
const onenine = range('19');
|
|
67
67
|
const fraction = () => ({
|
|
68
68
|
none,
|
|
69
69
|
digits: ['.', digits],
|
|
@@ -86,53 +86,57 @@ const _classic = () => {
|
|
|
86
86
|
});
|
|
87
87
|
return json;
|
|
88
88
|
};
|
|
89
|
-
const
|
|
90
|
-
const onenine = range('
|
|
91
|
-
const digit =
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
89
|
+
export const deterministic = () => {
|
|
90
|
+
const onenine = range('19');
|
|
91
|
+
const digit = range('09');
|
|
92
|
+
const string = [
|
|
93
|
+
'"',
|
|
94
|
+
repeat0Plus({
|
|
95
|
+
...remove(range(` ${max}`), set('"\\')),
|
|
96
|
+
escape: [
|
|
97
|
+
'\\',
|
|
98
|
+
{
|
|
99
|
+
...set('"\\/bfnrt'),
|
|
100
|
+
u: [
|
|
101
|
+
'u',
|
|
102
|
+
...repeat(4)({
|
|
103
|
+
digit,
|
|
104
|
+
AF: range('AF'),
|
|
105
|
+
af: range('af'),
|
|
106
|
+
})
|
|
107
|
+
],
|
|
108
|
+
}
|
|
109
|
+
],
|
|
110
|
+
}),
|
|
111
|
+
'"'
|
|
112
|
+
];
|
|
113
|
+
const digits0 = repeat0Plus(digit);
|
|
113
114
|
const digits = [digit, digits0];
|
|
114
|
-
const
|
|
115
|
-
|
|
115
|
+
const number = [
|
|
116
|
+
option('-'),
|
|
117
|
+
{
|
|
118
|
+
0: '0',
|
|
116
119
|
onenine: [onenine, digits0],
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
const
|
|
122
|
-
const
|
|
120
|
+
},
|
|
121
|
+
option(['.', digits]),
|
|
122
|
+
option([set('Ee'), option(set('+-')), digits])
|
|
123
|
+
];
|
|
124
|
+
const ws = repeat0Plus(set(' \n\r\t'));
|
|
125
|
+
const commaJoin0Plus = ([open, close], a) => [
|
|
126
|
+
open,
|
|
127
|
+
ws,
|
|
128
|
+
join0Plus([a, ws], [',', ws]),
|
|
129
|
+
close,
|
|
130
|
+
];
|
|
123
131
|
const value = () => ({
|
|
124
|
-
object,
|
|
125
|
-
array,
|
|
132
|
+
object: commaJoin0Plus('{}', [string, ws, ':', ws, value]),
|
|
133
|
+
array: commaJoin0Plus('[]', value),
|
|
126
134
|
string,
|
|
127
135
|
number,
|
|
128
136
|
true: 'true',
|
|
129
137
|
false: 'false',
|
|
130
138
|
null: 'null'
|
|
131
139
|
});
|
|
132
|
-
const commaJoin0 = ([open, close], a) => [open, ws, join0([a, ws], [',', ws]), close];
|
|
133
|
-
const array = commaJoin0('[]', value);
|
|
134
|
-
const member = [string, ws, ':', ws, value];
|
|
135
|
-
const object = commaJoin0('{}', member);
|
|
136
140
|
const json = [ws, value, ws];
|
|
137
141
|
return json;
|
|
138
142
|
};
|
|
@@ -65,4 +65,12 @@ export declare const secp256k1: Init;
|
|
|
65
65
|
* https://neuromancer.sk/std/secg/secp256r1
|
|
66
66
|
*/
|
|
67
67
|
export declare const secp256r1: Init;
|
|
68
|
+
/**
|
|
69
|
+
* https://neuromancer.sk/std/secg/secp384r1
|
|
70
|
+
*/
|
|
71
|
+
export declare const secp384r1: Init;
|
|
72
|
+
/**
|
|
73
|
+
* https://neuromancer.sk/std/secg/secp521r1
|
|
74
|
+
*/
|
|
75
|
+
export declare const secp521r1: Init;
|
|
68
76
|
export {};
|
package/crypto/secp/module.f.js
CHANGED
|
@@ -124,3 +124,33 @@ export const secp256r1 = {
|
|
|
124
124
|
],
|
|
125
125
|
n: 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551n,
|
|
126
126
|
};
|
|
127
|
+
/**
|
|
128
|
+
* https://neuromancer.sk/std/secg/secp384r1
|
|
129
|
+
*/
|
|
130
|
+
export const secp384r1 = {
|
|
131
|
+
p: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffffn,
|
|
132
|
+
a: [
|
|
133
|
+
0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aefn, //< b
|
|
134
|
+
0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffcn, //< a
|
|
135
|
+
],
|
|
136
|
+
g: [
|
|
137
|
+
0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7n, //< x
|
|
138
|
+
0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5fn, //< y
|
|
139
|
+
],
|
|
140
|
+
n: 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973n,
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* https://neuromancer.sk/std/secg/secp521r1
|
|
144
|
+
*/
|
|
145
|
+
export const secp521r1 = {
|
|
146
|
+
p: 0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn,
|
|
147
|
+
a: [
|
|
148
|
+
0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00n, //< b
|
|
149
|
+
0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcn, //< a
|
|
150
|
+
],
|
|
151
|
+
g: [
|
|
152
|
+
0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66n,
|
|
153
|
+
0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650n,
|
|
154
|
+
],
|
|
155
|
+
n: 0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409n
|
|
156
|
+
};
|
package/crypto/secp/test.f.d.ts
CHANGED
package/crypto/secp/test.f.js
CHANGED
|
@@ -1,4 +1,58 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { prime_field } from "../prime_field/module.f.js";
|
|
2
|
+
import { curve, secp256k1, secp192r1, secp256r1, eq, secp384r1, secp521r1 } from "./module.f.js";
|
|
3
|
+
const poker = (param) => () => {
|
|
4
|
+
// (c ^ x) ^ y = c ^ (x * y)
|
|
5
|
+
// c ^ ((x * y) * (1/x * 1/y)) = c
|
|
6
|
+
const { g, n } = param;
|
|
7
|
+
const { mul, y } = curve(param);
|
|
8
|
+
const f = (m) => (pList) => pList.map(i => mul(i)(m));
|
|
9
|
+
//
|
|
10
|
+
const pf = prime_field(n);
|
|
11
|
+
// 0 1 2 3 4 5 6 7
|
|
12
|
+
const sA = 0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefn % n;
|
|
13
|
+
const sB = 0xfedcba98fedcba98fedcba98fedcba98fedcba98fedcba98fedcba98fedcba98n % n;
|
|
14
|
+
// "22d3ad011aec6aabdb3d3d47636f3e2859de02298c87a496"
|
|
15
|
+
// "2b359de5cfb5937a5610d565dceaef2a760ceeaec96e68140757f0c8371534e0"
|
|
16
|
+
// "1359162ede91207ccaea1de94afc63c1db5a967c1e6e21f91ef9f077f20a46b6"
|
|
17
|
+
const rA = pf.reciprocal(sA);
|
|
18
|
+
// "e1e768c7427cf5bafd58756df9b54b9ec2558201f129f4ab"
|
|
19
|
+
// "edaf7ede285c3da723c54fcdaa3b631f626681f884d8f41fae55c4f552bb551e"
|
|
20
|
+
// "6ca248e88c124478975b57c4c3ca682bd8be0f0d9f11593d01273d9ceebdb735"
|
|
21
|
+
const rB = pf.reciprocal(sB);
|
|
22
|
+
//
|
|
23
|
+
let d = [];
|
|
24
|
+
for (let i = 0n; i < 52n; ++i) {
|
|
25
|
+
let nonce = 0n; // can be a random number in a range [`0`, `p >> 6n`).
|
|
26
|
+
let x = 0n;
|
|
27
|
+
let yi;
|
|
28
|
+
while (true) {
|
|
29
|
+
x = i | (nonce << 6n);
|
|
30
|
+
yi = y(x);
|
|
31
|
+
if (yi !== null) {
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
++nonce;
|
|
35
|
+
}
|
|
36
|
+
d = [...d, [x, yi]];
|
|
37
|
+
}
|
|
38
|
+
//
|
|
39
|
+
const dA = f(sA)(d);
|
|
40
|
+
const dAB = f(sB)(dA);
|
|
41
|
+
const dB = f(rA)(dAB);
|
|
42
|
+
const dN = f(rB)(dB);
|
|
43
|
+
//
|
|
44
|
+
let m = 0n;
|
|
45
|
+
for (const p of dN) {
|
|
46
|
+
if (p === null) {
|
|
47
|
+
throw 'null';
|
|
48
|
+
}
|
|
49
|
+
const x = p[0] & 0x3fn;
|
|
50
|
+
if (x !== m) {
|
|
51
|
+
throw [p[0], x, m];
|
|
52
|
+
}
|
|
53
|
+
++m;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
2
56
|
export default {
|
|
3
57
|
example: () => {
|
|
4
58
|
const curveParams = {
|
|
@@ -17,7 +71,7 @@ export default {
|
|
|
17
71
|
const test_curve = c => {
|
|
18
72
|
const { g } = c;
|
|
19
73
|
const { mul, neg, pf: { abs }, y: yf, nf: { p: n } } = curve(c);
|
|
20
|
-
const point_check = p => {
|
|
74
|
+
const point_check = (p) => {
|
|
21
75
|
if (p === null) {
|
|
22
76
|
throw 'p === null';
|
|
23
77
|
}
|
|
@@ -32,7 +86,7 @@ export default {
|
|
|
32
86
|
};
|
|
33
87
|
point_check(g);
|
|
34
88
|
point_check(neg(g));
|
|
35
|
-
const test_mul = p => {
|
|
89
|
+
const test_mul = (p) => {
|
|
36
90
|
if (mul(p)(0n) !== null) {
|
|
37
91
|
throw 'O';
|
|
38
92
|
}
|
|
@@ -68,5 +122,15 @@ export default {
|
|
|
68
122
|
test_curve(secp256k1);
|
|
69
123
|
test_curve(secp192r1);
|
|
70
124
|
test_curve(secp256r1);
|
|
125
|
+
test_curve(secp384r1);
|
|
126
|
+
test_curve(secp521r1);
|
|
127
|
+
},
|
|
128
|
+
poker: () => {
|
|
129
|
+
const c = {
|
|
130
|
+
secp192r1,
|
|
131
|
+
//secp256k1,
|
|
132
|
+
//secp256r1,
|
|
133
|
+
};
|
|
134
|
+
return Object.fromEntries(Object.entries(c).map(([k, v]) => [k, poker(v)]));
|
|
71
135
|
}
|
|
72
136
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type * as djs from '../module.f.ts';
|
|
2
|
+
export type AstModule = [readonly string[], AstBody];
|
|
3
|
+
export type AstConst = djs.Primitive | AstModuleRef | AstArray | AstObject;
|
|
4
|
+
export type AstModuleRef = ['aref' | 'cref', number];
|
|
5
|
+
export type AstArray = ['array', readonly AstConst[]];
|
|
6
|
+
export type AstObject = {
|
|
7
|
+
readonly [k in string]: AstConst;
|
|
8
|
+
};
|
|
9
|
+
export type AstBody = readonly AstConst[];
|
|
10
|
+
export declare const run: (body: AstBody) => (args: djs.Array) => djs.Unknown;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { concat, fold, last, map, take, toArray } from "../../types/list/module.f.js";
|
|
2
|
+
import { fromEntries } from "../../types/object/module.f.js";
|
|
3
|
+
const { entries } = Object;
|
|
4
|
+
const foldOp = ast => state => {
|
|
5
|
+
const djs = toDjs(state)(ast);
|
|
6
|
+
return { ...state, consts: concat(state.consts)([djs]) };
|
|
7
|
+
};
|
|
8
|
+
const foldAstObjectOp = entry => state => {
|
|
9
|
+
const e = concat(state.entries)([[entry[0], (toDjs(state.runState)(entry[1]))]]);
|
|
10
|
+
return { ...state, entries: e };
|
|
11
|
+
};
|
|
12
|
+
const toDjs = state => ast => {
|
|
13
|
+
switch (typeof ast) {
|
|
14
|
+
case 'boolean':
|
|
15
|
+
case 'number':
|
|
16
|
+
case 'string':
|
|
17
|
+
case 'bigint': {
|
|
18
|
+
return ast;
|
|
19
|
+
}
|
|
20
|
+
default: {
|
|
21
|
+
if (ast === null) {
|
|
22
|
+
return ast;
|
|
23
|
+
}
|
|
24
|
+
if (ast === undefined) {
|
|
25
|
+
return ast;
|
|
26
|
+
}
|
|
27
|
+
if (ast instanceof Array) {
|
|
28
|
+
switch (ast[0]) {
|
|
29
|
+
case 'aref': {
|
|
30
|
+
return state.args[ast[1]];
|
|
31
|
+
}
|
|
32
|
+
case 'cref': {
|
|
33
|
+
return last(null)(take(ast[1] + 1)(state.consts));
|
|
34
|
+
}
|
|
35
|
+
case 'array': {
|
|
36
|
+
return toArray(map(toDjs(state))(ast[1]));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const e = fold(foldAstObjectOp)({ runState: state, entries: null })(entries(ast)).entries;
|
|
41
|
+
return fromEntries(e);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
export const run = body => args => {
|
|
46
|
+
const state = fold(foldOp)({ body, args, consts: null })(body);
|
|
47
|
+
return last(null)(state.consts);
|
|
48
|
+
};
|
|
49
|
+
// for functions
|
|
50
|
+
// export const astBodyToAstConst
|
|
51
|
+
// :(body: AstBody) => (args: AstArray) => AstConst
|
|
52
|
+
// = body => args => todo()
|