functionalscript 0.0.498 → 0.0.500

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,228 @@
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 json = require('../module.f.cjs')
9
+ const { fromMap } = require('../../types/object/module.f.cjs')
10
+
11
+
12
+ /**
13
+ * @typedef {{
14
+ * readonly kind: 'object'
15
+ * readonly values: map.Map<json.Unknown>
16
+ * readonly key: string
17
+ * }} JsonObject
18
+ * */
19
+
20
+ /**
21
+ * @typedef {{
22
+ * readonly kind: 'array'
23
+ * readonly values: list.List<json.Unknown>
24
+ * }} JsonArray
25
+ * */
26
+
27
+ /**
28
+ * @typedef {|
29
+ * JsonObject |
30
+ * JsonArray
31
+ * } JsonStackElement
32
+ */
33
+
34
+ /** @typedef {list.List<JsonStackElement>} JsonStack */
35
+
36
+ /**
37
+ * @typedef {{
38
+ * readonly status: '' | '[' | '[v' | '[,' | '{' | '{k' | '{:' | '{v' | '{,'
39
+ * readonly top: JsonStackElement | null
40
+ * readonly stack: JsonStack
41
+ * }} StateParse
42
+ */
43
+
44
+ /**
45
+ * @typedef {{
46
+ * readonly status: 'result'
47
+ * readonly value: json.Unknown
48
+ * }} StateResult
49
+ */
50
+
51
+ /**
52
+ * @typedef {{
53
+ * readonly status: 'error'
54
+ * readonly message: string
55
+ * }} StateError
56
+ */
57
+
58
+ /**
59
+ * @typedef {|
60
+ * StateParse |
61
+ * StateResult |
62
+ * StateError
63
+ * } JsonState
64
+ */
65
+
66
+ /** @type {(obj: JsonObject) => (key: string) => JsonObject} */
67
+ const addKeyToObject = obj => key => ({ kind: 'object', values: obj.values, key: key })
68
+
69
+ /** @type {(obj: JsonObject) => (value: json.Unknown) => JsonObject} */
70
+ const addValueToObject = obj => value => ({ kind: 'object', values: setReplace(obj.key)(value)(obj.values), key: '' })
71
+
72
+ /** @type {(array: JsonArray) => (value: json.Unknown) => JsonArray} */
73
+ const addToArray = array => value => ({ kind: 'array', values: list.concat(array.values)([value]) })
74
+
75
+ /** @type {(state: StateParse) => (key: string) => JsonState} */
76
+ const pushKey = state => value => {
77
+ if (state.top?.kind === 'object') { return { status: '{k', top: addKeyToObject(state.top)(value), stack: state.stack } }
78
+ return { status: 'error', message: 'error' }
79
+ }
80
+
81
+ /** @type {(state: StateParse) => (value: json.Unknown) => JsonState} */
82
+ const pushValue = state => value => {
83
+ if (state.top === null) { return { status: 'result', value: value } }
84
+ if (state.top.kind === 'array') { return { status: '[v', top: addToArray(state.top)(value), stack: state.stack } }
85
+ return { status: '{v', top: addValueToObject(state.top)(value), stack: state.stack }
86
+ }
87
+
88
+ /** @type {(state: StateParse) => JsonState} */
89
+ const startArray = state => {
90
+ const newStack = state.top === null ? null : { first: state.top, tail: state.stack }
91
+ return { status: '[', top: { kind: 'array', values: null }, stack: newStack }
92
+ }
93
+
94
+ /** @type {(state: StateParse) => JsonState} */
95
+ const endArray = state => {
96
+ const array = state.top !== null ? toArray(state.top.values) : null
97
+ /** @type {StateParse} */
98
+ const newState = { status: '', top: first(null)(state.stack), stack: drop(1)(state.stack) }
99
+ return pushValue(newState)(array)
100
+ }
101
+
102
+ /** @type {(state: StateParse) => JsonState} */
103
+ const startObject = state => {
104
+ const newStack = state.top === null ? null : { first: state.top, tail: state.stack }
105
+ return { status: '{', top: { kind: 'object', values: null, key: '' }, stack: newStack }
106
+ }
107
+
108
+ /** @type {(state: StateParse) => JsonState} */
109
+ const endObject = state => {
110
+ const obj = state.top?.kind === 'object' ? fromMap(state.top.values) : null
111
+ /** @type {StateParse} */
112
+ const newState = { status: '', top: first(null)(state.stack), stack: drop(1)(state.stack) }
113
+ return pushValue(newState)(obj)
114
+ }
115
+
116
+ /** @type {(token: tokenizer.JsonToken) => json.Unknown} */
117
+ const tokenToValue = token => {
118
+ switch (token.kind) {
119
+ case 'null': return null
120
+ case 'false': return false
121
+ case 'true': return true
122
+ case 'number': return parseFloat(token.value)
123
+ case 'string': return token.value
124
+ default: return null
125
+ }
126
+ }
127
+
128
+ /** @type {(token: tokenizer.JsonToken) => boolean} */
129
+ const isValueToken = token => {
130
+ switch (token.kind) {
131
+ case 'null':
132
+ case 'false':
133
+ case 'true':
134
+ case 'number':
135
+ case 'string': return true
136
+ default: return false
137
+ }
138
+ }
139
+
140
+ /** @type {(token: tokenizer.JsonToken) => (state: StateParse) => JsonState}} */
141
+ const parseValueOp = token => state => {
142
+ if (isValueToken(token)) { return pushValue(state)(tokenToValue(token)) }
143
+ if (token.kind === '[') { return startArray(state) }
144
+ if (token.kind === '{') { return startObject(state) }
145
+ return { status: 'error', message: 'unexpected token' }
146
+ }
147
+
148
+ /** @type {(token: tokenizer.JsonToken) => (state: StateParse) => JsonState}} */
149
+ const parseArrayStartOp = token => state => {
150
+ if (isValueToken(token)) { return pushValue(state)(tokenToValue(token)) }
151
+ if (token.kind === '[') { return startArray(state) }
152
+ if (token.kind === ']') { return endArray(state) }
153
+ if (token.kind === '{') { return startObject(state) }
154
+ return { status: 'error', message: 'unexpected token' }
155
+ }
156
+
157
+ /** @type {(token: tokenizer.JsonToken) => (state: StateParse) => JsonState}} */
158
+ const parseArrayValueOp = token => state => {
159
+ if (token.kind === ']') { return endArray(state) }
160
+ if (token.kind === ',') { return { status: '[,', top: state.top, stack: state.stack } }
161
+ return { status: 'error', message: 'unexpected token' }
162
+ }
163
+
164
+ /** @type {(token: tokenizer.JsonToken) => (state: StateParse) => JsonState}} */
165
+ const parseObjectStartOp = token => state => {
166
+ if (token.kind === 'string') { return pushKey(state)(token.value) }
167
+ if (token.kind === '}') { return endObject(state) }
168
+ return { status: 'error', message: 'unexpected token' }
169
+ }
170
+
171
+ /** @type {(token: tokenizer.JsonToken) => (state: StateParse) => JsonState}} */
172
+ const parseObjectKeyOp = token => state => {
173
+ if (token.kind === ':') { return { status: '{:', top: state.top, stack: state.stack } }
174
+ return { status: 'error', message: 'unexpected token' }
175
+ }
176
+
177
+ /** @type {(token: tokenizer.JsonToken) => (state: StateParse) => JsonState}} */
178
+ const parseObjectColonOp = token => state => {
179
+ if (isValueToken(token)) { return pushValue(state)(tokenToValue(token)) }
180
+ if (token.kind === '[') { return startArray(state) }
181
+ if (token.kind === '{') { return startObject(state) }
182
+ return { status: 'error', message: 'unexpected token' }
183
+ }
184
+
185
+ /** @type {(token: tokenizer.JsonToken) => (state: StateParse) => JsonState}} */
186
+ const parseObjectNextOp = token => state => {
187
+ if (token.kind === '}') { return endObject(state) }
188
+ if (token.kind === ',') { return { status: '{,', top: state.top, stack: state.stack } }
189
+ return { status: 'error', message: 'unexpected token' }
190
+ }
191
+
192
+ /** @type {(token: tokenizer.JsonToken) => (state: StateParse) => JsonState}} */
193
+ const parseObjectCommaOp = token => state => {
194
+ if (token.kind === 'string') { return pushKey(state)(token.value) }
195
+ return { status: 'error', message: 'unexpected token' }
196
+ }
197
+
198
+ /** @type {operator.Fold<tokenizer.JsonToken, JsonState>} */
199
+ const foldOp = token => state => {
200
+ switch (state.status) {
201
+ case 'result': return { status: 'error', message: 'unexpected token' }
202
+ case 'error': return { status: 'error', message: state.message }
203
+ case '': return parseValueOp(token)(state)
204
+ case '[': return parseArrayStartOp(token)(state)
205
+ case '[v': return parseArrayValueOp(token)(state)
206
+ case '[,': return parseValueOp(token)(state)
207
+ case '{': return parseObjectStartOp(token)(state)
208
+ case '{k': return parseObjectKeyOp(token)(state)
209
+ case '{:': return parseObjectColonOp(token)(state)
210
+ case '{v': return parseObjectNextOp(token)(state)
211
+ case '{,': return parseObjectCommaOp(token)(state)
212
+ }
213
+ }
214
+
215
+ /** @type {(tokenList: list.List<tokenizer.JsonToken>) => result.Result<json.Unknown, string>} */
216
+ const parse = tokenList => {
217
+ const state = fold(foldOp)({ status: '', top: null, stack: null })(tokenList)
218
+ switch (state.status) {
219
+ case 'result': return result.ok(state.value)
220
+ case 'error': return result.error(state.message)
221
+ default: return result.error('unexpected end')
222
+ }
223
+ }
224
+
225
+ module.exports = {
226
+ /** @readonly */
227
+ parse
228
+ }
@@ -0,0 +1,240 @@
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 json = 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.JsonToken[]} */
9
+ const tokenizeString = s => toArray(tokenizer.tokenize(encoding.stringToList(s)))
10
+
11
+ const stringify = json.stringify(sort)
12
+
13
+ module.exports = {
14
+ valud: [
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
+ invalid: [
101
+ () => {
102
+ const tokenList = tokenizeString('')
103
+ const obj = parser.parse(tokenList)
104
+ const result = stringify(obj)
105
+ if (result !== '["error","unexpected end"]') { throw result }
106
+ },
107
+ () => {
108
+ const tokenList = tokenizeString('"123')
109
+ const obj = parser.parse(tokenList)
110
+ const result = stringify(obj)
111
+ if (result !== '["error","unexpected token"]') { throw result }
112
+ },
113
+ () => {
114
+ const tokenList = tokenizeString('[,]')
115
+ const obj = parser.parse(tokenList)
116
+ const result = stringify(obj)
117
+ if (result !== '["error","unexpected token"]') { throw result }
118
+ },
119
+ () => {
120
+ const tokenList = tokenizeString('[1 2]')
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('[1,,2]')
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('[]]')
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('["a"')
139
+ const obj = parser.parse(tokenList)
140
+ const result = stringify(obj)
141
+ if (result !== '["error","unexpected end"]') { throw result }
142
+ },
143
+ () => {
144
+ const tokenList = tokenizeString('[1,]')
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('[,1]')
151
+ const obj = parser.parse(tokenList)
152
+ const result = stringify(obj)
153
+ if (result !== '["error","unexpected token"]') { throw result }
154
+ },
155
+ () => {
156
+ const tokenList = tokenizeString('[:]')
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(']')
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('{1:2}')
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('{"1"2}')
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,,"3":4')
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('{}}')
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')
205
+ const obj = parser.parse(tokenList)
206
+ const result = stringify(obj)
207
+ if (result !== '["error","unexpected end"]') { throw result }
208
+ },
209
+ () => {
210
+ const tokenList = tokenizeString('{"1":2,}')
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 token"]') { throw result }
220
+ },
221
+ () => {
222
+ const tokenList = tokenizeString('}')
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('[{]}')
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
+ }
@@ -238,7 +238,7 @@ const initialStateOp = create(state => () => [[{ kind: 'error', message: 'unexpe
238
238
  rangeFunc(one(hyphenMinus))(() => input => [empty, { kind: 'number', value: fromCharCode(input), numberKind: '-' }])
239
239
  ])
240
240
 
241
- /** @type {(state: any) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
241
+ /** @type {() => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
242
242
  const invalidNumberToToken = () => input => tokenizeOp({ kind: 'invalidNumber' })(input)
243
243
 
244
244
  /** @type {(state: ParseNumberState) => (input: number) => readonly[list.List<JsonToken>, TokenizerState]} */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.498",
3
+ "version": "0.0.500",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "module.f.cjs",
6
6
  "scripts": {
@@ -22,5 +22,20 @@ module.exports = {
22
22
  cmp: () => {
23
23
  const result = cmp(4)(5)
24
24
  if (result !== -1) { throw result }
25
+ },
26
+ standard: () => {
27
+ /** @type {(v: bigint) => void} */
28
+ const eq = v => {
29
+ if (BigInt(Number(v)) != v) { throw v }
30
+ }
31
+
32
+ // 0x35 bits.
33
+ // 3 2 1 0
34
+ // 4_3210_FEDC_BA98_7654_3210_FEDC_BA98_7654_3210_FEDC_BA98_7654_3210
35
+ eq(0b1_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000n)
36
+ eq(0b1_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0001n)
37
+ eq(0b1_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0010n)
38
+ eq(0b1_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0011n)
39
+ eq(0b1_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0100n)
25
40
  }
26
41
  }