functionalscript 0.2.2 → 0.2.4
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/CHANGELOG.md +4 -0
- package/com/cpp/module.f.mjs +10 -1
- package/com/cs/module.f.mjs +11 -1
- package/com/rust/module.f.mjs +13 -1
- package/issues/lang/3370-type-inference.md +69 -0
- package/issues/lang/3380-promise.md +22 -0
- package/issues/lang/3390-class.md +3 -0
- package/issues/lang/README.md +79 -8
- package/jsr.json +3 -1
- package/out/com/cpp/module.f.d.mts +4 -1
- package/out/com/cpp/module.f.mjs +8 -1
- package/out/com/cs/module.f.d.mts +4 -1
- package/out/com/cs/module.f.mjs +10 -1
- package/out/com/rust/module.f.d.mts +1 -2
- package/out/com/rust/module.f.mjs +12 -1
- package/out/prime_field/module.f.d.mts +28 -2
- package/out/prime_field/module.f.mjs +25 -2
- package/out/prime_field/test.f.d.mts +1 -0
- package/out/prime_field/test.f.mjs +7 -0
- package/out/secp/module.f.d.mts +68 -6
- package/out/secp/module.f.mjs +72 -12
- package/out/secp/test.f.d.mts +1 -0
- package/out/secp/test.f.mjs +18 -3
- package/out/types/bigint/test.f.mjs +7 -0
- package/out/types/bit_vec/module.f.d.mts +72 -0
- package/out/types/bit_vec/module.f.mjs +83 -0
- package/out/types/bit_vec/test.f.d.mts +9 -0
- package/out/types/bit_vec/test.f.mjs +60 -0
- package/package.json +1 -1
- package/prime_field/module.f.mjs +25 -2
- package/prime_field/test.f.mjs +5 -0
- package/secp/module.f.mjs +73 -12
- package/secp/test.f.mjs +18 -3
- package/types/bigint/test.f.mjs +5 -0
- package/types/bit_vec/module.f.mjs +90 -0
- package/types/bit_vec/test.f.mjs +41 -0
- /package/issues/lang/{3310-expression.md → 3410-expression.md} +0 -0
- /package/issues/lang/{3320-one-parameter.md → 3420-one-parameter.md} +0 -0
- /package/issues/lang/{3330-assignments.md → 3430-assignments.md} +0 -0
package/CHANGELOG.md
CHANGED
package/com/cpp/module.f.mjs
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
// @ts-self-types="./module.f.d.mts"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This module generates C++ code blocks, including structs, interfaces, and method headers,
|
|
5
|
+
* based on a COM library of type definitions.
|
|
6
|
+
*/
|
|
7
|
+
|
|
2
8
|
import * as types from '../types/module.f.mjs'
|
|
3
9
|
import * as text from '../../text/module.f.mjs'
|
|
4
10
|
import * as O from '../../types/object/module.f.mjs'
|
|
@@ -51,7 +57,10 @@ const mapParamName = map(paramName)
|
|
|
51
57
|
|
|
52
58
|
const joinComma = join(', ')
|
|
53
59
|
|
|
54
|
-
/**
|
|
60
|
+
/**
|
|
61
|
+
* Generates the C++ code for a library.
|
|
62
|
+
* @type {(name: string) => (lib: types.Library) => text.Block}
|
|
63
|
+
*/
|
|
55
64
|
export const cpp = name => lib => {
|
|
56
65
|
|
|
57
66
|
/** @type {(t: types.Type) => string|null} */
|
package/com/cs/module.f.mjs
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
// @ts-self-types="./module.f.d.mts"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This module generates C# code blocks for COM interop from a high-level type library definition.
|
|
5
|
+
*
|
|
6
|
+
* The module maps type definitions (e.g., structs, interfaces, and methods) into C# constructs
|
|
7
|
+
* with appropriate attributes for COM interop, such as `[StructLayout]`, `[Guid]`, and `[InterfaceType]`.
|
|
8
|
+
*/
|
|
2
9
|
import * as types from '../types/module.f.mjs'
|
|
3
10
|
const { result, paramList } = types
|
|
4
11
|
import * as text from '../../text/module.f.mjs'
|
|
@@ -118,7 +125,10 @@ const header = [
|
|
|
118
125
|
''
|
|
119
126
|
]
|
|
120
127
|
|
|
121
|
-
/**
|
|
128
|
+
/**
|
|
129
|
+
* Generates the C# code for a library.
|
|
130
|
+
* @type {(name: string) => (library: types.Library) => text.Block}
|
|
131
|
+
*/
|
|
122
132
|
export const cs = name => library => {
|
|
123
133
|
const v = flatMapDef(entries(library))
|
|
124
134
|
const ns = namespace(name)(v)
|
package/com/rust/module.f.mjs
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
// @ts-self-types="./module.f.d.mts"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This module generates Rust code for COM interop from a high-level type library definition.
|
|
5
|
+
*
|
|
6
|
+
* The module provides functions to define structs, traits, and implementations in Rust,
|
|
7
|
+
* specifically tailored for `nanocom` interoperation.
|
|
8
|
+
*/
|
|
2
9
|
import * as types from '../types/module.f.mjs'
|
|
3
10
|
const { paramList } = types
|
|
4
11
|
import * as Text from '../../text/module.f.mjs'
|
|
@@ -131,7 +138,12 @@ const traitImpl = t => {
|
|
|
131
138
|
|
|
132
139
|
const where = ['Self: nanocom::Class<Interface = Interface>', 'nanocom::CObject<Self>: Ex']
|
|
133
140
|
|
|
134
|
-
/**
|
|
141
|
+
/**
|
|
142
|
+
* Generates Rust code for the given type library.
|
|
143
|
+
*
|
|
144
|
+
* @param {types.Library} library - The library of type definitions to generate Rust code for.
|
|
145
|
+
* @returns {Text.Block} - A block of Rust code representing the library.
|
|
146
|
+
*/
|
|
135
147
|
export const rust = library => {
|
|
136
148
|
|
|
137
149
|
/** @type {(p: string) => (o: (_: string) => string) => (t: types.Type) => string} */
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Type Inference
|
|
2
|
+
|
|
3
|
+
We need type inference to prove that specific values have specific types. Type annotations can help, but we can't trust them.
|
|
4
|
+
|
|
5
|
+
## Level 1
|
|
6
|
+
|
|
7
|
+
```rust
|
|
8
|
+
enum Type {
|
|
9
|
+
Unknown,
|
|
10
|
+
Null,
|
|
11
|
+
Undefined,
|
|
12
|
+
Bool,
|
|
13
|
+
Number,
|
|
14
|
+
String,
|
|
15
|
+
BigInt,
|
|
16
|
+
Object,
|
|
17
|
+
Array,
|
|
18
|
+
Function,
|
|
19
|
+
// ...
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Level 2
|
|
24
|
+
|
|
25
|
+
It is a set. For example,
|
|
26
|
+
|
|
27
|
+
```rust
|
|
28
|
+
Set<Type>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
On this level, we can extend our `Type` definition with some known finite values:
|
|
32
|
+
|
|
33
|
+
```rs
|
|
34
|
+
enum Type {
|
|
35
|
+
Unknown,
|
|
36
|
+
Null,
|
|
37
|
+
Undefined,
|
|
38
|
+
False,
|
|
39
|
+
True,
|
|
40
|
+
Number,
|
|
41
|
+
String,
|
|
42
|
+
BigInt,
|
|
43
|
+
Object,
|
|
44
|
+
Array,
|
|
45
|
+
Function,
|
|
46
|
+
// ...
|
|
47
|
+
// ...
|
|
48
|
+
EmptyString,
|
|
49
|
+
NumberZero,
|
|
50
|
+
NumberNaN,
|
|
51
|
+
NumberPositive,
|
|
52
|
+
NumberNegative,
|
|
53
|
+
NumberPInf,
|
|
54
|
+
NumberNInf,
|
|
55
|
+
BigIntZero,
|
|
56
|
+
BigIntPositive,
|
|
57
|
+
BigIntNegative,
|
|
58
|
+
EmptyObject,
|
|
59
|
+
EmptyArray,
|
|
60
|
+
FunctionId,
|
|
61
|
+
// ...
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The set is finite and can be implemented using a bit-set.
|
|
66
|
+
|
|
67
|
+
### Level 3
|
|
68
|
+
|
|
69
|
+
Compared to level 2, this level contains dynamic information about subsets of the type.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Promise
|
|
2
|
+
|
|
3
|
+
It could be blocked until we solve the ownership problem.
|
|
4
|
+
|
|
5
|
+
Promise is the main object. `async` and `await` are syntax sugars. If we can safely work with promises, we can transform a FunctionalScript program with `async` functions into a normal function with Promises.
|
|
6
|
+
|
|
7
|
+
## `.then()`
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
a.then(f)
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
const g0 = async(a) => f(await a)
|
|
15
|
+
// g0 = a => a.then(f)
|
|
16
|
+
|
|
17
|
+
const g1 = async(a) => f(await a)
|
|
18
|
+
|
|
19
|
+
const a = io.wrtieFile('a', 'x')
|
|
20
|
+
const p0 = g0(a)
|
|
21
|
+
const p1 = g1(a)
|
|
22
|
+
```
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
# Classes
|
|
2
|
+
|
|
3
|
+
Classes are [nominal types](https://en.wikipedia.org/wiki/Nominal_type_system). In other words, their definitions are location-based, not content-based. This can cause many problems, such as duplicate incompatible class definitions during serialization and code importing. So, the best way to use classes would be to use CA VM.
|
package/issues/lang/README.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# FunctionalScript Language
|
|
2
2
|
|
|
3
|
-
Two main FunctionsScript
|
|
4
|
-
|
|
3
|
+
Two main FunctionsScript principles:
|
|
4
|
+
|
|
5
|
+
1. if FS code passes validation/compilation, then it doesn't have side-effects,
|
|
5
6
|
2. the code that passed validation/compilation should behave on FunctionalScript VM the same way as on any other modern JavaScript engine.
|
|
6
7
|
|
|
7
8
|
When we implement features of FunctionalScript, the first priority is a simplification of the VM.
|
|
@@ -22,7 +23,7 @@ File Types:
|
|
|
22
23
|
|
|
23
24
|
**VM**:
|
|
24
25
|
|
|
25
|
-
We are introducing new commands in
|
|
26
|
+
We are introducing new commands in such a way that every new command depends only on previous commands.
|
|
26
27
|
|
|
27
28
|
|format|any |Tag| |
|
|
28
29
|
|------|--------------|---|----------|
|
|
@@ -98,18 +99,27 @@ File extensions: `.f.js` and `.f.mjs`.
|
|
|
98
99
|
2. [ ] [parameters](./3120-parameters.md)
|
|
99
100
|
3. [ ] [body-const](./3130-body-const.md)
|
|
100
101
|
|
|
101
|
-
### 3.2. Priority
|
|
102
|
+
### 3.2. Priority 2
|
|
102
103
|
|
|
103
104
|
1. [ ] `if`. See https://developer.mozilla.org/en-US/docs/Glossary/Falsy
|
|
104
105
|
2. [ ] [let](./3220-let.md)
|
|
105
106
|
3. [ ] `while`
|
|
106
107
|
4. [ ] [export](./3240-export.md)
|
|
108
|
+
5. [ ] Ownership of Mutable Objects (Singletons)
|
|
109
|
+
|
|
110
|
+
### 3.3. Priority 3
|
|
107
111
|
|
|
108
|
-
|
|
112
|
+
1. [ ] Regular Expressions
|
|
113
|
+
2. [ ] [type inference](./3370-type-inference.md)
|
|
114
|
+
3. [ ] [promise](./3380-promise.md)
|
|
115
|
+
4. [ ] [class](./3390-class.md)
|
|
109
116
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
117
|
+
### 3.4. Syntactic Sugar
|
|
118
|
+
|
|
119
|
+
1. [ ] [expression](./3410-expression.md)
|
|
120
|
+
2. [ ] [one-parameter](./3420-one-parameter.md)
|
|
121
|
+
3. [ ] [assignments](./3430-assignments.md)
|
|
122
|
+
4. [ ] `async`/`await`. Depends on the implementation of promises.
|
|
113
123
|
|
|
114
124
|
## 4. ECMAScript Proposals
|
|
115
125
|
|
|
@@ -120,3 +130,64 @@ File extensions: `.f.js` and `.f.mjs`.
|
|
|
120
130
|
- most browsers don't support the feature.
|
|
121
131
|
2. [ ] [Pipe Operator `|>`](https://github.com/tc39/proposal-pipeline-operator), Stage 2.
|
|
122
132
|
3. [ ] [Records and Tuples](https://github.com/tc39/proposal-record-tuple), Stage 2.
|
|
133
|
+
|
|
134
|
+
## 5. I/O
|
|
135
|
+
|
|
136
|
+
### 5.1. Isolated I/O
|
|
137
|
+
|
|
138
|
+
Using dependency injection.
|
|
139
|
+
|
|
140
|
+
This implementation of VM requires external function implementation.
|
|
141
|
+
|
|
142
|
+
### 5.2 Isolated Asynchronous I/O
|
|
143
|
+
|
|
144
|
+
It requires a promise implementation.
|
|
145
|
+
|
|
146
|
+
### 5.3. State Machine with Asynchronous Requests
|
|
147
|
+
|
|
148
|
+
VM doesn't need to implement external functions or promises.
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
type RequestType = ...;
|
|
152
|
+
type Request = readonly[Input, Continuation];
|
|
153
|
+
type Continuation = (_: Output) => Request;
|
|
154
|
+
type Main = Request
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## 6. Content-Addressable VM
|
|
158
|
+
|
|
159
|
+
See also [Unison](https://www.unison-lang.org/).
|
|
160
|
+
|
|
161
|
+
The main target is run-time performance.
|
|
162
|
+
|
|
163
|
+
Hash function: most likely SHA256 because there is a lot of hardware support from modern processors.
|
|
164
|
+
|
|
165
|
+
Hash structure: we will use several initial hashes for a compress function.
|
|
166
|
+
|
|
167
|
+
We may use CDT for huge arrays, objects, strings, and BigInts.
|
|
168
|
+
|
|
169
|
+
The first bit of a hash is reserved for a tag. If the tag is `0`, we have raw data with `1` at the end. A hash with all zeroes is used for `undefined`. If the first bit is `0`, then the value is a hash. So, we have only 255 bits for a hash.
|
|
170
|
+
|
|
171
|
+
Because we use tagged hash, we can keep small values in a `nanenum`. So it may reuse a lot from non-content addressable VM and ref-values can keep a hash value inside.
|
|
172
|
+
|
|
173
|
+
Instead of an address, we can use a prefix, hash. 48 bits should be enough for most cases. However, we also need a mechanism to resolve collisions (even if they are rare). For example, our value can be an enum like this
|
|
174
|
+
|
|
175
|
+
```rust
|
|
176
|
+
enum Value {
|
|
177
|
+
Data(...),
|
|
178
|
+
Hash(u48),
|
|
179
|
+
Ref(u48),
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
However, while the `===` operation can be faster, `Value::Hash` is slower when we need to access the object's internals because it requires two dereference operations. So, we may come back to using only references.
|
|
184
|
+
|
|
185
|
+
```rust
|
|
186
|
+
enum Value {
|
|
187
|
+
Data(...)
|
|
188
|
+
Ref(u48)
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Collision probability for 48 bits is 50% for `16777216 = 2^24` hashes (birthday attack).
|
|
193
|
+
|
package/jsr.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@functionalscript/functionalscript",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
|
+
"license": "AGPL-3.0-only",
|
|
4
5
|
"exports": {
|
|
5
6
|
"./com/cpp": "./out/com/cpp/module.f.mjs",
|
|
6
7
|
"./com/cs": "./out/com/cs/module.f.mjs",
|
|
@@ -38,6 +39,7 @@
|
|
|
38
39
|
"./types/array": "./out/types/array/module.f.mjs",
|
|
39
40
|
"./types/bigfloat": "./out/types/bigfloat/module.f.mjs",
|
|
40
41
|
"./types/bigint": "./out/types/bigint/module.f.mjs",
|
|
42
|
+
"./types/bit_vec": "./out/types/bit_vec/module.f.mjs",
|
|
41
43
|
"./types/btree/find": "./out/types/btree/find/module.f.mjs",
|
|
42
44
|
"./types/btree": "./out/types/btree/module.f.mjs",
|
|
43
45
|
"./types/btree/remove": "./out/types/btree/remove/module.f.mjs",
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Generates the C++ code for a library.
|
|
3
|
+
* @type {(name: string) => (lib: types.Library) => text.Block}
|
|
4
|
+
*/
|
|
2
5
|
export const cpp: (name: string) => (lib: types.Library) => text.Block;
|
|
3
6
|
import * as types from '../types/module.f.mjs';
|
|
4
7
|
import * as text from '../../text/module.f.mjs';
|
package/out/com/cpp/module.f.mjs
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
// @ts-self-types="./module.f.d.mts"
|
|
2
|
+
/**
|
|
3
|
+
* This module generates C++ code blocks, including structs, interfaces, and method headers,
|
|
4
|
+
* based on a COM library of type definitions.
|
|
5
|
+
*/
|
|
2
6
|
import * as types from '../types/module.f.mjs';
|
|
3
7
|
import * as text from '../../text/module.f.mjs';
|
|
4
8
|
import * as O from '../../types/object/module.f.mjs';
|
|
@@ -39,7 +43,10 @@ const ref = id => `${id} const&`;
|
|
|
39
43
|
const paramName = ([name]) => name;
|
|
40
44
|
const mapParamName = map(paramName);
|
|
41
45
|
const joinComma = join(', ');
|
|
42
|
-
/**
|
|
46
|
+
/**
|
|
47
|
+
* Generates the C++ code for a library.
|
|
48
|
+
* @type {(name: string) => (lib: types.Library) => text.Block}
|
|
49
|
+
*/
|
|
43
50
|
export const cpp = name => lib => {
|
|
44
51
|
/** @type {(t: types.Type) => string|null} */
|
|
45
52
|
const interface_ = t => {
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Generates the C# code for a library.
|
|
3
|
+
* @type {(name: string) => (library: types.Library) => text.Block}
|
|
4
|
+
*/
|
|
2
5
|
export const cs: (name: string) => (library: types.Library) => text.Block;
|
|
3
6
|
import * as types from '../types/module.f.mjs';
|
|
4
7
|
import * as text from '../../text/module.f.mjs';
|
package/out/com/cs/module.f.mjs
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
// @ts-self-types="./module.f.d.mts"
|
|
2
|
+
/**
|
|
3
|
+
* This module generates C# code blocks for COM interop from a high-level type library definition.
|
|
4
|
+
*
|
|
5
|
+
* The module maps type definitions (e.g., structs, interfaces, and methods) into C# constructs
|
|
6
|
+
* with appropriate attributes for COM interop, such as `[StructLayout]`, `[Guid]`, and `[InterfaceType]`.
|
|
7
|
+
*/
|
|
2
8
|
import * as types from '../types/module.f.mjs';
|
|
3
9
|
const { result, paramList } = types;
|
|
4
10
|
import * as text from '../../text/module.f.mjs';
|
|
@@ -87,7 +93,10 @@ const header = [
|
|
|
87
93
|
using('System.Runtime.InteropServices'),
|
|
88
94
|
''
|
|
89
95
|
];
|
|
90
|
-
/**
|
|
96
|
+
/**
|
|
97
|
+
* Generates the C# code for a library.
|
|
98
|
+
* @type {(name: string) => (library: types.Library) => text.Block}
|
|
99
|
+
*/
|
|
91
100
|
export const cs = name => library => {
|
|
92
101
|
const v = flatMapDef(entries(library));
|
|
93
102
|
const ns = namespace(name)(v);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
export const rust: (library: types.Library) => Text.Block;
|
|
1
|
+
export function rust(library: types.Library): Text.Block;
|
|
3
2
|
export type OptionalProperty<T> = T | {};
|
|
4
3
|
export type Where = {
|
|
5
4
|
readonly where: readonly string[];
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
// @ts-self-types="./module.f.d.mts"
|
|
2
|
+
/**
|
|
3
|
+
* This module generates Rust code for COM interop from a high-level type library definition.
|
|
4
|
+
*
|
|
5
|
+
* The module provides functions to define structs, traits, and implementations in Rust,
|
|
6
|
+
* specifically tailored for `nanocom` interoperation.
|
|
7
|
+
*/
|
|
2
8
|
import * as types from '../types/module.f.mjs';
|
|
3
9
|
const { paramList } = types;
|
|
4
10
|
import * as Text from '../../text/module.f.mjs';
|
|
@@ -102,7 +108,12 @@ const traitImpl = t => {
|
|
|
102
108
|
return flat([trait({ ...t, where }), i]);
|
|
103
109
|
};
|
|
104
110
|
const where = ['Self: nanocom::Class<Interface = Interface>', 'nanocom::CObject<Self>: Ex'];
|
|
105
|
-
/**
|
|
111
|
+
/**
|
|
112
|
+
* Generates Rust code for the given type library.
|
|
113
|
+
*
|
|
114
|
+
* @param {types.Library} library - The library of type definitions to generate Rust code for.
|
|
115
|
+
* @returns {Text.Block} - A block of Rust code representing the library.
|
|
116
|
+
*/
|
|
106
117
|
export const rust = library => {
|
|
107
118
|
/** @type {(p: string) => (o: (_: string) => string) => (t: types.Type) => string} */
|
|
108
119
|
const type = p => {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/** @typedef {Operator.Reduce<bigint>} Reduce */
|
|
2
2
|
/** @typedef {Operator.Unary<bigint, bigint>} Unary*/
|
|
3
3
|
/**
|
|
4
|
+
* A type representing a prime field and its associated operations.
|
|
5
|
+
*
|
|
4
6
|
* @typedef {{
|
|
5
7
|
* readonly p: bigint
|
|
6
8
|
* readonly middle: bigint
|
|
@@ -17,12 +19,36 @@
|
|
|
17
19
|
* readonly pow3: Unary
|
|
18
20
|
* }} PrimeField
|
|
19
21
|
*/
|
|
20
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* Creates a prime field with the specified prime modulus and associated operations.
|
|
24
|
+
*
|
|
25
|
+
* @param p - A prime number to define the field.
|
|
26
|
+
* @returns The prime field object.
|
|
27
|
+
*
|
|
28
|
+
* @type {(p: bigint) => PrimeField}
|
|
29
|
+
*/
|
|
21
30
|
export const prime_field: (p: bigint) => PrimeField;
|
|
22
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* Computes the square root of a number in a prime field.
|
|
33
|
+
*
|
|
34
|
+
* @throws If the prime modulus `p` does not satisfy `p % 4 == 3`.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
*
|
|
38
|
+
* ```js
|
|
39
|
+
* const field = prime_field(7n);
|
|
40
|
+
* const root = sqrt(field)(4n);
|
|
41
|
+
* if (root !== 2n) { throw root }
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @type {(f: PrimeField) => (a: bigint) => bigint|null}
|
|
45
|
+
*/
|
|
23
46
|
export const sqrt: (f: PrimeField) => (a: bigint) => bigint | null;
|
|
24
47
|
export type Reduce = Operator.Reduce<bigint>;
|
|
25
48
|
export type Unary = Operator.Unary<bigint, bigint>;
|
|
49
|
+
/**
|
|
50
|
+
* A type representing a prime field and its associated operations.
|
|
51
|
+
*/
|
|
26
52
|
export type PrimeField = {
|
|
27
53
|
readonly p: bigint;
|
|
28
54
|
readonly middle: bigint;
|
|
@@ -5,6 +5,8 @@ const { scalar_mul } = bi;
|
|
|
5
5
|
/** @typedef {Operator.Reduce<bigint>} Reduce */
|
|
6
6
|
/** @typedef {Operator.Unary<bigint, bigint>} Unary*/
|
|
7
7
|
/**
|
|
8
|
+
* A type representing a prime field and its associated operations.
|
|
9
|
+
*
|
|
8
10
|
* @typedef {{
|
|
9
11
|
* readonly p: bigint
|
|
10
12
|
* readonly middle: bigint
|
|
@@ -21,7 +23,14 @@ const { scalar_mul } = bi;
|
|
|
21
23
|
* readonly pow3: Unary
|
|
22
24
|
* }} PrimeField
|
|
23
25
|
*/
|
|
24
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* Creates a prime field with the specified prime modulus and associated operations.
|
|
28
|
+
*
|
|
29
|
+
* @param p - A prime number to define the field.
|
|
30
|
+
* @returns The prime field object.
|
|
31
|
+
*
|
|
32
|
+
* @type {(p: bigint) => PrimeField}
|
|
33
|
+
*/
|
|
25
34
|
export const prime_field = p => {
|
|
26
35
|
/** @type {Reduce} */
|
|
27
36
|
const sub = a => b => {
|
|
@@ -74,7 +83,21 @@ export const prime_field = p => {
|
|
|
74
83
|
pow3: a => mul(a)(pow2(a))
|
|
75
84
|
};
|
|
76
85
|
};
|
|
77
|
-
/**
|
|
86
|
+
/**
|
|
87
|
+
* Computes the square root of a number in a prime field.
|
|
88
|
+
*
|
|
89
|
+
* @throws If the prime modulus `p` does not satisfy `p % 4 == 3`.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
*
|
|
93
|
+
* ```js
|
|
94
|
+
* const field = prime_field(7n);
|
|
95
|
+
* const root = sqrt(field)(4n);
|
|
96
|
+
* if (root !== 2n) { throw root }
|
|
97
|
+
* ```
|
|
98
|
+
*
|
|
99
|
+
* @type {(f: PrimeField) => (a: bigint) => bigint|null}
|
|
100
|
+
*/
|
|
78
101
|
export const sqrt = ({ p, mul, pow }) => {
|
|
79
102
|
if ((p & 3n) !== 3n) {
|
|
80
103
|
throw 'sqrt';
|
|
@@ -123,6 +123,13 @@ export default {
|
|
|
123
123
|
test(f.max - 1n);
|
|
124
124
|
test(f.max);
|
|
125
125
|
},
|
|
126
|
+
sqrtExample: () => {
|
|
127
|
+
const field = prime_field(7n);
|
|
128
|
+
const root = sqrt(field)(4n);
|
|
129
|
+
if (root !== 2n) {
|
|
130
|
+
throw root;
|
|
131
|
+
}
|
|
132
|
+
},
|
|
126
133
|
sqrt: () => {
|
|
127
134
|
/** @type {(a: bigint) => void} */
|
|
128
135
|
const test = a => {
|
package/out/secp/module.f.d.mts
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
|
-
/** @typedef {readonly[bigint, bigint]} Point2D */
|
|
2
|
-
/** @typedef {Point2D|null} Point */
|
|
3
1
|
/**
|
|
2
|
+
* A 2D point represented as a pair of `bigint` values `[x, y]`.
|
|
3
|
+
*
|
|
4
|
+
* @typedef {readonly[bigint, bigint]} Point2D
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* A 2D point on an elliptic curve, represented as a pair of `bigint` values.
|
|
8
|
+
* `null` represents the point at infinity (`O`).
|
|
9
|
+
*
|
|
10
|
+
* @typedef {Point2D|null} Point
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Initialization parameters for an elliptic curve.
|
|
14
|
+
*
|
|
4
15
|
* @typedef {{
|
|
5
16
|
* readonly p: bigint
|
|
6
17
|
* readonly a: readonly[bigint, bigint]
|
|
@@ -9,6 +20,8 @@
|
|
|
9
20
|
* }} Init
|
|
10
21
|
*/
|
|
11
22
|
/**
|
|
23
|
+
* Represents an elliptic curve and its associated operations.
|
|
24
|
+
*
|
|
12
25
|
* @typedef {{
|
|
13
26
|
* readonly pf: pf.PrimeField
|
|
14
27
|
* readonly nf: pf.PrimeField
|
|
@@ -19,22 +32,71 @@
|
|
|
19
32
|
* readonly mul: (a: Point) => (n: bigint) => Point
|
|
20
33
|
* }} Curve
|
|
21
34
|
*/
|
|
22
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* Constructs an elliptic curve with the given initialization parameters.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
*
|
|
40
|
+
* ```js
|
|
41
|
+
* const curveParams = {
|
|
42
|
+
* p: 23n,
|
|
43
|
+
* a: [0n, 1n],
|
|
44
|
+
* g: [1n, 1n],
|
|
45
|
+
* n: 19n
|
|
46
|
+
* };
|
|
47
|
+
* const curveInstance = curve(curveParams);
|
|
48
|
+
*
|
|
49
|
+
* // Access curve operations
|
|
50
|
+
* const point = curveInstance.add([1n, 1n])([2n, 5n]); // Add two points
|
|
51
|
+
* const negPoint = curveInstance.neg([1n, 1n]); // Negate a point
|
|
52
|
+
* const mulPoint = curveInstance.mul([1n, 1n])(3n); // Multiply a point by 3
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @type {(i: Init) => Curve}
|
|
56
|
+
*/
|
|
23
57
|
export const curve: (i: Init) => Curve;
|
|
24
58
|
/** @type {(a: Point) => (b: Point) => boolean} */
|
|
25
59
|
export const eq: (a: Point) => (b: Point) => boolean;
|
|
26
|
-
/**
|
|
27
|
-
|
|
28
|
-
|
|
60
|
+
/**
|
|
61
|
+
* https://neuromancer.sk/std/secg/secp192r1
|
|
62
|
+
*
|
|
63
|
+
* @type {Init}
|
|
64
|
+
*/
|
|
29
65
|
export const secp192r1: Init;
|
|
66
|
+
/**
|
|
67
|
+
* https://en.bitcoin.it/wiki/Secp256k1
|
|
68
|
+
* https://neuromancer.sk/std/secg/secp256k1
|
|
69
|
+
*
|
|
70
|
+
* @type {Init}
|
|
71
|
+
*/
|
|
72
|
+
export const secp256k1: Init;
|
|
73
|
+
/**
|
|
74
|
+
* https://neuromancer.sk/std/secg/secp256r1
|
|
75
|
+
*
|
|
76
|
+
* @type { Init }
|
|
77
|
+
*/
|
|
78
|
+
export const secp256r1: Init;
|
|
79
|
+
/**
|
|
80
|
+
* A 2D point represented as a pair of `bigint` values `[x, y]`.
|
|
81
|
+
*/
|
|
30
82
|
export type Point2D = readonly [bigint, bigint];
|
|
83
|
+
/**
|
|
84
|
+
* A 2D point on an elliptic curve, represented as a pair of `bigint` values.
|
|
85
|
+
* `null` represents the point at infinity (`O`).
|
|
86
|
+
*/
|
|
31
87
|
export type Point = Point2D | null;
|
|
88
|
+
/**
|
|
89
|
+
* Initialization parameters for an elliptic curve.
|
|
90
|
+
*/
|
|
32
91
|
export type Init = {
|
|
33
92
|
readonly p: bigint;
|
|
34
93
|
readonly a: readonly [bigint, bigint];
|
|
35
94
|
readonly g: readonly [bigint, bigint];
|
|
36
95
|
readonly n: bigint;
|
|
37
96
|
};
|
|
97
|
+
/**
|
|
98
|
+
* Represents an elliptic curve and its associated operations.
|
|
99
|
+
*/
|
|
38
100
|
export type Curve = {
|
|
39
101
|
readonly pf: pf.PrimeField;
|
|
40
102
|
readonly nf: pf.PrimeField;
|