functionalscript 0.0.269 → 0.0.274

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/README.md CHANGED
@@ -172,6 +172,7 @@ The format of an arrow function is `ARGUMENT_NAME => FUNCTION_BODY`. An arrow fu
172
172
  x => x * 2
173
173
  a => a + 4
174
174
  s => `template literal ${s}`
175
+ a => b => a + b // an arrow functions that returns another arrow functions.
175
176
  () => 'hello' // an arrow function with no arguments
176
177
  ```
177
178
 
@@ -1,12 +1,12 @@
1
1
  const json = require('../../json')
2
2
  const dependencies = require('./dependencies')
3
3
 
4
- /**
4
+ /**
5
5
  * @typedef {{
6
6
  * readonly name: string
7
7
  * readonly version: string
8
8
  * readonly dependencies?: dependencies.DependenciesJson
9
- * }} PackageJson
9
+ * }} PackageJson
10
10
  */
11
11
 
12
12
  /** @type {(j: json.Unknown) => j is PackageJson} */
@@ -1,9 +1,9 @@
1
- const seq = require("../../types/list")
1
+ const list = require("../../types/list")
2
2
  const option = require("../../types/option")
3
3
  const { compose } = require("../../types/function")
4
- const dep = require("../package/dependencies")
5
- const { at } = require("../../types/object")
6
- // const pack = require("../package")
4
+ const { todo } = require("../../dev")
5
+ const package_ = require("../package")
6
+ const module_ = require("../module")
7
7
 
8
8
  /** @typedef {readonly string[]} Items */
9
9
 
@@ -18,55 +18,62 @@ const { at } = require("../../types/object")
18
18
  /** @type {(path: string) => readonly string[]} */
19
19
  const split = path => path.split('/')
20
20
 
21
- /** @type {(s: undefined|seq.List<string>) => (items: string) => undefined|seq.List<string>} */
21
+ /** @typedef {readonly[list.List<string>] | undefined} OptionList */
22
+
23
+ /** @type {(s: OptionList) => (items: string) => OptionList} */
22
24
  const normItemsOp = prior => item => {
23
25
  if (prior === undefined) { return undefined }
26
+ const priorList = prior[0]
24
27
  switch (item) {
25
28
  case '': case '.': { return prior }
26
29
  case '..': {
27
- const result = seq.next(prior)
30
+ const result = list.next(priorList)
28
31
  if (result === undefined) { return undefined }
29
- return result.tail
32
+ return [result.tail]
30
33
  }
31
34
  default: {
32
- return seq.nonEmpty(item)(prior)
35
+ return [list.nonEmpty(item)(priorList)]
33
36
  }
34
37
  }
35
38
  }
36
39
 
37
- /** @type {(items: seq.List<string>) => seq.List<string>|undefined} */
38
- const normItems = compose(seq.reduce(normItemsOp)([]))(option.map(seq.reverse))
40
+ /** @type {(items: list.List<string>) => OptionList} */
41
+ const normItems = items => {
42
+ const result = list.reduce(normItemsOp)([undefined])(items)
43
+ if (result === undefined) { return result }
44
+ return [list.reverse(result[0])]
45
+ }
39
46
 
40
47
  /** @type {(local: string) => (path: string) => LocalPath|undefined} */
41
48
  const parseLocal = local => {
42
- /** @type {(path: string) => readonly[boolean, seq.List<string>]} */
49
+ /** @type {(path: string) => readonly[boolean, boolean, list.List<string>]} */
43
50
  const fSeq = path => {
44
51
  const pathSeq = split(path)
45
- switch (seq.first(undefined)(pathSeq)) {
46
- case '.': case '..': { return [false, seq.flat([split(local), pathSeq])] }
47
- default: { return [true, pathSeq] }
48
- }
52
+ const dir = [undefined, '', '.', '..'].includes(pathSeq[pathSeq.length - 1])
53
+ return /** @type {readonly (string|undefined)[]} */(['.', '..']).includes(list.first(undefined)(pathSeq)) ?
54
+ [false, dir, list.flat([split(local), pathSeq])] :
55
+ [true, dir, pathSeq]
49
56
  }
50
57
  /** @type {(path: string) => LocalPath|undefined} */
51
58
  const f = path => {
52
- const [external, items] = fSeq(path)
59
+ const [external, dir, items] = fSeq(path)
53
60
  const n = normItems(items)
54
61
  if (n === undefined) { return undefined }
55
62
  return {
56
63
  external,
57
- dir: path[path.length - 1] === '/',
58
- items: seq.toArray(n)
64
+ dir,
65
+ items: list.toArray(n[0])
59
66
  }
60
67
  }
61
68
  return f
62
69
  }
63
70
 
64
- /** @typedef {readonly[string, seq.List<string>]} IdPath */
71
+ /** @typedef {readonly[string, list.List<string>]} IdPath */
65
72
 
66
- /** @type {(prior: readonly[string|undefined, seq.List<string>]) => seq.Thunk<IdPath>} */
73
+ /** @type {(prior: readonly[string|undefined, list.List<string>]) => list.Thunk<IdPath>} */
67
74
  const variants = prior => () => {
68
75
  const [a, b] = prior
69
- const r = seq.next(b)
76
+ const r = list.next(b)
70
77
  if (r === undefined) { return undefined }
71
78
  const { first, tail } = r
72
79
  /** @type {IdPath} */
@@ -82,35 +89,74 @@ const mapDependency = d => ([external, internal]) => {
82
89
 
83
90
  /**
84
91
  * @typedef {{
85
- * readonly name: string,
92
+ * readonly packageId: string,
86
93
  * readonly items: Items,
87
94
  * readonly dir: boolean,
88
95
  * }} Path
89
96
  */
90
97
 
91
- /** @type {(d: (local: string) => string|undefined) => (dir: boolean) => (items: seq.List<string>) => Path|undefined} */
98
+ /**
99
+ * @type {(d: (local: string) => string|undefined) =>
100
+ * (dir: boolean) =>
101
+ * (items: list.List<string>) =>
102
+ * Path|undefined}
103
+ */
92
104
  const parseGlobal = d => dir => items => {
93
105
  const v = variants([undefined, items])
94
- const r = seq.first(undefined)(seq.filterMap(mapDependency(d))(v))
106
+ const r = list.first(undefined)(list.filterMap(mapDependency(d))(v))
95
107
  if (r === undefined) { return undefined }
96
- return { name: r[0], items: seq.toArray(r[1]), dir }
108
+ return { packageId: r[0], items: list.toArray(r[1]), dir }
97
109
  }
98
110
 
99
111
  /**
100
- * @type {(name: string) =>
112
+ * @type {(packageId: string) =>
101
113
  * (dependencies: (local: string) => string|undefined) =>
102
114
  * (local: string) =>
103
115
  * (path: string) =>
104
116
  * Path|undefined }
105
117
  */
106
- const parse = name => dependencies => local => path => {
118
+ const parse = packageId => dependencies => local => path => {
107
119
  const parsed = parseLocal(local)(path)
108
120
  if (parsed === undefined) { return undefined }
109
- const {external, dir, items} = parsed
110
- if (!external) { return { name, items, dir } }
121
+ const {external, dir, items } = parsed
122
+ if (!external) { return { packageId, items, dir } }
111
123
  return parseGlobal(dependencies)(dir)(items)
112
124
  }
113
125
 
126
+ /**
127
+ * @typedef {{
128
+ * readonly package: string
129
+ * readonly file: string
130
+ * readonly source: string
131
+ * }| undefined} Result
132
+ */
133
+
134
+ /**
135
+ * @type {(packageGet: package_.Get) =>
136
+ * (packageId: string) =>
137
+ * (local: string) =>
138
+ * (path: string) =>
139
+ * Result
140
+ * }
141
+ */
142
+ const parseAndFind = packageGet => packageId => local => path => {
143
+ const currentPack = packageGet(packageId)
144
+ if (currentPack === undefined) { return undefined }
145
+ const p = parse(packageId)(currentPack.dependency)(local)(path)
146
+ if (p === undefined) { return undefined }
147
+ const pack = packageGet(p.packageId)
148
+ if (pack === undefined) { return undefined }
149
+ /** @type {(file: string) => Result } */
150
+ const tryFile = file => {
151
+ const source = pack.file(file)
152
+ return source === undefined ? undefined : { package: p.packageId, file, source }
153
+ }
154
+ const file = p.items.join('/')
155
+ const indexJs = list.join('/')(list.concat(p.items)(['index.js']))
156
+ const fileList = p.dir || list.isEmpty(p.items) ? [indexJs] : [file, `${file}.js`, indexJs]
157
+ return list.first(undefined)(list.filterMap(tryFile)(fileList))
158
+ }
159
+
114
160
  module.exports = {
115
161
  /** @readonly */
116
162
  parseLocal,
@@ -118,4 +164,6 @@ module.exports = {
118
164
  parseGlobal,
119
165
  /** @readonly */
120
166
  parse,
167
+ /** @readonly */
168
+ parseAndFind,
121
169
  }
@@ -1,7 +1,10 @@
1
1
  const _ = require('.')
2
+ const { todo } = require('../../dev')
2
3
  const json = require('../../json')
3
4
  const { identity } = require('../../types/function')
5
+ const object = require('../../types/object')
4
6
  const { at } = require('../../types/object')
7
+ const package_ = require('../package')
5
8
 
6
9
  /** @type {(g: json.Unknown|undefined) => string} */
7
10
  const stringify = g => {
@@ -27,7 +30,7 @@ const stringify = g => {
27
30
 
28
31
  {
29
32
  const result = _.parseLocal('a')('')
30
- if (stringify(result) !== '{"external":true,"dir":false,"items":[]}') { throw result }
33
+ if (stringify(result) !== '{"external":true,"dir":true,"items":[]}') { throw result }
31
34
  }
32
35
 
33
36
  {
@@ -45,21 +48,142 @@ const stringify = g => {
45
48
  if (stringify(result) !== '{"external":true,"dir":false,"items":["a","c"]}') { throw result }
46
49
  }
47
50
 
51
+ {
52
+ const result = _.parseLocal('')('./x/..')
53
+ if (stringify(result) !== '{"external":false,"dir":true,"items":[]}') { throw result }
54
+ }
55
+
48
56
  {
49
57
  if (_.parseGlobal(() => undefined)(false)(['a', 'b']) !== undefined) { throw 'error' }
50
58
  if (_.parseGlobal(() => undefined)(false)(['b']) !== undefined) { throw 'error' }
51
59
  if (_.parseGlobal(d => at(d)({ b: 'x' }))(false)(['d']) !== undefined) { throw 'error' }
52
60
  {
53
61
  const result = stringify(_.parseGlobal(d => at(d)({ b: 'x' }))(false)(['b']))
54
- if (result !== '["x",""]') { throw result }
62
+ if (result !== '{"packageId":"x","items":[],"dir":false}') { throw result }
55
63
  }
56
64
  if (_.parseGlobal(d => at(d)({ 'b/r': 'x' }))(false)(['b']) !== undefined) { throw 'error' }
57
65
  {
58
66
  const result = stringify(_.parseGlobal(d => at(d)({ 'b/r': 'x' }))(false)(['b', 'r']))
59
- if (result !== '["x",""]') { throw result }
67
+ if (result !== '{"packageId":"x","items":[],"dir":false}') { throw result }
60
68
  }
61
69
  {
62
70
  const result = stringify(_.parseGlobal(d => at(d)({ 'b/r': 'x' }))(false)(['b', 'r', 'd', 't']))
63
- if (result !== '["x","d/t"]') { throw result }
71
+ if (result !== '{"packageId":"x","items":["d","t"],"dir":false}') { throw result }
72
+ }
73
+ {
74
+ const result = stringify(_.parseGlobal(d => at(d)({ 'b/r': 'x' }))(true)(['b', 'r', 'd', 't']))
75
+ if (result !== '{"packageId":"x","items":["d","t"],"dir":true}') { throw result }
76
+ }
77
+ }
78
+
79
+ {
80
+ /** @type {object.Map<package_.Package>} */
81
+ const packages = {
82
+ '': {
83
+ dependency: () => todo(),
84
+ file: path => at(path)({ 'a/c': 'return "a/c"' }),
85
+ }
86
+ }
87
+ const result = stringify(_.parseAndFind(p => at(p)(packages))('')('a/b')('../c'))
88
+ if (result !== '{"package":"","file":"a/c","source":"return \\"a/c\\""}') { throw result }
89
+ }
90
+
91
+ {
92
+ /** @type {object.Map<package_.Package>} */
93
+ const packages = {
94
+ '': {
95
+ dependency: x => {
96
+ const path = `node_modules/${x}`
97
+ return at(path)(packages) !== undefined ? path : undefined
98
+ },
99
+ file: path => at(path)({
100
+ 'index.js': 'return "index.js"',
101
+ 'x/index.js': 'return "x/index.js"',
102
+ 'x.js': 'return "x.js"',
103
+ })
104
+ },
105
+ 'node_modules/z': {
106
+ dependency: () => todo(),
107
+ file: path => at(path)({ 'a/c/index.js': 'return "a/c"' }),
108
+ }
109
+ }
110
+ {
111
+ const result = stringify(_.parseAndFind(p => at(p)(packages))('')('a/b')('z/a/c'))
112
+ if (result !== '{"package":"node_modules/z","file":"a/c/index.js","source":"return \\"a/c\\""}') { throw result }
113
+ }
114
+ {
115
+ const result = stringify(_.parseAndFind(p => at(p)(packages))('')('a/b')('../..'))
116
+ if (result !== '{"package":"","file":"index.js","source":"return \\"index.js\\""}') { throw result }
117
+ }
118
+ {
119
+ const result = stringify(_.parseAndFind(p => at(p)(packages))('')('')('./x'))
120
+ if (result !== '{"package":"","file":"x.js","source":"return \\"x.js\\""}') { throw result }
121
+ }
122
+ {
123
+ const result = stringify(_.parseAndFind(p => at(p)(packages))('')('')('./x.js'))
124
+ if (result !== '{"package":"","file":"x.js","source":"return \\"x.js\\""}') { throw result }
125
+ }
126
+ {
127
+ const result = stringify(_.parseAndFind(p => at(p)(packages))('')('')('./x/'))
128
+ if (result !== '{"package":"","file":"x/index.js","source":"return \\"x/index.js\\""}') { throw result }
129
+ }
130
+ {
131
+ const result = stringify(_.parseAndFind(p => at(p)(packages))('')('x/a')('../'))
132
+ if (result !== '{"package":"","file":"x/index.js","source":"return \\"x/index.js\\""}') { throw result }
133
+ }
134
+ {
135
+ const result = stringify(_.parseAndFind(p => at(p)(packages))('')('x/a')('..'))
136
+ if (result !== '{"package":"","file":"x/index.js","source":"return \\"x/index.js\\""}') { throw result }
64
137
  }
65
138
  }
139
+
140
+ {
141
+ /** @type {object.Map<package_.Package>} */
142
+ const packages = {
143
+ '': {
144
+ dependency: x => {
145
+ const path = `node_modules/${x}`
146
+ return at(path)(packages) !== undefined ? path : undefined
147
+ },
148
+ file: todo
149
+ },
150
+ 'node_modules/z/a': {
151
+ dependency: () => todo(),
152
+ file: path => at(path)({
153
+ 'c/index.js': 'return "c/index.js"',
154
+ 'c.js': 'return "c.js"'
155
+ }),
156
+ }
157
+ }
158
+ {
159
+ const result = stringify(_.parseAndFind(p => at(p)(packages))('')('a/b')('z/a/c'))
160
+ if (result !== '{"package":"node_modules/z/a","file":"c.js","source":"return \\"c.js\\""}') { throw result }
161
+ }
162
+ {
163
+ const result = stringify(_.parseAndFind(p => at(p)(packages))('')('a/b')('z/a/c/'))
164
+ if (result !== '{"package":"node_modules/z/a","file":"c/index.js","source":"return \\"c/index.js\\""}') { throw result }
165
+ }
166
+ }
167
+
168
+ {
169
+ /** @type {object.Map<package_.Package>} */
170
+ const packages = {
171
+ '': {
172
+ dependency: x => {
173
+ const path = `node_modules/${x}`
174
+ return at(path)(packages) !== undefined ? path : undefined
175
+ },
176
+ file: todo
177
+ },
178
+ 'node_modules/z/a/c': {
179
+ dependency: () => todo(),
180
+ file: path => at(path)({
181
+ '': 'throw',
182
+ '.js': 'throw',
183
+ 'index.js': 'return "a/c"'
184
+ }),
185
+ }
186
+ }
187
+ const result = stringify(_.parseAndFind(p => at(p)(packages))('')('a/b')('z/a/c'))
188
+ if (result !== '{"package":"node_modules/z/a/c","file":"index.js","source":"return \\"a/c\\""}') { throw result }
189
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.269",
3
+ "version": "0.0.274",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/test.js CHANGED
@@ -7,6 +7,7 @@ require('./types/object/test')
7
7
  require('./io/commonjs/test')
8
8
  require('./commonjs/package/dependencies/test')
9
9
  require('./commonjs/package/test')
10
+ require('./commonjs/path/test')
10
11
 
11
12
  /** @type {() => never} */
12
13
  const assert = () => { throw 'assert' }
@@ -100,12 +101,12 @@ const assert_if = c => { if (c) { throw 'assert_if' } }
100
101
  //const c = o['__defineGetter__']
101
102
  //const c = o['__defineSetter__']
102
103
  //const c = o['__lookupGetter__']
103
- //const c = o['__lookupSetter__']
104
- //const c = o['hasOwnProperty']
104
+ //const c = o['__lookupSetter__']
105
+ //const c = o['hasOwnProperty']
105
106
  //const c = o['isPrototypeOf']
106
107
  //const c = o['propertyIsEnumerable']
107
108
  //const c = o['toString']
108
- const c = o['valueOf']
109
+ const c = o['valueOf']
109
110
  //console.log(c)
110
111
  }
111
112
 
@@ -199,6 +199,9 @@ const some = input => find
199
199
  (/** @type {(_: boolean) => boolean} */(identity))
200
200
  (input)
201
201
 
202
+ /** @type {<T>(input: List<T>) => boolean} */
203
+ const isEmpty = input => !some(map(() => true)(input))
204
+
202
205
  /** @type {(input: List<boolean>) => boolean} */
203
206
  const every = input => !some(map(logicalNot)(input))
204
207
 
@@ -336,6 +339,8 @@ module.exports = {
336
339
  /** @readonly */
337
340
  every,
338
341
  /** @readonly */
342
+ isEmpty,
343
+ /** @readonly */
339
344
  includes,
340
345
  /** @readonly */
341
346
  countdown,
@@ -58,6 +58,11 @@ const stringify = sequence => json.stringify(sort)(_.toArray(sequence))
58
58
  if (result !== '[]') { throw result }
59
59
  }
60
60
 
61
+ {
62
+ const result = _.find(undefined)(x => x % 2 === 0)([1, 3, 5, 7])
63
+ if (result !== undefined) { throw result }
64
+ }
65
+
61
66
  {
62
67
  const result = _.find(undefined)(x => x % 2 === 0)([1, 2, 3, 4])
63
68
  if (result !== 2) { throw result }
@@ -119,6 +124,11 @@ const stringify = sequence => json.stringify(sort)(_.toArray(sequence))
119
124
  if (result !== '') { throw result }
120
125
  }
121
126
 
127
+ {
128
+ const result = _.join(' ')(['hello', 'world', '!'])
129
+ if (result !== 'hello world !') { throw result }
130
+ }
131
+
122
132
  {
123
133
  const result = stringify(_.entries([]))
124
134
  if (result !== '[]') { throw result }
@@ -214,6 +224,16 @@ const stringify = sequence => json.stringify(sort)(_.toArray(sequence))
214
224
  if (result !== 12) { throw result }
215
225
  }
216
226
 
227
+ {
228
+ const result = _.isEmpty(() => [])
229
+ if (result !== true) { throw result }
230
+ }
231
+
232
+ {
233
+ const result = _.isEmpty(() => [2])
234
+ if (result !== false) { throw result }
235
+ }
236
+
217
237
  // stress tests
218
238
 
219
239
  const stress = () => {
@@ -319,7 +339,7 @@ const stress = () => {
319
339
  }
320
340
  }
321
341
 
322
- stress()
342
+ // stress()
323
343
 
324
344
  module.exports = {
325
345