functionalscript 0.0.504 → 0.0.505

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.
@@ -0,0 +1,8 @@
1
+ # FJSON, FJS Object Notation
2
+
3
+ - additional types: bigint
4
+
5
+ ## Rules
6
+
7
+ - can serialize/deserialize without reading source code
8
+ - no function serialization/deserialization
@@ -0,0 +1,111 @@
1
+ const list = require('../types/list/module.f.cjs')
2
+ const { next, flat, reduce, map, empty } = list
3
+ const { concat } = require('../types/string/module.f.cjs')
4
+ const object = require('../types/object/module.f.cjs')
5
+ const { at } = object
6
+ const operator = require('../types/function/operator/module.f.cjs')
7
+ const { compose, fn } = require('../types/function/module.f.cjs')
8
+ const { entries } = Object
9
+ const { serialize: bigintSerialize } = require('../types/bigint/module.f.cjs')
10
+
11
+ /**
12
+ * @typedef {{
13
+ * readonly [k in string]: Unknown
14
+ * }} Object
15
+ */
16
+
17
+ /** @typedef {readonly Unknown[]} Array */
18
+
19
+ /** @typedef {Object|boolean|string|number|null|Array|bigint} Unknown */
20
+
21
+ const jsonStringify = JSON.stringify
22
+
23
+ /** @type {(_: string) => list.List<string>} */
24
+ const stringSerialize = input => [jsonStringify(input)]
25
+
26
+ /** @type {(_: number) => list.List<string>} */
27
+ const numberSerialize = input => [jsonStringify(input)]
28
+
29
+ const nullSerialize = ['null']
30
+
31
+ const trueSerialize = ['true']
32
+
33
+ const falseSerialize = ['false']
34
+
35
+ /** @type {(_: boolean) => list.List<string>} */
36
+ const boolSerialize = value => value ? trueSerialize : falseSerialize
37
+
38
+ const colon = [':']
39
+ const comma = [',']
40
+
41
+ /** @type {operator.Reduce<list.List<string>>} */
42
+ const joinOp = b => prior => flat([prior, comma, b])
43
+
44
+ /** @type {(input: list.List<list.List<string>>) => list.List<string>} */
45
+ const join = reduce(joinOp)(empty)
46
+
47
+ /** @type {(open: string) => (close: string) => (input: list.List<list.List<string>>) => list.List<string>} */
48
+ const wrap = open => close => {
49
+ const seqOpen = [open]
50
+ const seqClose = [close]
51
+ return input => flat([seqOpen, join(input), seqClose])
52
+ }
53
+
54
+ const objectWrap = wrap('{')('}')
55
+
56
+ const arrayWrap = wrap('[')(']')
57
+
58
+ /** @typedef {object.Entry<Unknown>} Entry*/
59
+
60
+ /** @typedef {(list.List<Entry>)} Entries */
61
+
62
+ /** @typedef {(entries: Entries) => Entries} MapEntries */
63
+
64
+ /** @type {(mapEntries: MapEntries) => (value: Unknown) => list.List<string>} */
65
+ const serialize = sort => {
66
+ /** @type {(kv: readonly[string, Unknown]) => list.List<string>} */
67
+ const propertySerialize = ([k, v]) => flat([
68
+ stringSerialize(k),
69
+ colon,
70
+ f(v)
71
+ ])
72
+ const mapPropertySerialize = map(propertySerialize)
73
+ /** @type {(object: Object) => list.List<string>} */
74
+ const objectSerialize = fn(entries)
75
+ .then(sort)
76
+ .then(mapPropertySerialize)
77
+ .then(objectWrap)
78
+ .result
79
+ /** @type {(value: Unknown) => list.List<string>} */
80
+ const f = value => {
81
+ switch (typeof value) {
82
+ case 'boolean': { return boolSerialize(value) }
83
+ case 'number': { return numberSerialize(value) }
84
+ case 'string': { return stringSerialize(value) }
85
+ case 'bigint': { return [bigintSerialize(value)] }
86
+ default: {
87
+ if (value === null) { return nullSerialize }
88
+ if (value instanceof Array) { return arraySerialize(value) }
89
+ return objectSerialize(value)
90
+ }
91
+ }
92
+ }
93
+ const arraySerialize = compose(map(f))(arrayWrap)
94
+ return f
95
+ }
96
+
97
+ /**
98
+ * The standard `JSON.stringify` rules determined by
99
+ * https://262.ecma-international.org/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys
100
+ *
101
+ * @type {(mapEntries: MapEntries) => (value: Unknown) => string}
102
+ */
103
+ const stringify = sort => compose(serialize(sort))(concat)
104
+
105
+ module.exports = {
106
+
107
+ /** @readonly */
108
+ stringify,
109
+ /** @readonly */
110
+ serialize,
111
+ }
@@ -0,0 +1,65 @@
1
+ const json = require('../json/module.f.cjs')
2
+ const { sort } = require('../types/object/module.f.cjs')
3
+ const { identity } = require('../types/function/module.f.cjs')
4
+ const fjson= require('./module.f.cjs')
5
+
6
+ module.exports = {
7
+ stringify: [
8
+ {
9
+ sort: () => {
10
+ const r = json.setProperty("Hello")(['a'])({})
11
+ const x = fjson.stringify(sort)(r)
12
+ if (x !== '{"a":"Hello"}') { throw x }
13
+ },
14
+ identity: () => {
15
+ const x = fjson.stringify(identity)(json.setProperty("Hello")(['a'])({}))
16
+ if (x !== '{"a":"Hello"}') { throw x }
17
+ },
18
+ },
19
+ {
20
+ sort: () => {
21
+ const x = fjson.stringify(sort)(json.setProperty("Hello")(['a'])({ c: [], b: 12 }))
22
+ if (x !== '{"a":"Hello","b":12,"c":[]}') { throw x }
23
+ },
24
+ identity: () => {
25
+ const x = fjson.stringify(identity)(json.setProperty("Hello")(['a'])({ c: [], b: 12 }))
26
+ if (x !== '{"c":[],"b":12,"a":"Hello"}') { throw x }
27
+ },
28
+ },
29
+ {
30
+ sort: () => {
31
+ const _0 = { a: { y: [24] }, c: [], b: 12 }
32
+ const _1 = json.setProperty("Hello")(['a', 'x'])(_0)
33
+ const _2 = fjson.stringify(sort)(_1)
34
+ if (_2 !== '{"a":{"x":"Hello","y":[24]},"b":12,"c":[]}') { throw _2 }
35
+ },
36
+ identity: () => {
37
+ const _0 = { a: { y: [24] }, c: [], b: 12 }
38
+ const _1 = json.setProperty("Hello")(['a', 'x'])(_0)
39
+ const _2 = fjson.stringify(identity)(_1)
40
+ if (_2 !== '{"a":{"y":[24],"x":"Hello"},"c":[],"b":12}') { throw _2 }
41
+ }
42
+ },
43
+ {
44
+ stringify: () => {
45
+ const bi = 1234567890n
46
+ const result = fjson.stringify(sort)(bi)
47
+ if (result !== '1234567890n') { throw result }
48
+ }
49
+ },
50
+ {
51
+ stringify: () => {
52
+ const arr = [0n, 1, 2n]
53
+ const result = fjson.stringify(sort)(arr)
54
+ if (result !== '[0n,1,2n]') { throw result }
55
+ }
56
+ },
57
+ {
58
+ stringify: () => {
59
+ const obj = {"a": 0n, "b": 1, "c": 2n}
60
+ const result = fjson.stringify(sort)(obj)
61
+ if (result !== '{"a":0n,"b":1,"c":2n}') { throw result }
62
+ }
63
+ }
64
+ ]
65
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.504",
3
+ "version": "0.0.505",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "module.f.cjs",
6
6
  "scripts": {
@@ -13,6 +13,9 @@ const abs = a => a >= 0 ? a : -a
13
13
  /** @type {(a: bigint) => compare.Sign} */
14
14
  const sign = a => unsafeCmp(a)(0n)
15
15
 
16
+ /** @type {(a: bigint) => string} */
17
+ const serialize = a => `${a}n`
18
+
16
19
  module.exports = {
17
20
  /** @readonly */
18
21
  addition,
@@ -22,4 +25,6 @@ module.exports = {
22
25
  abs,
23
26
  /** @readonly */
24
27
  sign,
28
+ /** @readonly */
29
+ serialize,
25
30
  }
@@ -1,4 +1,4 @@
1
- const { sum, abs } = require('./module.f.cjs')
1
+ const { sum, abs, serialize } = require('./module.f.cjs')
2
2
 
3
3
  module.exports = {
4
4
  sum: () => {
@@ -14,5 +14,19 @@ module.exports = {
14
14
  const result = abs(-10n)
15
15
  if (result !== 10n) { throw result }
16
16
  }
17
+ ],
18
+ serialize: [
19
+ () => {
20
+ const result = serialize(0n)
21
+ if (result !== '0n') { throw result }
22
+ },
23
+ () => {
24
+ const result = serialize(123456789012345678901234567890n)
25
+ if (result !== '123456789012345678901234567890n') { throw result }
26
+ },
27
+ () => {
28
+ const result = serialize(-55555n)
29
+ if (result !== '-55555n') { throw result }
30
+ },
17
31
  ]
18
32
  }