functionalscript 0.0.387 → 0.0.390

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/doc/vm.md CHANGED
@@ -1,17 +1,35 @@
1
- # VM
1
+ # NaNVM
2
2
 
3
- [Tagged Pointer](https://en.wikipedia.org/wiki/Tagged_pointer).
3
+ https://en.wikipedia.org/wiki/Double-precision_floating-point_format
4
4
 
5
- ## Common (3 bit)
5
+ https://anniecherkaev.com/the-secret-life-of-nan
6
+ https://brionv.com/log/2018/05/17/javascript-engine-internals-nan-boxing/
6
7
 
7
- - `false`
8
- - `true`
9
- - `undefined`
10
- - `""`
11
- - `+infinity`
12
- - `-infinity`
13
- - `-0`
14
- - `NaN`
8
+
9
+ - 1 bit - sign (S)
10
+ - 11 bit - exponent (E)
11
+ - 52 bit - fraction (F)
12
+
13
+ |SE |F |Value |
14
+ |---|--------------|----------------|
15
+ |000|00000_00000000|+000000_00000000|
16
+ |...| | |
17
+ |3FF|00000_00000000|+000000_00000001|
18
+ |...| | |
19
+ |434|00000_00000000|+200000_00000000|
20
+ |...| | |
21
+ |7FF|00000_00000000|+inf |
22
+ |...| |NaN |
23
+ |800|00000_00000000|-0.0 |
24
+ |...| | |
25
+ |BFF|00000_00000000|-000000_00000001|
26
+ |...| | |
27
+ |C34|00000_00000000|-200000_00000000|
28
+ |...| | |
29
+ |FFF|00000_00000000|-inf |
30
+ |...| |NaN |
31
+
32
+ integer range: `[-2^53; +2^53]`.
15
33
 
16
34
  ## 6-bit Id String
17
35
 
@@ -23,143 +41,90 @@
23
41
  |`_` |`\x5F` | 1| 26|
24
42
  |`a`..`z`|`\x61`..`\x7A`|1A| 40|
25
43
 
26
- ## 64 bit platform
27
-
28
- Alignment: 8 bytes.
29
-
30
- Pointer: 2^64 / 2^3 = 2^61 bit
31
-
32
- ### Value
33
-
34
- - `63`: 9 x 7 bit string
35
- - `63`:
36
- - `61`: pointer + null, alignment - 8 bytes
37
- - `61`:
38
- - `60`: 4 x 15 bit string
39
- - `60`: 10 x 6 bit string
40
- - `61`:
41
- - `60`: 6 x 10 bit string
42
- - `60`: 5 x 12 bit string
43
- - `61`
44
- - `60`: float60
45
- - `60`:
46
- - `59`: bigInt59 (-576_460_752_303_423_488..576_460_752_303_423_487)
47
- - `59`:
48
- - `56`: 8 x 7-bit string
49
- - `56`: 7 x 8-bit string
50
- - `53`: int53
51
- - `53`: stringUInt53
52
- - `48`: 3 x 16 bit string
53
- - `32`: 2 x 16 bit string
54
- - `16`: 1 x UTF16 string
55
- - `3`: common
56
-
57
- ## Float64
44
+ ## 7FF & FFF
58
45
 
59
- https://en.wikipedia.org/wiki/Double-precision_floating-point_format
46
+ 53 bits.
60
47
 
61
- - 1 bit - sign (S)
62
- - 11 bit - exponent (E)
63
- - 52 bit - fraction (F)
48
+ Other values:
49
+
50
+ - `NaN`
51
+ - `+Inf`: 0x7FF00000_00000000
52
+ - `-Inf`: 0xFFF00000_00000000
53
+ - pointer + null:
54
+ - 32 bit for 32 bit platforms.
55
+ - 48 bit for current AMD64 https://en.wikipedia.org/wiki/X86-64#Canonical_form_addresses and ARM64
56
+ note: with alignments it can be further narrowed to 44-45 bit.
57
+ - `true`
58
+ - `false`
59
+ - `undefined`
64
60
 
65
- |E |Description |
66
- |-------------|------------------------|
67
- |000_0000_0000|F = 0: signed zeros |
68
- | |F != 0: subnormals |
69
- |000_0000_0001|E = 2^-1022 |
70
- |... | |
71
- |011_1111_1111|E = 2^0 |
72
- |100_0000_0000|E = 2^1 |
73
- |... | |
74
- |111_1111_1110|E = 2^1023 |
75
- |111_1111_1111|F = 0: signed infinities|
76
- | |F != 0: NaN |
77
-
78
- ## Float60
79
-
80
- - 1 bit - sign
81
- - 7 bit - exponent
82
- - 52 bit - fraction
83
-
84
- |E |Description|
85
- |--------|-----------|
86
- |000_0000|E = 2^-63 |
87
- |... | |
88
- |011_1111|E = 2^0 |
89
- |100_0000|E = 2^1 |
90
- |... | |
91
- |111_1111|E = 2^64 |
92
-
93
- Note: the type has no `+0`, `-0`, `+inf`, `-inf`, `NaN`.
94
-
95
- ## Object Structure
96
-
97
- Value Size = 8
98
- Counter size = max_memory_size / value_size.
99
-
100
- ### Type
101
-
102
- - `000`: double
103
- - `001`: string
104
- - `010`: array
105
- - `011`: object
106
- - `100`: bigInt
107
- - `101`: function
108
- - `110`:
109
- - `111`:
110
-
111
- ### Type & Counter
112
-
113
- - AtomicUSize:
114
- - `3`: type
115
- - `...`: counter
116
-
117
- ### String
118
-
119
- ```rust
120
- struct String {
121
- length: u32,
122
- array: [u16; self.length],
123
- }
124
- ```
125
-
126
- ### Function
127
-
128
- ```rust
129
- struct Function<length: u32> {
130
- func: pointer,
131
- array: [value; length]
132
- }
133
- ```
134
-
135
- ### BigInt
136
-
137
- ```rust
138
- struct BigInt {
139
- length: u32,
140
- array: [u64; self.length],
141
- }
142
- ```
143
-
144
- ### Array
145
-
146
- ```rust
147
- struct Array {
148
- length: u32,
149
- array: [Value; self.length],
150
- }
151
- ```
152
-
153
- ### Object
154
-
155
- ```rust
156
- struct Object {
157
- length: u32,
158
- array: [(Value, Value), self.length],
159
- indexArray: [u32, (self.length * log2(self.length) + 31) / u32],
160
- }
161
- ```
162
-
163
- Note: see https://262.ecma-international.org/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys and https://262.ecma-international.org/6.0/#sec-object-type
61
+ Optimization for
62
+ - string
63
+ - bigInt
64
+
65
+ Least used letters in English: Q, J, Z and X.
66
+
67
+ ### Layout 52
68
+
69
+ Starts with `0xFFF`
70
+
71
+ - `50`:
72
+ - `48`: stringUInt48 (0..281_474_976_710_655)
73
+ - `48`: 8 x 6 string
74
+ - `48`: `42` 7 x 6 string
75
+ - `48`: 6 x 8 string
76
+ - `50`:
77
+ - `48`: `45` 5 x 9 string
78
+ - `48`: 4 x 12 string
79
+ - `48`: 3 x 16 string
80
+ - `48`: `32`: 2 x 16 string
81
+ - `50`:
82
+ - `48`: `16`: 1 x 16 string
83
+ - `48`: `0`: ""
84
+ - `48`: false
85
+ - `48`: true
86
+ - `50`:
87
+ - `48`: ptr
88
+ - `48`: bigInt48 (140_737_488_355_328..140_737_488_355_327)
89
+ - `48`: undefined
90
+ - `48`: `-inf`
91
+
92
+ | | | |type |
93
+ |------|--|-------------|-----------|
94
+ |`1111`|48|stringUInt48 |`string` |
95
+ |`1110`|48|8 x 6 string | |
96
+ |`1101`|48|7 x 7 stringA| |
97
+ |`1100`|48|7 x 7 stringB| |
98
+ |`1011`|48|6 x 8 string | |
99
+ |`1010`|45|5 x 9 string | |
100
+ |`1001`|48|4 x 12 string| |
101
+ |`1000`|48|3 x 16 string| |
102
+ |`0111`|32|2 x 16 string| |
103
+ |`0110`|16|1 x 16 string| |
104
+ |`0101`| 0|empty string | |
105
+ |`0100`| 0|undefined |`undefined`|
106
+ |`0011`|48|ptr |... |
107
+ |`0010`|48|bigInt48 |`bigint` |
108
+ |`0001`| 0|bool |`bool` |
109
+ |`0000`| 0|-inf |`number` |
110
+
111
+ ## Pointer Kind
112
+
113
+ Alignment 8 bytes. 3 bits.
114
+
115
+ | |type | |
116
+ |----|----------|---------------|
117
+ |00.0|`object` |null |
118
+ |00.1| |object |
119
+ |01.0|`string` |string |
120
+ |01.1| | |
121
+ |10.0|`function`|function |
122
+ |10.1| |static function|
123
+ |11.0|`bigint` |bigint |
124
+ |11.1| | |
125
+
126
+ ## Order of object properties
127
+
128
+ See https://262.ecma-international.org/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys and https://262.ecma-international.org/6.0/#sec-object-type
164
129
 
165
130
  An integer index for Node.js, Deno and Bun means a value from `0` to `4294967294` including. 4_294_967_294 = 0xFFFF_FFFE. But an integer index in the ES6 standard is +0..2^53-1.
package/html/module.f.cjs CHANGED
@@ -1,6 +1,7 @@
1
1
  const list = require('../types/list/module.f.cjs')
2
2
  const object = require('../types/object/module.f.cjs')
3
3
  const { operator, compose } = require('../types/function/module.f.cjs')
4
+ const encoding = require('../text/encoding/module.f.cjs');
4
5
 
5
6
  /**
6
7
  * @typedef {|
@@ -73,7 +74,7 @@ const escapeCharCode = code => {
73
74
  }
74
75
  }
75
76
 
76
- const escape = compose(list.toCharCodeList)(list.map(escapeCharCode))
77
+ const escape = compose(encoding.stringToUtf16List)(list.map(escapeCharCode))
77
78
 
78
79
  /** @type {(n: Node) => list.List<string>} */
79
80
  const node = n => typeof n === 'string' ? escape(n) : element(n)
@@ -2,9 +2,10 @@ const tokenizer = require('./module.f.cjs')
2
2
  const list = require('../../types/list/module.f.cjs')
3
3
  const json = require('../module.f.cjs')
4
4
  const { sort } = require('../../types/object/module.f.cjs')
5
+ const encoding = require('../../text/encoding/module.f.cjs');
5
6
 
6
7
  /** @type {(s: string) => readonly tokenizer.JsonToken[]} */
7
- const tokenizeString = s => list.toArray(tokenizer.tokenize(list.toCharCodeList(s)))
8
+ const tokenizeString = s => list.toArray(tokenizer.tokenize(encoding.stringToUtf16List(s)))
8
9
 
9
10
  const stringify = json.stringify(sort)
10
11
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.387",
3
+ "version": "0.0.390",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "module.f.cjs",
6
6
  "scripts": {
@@ -3,6 +3,8 @@ const list = require('../../types/list/module.f.cjs')
3
3
  const operator = require('../../types/function/operator/module.f.cjs')
4
4
  const array = require('../../types/array/module.f.cjs')
5
5
  const { contains } = require('../../types/range/module.f.cjs')
6
+ const { compose } = require('../../types/function/module.f.cjs')
7
+ const { map, flat, stateScan, concat, fold, toArray, flatMap } = list
6
8
  const { ok, error } = result
7
9
 
8
10
  /** @typedef {result.Result<number,number>} ByteResult */
@@ -54,10 +56,10 @@ const codePointToUtf16 = input =>
54
56
  }
55
57
 
56
58
  /** @type {(input: list.List<number>) => list.List<ByteResult>} */
57
- const codePointListToUtf8List = list.flatMap(codePointToUtf8)
59
+ const codePointListToUtf8List = flatMap(codePointToUtf8)
58
60
 
59
61
  /** @type {(input: list.List<i32>) => list.List<u16>} */
60
- const codePointListToUtf16List = list.flatMap(codePointToUtf16)
62
+ const codePointListToUtf16List = flatMap(codePointToUtf16)
61
63
 
62
64
  /** @type {operator.StateScan<number, Utf8State, list.List<CodePointResult>>} */
63
65
  const utf8ByteToCodePointOp = state => byte => {
@@ -85,7 +87,7 @@ const utf8ByteToCodePointOp = state => byte => {
85
87
  return [[ok(((state[0] & 0x07) << 18) + ((state[1] & 0x3f) << 12) + ((state[2] & 0x3f) << 6) + (byte & 0x3f))], undefined]
86
88
  }
87
89
  }
88
- return [[error(list.toArray(list.concat(state)([byte])))], undefined]
90
+ return [[error(toArray(concat(state)([byte])))], undefined]
89
91
  }
