functionalscript 0.0.302 → 0.0.306

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.302",
3
+ "version": "0.0.306",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/sha2/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ const array = require('../types/array')
2
+
1
3
  /**
2
4
  * @typedef {{
3
5
  * readonly f: (i: number) => number
@@ -5,12 +7,12 @@
5
7
  * }} HashInput
6
8
  */
7
9
 
8
- /** @typedef {Int32Array} Hash8 */
10
+ /** @typedef {array.Array8<number>} Hash8 */
9
11
 
10
- /** @typedef {Int32Array} Array16 */
12
+ /** @typedef {array.Array16<number>} Array16 */
11
13
 
12
14
  /** @type {(input: number) => (pos: number) => number} */
13
- const appendOne = input => pos => input | (1 << 31 - pos)
15
+ const appendOneWithZeros = input => pos => (input >> pos << pos) | (1 << pos)
14
16
 
15
17
  /** @type {(input: number) => (pos: number) => number} */
16
18
  const mod = a => b => (a % b + b) % b
@@ -24,7 +26,7 @@ const padding = input => bitsCount => {
24
26
  i < appendBlockIndex ?
25
27
  input[i] :
26
28
  i === appendBlockIndex ?
27
- (appendBlockIndex >= input.length ? 0x8000_0000 : appendOne(input[appendBlockIndex])(bitsCount % 32)) :
29
+ (appendBlockIndex >= input.length ? 0x8000_0000 : appendOneWithZeros(input[appendBlockIndex])(31 - bitsCount % 32)) :
28
30
  i === length - 2 ?
29
31
  (bitsCount / 0x1_0000_0000) | 0 :
30
32
  i === length - 1 ?
@@ -72,46 +74,59 @@ const smallSigma0 = smallSigma(7)(18)(3)
72
74
  const smallSigma1 = smallSigma(17)(19)(10)
73
75
 
74
76
  /** @type {Hash8} */
75
- const init256 = new Int32Array([0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19])
77
+ const init256 = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19]
76
78
 
77
79
  /** @type {(input: readonly number[]) => (bitsCount: number) => Hash8} */
78
80
  const computeSha256 = input => bitsCount => compute(input)(bitsCount)(init256)
79
81
 
80
82
  /** @type {Hash8} */
81
- const init224 = new Int32Array([0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4])
83
+ const init224 = [0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4]
82
84
 
83
85
  const k = [
84
- new Int32Array([
86
+ [
85
87
  0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
86
- 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174]),
87
- new Int32Array([
88
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174],
89
+ [
88
90
  0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
89
- 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967]),
90
- new Int32Array([
91
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967],
92
+ [
91
93
  0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
92
- 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070]),
93
- new Int32Array([
94
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070],
95
+ [
94
96
  0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
95
- 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2]),
97
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2],
96
98
  ];
97
99
 
98
100
  /** @type {(input: readonly number[]) => (bitsCount: number) => Hash8} */
99
101
  const computeSha224 = input => bitsCount => compute(input)(bitsCount)(init224)
100
102
 
103
+ /** @type {(a: array.Array4<number>) => number} */
104
+ const wi = a => (smallSigma1(a[0]) + a[1] + smallSigma0(a[2]) + a[3]) | 0
105
+
101
106
  /** @type {(input: Array16) => Array16} */
102
107
  const nextW = w => {
103
- for (let t = 0; t < 16; t++) {
104
- w[t] = smallSigma1(w[(t + 14) & 0xF]) + w[(t + 9) & 0xF] + smallSigma0(w[(t + 1) & 0xF]) + w[t]
105
- }
106
- return w
108
+ const _0 = wi([w[14], w[ 9], w[ 1], w[ 0]])
109
+ const _1 = wi([w[15], w[10], w[ 2], w[ 1]])
110
+ const _2 = wi([ _0, w[11], w[ 3], w[ 2]])
111
+ const _3 = wi([ _1, w[12], w[ 4], w[ 3]])
112
+ const _4 = wi([ _2, w[13], w[ 5], w[ 4]])
113
+ const _5 = wi([ _3, w[14], w[ 6], w[ 5]])
114
+ const _6 = wi([ _4, w[15], w[ 7], w[ 6]])
115
+ const _7 = wi([ _5, _0, w[ 8], w[ 7]])
116
+ const _8 = wi([ _6, _1, w[ 9], w[ 8]])
117
+ const _9 = wi([ _7, _2, w[10], w[ 9]])
118
+ const _A = wi([ _8, _3, w[11], w[10]])
119
+ const _B = wi([ _9, _4, w[12], w[11]])
120
+ const _C = wi([ _A, _5, w[13], w[12]])
121
+ const _D = wi([ _B, _6, w[14], w[13]])
122
+ const _E = wi([ _C, _7, w[15], w[14]])
123
+ const _F = wi([ _D, _8, _0, w[15]])
124
+ return [_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _A, _B, _C, _D, _E, _F]
107
125
  }
