functionalscript 0.2.5 → 0.2.6

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 CHANGED
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## Unreleased
9
9
 
10
+ ## 0.2.6
11
+
12
+ - Refactoring of a vector of bits [PR #328](https://github.com/functionalscript/functionalscript/pull/328)
13
+
10
14
  ## 0.2.5
11
15
 
12
16
  - new [crypto/] directory [PR #327](https://github.com/functionalscript/functionalscript/pull/327).
package/html/README.md CHANGED
@@ -4,7 +4,8 @@
4
4
  |--------------------------------------------|-------------------------------------------------|
5
5
  |`<br>` |`['br']` |
6
6
  |`<img src="https://example.com/image.jpg">` |`['img',{src:'https://example.com/image.jpg'}]` |
7
- |`<a href="https://example.com/">Example</a>`|`['a',{href:'https://example.com/'},['Example']]`|
7
+ |`<a href="https://example.com/">Example</a>`|`['a',{href:'https://example.com/'}, 'Example']` |
8
+ |`<ul><li>Apple</li><li>Tomato</li></ul>` |`['ul',['li','Apple'],['li','Tomato']]` |
8
9
 
9
10
  ## Example
10
11
 
@@ -20,12 +21,12 @@
20
21
  ```
21
22
 
22
23
  ```js
23
- ['html', [
24
- ['head', [
25
- ['title', ['Page']]
26
- ]]
27
- ['body', [
28
- ['a', { href: 'https://example.com/' }, ['Example']]
29
- ]]
30
- ]]
24
+ ['html',
25
+ ['head',
26
+ ['title', 'Page']
27
+ ]
28
+ ['body',
29
+ ['a', { href: 'https://example.com/' }, 'Example']
30
+ ]
31
+ ]
31
32
  ```
package/issues/README.md CHANGED
@@ -33,6 +33,9 @@
33
33
  24. [ ] create `./module.mjs` that supports the same behavior like current NaNVM Rust implementation:
34
34
  - [ ] run `node ./module.mjs input.f.mjs output.f.mjs`
35
35
  - [ ] run `deno ./module.mjs input.f.mjs output.f.mjs`
36
+ 25. [ ] Switch to Deno an `.ts`?
37
+ 1. Deno TypeScript and Microsoft TypeScript are different https://bsky.app/profile/macwright.com/post/3lbrwioa5zs27
38
+ 2. One day we may switch back to `.js` extension if [Type Annotation Proposal](https://github.com/tc39/proposal-type-annotations) is included into ECMAScript. BTW, we should only use JS with type annotations instead of full TypeScript.
36
39
 
37
40
  ## Language Specification
38
41
 
package/jsr.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@functionalscript/functionalscript",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "license": "AGPL-3.0-only",
5
5
  "exports": {
6
6
  "./com/cpp": "./out/com/cpp/module.f.mjs",
@@ -10,62 +10,148 @@ export const empty: 1n;
10
10
  /**
11
11
  * Calculates the length of the given vector of bits.
12
12
  */
13
- export const len: (v: bigint) => bigint;
13
+ export const length: (v: bigint) => bigint;
14
14
  /**
15
- * Extract an unsigned integer of the given `uintLen` from the given vector.
15
+ * Creates a vector of bits of the given `len` and the given unsigned integer.
16
+ *
17
+ * @type {(len: bigint) => (ui: bigint) => Vec}
18
+ *
19
+ * @example
20
+ *
21
+ * ```js
22
+ * const vec4 = vec(4n)
23
+ * const v0 = vec4(5n) // 0x15n
24
+ * const v1 = vec4(0x5FEn) // 0x1En
25
+ * ```
26
+ */
27
+ export const vec: (len: bigint) => (ui: bigint) => Vec;
28
+ /**
29
+ * Returns the unsigned integer of the given vector by removing a stop bit.
30
+ *
31
+ * @type {(len: Vec) => bigint}
32
+ *
33
+ * @example
34
+ *
35
+ * ```js
36
+ * const vector = vec(8n)(0x5n) // 0x105n
37
+ * const result = uint(vector); // result is 0x5n
38
+ * ```
39
+ */
40
+ export const uint: (len: Vec) => bigint;
41
+ /**
42
+ * Extract the least significant unsigned integer from the given vector.
16
43
  *
17
44
  * @type {(uintLen: bigint) => (v: Vec) => bigint}
18
45
  *
19
46
  * @example
20
47
  *
21
48
  * ```js
22
- * const vector = 0b110101n;
23
- * const extract3Bits = uint(3n);
24
- * const result = extract3Bits(vector); // result is 0b101n (5n)
49
+ * const vector = vec(8n)(0xF5n) // 0x1F5n
50
+ * const result = uintLsb(4n)(vector); // result is 5n
51
+ * const result2 = uintLsb(16n)(vector); // result2 is 0xF5n
25
52
  * ```
26
53
  */
27
- export const uint: (uintLen: bigint) => (v: Vec) => bigint;
54
+ export const uintLsb: (uintLen: bigint) => (v: Vec) => bigint;
28
55
  /**
29
- * Creates a vector of bits of the given `vecLen` from the given unsigned integer.
56
+ * Removes the first `len` least significant bits from the given vector.
30
57
  *
31
- * @type {(vecLen: bigint) => (ui: bigint) => Vec}
58
+ * @type {(len: bigint) => (v: Vec) => Vec}
32
59
  *
33
60
  * @example
34
61
  *
35
62
  * ```js
36
- * const createVector = vec(4n);
37
- * const vector = createVector(5n); // vector is 0b10101n
63
+ * const v = vec(16n)(0x3456n) // 0x13456n
64
+ * const r = removeLsb(4n)(v) // 0x1345n
65
+ * const r2 = removeLsb(24n)(v) // 0x1n
38
66
  * ```
39
67
  */
40
- export const vec: (vecLen: bigint) => (ui: bigint) => Vec;
68
+ export const removeLsb: (len: bigint) => (v: Vec) => Vec;
41
69
  /**
42
- * Appends the vector `b` to the back of the vector `a`.
70
+ * Extracts the least significant unsigned integer and removes it from the vector.
43
71
  *
44
- * @type {(a: Vec) => (b: Vec) => Vec}
72
+ * @type {(len: bigint) => (v: Vec) => [bigint, Vec]}
73
+ *
74
+ * @example
75
+ *
76
+ * ```js
77
+ * const vector = vec(8n)(0xF5n) // 0x1F5n
78
+ * const [result, rest] = popUintLsb(4n)(vector); // result is 5n, rest is 0x1Fn
79
+ * const [result2, rest2] = popUintLsb(16n)(vector); // result2 is 0xF5n, rest2 is 1n
80
+ * ```
81
+ */
82
+ export const popUintLsb: (len: bigint) => (v: Vec) => [bigint, Vec];
83
+ /**
84
+ * Extract the most significant unsigned integer of the given `len` from the given vector.
85
+ *
86
+ * @type {(len: bigint) => (v: Vec) => bigint}
45
87
  *
46
88
  * @example
47
89
  *
48
90
  * ```js
49
- * const vec8 = vec(8n)
50
- * const a = vec8(0x345n)
51
- * const b = vec8(0x789n)
52
- * const ab = appendBack(a)(b) // 0x18945n
91
+ * const vector = vec(8n)(0xF5n) // 0x1F5n
92
+ * const result = uintMsb(4n)(vector); // result is 0xFn
93
+ * const result2 = uintMsb(16n)(vector); // result2 is 0xF500n
53
94
  * ```
54
95
  */
55
- export const appendBack: (a: Vec) => (b: Vec) => Vec;
96
+ export const uintMsb: (len: bigint) => (v: Vec) => bigint;
56
97
  /**
57
- * Removes the first `len` bits from the given vector.
98
+ * Removes the first `len` most significant bits from the given vector.
58
99
  *
59
100
  * @type {(len: bigint) => (v: Vec) => Vec}
60
101
  *
61
102
  * @example
62
103
  *
63
104
  * ```js
64
- * const v = vec(17n)(0x12345n) // v = 0x32345n
65
- * const r = removeFront(9n)(v) // r = 0x191n
105
+ * const v = vec(16n)(0x3456n) // 0x13456n
106
+ * const r = removeMsb(4n)(v) // 0x1456n
107
+ * const r2 = removeMsb(24n)(v) // 0x1n
108
+ * ```
109
+ */
110
+ export const removeMsb: (len: bigint) => (v: Vec) => Vec;
111
+ /**
112
+ * Extracts the most significant unsigned integer and removes it from the vector.
113
+ *
114
+ * @type {(len: bigint) => (v: Vec) => [bigint, Vec]}
115
+ *
116
+ * @example
117
+ *
118
+ * ```js
119
+ * const vector = vec(8n)(0xF5n) // 0x1F5n
120
+ * const [result, rest] = popUintMsb(4n)(vector); // [0xFn, 0x15n]
121
+ * const [result2, rest2] = popUintMsb(16n)(vector); // [0xF500n, 1n]
122
+ * ```
123
+ */
124
+ export const popUintMsb: (len: bigint) => (v: Vec) => [bigint, Vec];
125
+ /**
126
+ * Concat the given vectors of bits. The first vector is the least significant.
127
+ *
128
+ * @type {(a: Vec) => (b: Vec) => Vec}
129
+ *
130
+ * @example
131
+ *
132
+ * ```js
133
+ * const u8 = vec(8n)
134
+ * const a = u8(0x45n) // 0x145n
135
+ * const b = u8(0x89n) // 0x189n
136
+ * const ab = concatLsb(a)(b) // 0x18945n
137
+ * ```
138
+ */
139
+ export const concatLsb: (a: Vec) => (b: Vec) => Vec;
140
+ /**
141
+ * Concat the given vectors of bits. The first vector is the most significant.
142
+ *
143
+ * @type {(b: Vec) => (a: Vec) => Vec}
144
+ *
145
+ * @example
146
+ *
147
+ * ```js
148
+ * const u8 = vec(8n)
149
+ * const a = u8(0x45n) // 0x145n
150
+ * const b = u8(0x89n) // 0x189n
151
+ * const ab = concatMsb(a)(b) // 0x14589n
66
152
  * ```
67
153
  */
68
- export const removeFront: (len: bigint) => (v: Vec) => Vec;
154
+ export const concatMsb: (b: Vec) => (a: Vec) => Vec;
69
155
  /**
70
156
  * A vector of bits represented as a `bigint`.
71
157
  */
@@ -1,5 +1,6 @@
1
1
  // @ts-self-types="./module.f.d.mts"
2
2
  import { log2 } from '../bigint/module.f.mjs';
3
+ import { flip } from '../function/module.f.mjs';
3
4
  /**
4
5
  * A vector of bits represented as a `bigint`.
5
6
  *
@@ -12,72 +13,182 @@ export const empty = 1n;
12
13
  /**
13
14
  * Calculates the length of the given vector of bits.
14
15
  */
15
- export const len = log2;
16
+ export const length = log2;
16
17
  /**
17
- * Extract an unsigned integer of the given `uintLen` from the given vector.
18
+ * Creates a vector of bits of the given `len` and the given unsigned integer.
18
19
  *
19
- * @type {(uintLen: bigint) => (v: Vec) => bigint}
20
+ * @type {(len: bigint) => (ui: bigint) => Vec}
20
21
  *
21
22
  * @example
22
23
  *
23
24
  * ```js
24
- * const vector = 0b110101n;
25
- * const extract3Bits = uint(3n);
26
- * const result = extract3Bits(vector); // result is 0b101n (5n)
25
+ * const vec4 = vec(4n)
26
+ * const v0 = vec4(5n) // 0x15n
27
+ * const v1 = vec4(0x5FEn) // 0x1En
27
28
  * ```
28
29
  */
29
- export const uint = uintLen => {
30
- const mask = (1n << uintLen) - 1n;
31
- return data => data & mask;
30
+ export const vec = len => {
31
+ if (len <= 0n) {
32
+ return () => empty;
33
+ }
34
+ const stop = 1n << len;
35
+ const mask = stop - 1n;
36
+ return data => stop | (data & mask);
32
37
  };
38
+ /** @type {(len: bigint) => bigint} */
39
+ const mask = len => (1n << len) - 1n;
33
40
  /**
34
- * Creates a vector of bits of the given `vecLen` from the given unsigned integer.
41
+ * Returns the unsigned integer of the given vector by removing a stop bit.
35
42
  *
36
- * @type {(vecLen: bigint) => (ui: bigint) => Vec}
43
+ * @type {(len: Vec) => bigint}
37
44
  *
38
45
  * @example
39
46
  *
40
47
  * ```js
41
- * const createVector = vec(4n);
42
- * const vector = createVector(5n); // vector is 0b10101n
48
+ * const vector = vec(8n)(0x5n) // 0x105n
49
+ * const result = uint(vector); // result is 0x5n
43
50
  * ```
44
51
  */
45
- export const vec = vecLen => {
46
- const stop = 1n << vecLen;
47
- const mask = stop - 1n;
48
- return data => (data & mask) | stop;
49
- };
52
+ export const uint = v => v ^ (1n << length(v));
50
53
  /**
51
- * Appends the vector `b` to the back of the vector `a`.
54
+ * Extract the least significant unsigned integer from the given vector.
52
55
  *
53
- * @type {(a: Vec) => (b: Vec) => Vec}
56
+ * @type {(uintLen: bigint) => (v: Vec) => bigint}
54
57
  *
55
58
  * @example
56
59
  *
57
60
  * ```js
58
- * const vec8 = vec(8n)
59
- * const a = vec8(0x345n)
60
- * const b = vec8(0x789n)
61
- * const ab = appendBack(a)(b) // 0x18945n
61
+ * const vector = vec(8n)(0xF5n) // 0x1F5n
62
+ * const result = uintLsb(4n)(vector); // result is 5n
63
+ * const result2 = uintLsb(16n)(vector); // result2 is 0xF5n
62
64
  * ```
63
65
  */
64
- export const appendBack = a => {
65
- const aLen = len(a);
66
- return b => a | (b << aLen);
66
+ export const uintLsb = len => {
67
+ const m = mask(len);
68
+ return v => {
69
+ const result = v & m;
70
+ return result === v ? uint(v) : result;
71
+ };
67
72
  };
68
73
  /**
69
- * Removes the first `len` bits from the given vector.
74
+ * Removes the first `len` least significant bits from the given vector.
70
75
  *
71
76
  * @type {(len: bigint) => (v: Vec) => Vec}
72
77
  *
73
78
  * @example
74
79
  *
75
80
  * ```js
76
- * const v = vec(17n)(0x12345n) // v = 0x32345n
77
- * const r = removeFront(9n)(v) // r = 0x191n
81
+ * const v = vec(16n)(0x3456n) // 0x13456n
82
+ * const r = removeLsb(4n)(v) // 0x1345n
83
+ * const r2 = removeLsb(24n)(v) // 0x1n
78
84
  * ```
79
85
  */
80
- export const removeFront = len => v => {
86
+ export const removeLsb = len => v => {
81
87
  const r = v >> len;
82
88
  return r === 0n ? empty : r;
83
89
  };
90
+ /**
91
+ * Extracts the least significant unsigned integer and removes it from the vector.
92
+ *
93
+ * @type {(len: bigint) => (v: Vec) => [bigint, Vec]}
94
+ *
95
+ * @example
96
+ *
97
+ * ```js
98
+ * const vector = vec(8n)(0xF5n) // 0x1F5n
99
+ * const [result, rest] = popUintLsb(4n)(vector); // result is 5n, rest is 0x1Fn
100
+ * const [result2, rest2] = popUintLsb(16n)(vector); // result2 is 0xF5n, rest2 is 1n
101
+ * ```
102
+ */
103
+ export const popUintLsb = len => {
104
+ const m = mask(len);
105
+ return v => {
106
+ const result = v & m;
107
+ return result === v ? [uint(v), empty] : [result, v >> len];
108
+ };
109
+ };
110
+ /**
111
+ * Extract the most significant unsigned integer of the given `len` from the given vector.
112
+ *
113
+ * @type {(len: bigint) => (v: Vec) => bigint}
114
+ *
115
+ * @example
116
+ *
117
+ * ```js
118
+ * const vector = vec(8n)(0xF5n) // 0x1F5n
119
+ * const result = uintMsb(4n)(vector); // result is 0xFn
120
+ * const result2 = uintMsb(16n)(vector); // result2 is 0xF500n
121
+ * ```
122
+ */
123
+ export const uintMsb = len => {
124
+ const m = mask(len);
125
+ return v => (v >> (length(v) - len)) & m;
126
+ };
127
+ /**
128
+ * Removes the first `len` most significant bits from the given vector.
129
+ *
130
+ * @type {(len: bigint) => (v: Vec) => Vec}
131
+ *
132
+ * @example
133
+ *
134
+ * ```js
135
+ * const v = vec(16n)(0x3456n) // 0x13456n
136
+ * const r = removeMsb(4n)(v) // 0x1456n
137
+ * const r2 = removeMsb(24n)(v) // 0x1n
138
+ * ```
139
+ */
140
+ export const removeMsb = len => v => vec(length(v) - len)(v);
141
+ /**
142
+ * Extracts the most significant unsigned integer and removes it from the vector.
143
+ *
144
+ * @type {(len: bigint) => (v: Vec) => [bigint, Vec]}
145
+ *
146
+ * @example
147
+ *
148
+ * ```js
149
+ * const vector = vec(8n)(0xF5n) // 0x1F5n
150
+ * const [result, rest] = popUintMsb(4n)(vector); // [0xFn, 0x15n]
151
+ * const [result2, rest2] = popUintMsb(16n)(vector); // [0xF500n, 1n]
152
+ * ```
153
+ */
154
+ export const popUintMsb = len => {
155
+ const m = mask(len);
156
+ return v => {
157
+ const d = length(v) - len;
158
+ return [(v >> d) & m, vec(d)(v)];
159
+ };
160
+ };
161
+ /**
162
+ * Concat the given vectors of bits. The first vector is the least significant.
163
+ *
164
+ * @type {(a: Vec) => (b: Vec) => Vec}
165
+ *
166
+ * @example
167
+ *
168
+ * ```js
169
+ * const u8 = vec(8n)
170
+ * const a = u8(0x45n) // 0x145n
171
+ * const b = u8(0x89n) // 0x189n
172
+ * const ab = concatLsb(a)(b) // 0x18945n
173
+ * ```
174
+ */
175
+ export const concatLsb = a => {
176
+ const aLen = length(a);
177
+ const m = mask(aLen);
178
+ return b => (b << aLen) | (a & m);
179
+ };
180
+ /**
181
+ * Concat the given vectors of bits. The first vector is the most significant.
182
+ *
183
+ * @type {(b: Vec) => (a: Vec) => Vec}
184
+ *
185
+ * @example
186
+ *
187
+ * ```js
188
+ * const u8 = vec(8n)
189
+ * const a = u8(0x45n) // 0x145n
190
+ * const b = u8(0x89n) // 0x189n
191
+ * const ab = concatMsb(a)(b) // 0x14589n
192
+ * ```
193
+ */
194
+ export const concatMsb = flip(concatLsb);
@@ -1,9 +1,23 @@
1
1
  declare namespace _default {
2
- function uintExample(): void;
3
- function vecExample(): void;
4
- function length(): void;
5
- function bitset(): void;
6
- function appendBack(): void;
7
- function removeBack(): void;
2
+ export namespace examples {
3
+ function vec(): void;
4
+ function uint(): void;
5
+ function uintLsb(): void;
6
+ function uintMsb(): void;
7
+ function popUintLsb(): void;
8
+ function popUintMsb(): void;
9
+ function concatLsb(): void;
10
+ function concatMsb(): void;
11
+ function removeLsb(): void;
12
+ function removeMsb(): void;
13
+ }
14
+ export function uintLsb_1(): void;
15
+ export { uintLsb_1 as uintLsb };
16
+ export function uintSmall(): void;
17
+ export function vecExample(): void;
18
+ export function length(): void;
19
+ export function bitset(): void;
20
+ export function appendBack(): void;
21
+ export function removeBack(): void;
8
22
  }
9
23
  export default _default;
@@ -1,13 +1,163 @@
1
- import { empty, len, appendBack, vec, uint, removeFront } from './module.f.mjs';
1
+ import { empty, vec, length, concatLsb, uintLsb, uintMsb, removeLsb, concatMsb, removeMsb, uint, popUintLsb, popUintMsb } from './module.f.mjs';
2
2
  export default {
3
- uintExample: () => {
4
- const vector = 53n;
5
- const extract3Bits = uint(3n);
3
+ examples: {
4
+ vec: () => {
5
+ const vec4 = vec(4n);
6
+ const v0 = vec4(5n); // 0x15n
7
+ if (v0 !== 0x15n) {
8
+ throw v0;
9
+ }
10
+ const v1 = vec4(0x5fen); // 0x1En
11
+ if (v1 !== 0x1en) {
12
+ throw v1;
13
+ }
14
+ },
15
+ uint: () => {
16
+ const vector = vec(8n)(0x5n); // 0x105n
17
+ if (vector !== 0x105n) {
18
+ throw vector;
19
+ }
20
+ const result = uint(vector); // result is 0x5n
21
+ if (result !== 0x5n) {
22
+ throw result;
23
+ }
24
+ },
25
+ uintLsb: () => {
26
+ const vector = vec(8n)(0xf5n); // 0x1F5n
27
+ if (vector !== 0x1f5n) {
28
+ throw vector;
29
+ }
30
+ const result = uintLsb(4n)(vector); // result is 5n
31
+ if (result !== 5n) {
32
+ throw result;
33
+ }
34
+ const result2 = uintLsb(16n)(vector); // result2 is 0xF5n
35
+ if (result2 !== 0xf5n) {
36
+ throw result2;
37
+ }
38
+ },
39
+ uintMsb: () => {
40
+ const vector = vec(8n)(0xf5n); // 0x1F5n
41
+ if (vector !== 0x1f5n) {
42
+ throw vector;
43
+ }
44
+ const result = uintMsb(4n)(vector); // result is 0xFn
45
+ if (result !== 0xfn) {
46
+ throw result;
47
+ }
48
+ const result2 = uintMsb(16n)(vector); // result2 is 0xF500n
49
+ if (result2 !== 0xf500n) {
50
+ throw result2;
51
+ }
52
+ },
53
+ popUintLsb: () => {
54
+ const vector = vec(8n)(0xf5n); // 0x1F5n
55
+ const [result, rest] = popUintLsb(4n)(vector); // result is 5n, rest is 0x1Fn
56
+ if (result !== 5n) {
57
+ throw result;
58
+ }
59
+ if (rest !== 0x1fn) {
60
+ throw rest;
61
+ }
62
+ const [result2, rest2] = popUintLsb(16n)(vector); // result2 is 0xF5n, rest2 is 1n
63
+ if (result2 !== 0xf5n) {
64
+ throw result2;
65
+ }
66
+ if (rest2 !== 1n) {
67
+ throw rest2;
68
+ }
69
+ },
70
+ popUintMsb: () => {
71
+ const vector = vec(8n)(0xf5n); // 0x1F5n
72
+ const [result, rest] = popUintMsb(4n)(vector); // [0xFn, 0x15n]
73
+ if (result !== 0xfn) {
74
+ throw result;
75
+ }
76
+ if (rest !== 0x15n) {
77
+ throw rest;
78
+ }
79
+ const [result2, rest2] = popUintMsb(16n)(vector); // [0xF500n, 1n]
80
+ if (result2 !== 0xf500n) {
81
+ throw result2;
82
+ }
83
+ if (rest2 !== 1n) {
84
+ throw rest2;
85
+ }
86
+ },
87
+ concatLsb: () => {
88
+ const u8 = vec(8n);
89
+ const a = u8(0x45n); // 0x145n
90
+ if (a !== 0x145n) {
91
+ throw a;
92
+ }
93
+ const b = u8(0x89n); // 0x189n
94
+ if (b !== 0x189n) {
95
+ throw b;
96
+ }
97
+ const ab = concatLsb(a)(b); // 0x18945n
98
+ if (ab !== 0x18945n) {
99
+ throw ab;
100
+ }
101
+ },
102
+ concatMsb: () => {
103
+ const u8 = vec(8n);
104
+ const a = u8(0x45n); // 0x145n
105
+ if (a !== 0x145n) {
106
+ throw a;
107
+ }
108
+ const b = u8(0x89n); // 0x189n
109
+ if (b !== 0x189n) {
110
+ throw b;
111
+ }
112
+ const ab = concatMsb(a)(b); // 0x14589n
113
+ if (ab !== 0x14589n) {
114
+ throw ab;
115
+ }
116
+ },
117
+ removeLsb: () => {
118
+ const v = vec(16n)(0x3456n); // 0x13456n
119
+ if (v !== 0x13456n) {
120
+ throw v;
121
+ }
122
+ const r = removeLsb(4n)(v); // 0x1345n
123
+ if (r !== 0x1345n) {
124
+ throw r;
125
+ }
126
+ const r2 = removeLsb(24n)(v); // 0x1n
127
+ if (r2 !== 0x1n) {
128
+ throw r2;
129
+ }
130
+ },
131
+ removeMsb: () => {
132
+ const v = vec(16n)(0x3456n); // 0x13456n
133
+ if (v !== 0x13456n) {
134
+ throw v;
135
+ }
136
+ const r = removeMsb(4n)(v); // 0x1456n
137
+ if (r !== 0x1456n) {
138
+ throw r;
139
+ }
140
+ const r2 = removeMsb(24n)(v); // 0x1n
141
+ if (r2 !== 0x1n) {
142
+ throw r2;
143
+ }
144
+ }
145
+ },
146
+ uintLsb: () => {
147
+ const vector = 117n;
148
+ const extract3Bits = uintLsb(3n);
6
149
  const result = extract3Bits(vector); // result is 0b101n (5n)
7
150
  if (result !== 5n) {
8
151
  throw result;
9
152
  }
10
153
  },
154
+ uintSmall: () => {
155
+ const vector = 3n;
156
+ const extract3Bits = uintLsb(3n)(vector);
157
+ if (extract3Bits !== 1n) {
158
+ throw extract3Bits;
159
+ }
160
+ },
11
161
  vecExample: () => {
12
162
  const createVector = vec(4n);
13
163
  const vector = createVector(5n); // vector is 0b10101n
@@ -16,7 +166,7 @@ export default {
16
166
  }
17
167
  },
18
168
  length: () => {
19
- const i = len(empty);
169
+ const i = length(empty);
20
170
  if (i !== 0n) {
21
171
  throw i;
22
172
  }
@@ -26,10 +176,10 @@ export default {
26
176
  if (v !== 0x1fen) {
27
177
  throw v;
28
178
  }
29
- if (len(v) !== 8n) {
179
+ if (length(v) !== 8n) {
30
180
  throw 'len';
31
181
  }
32
- const u = uint(8n)(v);
182
+ const u = uintLsb(8n)(v);
33
183
  if (u !== 0xfen) {
34
184
  throw v;
35
185
  }
@@ -38,11 +188,11 @@ export default {
38
188
  const vec8 = vec(8n);
39
189
  const a = vec8(0x345n);
40
190
  const b = vec8(0x789n);
41
- const ab = appendBack(a)(b);
191
+ const ab = concatLsb(a)(b);
42
192
  if (ab !== 0x18945n) {
43
193
  throw ab;
44
194
  }
45
- const s = len(ab);
195
+ const s = length(ab);
46
196
  if (s !== 16n) {
47
197
  throw `appendBack: ${s}`;
48
198
  }
@@ -52,7 +202,7 @@ export default {
52
202
  if (v !== 0x32345n) {
53
203
  throw v.toString(16);
54
204
  }
55
- const r = removeFront(9n)(v);
205
+ const r = removeLsb(9n)(v);
56
206
  if (r !== 0x191n) {
57
207
  throw r.toString(16);
58
208
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "type": "module",
5
5
  "description": "FunctionalScript is a functional subset of JavaScript",
6
6
  "scripts": {
@@ -0,0 +1,18 @@
1
+ # Vector of Bits
2
+
3
+ A **vector of bits** is represented as a `bigint`. The value is always positive, and an **empty vector** is denoted by `1n`.
4
+
5
+ ## Key Characteristics
6
+
7
+ - The **most significant bit** with a value of `1` is called the **`stop bit`**.
8
+ - The **`stop bit`** marks the boundary of the vector.
9
+ - The **`length`** of a vector represents the number of meaningful bits (excluding the **`stop bit`**).
10
+ - An **empty vector** is represented by `1n`, with the implicit **`stop bit`** as the only bit.
11
+
12
+ ## Example
13
+
14
+ | Vector | Binary Representation | `length` | Vector Items |
15
+ |---------------|-----------------------|----------|--------------|
16
+ | `0b1001n` | `0b1001n` | 3 | `001` |
17
+ | `0x1FF` | `0b111111111` | 8 | `11111111` |
18
+ | `1n` (empty) | `0b1` | 0 | (none) |
@@ -1,5 +1,6 @@
1
1
  // @ts-self-types="./module.f.d.mts"
2
2
  import { log2 } from '../bigint/module.f.mjs'
3
+ import { flip } from '../function/module.f.mjs'
3
4
 
4
5
  /**
5
6
  * A vector of bits represented as a `bigint`.
@@ -15,76 +16,191 @@ export const empty = 1n
15
16
  /**
16
17
  * Calculates the length of the given vector of bits.
17
18
  */
18
- export const len = log2
19
+ export const length = log2
19
20
 
20
21
  /**
21
- * Extract an unsigned integer of the given `uintLen` from the given vector.
22
+ * Creates a vector of bits of the given `len` and the given unsigned integer.
22
23
  *
23
- * @type {(uintLen: bigint) => (v: Vec) => bigint}
24
+ * @type {(len: bigint) => (ui: bigint) => Vec}
24
25
  *
25
26
  * @example
26
27
  *
27
28
  * ```js
28
- * const vector = 0b110101n;
29
- * const extract3Bits = uint(3n);
30
- * const result = extract3Bits(vector); // result is 0b101n (5n)
29
+ * const vec4 = vec(4n)
30
+ * const v0 = vec4(5n) // 0x15n
31
+ * const v1 = vec4(0x5FEn) // 0x1En
31
32
  * ```
32
33
  */
33
- export const uint = uintLen => {
34
- const mask = (1n << uintLen) - 1n
35
- return data => data & mask
34
+ export const vec = len => {
35
+ if (len <= 0n) { return () => empty }
36
+ const stop = 1n << len
37
+ const mask = stop - 1n
38
+ return data => stop | (data & mask)
36
39
  }
37
40
 
41
+ /** @type {(len: bigint) => bigint} */
42
+ const mask = len => (1n << len) - 1n
43
+
38
44
  /**
39
- * Creates a vector of bits of the given `vecLen` from the given unsigned integer.
45
+ * Returns the unsigned integer of the given vector by removing a stop bit.
40
46
  *
41
- * @type {(vecLen: bigint) => (ui: bigint) => Vec}
47
+ * @type {(len: Vec) => bigint}
42
48
  *
43
49
  * @example
44
50
  *
45
51
  * ```js
46
- * const createVector = vec(4n);
47
- * const vector = createVector(5n); // vector is 0b10101n
52
+ * const vector = vec(8n)(0x5n) // 0x105n
53
+ * const result = uint(vector); // result is 0x5n
48
54
  * ```
49
55
  */
50
- export const vec = vecLen => {
51
- const stop = 1n << vecLen
52
- const mask = stop - 1n
53
- return data => (data & mask) | stop
54
- }
56
+ export const uint = v => v ^ (1n << length(v))
55
57
 
56
58
  /**
57
- * Appends the vector `b` to the back of the vector `a`.
59
+ * Extract the least significant unsigned integer from the given vector.
58
60
  *
59
- * @type {(a: Vec) => (b: Vec) => Vec}
61
+ * @type {(uintLen: bigint) => (v: Vec) => bigint}
60
62
  *
61
63
  * @example
62
64
  *
63
65
  * ```js
64
- * const vec8 = vec(8n)
65
- * const a = vec8(0x345n)
66
- * const b = vec8(0x789n)
67
- * const ab = appendBack(a)(b) // 0x18945n
66
+ * const vector = vec(8n)(0xF5n) // 0x1F5n
67
+ * const result = uintLsb(4n)(vector); // result is 5n
68
+ * const result2 = uintLsb(16n)(vector); // result2 is 0xF5n
68
69
  * ```
69
70
  */
70
- export const appendBack = a => {
71
- const aLen = len(a)
72
- return b => a | (b << aLen)
71
+ export const uintLsb = len => {
72
+ const m = mask(len)
73
+ return v => {
74
+ const result = v & m
75
+ return result === v ? uint(v) : result
76
+ }
73
77
  }
74
78
 
75
79
  /**
76
- * Removes the first `len` bits from the given vector.
80
+ * Removes the first `len` least significant bits from the given vector.
77
81
  *
78
82
  * @type {(len: bigint) => (v: Vec) => Vec}
79
83
  *
80
84
  * @example
81
85
  *
82
86
  * ```js
83
- * const v = vec(17n)(0x12345n) // v = 0x32345n
84
- * const r = removeFront(9n)(v) // r = 0x191n
87
+ * const v = vec(16n)(0x3456n) // 0x13456n
88
+ * const r = removeLsb(4n)(v) // 0x1345n
89
+ * const r2 = removeLsb(24n)(v) // 0x1n
85
90
  * ```
86
91
  */
87
- export const removeFront = len => v => {
92
+ export const removeLsb = len => v => {
88
93
  const r = v >> len
89
94
  return r === 0n ? empty : r
90
95
  }
96
+
97
+ /**
98
+ * Extracts the least significant unsigned integer and removes it from the vector.
99
+ *
100
+ * @type {(len: bigint) => (v: Vec) => [bigint, Vec]}
101
+ *
102
+ * @example
103
+ *
104
+ * ```js
105
+ * const vector = vec(8n)(0xF5n) // 0x1F5n
106
+ * const [result, rest] = popUintLsb(4n)(vector); // result is 5n, rest is 0x1Fn
107
+ * const [result2, rest2] = popUintLsb(16n)(vector); // result2 is 0xF5n, rest2 is 1n
108
+ * ```
109
+ */
110
+ export const popUintLsb = len => {
111
+ const m = mask(len)
112
+ return v => {
113
+ const result = v & m
114
+ return result === v ? [uint(v), empty] : [result, v >> len]
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Extract the most significant unsigned integer of the given `len` from the given vector.
120
+ *
121
+ * @type {(len: bigint) => (v: Vec) => bigint}
122
+ *
123
+ * @example
124
+ *
125
+ * ```js
126
+ * const vector = vec(8n)(0xF5n) // 0x1F5n
127
+ * const result = uintMsb(4n)(vector); // result is 0xFn
128
+ * const result2 = uintMsb(16n)(vector); // result2 is 0xF500n
129
+ * ```
130
+ */
131
+ export const uintMsb = len => {
132
+ const m = mask(len)
133
+ return v => (v >> (length(v) - len)) & m
134
+ }
135
+
136
+ /**
137
+ * Removes the first `len` most significant bits from the given vector.
138
+ *
139
+ * @type {(len: bigint) => (v: Vec) => Vec}
140
+ *
141
+ * @example
142
+ *
143
+ * ```js
144
+ * const v = vec(16n)(0x3456n) // 0x13456n
145
+ * const r = removeMsb(4n)(v) // 0x1456n
146
+ * const r2 = removeMsb(24n)(v) // 0x1n
147
+ * ```
148
+ */
149
+ export const removeMsb = len => v => vec(length(v) - len)(v)
150
+
151
+ /**
152
+ * Extracts the most significant unsigned integer and removes it from the vector.
153
+ *
154
+ * @type {(len: bigint) => (v: Vec) => [bigint, Vec]}
155
+ *
156
+ * @example
157
+ *
158
+ * ```js
159
+ * const vector = vec(8n)(0xF5n) // 0x1F5n
160
+ * const [result, rest] = popUintMsb(4n)(vector); // [0xFn, 0x15n]
161
+ * const [result2, rest2] = popUintMsb(16n)(vector); // [0xF500n, 1n]
162
+ * ```
163
+ */
164
+ export const popUintMsb = len => {
165
+ const m = mask(len)
166
+ return v => {
167
+ const d = length(v) - len
168
+ return [(v >> d) & m, vec(d)(v)]
169
+ }
170
+ }
171
+
172
+ /**
173
+ * Concat the given vectors of bits. The first vector is the least significant.
174
+ *
175
+ * @type {(a: Vec) => (b: Vec) => Vec}
176
+ *
177
+ * @example
178
+ *
179
+ * ```js
180
+ * const u8 = vec(8n)
181
+ * const a = u8(0x45n) // 0x145n
182
+ * const b = u8(0x89n) // 0x189n
183
+ * const ab = concatLsb(a)(b) // 0x18945n
184
+ * ```
185
+ */
186
+ export const concatLsb = a => {
187
+ const aLen = length(a)
188
+ const m = mask(aLen)
189
+ return b => (b << aLen) | (a & m)
190
+ }
191
+
192
+ /**
193
+ * Concat the given vectors of bits. The first vector is the most significant.
194
+ *
195
+ * @type {(b: Vec) => (a: Vec) => Vec}
196
+ *
197
+ * @example
198
+ *
199
+ * ```js
200
+ * const u8 = vec(8n)
201
+ * const a = u8(0x45n) // 0x145n
202
+ * const b = u8(0x89n) // 0x189n
203
+ * const ab = concatMsb(a)(b) // 0x14589n
204
+ * ```
205
+ */
206
+ export const concatMsb = flip(concatLsb)
@@ -1,41 +1,129 @@
1
- import { empty, len, appendBack, vec, uint, removeFront } from './module.f.mjs'
1
+ import { empty, vec, length, concatLsb, uintLsb, uintMsb, removeLsb, concatMsb, removeMsb, uint, popUintLsb, popUintMsb } from './module.f.mjs'
2
2
 
3
3
  export default {
4
- uintExample: () => {
5
- const vector = 0b110101n;
6
- const extract3Bits = uint(3n);
7
- const result = extract3Bits(vector); // result is 0b101n (5n)
4
+ examples: {
5
+ vec: () => {
6
+ const vec4 = vec(4n)
7
+ const v0 = vec4(5n) // 0x15n
8
+ if (v0 !== 0x15n) { throw v0 }
9
+ const v1 = vec4(0x5FEn) // 0x1En
10
+ if (v1 !== 0x1En) { throw v1 }
11
+ },
12
+ uint: () => {
13
+ const vector = vec(8n)(0x5n) // 0x105n
14
+ if (vector !== 0x105n) { throw vector }
15
+ const result = uint(vector); // result is 0x5n
16
+ if (result !== 0x5n) { throw result }
17
+ },
18
+ uintLsb: () => {
19
+ const vector = vec(8n)(0xF5n) // 0x1F5n
20
+ if (vector !== 0x1F5n) { throw vector }
21
+ const result = uintLsb(4n)(vector); // result is 5n
22
+ if (result !== 5n) { throw result }
23
+ const result2 = uintLsb(16n)(vector); // result2 is 0xF5n
24
+ if (result2 !== 0xF5n) { throw result2 }
25
+ },
26
+ uintMsb: () => {
27
+ const vector = vec(8n)(0xF5n) // 0x1F5n
28
+ if (vector !== 0x1F5n) { throw vector }
29
+ const result = uintMsb(4n)(vector); // result is 0xFn
30
+ if (result !== 0xFn) { throw result }
31
+ const result2 = uintMsb(16n)(vector); // result2 is 0xF500n
32
+ if (result2 !== 0xF500n) { throw result2 }
33
+ },
34
+ popUintLsb: () => {
35
+ const vector = vec(8n)(0xF5n) // 0x1F5n
36
+ const [result, rest] = popUintLsb(4n)(vector); // result is 5n, rest is 0x1Fn
37
+ if (result !== 5n) { throw result }
38
+ if (rest !== 0x1Fn) { throw rest }
39
+ const [result2, rest2] = popUintLsb(16n)(vector); // result2 is 0xF5n, rest2 is 1n
40
+ if (result2 !== 0xF5n) { throw result2 }
41
+ if (rest2 !== 1n) { throw rest2 }
42
+ },
43
+ popUintMsb: () => {
44
+ const vector = vec(8n)(0xF5n) // 0x1F5n
45
+ const [result, rest] = popUintMsb(4n)(vector); // [0xFn, 0x15n]
46
+ if (result !== 0xFn) { throw result }
47
+ if (rest !== 0x15n) { throw rest }
48
+ const [result2, rest2] = popUintMsb(16n)(vector); // [0xF500n, 1n]
49
+ if (result2 !== 0xF500n) { throw result2 }
50
+ if (rest2 !== 1n) { throw rest2 }
51
+ },
52
+ concatLsb: () => {
53
+ const u8 = vec(8n)
54
+ const a = u8(0x45n) // 0x145n
55
+ if (a !== 0x145n) { throw a }
56
+ const b = u8(0x89n) // 0x189n
57
+ if (b !== 0x189n) { throw b }
58
+ const ab = concatLsb(a)(b) // 0x18945n
59
+ if (ab !== 0x18945n) { throw ab }
60
+ },
61
+ concatMsb: () => {
62
+ const u8 = vec(8n)
63
+ const a = u8(0x45n) // 0x145n
64
+ if (a !== 0x145n) { throw a }
65
+ const b = u8(0x89n) // 0x189n
66
+ if (b !== 0x189n) { throw b }
67
+ const ab = concatMsb(a)(b) // 0x14589n
68
+ if (ab !== 0x14589n) { throw ab }
69
+ },
70
+ removeLsb: () => {
71
+ const v = vec(16n)(0x3456n) // 0x13456n
72
+ if (v !== 0x13456n) { throw v }
73
+ const r = removeLsb(4n)(v) // 0x1345n
74
+ if (r !== 0x1345n) { throw r }
75
+ const r2 = removeLsb(24n)(v) // 0x1n
76
+ if (r2 !== 0x1n) { throw r2 }
77
+ },
78
+ removeMsb: () => {
79
+ const v = vec(16n)(0x3456n) // 0x13456n
80
+ if (v !== 0x13456n) { throw v }
81
+ const r = removeMsb(4n)(v) // 0x1456n
82
+ if (r !== 0x1456n) { throw r }
83
+ const r2 = removeMsb(24n)(v) // 0x1n
84
+ if (r2 !== 0x1n) { throw r2 }
85
+ }
86
+ },
87
+ uintLsb: () => {
88
+ const vector = 0b1110101n
89
+ const extract3Bits = uintLsb(3n)
90
+ const result = extract3Bits(vector) // result is 0b101n (5n)
8
91
  if (result !== 0b101n) { throw result }
9
92
  },
93
+ uintSmall: () => {
94
+ const vector = 0b11n
95
+ const extract3Bits = uintLsb(3n)(vector)
96
+ if (extract3Bits !== 0b1n) { throw extract3Bits }
97
+ },
10
98
  vecExample: () => {
11
- const createVector = vec(4n);
12
- const vector = createVector(5n); // vector is 0b10101n
99
+ const createVector = vec(4n)
100
+ const vector = createVector(5n) // vector is 0b10101n
13
101
  if (vector !== 0b10101n) { throw vector }
14
102
  },
15
103
  length: () => {
16
- const i = len(empty)
104
+ const i = length(empty)
17
105
  if (i !== 0n) { throw i}
18
106
  },
19
107
  bitset: () => {
20
108
  const v = vec(8n)(0x5FEn)
21
109
  if (v !== 0x1FEn) { throw v }
22
- if (len(v) !== 8n) { throw 'len' }
23
- const u = uint(8n)(v)
110
+ if (length(v) !== 8n) { throw 'len' }
111
+ const u = uintLsb(8n)(v)
24
112
  if (u !== 0xFEn) { throw v }
25
113
  },
26
114
  appendBack: () => {
27
115
  const vec8 = vec(8n)
28
116
  const a = vec8(0x345n)
29
117
  const b = vec8(0x789n)
30
- const ab = appendBack(a)(b)
118
+ const ab = concatLsb(a)(b)
31
119
  if (ab !== 0x18945n) { throw ab }
32
- const s = len(ab)
120
+ const s = length(ab)
33
121
  if (s !== 16n) { throw `appendBack: ${s}` }
34
122
  },
35
123
  removeBack: () => {
36
124
  const v = vec(17n)(0x12345n)
37
125
  if (v !== 0x32345n) { throw v.toString(16) }
38
- const r = removeFront(9n)(v)
126
+ const r = removeLsb(9n)(v)
39
127
  if (r !== 0x191n) { throw r.toString(16) }
40
128
  }
41
129
  }