90
92
 
91
93
  /** @type {(state: Utf8State) => readonly[list.List<CodePointResult>, Utf8State]} */
@@ -95,7 +97,7 @@ const utf8EofToCodePointOp = state => [state === undefined ? undefined : [error(
95
97
  const utf8ByteOrEofToCodePointOp = state => input => input === undefined ? utf8EofToCodePointOp(state) : utf8ByteToCodePointOp(state)(input)
96
98
 
97
99
  /** @type {(input: list.List<number>) => list.List<CodePointResult>} */
98
- const utf8ListToCodePointList = input => list.flat(list.stateScan(utf8ByteOrEofToCodePointOp)(undefined)(list.concat(/** @type {list.List<ByteOrEof>} */(input))([undefined])))
100
+ const utf8ListToCodePointList = input => flat(stateScan(utf8ByteOrEofToCodePointOp)(undefined)(concat(/** @type {list.List<ByteOrEof>} */(input))([undefined])))
99
101
 
100
102
  /** @type {operator.StateScan<u16, Utf16State, list.List<i32>>} */
101
103
  const utf16ByteToCodePointOp = state => byte => {
@@ -124,7 +126,19 @@ const utf16EofToCodePointOp = state => [state === undefined ? undefined : [state
124
126
  const utf16ByteOrEofToCodePointOp = state => input => input === undefined ? utf16EofToCodePointOp(state) : utf16ByteToCodePointOp(state)(input)
125
127
 
126
128
  /** @type {(input: list.List<u16>) => list.List<i32>} */
127
- const utf16ListToCodePointList = input => list.flat(list.stateScan(utf16ByteOrEofToCodePointOp)(undefined)(list.concat(/** @type {list.List<WordOrEof>} */(input))([undefined])))
129
+ const utf16ListToCodePointList = input => flat(stateScan(utf16ByteOrEofToCodePointOp)(undefined)(concat(/** @type {list.List<WordOrEof>} */(input))([undefined])))
130
+
131
+ /** @type {(s: string) => list.List<u16>} */
132
+ const stringToUtf16List = s => {
133
+ /** @type {(i: number) => list.Result<number>} */
134
+ const at = i => {
135
+ const first = s.charCodeAt(i)
136
+ return isNaN(first) ? undefined : { first, tail: () => at(i + 1) }
137
+ }
138
+ return at(0)
139
+ }
140
+
141
+ const utf16ListToString = compose(map(String.fromCharCode))(fold(operator.concat)(''))
128
142
 
129
143
  module.exports = {
130
144
  /** @readonly */
@@ -134,5 +148,9 @@ module.exports = {
134
148
  /** @readonly */
135
149
  utf8ListToCodePointList,
136
150
  /** @readonly */
137
- utf16ListToCodePointList
151
+ utf16ListToCodePointList,
152
+ /** @readonly */
153
+ stringToUtf16List,
154
+ /** @readonly */
155
+ utf16ListToString
138
156
  }
@@ -206,4 +206,18 @@ const stringify = a => json.stringify(sort)(a)
206
206
  if (result !== '[-2147427328,0]') { throw result }
207
207
  }
208
208
 
209
+ {
210
+ const utf16List = encoding.stringToUtf16List("Hello world!😂🚜🚲")
211
+ const result = encoding.utf16ListToString(utf16List)
212
+ if (result !== "Hello world!😂🚜🚲") { throw result }
213
+ }
214
+
215
+ {
216
+ const a = encoding.stringToUtf16List("Hello world!😂🚜🚲")
217
+ const b = encoding.utf16ListToCodePointList(a)
218
+ const c = encoding.codePointListToUtf16List(b)
219
+ const result = encoding.utf16ListToString(c)
220
+ if (result !== "Hello world!😂🚜🚲") { throw result }
221
+ }
222
+
209
223
  module.exports = {}
@@ -296,18 +296,6 @@ const equalZip = e => a => b => () => {
296
296
  /** @type {<T>(e: operator.Equal<T>) => (a: List<T>) => (b: List<T>) => boolean} */
297
297
  const equal = e => a => b => every(equalZip(e)(a)(b))
298
298
 
299
- /** @type {(s: string) => List<number>} */
300
- const toCharCodeList = s => {
301
- /** @type {(i: number) => Result<number>} */
302
- const at = i => {
303
- const first = s.charCodeAt(i)
304
- return isNaN(first) ? undefined : { first, tail: () => at(i + 1) }
305
- }
306
- return at(0)
307
- }
308
-
309
- const fromCharCodeList = compose(map(String.fromCharCode))(fold(operator.concat)(''))
310
-
311
299
  module.exports = {
312
300
  /** @readonly */
313
301
  empty: undefined,
@@ -384,9 +372,5 @@ module.exports = {
384
372
  /** @readonly */
385
373
  zip,
386
374
  /** @readonly */
387
- equal,
388
- /** @readonly */
389
- toCharCodeList,
390
- /** @readonly */
391
- fromCharCodeList,
375
+ equal
392
376
  }
@@ -236,11 +236,7 @@ const map5 = _.map(x => x > 5)
236
236
  if (result !== false) { throw result }
237
237
  }
238
238
 
239
- {
240
- const r = _.toCharCodeList("Hello world!")
241
- const x = _.fromCharCodeList(r)
242
- if (x !== "Hello world!") { throw x }
243
- }
239
+
244
240
 
245
241
  // stress tests
246
242