108
126
 
109
127
  /** @type {(init: Hash8) => (data: Array16) => Hash8} */
110
128
  const compress = init => data => {
111
- let w = new Int32Array(16)
112
- for (let t = 0; t < 16; t++) {
113
- w[t] = data[t]
114
- }
129
+ let w = data
115
130
 
116
131
  let a = init[0]
117
132
  let b = init[1]
@@ -139,16 +154,16 @@ const compress = init => data => {
139
154
  w = nextW(w)
140
155
  }
141
156
 
142
- return new Int32Array([
143
- init[0] + a,
144
- init[1] + b,
145
- init[2] + c,
146
- init[3] + d,
147
- init[4] + e,
148
- init[5] + f,
149
- init[6] + g,
150
- init[7] + h,
151
- ])
157
+ return [
158
+ (init[0] + a) | 0,
159
+ (init[1] + b) | 0,
160
+ (init[2] + c) | 0,
161
+ (init[3] + d) | 0,
162
+ (init[4] + e) | 0,
163
+ (init[5] + f) | 0,
164
+ (init[6] + g) | 0,
165
+ (init[7] + h) | 0,
166
+ ]
152
167
  }
153
168
 
154
169
  /** @type {(input: readonly number[]) => (bitsCount: number) => (init: Hash8) => Hash8} */
