functionalscript 0.0.532 → 0.0.534

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/fjson/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
  ## Next steps
11
11
 
12
12
  - [ ] rename `fjson` to `djs` (data javascript), File extensions: `.d.cjs`, `.d.mjs`, `.d.js`.
13
- - [ ] use JS tokenizer
13
+ - [x] use JS tokenizer
14
14
  - [x] identifiers `{a:5}`
15
15
  - [x] big int
16
16
  - [ ] `module.exports = ...`
@@ -0,0 +1,229 @@
1
+ const result = require('../../types/result/module.f.cjs')
2
+ const list = require('../../types/list/module.f.cjs')
3
+ const { fold, first, drop, toArray } = list
4
+ const operator = require('../../types/function/operator/module.f.cjs')
5
+ const tokenizer = require('../tokenizer/module.f.cjs')
6
+ const map = require('../../types/map/module.f.cjs')
7
+ const { setReplace } = map
8
+ const fjson = require('../module.f.cjs')
9
+ const { fromMap } = require('../../types/object/module.f.cjs')
10
+
11
+ /**
12
+ * @typedef {{
13
+ * readonly kind: 'object'
14
+ * readonly values: map.Map<fjson.Unknown>
15
+ * readonly key: string
16
+ * }} JsonObject
17
+ * */
18
+
19
+ /**
20
+ * @typedef {{
21
+ * readonly kind: 'array'
22
+ * readonly values: list.List<fjson.Unknown>
23
+ * }} JsonArray
24
+ * */
25
+
26
+ /**
27
+ * @typedef {|
28
+ * JsonObject |
29
+ * JsonArray
30
+ * } JsonStackElement
31
+ */
32
+
33
+ /** @typedef {list.List<JsonStackElement>} JsonStack */
34
+
35
+ /**
36
+ * @typedef {{
37
+ * readonly status: '' | '[' | '[v' | '[,' | '{' | '{k' | '{:' | '{v' | '{,'
38
+ * readonly top: JsonStackElement | null
39
+ * readonly stack: JsonStack
40
+ * }} StateParse
41
+ */
42
+
43
+ /**
44
+ * @typedef {{
45
+ * readonly status: 'result'
46
+ * readonly value: fjson.Unknown
47
+ * }} StateResult
48
+ */
49
+
50
+ /**
51
+ * @typedef {{
52
+ * readonly status: 'error'
53
+ * readonly message: string
54
+ * }} StateError
55
+ */
56
+
57
+ /**
58
+ * @typedef {|
59
+ * StateParse |
60
+ * StateResult |
61
+ * StateError
62
+ * } FjsonState
63
+ */
64
+
65
+ /** @type {(obj: JsonObject) => (key: string) => JsonObject} */
66
+ const addKeyToObject = obj => key => ({ kind: 'object', values: obj.values, key: key })
67
+
68
+ /** @type {(obj: JsonObject) => (value: fjson.Unknown) => JsonObject} */
69
+ const addValueToObject = obj => value => ({ kind: 'object', values: setReplace(obj.key)(value)(obj.values), key: '' })
70
+
71
+ /** @type {(array: JsonArray) => (value: fjson.Unknown) => JsonArray} */
72
+ const addToArray = array => value => ({ kind: 'array', values: list.concat(array.values)([value]) })
73
+
74
+ /** @type {(state: StateParse) => (key: string) => FjsonState} */
75
+ const pushKey = state => value => {
76
+ if (state.top?.kind === 'object') { return { status: '{k', top: addKeyToObject(state.top)(value), stack: state.stack } }
77
+ return { status: 'error', message: 'error' }
78
+ }
79
+
80
+ /** @type {(state: StateParse) => (value: fjson.Unknown) => FjsonState} */
81
+ const pushValue = state => value => {
82
+ if (state.top === null) { return { status: 'result', value: value } }
83
+ if (state.top.kind === 'array') { return { status: '[v', top: addToArray(state.top)(value), stack: state.stack } }
84
+ return { status: '{v', top: addValueToObject(state.top)(value), stack: state.stack }
85
+ }
86
+
87
+ /** @type {(state: StateParse) => FjsonState} */
88
+ const startArray = state => {
89
+ const newStack = state.top === null ? null : { first: state.top, tail: state.stack }
90
+ return { status: '[', top: { kind: 'array', values: null }, stack: newStack }
91
+ }
92
+
93
+ /** @type {(state: StateParse) => FjsonState} */
94
+ const endArray = state => {
95
+ const array = state.top !== null ? toArray(state.top.values) : null
96
+ /** @type {StateParse} */
97
+ const newState = { status: '', top: first(null)(state.stack), stack: drop(1)(state.stack) }
98
+ return pushValue(newState)(array)
99
+ }
100
+
101
+ /** @type {(state: StateParse) => FjsonState} */
102
+ const startObject = state => {
103
+ const newStack = state.top === null ? null : { first: state.top, tail: state.stack }
104
+ return { status: '{', top: { kind: 'object', values: null, key: '' }, stack: newStack }
105
+ }
106
+
107
+ /** @type {(state: StateParse) => FjsonState} */
108
+ const endObject = state => {
109
+ const obj = state.top?.kind === 'object' ? fromMap(state.top.values) : null
110
+ /** @type {StateParse} */
111
+ const newState = { status: '', top: first(null)(state.stack), stack: drop(1)(state.stack) }
112
+ return pushValue(newState)(obj)
113
+ }
114
+
115
+ /** @type {(token: tokenizer.FjsonToken) => fjson.Unknown} */
116
+ const tokenToValue = token => {
117
+ switch (token.kind) {
118
+ case 'null': return null
119
+ case 'false': return false
120
+ case 'true': return true
121
+ case 'number': return parseFloat(token.value)
122
+ case 'string': return token.value
123
+ case 'bigint': return token.value
124
+ default: return null
125
+ }
126
+ }
127
+
128
+ /** @type {(token: tokenizer.FjsonToken) => boolean} */
129
+ const isValueToken = token => {
130
+ switch (token.kind) {
131
+ case 'null':
132
+ case 'false':
133
+ case 'true':
134
+ case 'number':
135
+ case 'string':
136
+ case 'bigint': return true
137
+ default: return false
138
+ }
139
+ }
140
+
141
+ /** @type {(token: tokenizer.FjsonToken) => (state: StateParse) => FjsonState}} */
142
+ const parseValueOp = token => state => {
143
+ if (isValueToken(token)) { return pushValue(state)(tokenToValue(token)) }
144
+ if (token.kind === '[') { return startArray(state) }
145
+ if (token.kind === '{') { return startObject(state) }
146
+ return { status: 'error', message: 'unexpected token' }
147
+ }
148
+
149
+ /** @type {(token: tokenizer.FjsonToken) => (state: StateParse) => FjsonState}} */
150
+ const parseArrayStartOp = token => state => {
151
+ if (isValueToken(token)) { return pushValue(state)(tokenToValue(token)) }
152
+ if (token.kind === '[') { return startArray(state) }
153
+ if (token.kind === ']') { return endArray(state) }
154
+ if (token.kind === '{') { return startObject(state) }
155
+ return { status: 'error', message: 'unexpected token' }
156
+ }
157
+
158
+ /** @type {(token: tokenizer.FjsonToken) => (state: StateParse) => FjsonState}} */
159
+ const parseArrayValueOp = token => state => {
160
+ if (token.kind === ']') { return endArray(state) }
161
+ if (token.kind === ',') { return { status: '[,', top: state.top, stack: state.stack } }
162
+ return { status: 'error', message: 'unexpected token' }
163
+ }
164
+
165
+ /** @type {(token: tokenizer.FjsonToken) => (state: StateParse) => FjsonState}} */
166
+ const parseObjectStartOp = token => state => {
167
+ if (token.kind === 'string') { return pushKey(state)(token.value) }
168
+ if (token.kind === '}') { return endObject(state) }
169
+ return { status: 'error', message: 'unexpected token' }
170
+ }
171
+
172
+ /** @type {(token: tokenizer.FjsonToken) => (state: StateParse) => FjsonState}} */
173
+ const parseObjectKeyOp = token => state => {
174
+ if (token.kind === ':') { return { status: '{:', top: state.top, stack: state.stack } }
175
+ return { status: 'error', message: 'unexpected token' }
176
+ }
177
+
178
+ /** @type {(token: tokenizer.FjsonToken) => (state: StateParse) => FjsonState}} */
179
+ const parseObjectColonOp = token => state => {
180
+ if (isValueToken(token)) { return pushValue(state)(tokenToValue(token)) }
181
+ if (token.kind === '[') { return startArray(state) }
182
+ if (token.kind === '{') { return startObject(state) }
183
+ return { status: 'error', message: 'unexpected token' }
184
+ }
185
+
186
+ /** @type {(token: tokenizer.FjsonToken) => (state: StateParse) => FjsonState}} */
187
+ const parseObjectNextOp = token => state => {
188
+ if (token.kind === '}') { return endObject(state) }
189
+ if (token.kind === ',') { return { status: '{,', top: state.top, stack: state.stack } }
190
+ return { status: 'error', message: 'unexpected token' }
191
+ }
192
+
193
+ /** @type {(token: tokenizer.FjsonToken) => (state: StateParse) => FjsonState}} */
194
+ const parseObjectCommaOp = token => state => {
195
+ if (token.kind === 'string') { return pushKey(state)(token.value) }
196
+ return { status: 'error', message: 'unexpected token' }
197
+ }
198
+
199
+ /** @type {operator.Fold<tokenizer.FjsonToken, FjsonState>} */
200
+ const foldOp = token => state => {
201
+ switch (state.status) {
202
+ case 'result': return { status: 'error', message: 'unexpected token' }
203
+ case 'error': return { status: 'error', message: state.message }
204
+ case '': return parseValueOp(token)(state)
205
+ case '[': return parseArrayStartOp(token)(state)
206
+ case '[v': return parseArrayValueOp(token)(state)
207
+ case '[,': return parseValueOp(token)(state)
208
+ case '{': return parseObjectStartOp(token)(state)
209
+ case '{k': return parseObjectKeyOp(token)(state)
210
+ case '{:': return parseObjectColonOp(token)(state)
211
+ case '{v': return parseObjectNextOp(token)(state)
212
+ case '{,': return parseObjectCommaOp(token)(state)
213
+ }
214
+ }
215
+
216
+ /** @type {(tokenList: list.List<tokenizer.FjsonToken>) => result.Result<fjson.Unknown, string>} */
217
+ const parse = tokenList => {
218
+ const state = fold(foldOp)({ status: '', top: null, stack: null })(tokenList)
219
+ switch (state.status) {
220
+ case 'result': return result.ok(state.value)
221
+ case 'error': return result.error(state.message)
222
+ default: return result.error('unexpected end')
223
+ }
224
+ }
225
+
226
+ module.exports = {
227
+ /** @readonly */
228
+ parse
229
+ }
@@ -0,0 +1,258 @@
1
+ const parser = require('./module.f.cjs')
2
+ const tokenizer = require('../tokenizer/module.f.cjs')
3
+ const { toArray } = require('../../types/list/module.f.cjs')
4
+ const fjson = require('../module.f.cjs')
5
+ const { sort } = require('../../types/object/module.f.cjs')
6
+ const encoding = require('../../text/utf16/module.f.cjs');
7
+
8
+ /** @type {(s: string) => readonly tokenizer.FjsonToken[]} */
9
+ const tokenizeString = s => toArray(tokenizer.tokenize(encoding.stringToList(s)))
10
+
11
+ const stringify = fjson.stringify(sort)
12
+
13
+ module.exports = {
14
+ valid: [
15
+ () => {
16
+ const tokenList = tokenizeString('null')
17
+ const obj = parser.parse(tokenList)
18
+ const result = stringify(obj)
19
+ if (result !== '["ok",null]') { throw result }
20
+ },
21
+ () => {
22
+ const tokenList = tokenizeString('true')
23
+ const obj = parser.parse(tokenList)
24
+ const result = stringify(obj)
25
+ if (result !== '["ok",true]') { throw result }
26
+ },
27
+ () => {
28
+ const tokenList = tokenizeString('false')
29
+ const obj = parser.parse(tokenList)
30
+ const result = stringify(obj)
31
+ if (result !== '["ok",false]') { throw result }
32
+ },
33
+ () => {
34
+ const tokenList = tokenizeString('0.1')
35
+ const obj = parser.parse(tokenList)
36
+ const result = stringify(obj)
37
+ if (result !== '["ok",0.1]') { throw result }
38
+ },
39
+ () => {
40
+ const tokenList = tokenizeString('1.1e+2')
41
+ const obj = parser.parse(tokenList)
42
+ const result = stringify(obj)
43
+ if (result !== '["ok",110]') { throw result }
44
+ },
45
+ () => {
46
+ const tokenList = tokenizeString('"abc"')
47
+ const obj = parser.parse(tokenList)
48
+ const result = stringify(obj)
49
+ if (result !== '["ok","abc"]') { throw result }
50
+ },
51
+ () => {
52
+ const tokenList = tokenizeString('[]')
53
+ const obj = parser.parse(tokenList)
54
+ const result = stringify(obj)
55
+ if (result !== '["ok",[]]') { throw result }
56
+ },
57
+ () => {
58
+ const tokenList = tokenizeString('[1]')
59
+ const obj = parser.parse(tokenList)
60
+ const result = stringify(obj)
61
+ if (result !== '["ok",[1]]') { throw result }
62
+ },
63
+ () => {
64
+ const tokenList = tokenizeString('[[]]')
65
+ const obj = parser.parse(tokenList)
66
+ const result = stringify(obj)
67
+ if (result !== '["ok",[[]]]') { throw result }
68
+ },
69
+ () => {
70
+ const tokenList = tokenizeString('[0,[1,[2,[]]],3]')
71
+ const obj = parser.parse(tokenList)
72
+ const result = stringify(obj)
73
+ if (result !== '["ok",[0,[1,[2,[]]],3]]') { throw result }
74
+ },
75
+ () => {
76
+ const tokenList = tokenizeString('{}')
77
+ const obj = parser.parse(tokenList)
78
+ const result = stringify(obj)
79
+ if (result !== '["ok",{}]') { throw result }
80
+ },
81
+ () => {
82
+ const tokenList = tokenizeString('[{}]')
83
+ const obj = parser.parse(tokenList)
84
+ const result = stringify(obj)
85
+ if (result !== '["ok",[{}]]') { throw result }
86
+ },
87
+ () => {
88
+ const tokenList = tokenizeString('{"a":true,"b":false,"c":null}')
89
+ const obj = parser.parse(tokenList)
90
+ const result = stringify(obj)
91
+ if (result !== '["ok",{"a":true,"b":false,"c":null}]') { throw result }
92
+ },
93
+ () => {
94
+ const tokenList = tokenizeString('{"a":{"b":{"c":["d"]}}}')
95
+ const obj = parser.parse(tokenList)
96
+ const result = stringify(obj)
97
+ if (result !== '["ok",{"a":{"b":{"c":["d"]}}}]') { throw result }
98
+ },
99
+ () => {
100
+ const tokenList = tokenizeString('1234567890n')
101
+ const obj = parser.parse(tokenList)
102
+ const result = stringify(obj)
103
+ if (result !== '["ok",1234567890n]') { throw result }
104
+ },
105
+ () => {
106
+ const tokenList = tokenizeString('[1234567890n]')
107
+ const obj = parser.parse(tokenList)
108
+ const result = stringify(obj)
109
+ if (result !== '["ok",[1234567890n]]') { throw result }
110
+ }
111
+ ],
112
+ invalid: [
113
+ () => {
114
+ const tokenList = tokenizeString('')
115
+ const obj = parser.parse(tokenList)
116
+ const result = stringify(obj)
117
+ if (result !== '["error","unexpected end"]') { throw result }
118
+ },
119
+ () => {
120
+ const tokenList = tokenizeString('"123')
121
+ const obj = parser.parse(tokenList)
122
+ const result = stringify(obj)
123
+ if (result !== '["error","unexpected token"]') { throw result }
124
+ },
125
+ () => {
126
+ const tokenList = tokenizeString('[,]')
127
+ const obj = parser.parse(tokenList)
128
+ const result = stringify(obj)
129
+ if (result !== '["error","unexpected token"]') { throw result }
130
+ },
131
+ () => {
132
+ const tokenList = tokenizeString('[1 2]')
133
+ const obj = parser.parse(tokenList)
134
+ const result = stringify(obj)
135
+ if (result !== '["error","unexpected token"]') { throw result }
136
+ },
137
+ () => {
138
+ const tokenList = tokenizeString('[1,,2]')
139
+ const obj = parser.parse(tokenList)
140
+ const result = stringify(obj)
141
+ if (result !== '["error","unexpected token"]') { throw result }
142
+ },
143
+ () => {
144
+ const tokenList = tokenizeString('[]]')
145
+ const obj = parser.parse(tokenList)
146
+ const result = stringify(obj)
147
+ if (result !== '["error","unexpected token"]') { throw result }
148
+ },
149
+ () => {
150
+ const tokenList = tokenizeString('["a"')
151
+ const obj = parser.parse(tokenList)
152
+ const result = stringify(obj)
153
+ if (result !== '["error","unexpected end"]') { throw result }
154
+ },
155
+ () => {
156
+ const tokenList = tokenizeString('[1,]')
157
+ const obj = parser.parse(tokenList)
158
+ const result = stringify(obj)
159
+ if (result !== '["error","unexpected token"]') { throw result }
160
+ },
161
+ () => {
162
+ const tokenList = tokenizeString('[,1]')
163
+ const obj = parser.parse(tokenList)
164
+ const result = stringify(obj)
165
+ if (result !== '["error","unexpected token"]') { throw result }
166
+ },
167
+ () => {
168
+ const tokenList = tokenizeString('[:]')
169
+ const obj = parser.parse(tokenList)
170
+ const result = stringify(obj)
171
+ if (result !== '["error","unexpected token"]') { throw result }
172
+ },
173
+ () => {
174
+ const tokenList = tokenizeString(']')
175
+ const obj = parser.parse(tokenList)
176
+ const result = stringify(obj)
177
+ if (result !== '["error","unexpected token"]') { throw result }
178
+ },
179
+ () => {
180
+ const tokenList = tokenizeString('{,}')
181
+ const obj = parser.parse(tokenList)
182
+ const result = stringify(obj)
183
+ if (result !== '["error","unexpected token"]') { throw result }
184
+ },
185
+ () => {
186
+ const tokenList = tokenizeString('{1:2}')
187
+ const obj = parser.parse(tokenList)
188
+ const result = stringify(obj)
189
+ if (result !== '["error","unexpected token"]') { throw result }
190
+ },
191
+ () => {
192
+ const tokenList = tokenizeString('{"1"2}')
193
+ const obj = parser.parse(tokenList)
194
+ const result = stringify(obj)
195
+ if (result !== '["error","unexpected token"]') { throw result }
196
+ },
197
+ () => {
198
+ const tokenList = tokenizeString('{"1"::2}')
199
+ const obj = parser.parse(tokenList)
200
+ const result = stringify(obj)
201
+ if (result !== '["error","unexpected token"]') { throw result }
202
+ },
203
+ () => {
204
+ const tokenList = tokenizeString('{"1":2,,"3":4')
205
+ const obj = parser.parse(tokenList)
206
+ const result = stringify(obj)
207
+ if (result !== '["error","unexpected token"]') { throw result }
208
+ },
209
+ () => {
210
+ const tokenList = tokenizeString('{}}')
211
+ const obj = parser.parse(tokenList)
212
+ const result = stringify(obj)
213
+ if (result !== '["error","unexpected token"]') { throw result }
214
+ },
215
+ () => {
216
+ const tokenList = tokenizeString('{"1":2')
217
+ const obj = parser.parse(tokenList)
218
+ const result = stringify(obj)
219
+ if (result !== '["error","unexpected end"]') { throw result }
220
+ },
221
+ () => {
222
+ const tokenList = tokenizeString('{"1":2,}')
223
+ const obj = parser.parse(tokenList)
224
+ const result = stringify(obj)
225
+ if (result !== '["error","unexpected token"]') { throw result }
226
+ },
227
+ () => {
228
+ const tokenList = tokenizeString('{,"1":2}')
229
+ const obj = parser.parse(tokenList)
230
+ const result = stringify(obj)
231
+ if (result !== '["error","unexpected token"]') { throw result }
232
+ },
233
+ () => {
234
+ const tokenList = tokenizeString('}')
235
+ const obj = parser.parse(tokenList)
236
+ const result = stringify(obj)
237
+ if (result !== '["error","unexpected token"]') { throw result }
238
+ },
239
+ () => {
240
+ const tokenList = tokenizeString('[{]}')
241
+ const obj = parser.parse(tokenList)
242
+ const result = stringify(obj)
243
+ if (result !== '["error","unexpected token"]') { throw result }
244
+ },
245
+ () => {
246
+ const tokenList = tokenizeString('{[}]')
247
+ const obj = parser.parse(tokenList)
248
+ const result = stringify(obj)
249
+ if (result !== '["error","unexpected token"]') { throw result }
250
+ },
251
+ () => {
252
+ const tokenList = tokenizeString('10-5')
253
+ const obj = parser.parse(tokenList)
254
+ const result = stringify(obj)
255
+ if (result !== '["error","unexpected token"]') { throw result }
256
+ },
257
+ ]
258
+ }
@@ -11,7 +11,7 @@ const tokenizeString = s => toArray(tokenizer.tokenize(encoding.stringToList(s))
11
11
  const stringify = json.stringify(sort)
12
12
 
13
13
  module.exports = {
14
- valud: [
14
+ valid: [
15
15
  () => {
16
16
  const tokenList = tokenizeString('null')
17
17
  const obj = parser.parse(tokenList)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.532",
3
+ "version": "0.0.534",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "module.f.cjs",
6
6
  "scripts": {