functionalscript 0.0.266 → 0.0.270

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
@@ -15,7 +15,7 @@ Try FunctionalScript [here](https://functionalscript.com/).
15
15
 
16
16
  In FunctionalScript:
17
17
 
18
- - Any module is a valid JavaScript module
18
+ - Any module is a valid JavaScript module. No additional build steps are required.
19
19
  - Code should not have [side-effects](https://en.wikipedia.org/wiki/Side_effect_(computer_science)). Any JavaScript statement, expression, or function which has a side effect is not allowed in FunctionalScript. There are no exceptions to this rule, such as `unsafe` code which can be found in Rust, C#, and other languages.
20
20
  - A module can't depend on non FunctionalScript module.
21
21
  - It also has no standard library, only a safe subset of standard JavaScript API can be used without referencing other modules.
@@ -82,7 +82,13 @@ module.exports = {
82
82
  // 1. references
83
83
  const first = require('./first.js')
84
84
 
85
+ // 2. definitions
85
86
  const _42plus7 = first.add42(7)
87
+
88
+ // 3. exports
89
+ module.exports = {
90
+ _42plus7,
91
+ }
86
92
  ```
87
93
 
88
94
  ### 2.4. References To Other Modules
@@ -166,6 +172,7 @@ The format of an arrow function is `ARGUMENT_NAME => FUNCTION_BODY`. An arrow fu
166
172
  x => x * 2
167
173
  a => a + 4
168
174
  s => `template literal ${s}`
175
+ a => b => a + b // an arrow functions that returns another arrow functions.
169
176
  () => 'hello' // an arrow function with no arguments
170
177
  ```
171
178
 
@@ -2,6 +2,9 @@ const package_ = require('../package')
2
2
  const module_ = require('../module')
3
3
  const function_ = require('../module/function')
4
4
  const { todo } = require('../../dev')
5
+ const map = require('../../types/map')
6
+ const object = require('../../types/object')
7
+ const list = require('../../types/list')
5
8
 
6
9
  /**
7
10
  * @template M
@@ -13,47 +16,81 @@ const { todo } = require('../../dev')
13
16
  * }} Config
14
17
  */
15
18
 
16
- /**
19
+ /**
17
20
  * @template M
18
- * @typedef {readonly[module_.State, M]} Result
21
+ * @typedef {readonly[module_.State, M]} Result
19
22
  */
20
23
 
21
- /**
24
+ /** @type {<M>(moduleMap: M) => Result<M>} */
25
+ const notFound = moduleMap => [['error', ['file not found']], moduleMap]
26
+
27
+ /**
22
28
  * @type {(packageGet: package_.Get) =>
23
29
  * <M>(moduleMapInterface: module_.MapInterface<M>) =>
24
30
  * (compile: function_.Compile) =>
25
31
  * (moduleId: module_.Id) =>
26
- * (moduleMap: M) =>
32
+ * (moduleMapFirst: M) =>
27
33
  * Result<M>
28
- * }
34
+ * }
29
35
  */
30
- const getOrBuild = packageGet => moduleMapInterface => compile => moduleId => moduleMap => {
36
+ const getOrBuild = packageGet => moduleMapInterface => compile => moduleId => {
37
+
38
+ /** @typedef {typeof moduleMapInterface extends module_.MapInterface<infer M> ? M : never} M */
39
+
31
40
  const moduleIdStr = module_.idToString(moduleId)
32
41
 
33
- /** @type {() => Result<typeof moduleMap>} */
34
- const notFound = () => [['error', ['file not found']], moduleMap]
35
-
36
- /** @type {(e: module_.Error) => Result<typeof moduleMap>} */
37
- const error = e => {
42
+ /** @type {(e: module_.Error) => (moduleMap: M) => Result<M>} */
43
+ const error = e => moduleMap => {
38
44
  /** @type {module_.State} */
39
45
  const state = ['error', e]
40
- moduleMapInterface.insert(moduleIdStr)(state)
41
- return [state, moduleMap]
46
+ return [state, moduleMapInterface.insert(moduleIdStr)(state)(moduleMap)]
42
47
  }
43
48
 
44
- const m = moduleMapInterface.at(moduleIdStr)(moduleMap)
45
- if (m !== undefined) { return [m, moduleMap] }
46
-
47
- const p = packageGet(moduleId.packageId)
48
- if (p === undefined) { return notFound() }
49
-
50
- const source = p.file(moduleId.path.join('/'))
51
- if (source === undefined) { return notFound() }
52
-
53
- const compileResult = compile(source)
54
- if (compileResult[0] === 'error') { return error(['compilation error', compileResult[1]]) }
55
-
56
- return todo()
49
+ /** @type {function_.Require<readonly[M, map.Map<string>]>} */
50
+ const require_ = path => ([moduleMap, requireMap]) => {
51
+ return todo()
52
+ }
53
+
54
+ return moduleMapFirst => {
55
+ let moduleMap = moduleMapFirst
56
+
57
+ {
58
+ const m = moduleMapInterface.at(moduleIdStr)(moduleMap)
59
+ if (m !== undefined) { return [m, moduleMap] }
60
+ }
61
+
62
+ const p = packageGet(moduleId.packageId)
63
+ if (p === undefined) { return notFound(moduleMap) }
64
+
65
+ const source = p.file(moduleId.path.join('/'))
66
+ if (source === undefined) { return notFound(moduleMap) }
67
+
68
+ const compileResult = compile(source)
69
+ if (compileResult[0] === 'error') { return error(['compilation error', compileResult[1]])(moduleMap) }
70
+
71
+ const moduleFunction = compileResult[1]
72
+
73
+ moduleMap = moduleMapInterface.insert(moduleIdStr)(['building'])(moduleMap)
74
+
75
+ const [[type, exportsOrError], [newModuleMap, requireMap]] = moduleFunction(require_)([moduleMap, map.empty])
76
+ moduleMap = newModuleMap
77
+
78
+ {
79
+ const m = moduleMapInterface.at(moduleIdStr)(moduleMap)
80
+ if (m === undefined ) { throw 'm === undefined' }
81
+ if (m[0] !== 'building') { return [m, moduleMap] }
82
+ }
83
+
84
+ /** @type {module_.State} */
85
+ const result = type === 'error' ?
86
+ ['error', ['runtime error', exportsOrError]] :
87
+ ['ok', {
88
+ exports: exportsOrError,
89
+ requireMap: object.fromMap(requireMap)
90
+ }]
91
+
92
+ return [result, moduleMapInterface.insert(moduleIdStr)(result)(moduleMap)]
93
+ }
57
94
  }
58
95
 
59
96
  module.exports = {
@@ -4,11 +4,11 @@
4
4
 
5
5
  const result = require('../../../types/result')
6
6
 
7
- /** @typedef {<M>(require: Require<M>) => (prior: M) => Result<M>} Function */
7
+ /** @typedef {<M>(require: Require<M>) => (prior: M) => Result<M>} Function_ */
8
8
 
9
9
  /**
10
10
  * @template M
11
- * @typedef {readonly[result.Result<unknown, unknown>, M]} Result
11
+ * @typedef {readonly[result.Result<unknown, unknown>, M]} Result
12
12
  */
13
13
 
14
14
  /**
@@ -16,6 +16,6 @@ const result = require('../../../types/result')
16
16
  * @typedef {(path: string) => (prior: M) => Result<M>} Require
17
17
  */
18
18
 
19
- /** @typedef {(source: string) => result.Result<Function, unknown>} Compile */
19
+ /** @typedef {(source: string) => result.Result<Function_, unknown>} Compile */
20
20
 
21
21
  module.exports = {}
@@ -8,12 +8,12 @@ const object = require('../../types/object')
8
8
  * }} MapInterface
9
9
  */
10
10
 
11
- /**
11
+ /**
12
12
  * @typedef {|
13
- * readonly['ok', Module] |
14
- * readonly['error', Error] |
13
+ * readonly['ok', Module] |
14
+ * readonly['error', Error] |
15
15
  * readonly['building']
16
- * } State
16
+ * } State
17
17
  */
18
18
 
19
19
  /**
@@ -23,11 +23,11 @@ const object = require('../../types/object')
23
23
  * }} Module
24
24
  */
25
25
 
26
- /**
26
+ /**
27
27
  * @typedef {|
28
- * ['file not found'] |
29
- * ['compilation error', unknown] |
30
- * ['runtime error'] |
28
+ * ['file not found'] |
29
+ * ['compilation error', unknown] |
30
+ * ['runtime error', unknown] |
31
31
  * ['circular reference']
32
32
  * } Error
33
33
  */
@@ -7,12 +7,12 @@ const { at } = require("../../types/object")
7
7
 
8
8
  /** @typedef {readonly string[]} Items */
9
9
 
10
- /**
10
+ /**
11
11
  * @typedef {{
12
12
  * readonly external: boolean
13
13
  * readonly dir: boolean
14
14
  * readonly items: Items
15
- * }} LocalPath
15
+ * }} LocalPath
16
16
  */
17
17
 
18
18
  /** @type {(path: string) => readonly string[]} */
@@ -74,9 +74,9 @@ const variants = prior => () => {
74
74
  return { first: n, tail: variants(n) }
75
75
  }
76
76
 
77
- /** @type {(d: dep.DependencyMapJson) => (p: IdPath) => IdPath|undefined} */
77
+ /** @type {(d: (local: string) => string|undefined) => (p: IdPath) => IdPath|undefined} */
78
78
  const mapDependency = d => ([external, internal]) => {
79
- const id = at(external)(d)
79
+ const id = d(external)
80
80
  return id === undefined ? undefined : [id, internal]
81
81
  }
82
82
 
@@ -88,16 +88,21 @@ const mapDependency = d => ([external, internal]) => {
88
88
  * }} Path
89
89
  */
90
90
 
91
- /** @type {(d: dep.DependenciesJson) => (dir: boolean) => (items: seq.List<string>) => Path|undefined} */
91
+ /** @type {(d: (local: string) => string|undefined) => (dir: boolean) => (items: seq.List<string>) => Path|undefined} */
92
92
  const parseGlobal = d => dir => items => {
93
- if (d === undefined) { return undefined }
94
93
  const v = variants([undefined, items])
95
94
  const r = seq.first(undefined)(seq.filterMap(mapDependency(d))(v))
96
95
  if (r === undefined) { return undefined }
97
96
  return { name: r[0], items: seq.toArray(r[1]), dir }
98
97
  }
99
98
 
100
- /** @type {(name: string) => (dependencies: dep.DependenciesJson) => (local: string) => (path: string) => Path|undefined } */
99
+ /**
100
+ * @type {(name: string) =>
101
+ * (dependencies: (local: string) => string|undefined) =>
102
+ * (local: string) =>
103
+ * (path: string) =>
104
+ * Path|undefined }
105
+ */
101
106
  const parse = name => dependencies => local => path => {
102
107
  const parsed = parseLocal(local)(path)
103
108
  if (parsed === undefined) { return undefined }
@@ -1,6 +1,7 @@
1
1
  const _ = require('.')
2
2
  const json = require('../../json')
3
3
  const { identity } = require('../../types/function')
4
+ const { at } = require('../../types/object')
4
5
 
5
6
  /** @type {(g: json.Unknown|undefined) => string} */
6
7
  const stringify = g => {
@@ -45,20 +46,20 @@ const stringify = g => {
45
46
  }
46
47
 
47
48
  {
48
- if (_.parseGlobal(undefined)(false)(['a', 'b']) !== undefined) { throw 'error' }
49
- if (_.parseGlobal({})(false)(['b']) !== undefined) { throw 'error' }
50
- if (_.parseGlobal({ b: 'x' })(false)(['d']) !== undefined) { throw 'error' }
49
+ if (_.parseGlobal(() => undefined)(false)(['a', 'b']) !== undefined) { throw 'error' }
50
+ if (_.parseGlobal(() => undefined)(false)(['b']) !== undefined) { throw 'error' }
51
+ if (_.parseGlobal(d => at(d)({ b: 'x' }))(false)(['d']) !== undefined) { throw 'error' }
51
52
  {
52
- const result = stringify(_.parseGlobal({ b: 'x' })(false)(['b']))
53
+ const result = stringify(_.parseGlobal(d => at(d)({ b: 'x' }))(false)(['b']))
53
54
  if (result !== '["x",""]') { throw result }
54
55
  }
55
- if (_.parseGlobal({ 'b/r': 'x' })(false)(['b']) !== undefined) { throw 'error' }
56
+ if (_.parseGlobal(d => at(d)({ 'b/r': 'x' }))(false)(['b']) !== undefined) { throw 'error' }
56
57
  {
57
- const result = stringify(_.parseGlobal({ 'b/r': 'x' })(false)(['b', 'r']))
58
+ const result = stringify(_.parseGlobal(d => at(d)({ 'b/r': 'x' }))(false)(['b', 'r']))
58
59
  if (result !== '["x",""]') { throw result }
59
60
  }
60
61
  {
61
- const result = stringify(_.parseGlobal({ 'b/r': 'x' })(false)(['b', 'r', 'd', 't']))
62
+ const result = stringify(_.parseGlobal(d => at(d)({ 'b/r': 'x' }))(false)(['b', 'r', 'd', 't']))
62
63
  if (result !== '["x","d/t"]') { throw result }
63
64
  }
64
65
  }
@@ -2,12 +2,12 @@ const { tryCatch } = require('../result')
2
2
  const { unwrap } = require('../../types/result')
3
3
  const moduleFunction = require('../../commonjs/module/function')
4
4
 
5
- /** @type {(f: Function) => moduleFunction.Function} */
5
+ /** @type {(f: Function) => moduleFunction.Function_} */
6
6
  const build = f => immutableRequire => mutableData => {
7
7
  /** @type {(path: string) => unknown} */
8
8
  const mutableRequire = path => {
9
9
  const [result, data] = immutableRequire(path)(mutableData)
10
- // Side effect: setting a variable from a nested function (closure)
10
+ // Side effect: setting a variable from a nested function (closure)
11
11
  // is not allowed in FunctionalScript.
12
12
  mutableData = data
13
13
  return unwrap(result)
@@ -21,7 +21,7 @@ const build = f => immutableRequire => mutableData => {
21
21
  }
22
22
 
23
23
  /** @type {moduleFunction.Compile} */
24
- const compile = source =>
24
+ const compile = source =>
25
25
  // Side effect: a `Function` constructor is not allowed in FunctionalScript.
26
26
  tryCatch(() => build(Function('module', 'require', `"use strict";${source}`)))
27
27
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.266",
3
+ "version": "0.0.270",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -36,8 +36,8 @@ const seq = require('../list')
36
36
  //
37
37
 
38
38
  /**
39
- * @template T
40
- * @typedef {Array1<T>} Leaf1
39
+ * @template T
40
+ * @typedef {Array1<T>} Leaf1
41
41
  */
42
42
 
43
43
  /**
@@ -62,9 +62,9 @@ const seq = require('../list')
62
62
 
63
63
  /** @typedef {readonly['done']} NotFoundDone */
64
64
 
65
- /**
65
+ /**
66
66
  * @template T
67
- * @typedef {readonly['done', T]} FoundDone
67
+ * @typedef {readonly['done', T]} FoundDone
68
68
  */
69
69
 
70
70
  /**
@@ -92,7 +92,7 @@ const seq = require('../list')
92
92
  /** @typedef {<T>(_: Lazy<T>) => (_: Branch3<T>) => Result<T>} InBranch3 */
93
93
  /** @typedef {<T>(_: Lazy<T>) => (_: Branch5<T>) => Result<T>} InBranch5 */
94
94
 
95
- /**
95
+ /**
96
96
  * @typedef {{
97
97
  * readonly leaf1: InLeaf1
98
98
  * readonly leaf2_left: InLeaf2
@@ -113,7 +113,7 @@ const seq = require('../list')
113
113
  * }} NotFound
114
114
  */
115
115
 
116
- /**
116
+ /**
117
117
  * @typedef {{
118
118
  * readonly found: Found
119
119
  * readonly notFound: NotFound
@@ -128,11 +128,11 @@ const seq = require('../list')
128
128
  /** @type {<T>(n: Branch7<T>) => Branch3<T>} */
129
129
  const split = ([n0, v1, n2, v3, n4, v5, n6]) => [[n0, v1, n2], v3, [n4, v5, n6]]
130
130
 
131
- /**
132
- * @type {<T>(extend: (o: Branch3<T>) => Result<T>) =>
133
- * (replace: (r: Node<T>) => Node<T>) =>
134
- * (result: Result<T>) =>
135
- * Result<T>}
131
+ /**
132
+ * @type {<T>(extend: (o: Branch3<T>) => Result<T>) =>
133
+ * (replace: (r: Node<T>) => Node<T>) =>
134
+ * (result: Result<T>) =>
135
+ * Result<T>}
136
136
  */
137
137
  const merge = extend => replace => result => {
138
138
  switch (result[0]) {
@@ -147,17 +147,17 @@ const visit = ({ found, notFound }) => cmp => {
147
147
  const i3 = index3(cmp)
148
148
  const i5 = index5(cmp)
149
149
  /** @typedef {typeof cmp extends Cmp<infer T> ? T : never} T */
150
- /**
151
- * @type {(extend: (o: Branch3<T>) => Branch5<T>) =>
152
- * (replace: (r: Node<T>) => Branch3<T>) =>
153
- * (result: Result<T>) =>
154
- * Result<T>}
150
+ /**
151
+ * @type {(extend: (o: Branch3<T>) => Branch5<T>) =>
152
+ * (replace: (r: Node<T>) => Branch3<T>) =>
153
+ * (result: Result<T>) =>
154
+ * Result<T>}
155
155
  */
156
156
  const merge2 = extend => merge(o => ['replace', extend(o)])
157
- /**
158
- * @type {(extend: (o: Branch3<T>) => Branch7<T>) =>
159
- * (replace: (r: Node<T>) => Branch5<T>) =>
160
- * (result: Result<T>) =>
157
+ /**
158
+ * @type {(extend: (o: Branch3<T>) => Branch7<T>) =>
159
+ * (replace: (r: Node<T>) => Branch5<T>) =>
160
+ * (result: Result<T>) =>
161
161
  * Result<T>}
162
162
  */
163
163
  const merge3 = extend => merge(o => ['overflow', split(extend(o))])
@@ -305,34 +305,31 @@ const replaceVisitor = {
305
305
 
306
306
  /** @type {<T>(node: Node<T>) => seq.List<T>} */
307
307
  const values = node => () => {
308
- const f = () => {
309
- switch (node.length) {
310
- case 1: case 2: { return node }
311
- case 3: {
312
- return seq.flat([
313
- values(node[0]),
314
- [node[1]],
315
- values(node[2])
316
- ])
317
- }
318
- default: {
319
- return seq.flat([
320
- values(node[0]),
321
- [node[1]],
322
- values(node[2]),
323
- [node[3]],
324
- values(node[4])
325
- ])
326
- }
308
+ switch (node.length) {
309
+ case 1: case 2: { return node }
310
+ case 3: {
311
+ return seq.flat([
312
+ values(node[0]),
313
+ [node[1]],
314
+ values(node[2])
315
+ ])
316
+ }
317
+ default: {
318
+ return seq.flat([
319
+ values(node[0]),
320
+ [node[1]],
321
+ values(node[2]),
322
+ [node[3]],
323
+ values(node[4])
324
+ ])
327
325
  }
328
326
  }
329
- return seq.next(f())
330
327
  }
331
328
 
332
329
  module.exports = {
333
330
  /** @readonly */
334
331
  values,
335
- /**
332
+ /**
336
333
  * @readonly
337
334
  * @type { <T>(cmp: Cmp<T>) => (node: Node<T>) => T|undefined }
338
335
  */
@@ -3,13 +3,13 @@ const btree = require('../btree')
3
3
  const { getVisitor, setVisitor, values } = require("../btree")
4
4
  const compare = require("../function/compare")
5
5
  const { cmp } = require("../function/compare")
6
- const seq = require("../list")
6
+ const list = require("../list")
7
7
 
8
8
  /** @typedef {compare.Sign} Sign */
9
9
 
10
10
  /**
11
- * @template T
12
- * @typedef {btree.Leaf1<T>} Leaf1
11
+ * @template T
12
+ * @typedef {btree.Leaf1<T>} Leaf1
13
13
  */
14
14
 
15
15
  /**
@@ -27,7 +27,7 @@ const seq = require("../list")
27
27
  * @typedef {readonly[string, T]} Entry
28
28
  */
29
29
 
30
- /**
30
+ /**
31
31
  * @template T
32
32
  * @typedef {undefined|TNode<Entry<T>>} Map
33
33
  */
@@ -54,16 +54,16 @@ const set = name => value => map => {
54
54
  }
55
55
  }
56
56
 
57
- /** @type {<T>(map: Map<T>) => seq.List<Entry<T>>} */
58
- const entries = map => map === undefined ? [] : values(map)
57
+ /** @type {<T>(map: Map<T>) => list.List<Entry<T>>} */
58
+ const entries = map => map === undefined ? undefined : values(map)
59
59
 
60
60
  /** @type {<T>(map: Map<T>) => (entry: Entry<T>) => Map<T>} */
61
61
  const setOp = map => ([name, value]) => set(name)(value)(map)
62
62
 
63
- /** @type {<T>(entries: seq.List<Entry<T>>) => Map<T>} */
63
+ /** @type {<T>(entries: list.List<Entry<T>>) => Map<T>} */
64
64
  const fromEntries = entries => {
65
- /** @typedef {typeof entries extends seq.List<Entry<infer T>> ? T : never} T */
66
- return seq.reduce(setOp)(/** @type {Map<T>} */(undefined))(entries)
65
+ /** @typedef {typeof entries extends list.List<Entry<infer T>> ? T : never} T */
66
+ return list.reduce(setOp)(/** @type {Map<T>} */(undefined))(entries)
67
67
  }
68
68
 
69
69
  module.exports = {
@@ -1,4 +1,4 @@
1
- const seq = require('../list')
1
+ const list = require('../list')
2
2
  const map = require('../map')
3
3
 
4
4
  /**
@@ -16,12 +16,17 @@ const map = require('../map')
16
16
  /** @type {(name: string) => <T>(object: Map<T>) => T|undefined} */
17
17
  const at = name => object => Object.getOwnPropertyDescriptor(object, name)?.value
18
18
 
19
- /** @type {<T>(entries: seq.List<Entry<T>>) => seq.List<Entry<T>>} */
19
+ /** @type {<T>(entries: list.List<Entry<T>>) => list.List<Entry<T>>} */
20
20
  const sort = entries => map.entries(map.fromEntries(entries))
21
21
 
22
+ /** @type {<T>(m: map.Map<T>) => Map<T>} */
23
+ const fromMap = m => Object.fromEntries(list.iterable(map.entries(m)))
24
+
22
25
  module.exports = {
23
26
  /** @readonly */
24
27
  at,
25
28
  /** @readonly */
26
29
  sort,
30
+ /** @readonly */
31
+ fromMap,
27
32
  }