@@ -160,9 +175,9 @@ const compute = input => bitsCount => init => {
160
175
  const chunkCount = length / 16
161
176
  for (let i = 0; i < chunkCount; i++) {
162
177
  const s = i * 16
163
- result = compress(result)(new Int32Array([
178
+ result = compress(result)([
164
179
  f(s + 0), f(s + 1), f(s + 2), f(s + 3), f(s + 4), f(s + 5), f(s + 6), f(s + 7),
165
- f(s + 8), f(s + 9), f(s + 10), f(s + 11), f(s + 12), f(s + 13), f(s + 14), f(s + 15)]))
180
+ f(s + 8), f(s + 9), f(s + 10), f(s + 11), f(s + 12), f(s + 13), f(s + 14), f(s + 15)])
166
181
  }
167
182
 
168
183
  return result
package/sha2/test.js CHANGED
@@ -34,20 +34,27 @@ const stringify = a => json.stringify(sort)(a)
34
34
 
35
35
  {
36
36
  const hash = _.computeSha256([])(0)
37
- const result = stringify(Array.from(hash).map(toHexString))
37
+ const result = stringify(hash.map(toHexString))
38
38
  if (result !== '["e3b0c442","98fc1c14","9afbf4c8","996fb924","27ae41e4","649b934c","a495991b","7852b855"]') { throw result }
39
39
  }
40
40
 
41
41
  {
42
42
  const hash = _.computeSha224([])(0)
43
- const result = stringify(Array.from(hash).map(toHexString))
43
+ const result = stringify(hash.map(toHexString))
44
44
  if (result !== '["d14a028c","2a3a2bc9","476102bb","288234c4","15a2b01f","828ea62a","c5b3e42f","bdd387cb"]') { throw result }
45
45
  }
46
46
 
47
47
  {
48
48
  //[0x68656C6C, 0x6F20776F, 0x726C6400] represents phrase 'hello world'
49
49
  const hash = _.computeSha256([0x68656C6C, 0x6F20776F, 0x726C6400])(88)
50
- const result = stringify(Array.from(hash).map(toHexString))
50
+ const result = stringify(hash.map(toHexString))
51
+ if (result !== '["b94d27b9","934d3e08","a52e52d7","da7dabfa","c484efe3","7a5380ee","9088f7ac","e2efcde9"]') { throw result }
52
+ }
53
+
54
+ {
55
+ //[0x68656C6C, 0x6F20776F, 0x726C6488] represents phrase 'hello world' with 1's at the end
56
+ const hash = _.computeSha256([0x68656C6C, 0x6F20776F, 0x726C64FF])(88)
57
+ const result = stringify(hash.map(toHexString))
51
58
  if (result !== '["b94d27b9","934d3e08","a52e52d7","da7dabfa","c484efe3","7a5380ee","9088f7ac","e2efcde9"]') { throw result }
52
59
  }
53
60
 
@@ -60,7 +67,7 @@ const stringify = a => json.stringify(sort)(a)
60
67
  {
61
68
  const input = Array(16).fill(0x31313131)
62
69
  const hash = _.computeSha256(input)(512)
63
- const result = stringify(Array.from(hash).map(toHexString))
70
+ const result = stringify(hash.map(toHexString))
64
71
  if (result !== '["3138bb9b","c78df27c","473ecfd1","410f7bd4","5ebac1f5","9cf3ff9c","fe4db77a","ab7aedd3"]') { throw result }
65
72
  }
66
73
 
@@ -47,6 +47,18 @@ const seq = require('../list')
47
47
  * @typedef {readonly[T, T, T, T, T]} Array5
48
48
  */
49
49
 
50
+ /**
51
+ * @template T
52
+ * @typedef {readonly[T, T, T, T, T, T, T, T]} Array8
53
+ */
54
+
55
+ /**
56
+ * @template T
57
+ * @typedef {readonly[T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T]} Array16
58
+ */
59
+
60
+ /** @typedef {0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15} Index16 */
61
+
50
62
  /**
51
63
  * @template T
52
64
  * @typedef {Array1<T>| Array2<T> | Array3<T> | Array4<T> | Array5<T>} Array1_5
@@ -13,6 +13,9 @@
13
13
  /** @type {(separator: string) => Fold<string>} */
14
14
  const join = separator => prior => value => `${prior}${separator}${value}`
15
15
 
16
+ /** @type {Fold<string>} */
17
+ const concat = a => b => `${a}${b}`
18
+
16
19
  /** @type {Fold<number>} */
17
20
  const addition = a => b => a + b
18
21
 
@@ -26,8 +29,8 @@ const addition = a => b => a + b
26
29
  const logicalNot = v => !v
27
30
 
28
31
  /**
29
- * @template T
30
- * @typedef {Binary<T, T, boolean>} Equal
32
+ * @template T
33
+ * @typedef {Binary<T, T, boolean>} Equal
31
34
  */
32
35
 
33
36
  /** @type {<T>(a: T) => (b: T) => boolean} */
@@ -93,4 +96,6 @@ module.exports = {
93
96
  foldToScan,
94
97
  /** @readonly */
95
98
  counter,
99
+ /** @readonly */
100
+ concat,
96
101
  }
@@ -297,6 +297,20 @@ const equalZip = e => a => b => () => {
297
297
  /** @type {<T>(e: operator.Equal<T>) => (a: List<T>) => (b: List<T>) => boolean} */
298
298
  const equal = e => a => b => every(equalZip(e)(a)(b))
299
299
 
300
+ /** @type {(s: string) => List<number>} */
301
+ const toCharCodes = s => {
302
+ /** @type {(i: number) => List<number>} */
303
+ const at = i => () => {
304
+ const r = s.charCodeAt(i)
305
+ if (isNaN(r)) { return undefined }
306
+ return { first: r, tail: at(i + 1) }
307
+ }
308
+ return at(0)
309
+ }
310
+
311
+ /** @type {(x: List<number>) => string} */
312
+ const fromCharCodes = x => fold(operator.concat)('')(map(String.fromCharCode)(x))
313
+
300
314
  module.exports = {
301
315
  /** @readonly */
302
316
  empty: undefined,
@@ -374,4 +388,8 @@ module.exports = {
374
388
  zip,
375
389
  /** @readonly */
376
390
  equal,
391
+ /** @readonly */
392
+ toCharCodes,
393
+ /** @readonly */
394
+ fromCharCodes,
377
395
  }
@@ -234,6 +234,12 @@ const stringify = sequence => json.stringify(sort)(_.toArray(sequence))
234
234
  if (result !== false) { throw result }
235
235
  }
236
236
 
237
+ {
238
+ const r = _.toCharCodes("Hello world!")
239
+ const x = _.fromCharCodes(r)
240
+ if (x !== "Hello world!") { throw x }
241
+ }
242
+
237
243
  // stress tests
238
244
 
239
245
  const stress = () => {