functionalscript 0.0.314 → 0.0.318

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.
@@ -5,6 +5,7 @@ name: Node.js CI
5
5
 
6
6
  on:
7
7
  push:
8
+ pull_request:
8
9
 
9
10
  jobs:
10
11
  build:
package/LANGUAGE.md CHANGED
@@ -1,4 +1,4 @@
1
- # FunctionaScript Programming Language
1
+ # FunctionalScript Programming Language
2
2
 
3
3
  ## 1. Module Ecosystem
4
4
 
@@ -3,7 +3,22 @@
3
3
  ```ts
4
4
  // package/index.js
5
5
 
6
+ // A dictionary of packages.
7
+ //
8
+ // A package contains a dictionary of dependencies and a dictionary of files.
9
+ //
10
+ // `packageId` examples:
11
+ // - Node.js:
12
+ // - normalized: `./node_modules/functionalscript`
13
+ // - fs modules:
14
+ // - normalized: `github:functionalscript/functionalscript:bf4f3ed9ad1d3c19ee7bea3e76000dec77d01b4f`
15
+ // - `localPackageId` examples:
16
+ // - `functionalscript`
17
+
6
18
  type PackageGet = (packageId: string) => Package | undefined
19
+
20
+ // A local file id is
21
+
7
22
  type Package = {
8
23
  // returns a global package id.
9
24
  readonly dependency: (localPackageId: string) => string | undefined
@@ -13,21 +28,35 @@ type Package = {
13
28
 
14
29
  // module/index.js
15
30
 
31
+ // A module map is a dictionary of modules.
32
+ //
33
+ // A module is a compiled and initialized source file.
34
+
35
+ type ModuleGet = (moduleId: string) => ModuleState | undefined
36
+
16
37
  type ModuleMapInterface<M> = {
17
- readonly at: (moduleId: string) => (moduleMap: M) => ModuleState | undefined
18
- readonly insert: (moduleId: string) => (moduleState: ModuleState) => (moduleMap: M) => M
38
+ readonly get: (moduleMap: M) => ModuleGet
39
+ readonly insert: (moduleMap: M) => (moduleId: string) => (moduleState: ModuleState) => M
19
40
  }
20
41
 
21
- type ModuleState = readonly['ok', Module] | readonly['error', ModuleError] | readonly['building']
42
+ type ModuleState = readonly['ok', Module] | readonly['error', ModuleError]
22
43
 
23
44
  type Module = {
45
+ // Exports is a result of module initialization.
24
46
  readonly exports: unknown
47
+ // A dictionary of required modules.
48
+ // For example, `require('functionalscript/types/list')` may produce the dictionary entry
49
+ // `['functionalscript/types/list', './node_modules/functionalscript/types/list/index.js']`
25
50
  readonly requireMap: object.Map<string>
26
51
  }
27
52
 
28
53
  type ModuleError = 'file not found' | 'compile error' | 'runtime error' | 'circular reference'
29
54
 
30
- type ModuleId = {
55
+ // A module id is a global module id. It contains a package id and file id. For example
56
+ // - `./node_modules/functionalscript/types/list/index.js`
57
+ // - `github:functionalscript/functionalscript:bf4f3ed9ad1d3c19ee7bea3e76000dec77d01b4f/types/list/index.js`
58
+
59
+ type ModuleId = {
31
60
  readonly packageId: string,
32
61
  readonly path: readonly string[],
33
62
  }
@@ -38,7 +67,7 @@ const moduleIdToString: (moduleId: ModuleId) => string;
38
67
 
39
68
  type BuildConfig<M> = {
40
69
  readonly packageGet: PackageGet
41
- readonly moduleMapInterface: ModuleMapInterface<M>
70
+ readonly moduleMapInterface: ModuleMapInterface<M>
42
71
  readonly moduleId: ModuleId
43
72
  readonly moduleMap: M // mutable
44
73
  }
@@ -25,98 +25,153 @@ const path = require('../path')
25
25
  const notFound = moduleMap => [['error', ['file not found']], moduleMap]
26
26
 
27
27
  /**
28
- * @type {(packageGet: package_.Get) =>
28
+ * @type {(compile: function_.Compile) =>
29
+ * (packageGet: package_.Get) =>
29
30
  * <M>(moduleMapInterface: module_.MapInterface<M>) =>
30
- * (compile: function_.Compile) =>
31
31
  * (moduleId: module_.Id) =>
32
- * (moduleMapFirst: M) =>
32
+ * (moduleMap: M) =>
33
33
  * Result<M>
34
34
  * }
35
35
  */
36
- const getOrBuild = packageGet => moduleMapInterface => compile => moduleId => {
37
-
36
+ const getOrBuild = compile => packageGet => moduleMapInterface => {
38
37
  /** @typedef {typeof moduleMapInterface extends module_.MapInterface<infer M> ? M : never} M */
39
-
40
- const moduleIdStr = module_.idToString(moduleId)
41
-
42
- /** @type {(e: module_.Error) => (moduleMap: M) => Result<M>} */
43
- const error = e => moduleMap => {
44
- /** @type {module_.State} */
45
- const state = ['error', e]
46
- return [state, moduleMapInterface.insert(moduleIdStr)(state)(moduleMap)]
47
- }
48
-
49
- /** @type {function_.Require<readonly[M, map.Map<string>]>} */
50
- const require_ = pathStr => prior => {
51
- const pathResult = path.parseAndFind(packageGet)(moduleId.packageId)(moduleIdStr)(pathStr)
52
- if (pathResult === undefined) { return [['error', `file not found: '${pathStr}'`], prior] }
53
- const mId = { packageId: pathResult.package, path: pathResult.file.split('/') }
54
- const [state, newMap] = getOrBuild
55
- (packageGet)
56
- (moduleMapInterface)
57
- (compile)
58
- (mId)
59
- (prior[0])
60
- switch (state[0]) {
61
- case 'ok': {
62
- const newRequireMap = map.set(pathStr)(module_.idToString(mId))(prior[1])
63
- return [
64
- ['ok', state[1].exports],
65
- [newMap, newRequireMap]
66
- ]
67
- }
68
- case 'building': {
69
- return todo()
70
- }
71
- // 'ok'
72
- default: {
73
- return todo()
74
- }
75
- }
38
+ /** @type {(moduleId: module_.Id) => function_.Require<[map.Map<string>, M]>} */
39
+ const req = moduleId => p => prior => {
40
+ const r = path.parseAndFind(packageGet)(moduleId.package)(moduleId.path.join('/'))(p)
41
+ if (r === undefined) { return [['error', 'file not found'], prior] }
42
+ const requireMap = map.set(p)(module_.idToString(moduleId))(prior[0])
43
+ r
44
+ return todo()
76
45
  }
77
-
78
- return moduleMapFirst => {
79
- let moduleMap = moduleMapFirst
80
-
46
+ /**
47
+ * @type {(moduleId: module_.Id) =>
48
+ * (moduleMapFirst: M) =>
49
+ * Result<M>
50
+ * }
51
+ */
52
+ const f = moduleId => moduleMap => {
53
+ const moduleIdStr = module_.idToString(moduleId)
54
+ /** @type {(s: module_.State) => (m: M) => Result<M>} */
55
+ const set = s => m => [s, moduleMapInterface.insert(moduleIdStr)(s)(m)]
56
+ /** @type {(e: module_.Error) => (m: M) => Result<M>} */
57
+ const error = e => set(['error', e])
58
+ // check moduleMap
81
59
  {
82
60
  const m = moduleMapInterface.at(moduleIdStr)(moduleMap)
83
61
  if (m !== undefined) { return [m, moduleMap] }
84
62
  }
85
-
86
- const p = packageGet(moduleId.packageId)
63
+ // check package
64
+ const p = packageGet(moduleId.package)
87
65
  if (p === undefined) { return notFound(moduleMap) }
88
-
89
- const source = p.file(moduleId.path.join('/'))
90
- if (source === undefined) { return notFound(moduleMap) }
91
-
92
- const compileResult = compile(source)
93
- if (compileResult[0] === 'error') { return error(['compilation error', compileResult[1]])(moduleMap) }
94
-
95
- const moduleFunction = compileResult[1]
96
-
97
- moduleMap = moduleMapInterface.insert(moduleIdStr)(['building'])(moduleMap)
98
-
99
- const [[type, exportsOrError], [newModuleMap, requireMap]] = moduleFunction(require_)([moduleMap, map.empty])
100
- moduleMap = newModuleMap
101
-
102
- {
103
- const m = moduleMapInterface.at(moduleIdStr)(moduleMap)
104
- if (m === undefined ) { throw 'm === undefined' }
105
- if (m[0] !== 'building') { return [m, moduleMap] }
106
- }
107
-
108
- /** @type {module_.State} */
109
- const result = type === 'error' ?
110
- ['error', ['runtime error', exportsOrError]] :
111
- ['ok', {
112
- exports: exportsOrError,
113
- requireMap: object.fromMap(requireMap)
114
- }]
115
-
116
- return [result, moduleMapInterface.insert(moduleIdStr)(result)(moduleMap)]
66
+ // check file
67
+ const f = p.file(moduleId.path.join('/'))
68
+ if (f === undefined) { return notFound(moduleMap) }
69
+ // check compilation
70
+ const j = compile(f)
71
+ if (j[0] === 'error') { return error(['compilation error', j[1]])(moduleMap) }
72
+ // build
73
+ const [r, [requireMap, moduleMap2]] = j[1](req(moduleId))([undefined, moduleMap])
74
+ const x = r[0] === 'error' ?
75
+ error(['runtime error', r[1]]) :
76
+ set(['ok', { exports: r[1], requireMap: object.fromEntries(map.entries(requireMap)) }])
77
+ return x(moduleMap2)
117
78
  }
79
+ return f
118
80
  }
119
81
 
82
+ // /**
83
+ // * @type {(packageGet: package_.Get) =>
84
+ // * <M>(moduleMapInterface: module_.MapInterface<M>) =>
85
+ // * (compile: function_.Compile) =>
86
+ // * (moduleId: module_.Id) =>
87
+ // * (moduleMapFirst: M) =>
88
+ // * Result<M>
89
+ // * }
90
+ // */
91
+ // const getOrBuild = packageGet => moduleMapInterface => compile => moduleId => {
92
+
93
+ // /** @typedef {typeof moduleMapInterface extends module_.MapInterface<infer M> ? M : never} M */
94
+
95
+ // const moduleIdStr = module_.idToString(moduleId)
96
+
97
+ // /** @type {(e: module_.Error) => (moduleMap: M) => Result<M>} */
98
+ // const error = e => moduleMap => {
99
+ // /** @type {module_.State} */
100
+ // const state = ['error', e]
101
+ // return [state, moduleMapInterface.insert(moduleIdStr)(state)(moduleMap)]
102
+ // }
103
+
104
+ // /** @type {function_.Require<readonly[M, map.Map<string>]>} */
105
+ // const require_ = pathStr => prior => {
106
+ // const pathResult = path.parseAndFind(packageGet)(moduleId.packageId)(moduleIdStr)(pathStr)
107
+ // if (pathResult === undefined) { return [['error', `file not found: '${pathStr}'`], prior] }
108
+ // const mId = { packageId: pathResult.package, path: pathResult.file.split('/') }
109
+ // const [state, newMap] = getOrBuild
110
+ // (packageGet)
111
+ // (moduleMapInterface)
112
+ // (compile)
113
+ // (mId)
114
+ // (prior[0])
115
+ // switch (state[0]) {
116
+ // case 'ok': {
117
+ // const newRequireMap = map.set(pathStr)(module_.idToString(mId))(prior[1])
118
+ // return [
119
+ // ['ok', state[1].exports],
120
+ // [newMap, newRequireMap]
121
+ // ]
122
+ // }
123
+ // case 'building': {
124
+ // return todo()
125
+ // }
126
+ // // 'ok'
127
+ // default: {
128
+ // return todo()
129
+ // }
130
+ // }
131
+ // }
132
+
133
+ // return moduleMapFirst => {
134
+ // let moduleMap = moduleMapFirst
135
+
136
+ // {
137
+ // const m = moduleMapInterface.at(moduleIdStr)(moduleMap)
138
+ // if (m !== undefined) { return [m, moduleMap] }
139
+ // }
140
+
141
+ // const p = packageGet(moduleId.packageId)
142
+ // if (p === undefined) { return notFound(moduleMap) }
143
+
144
+ // const source = p.file(moduleId.path.join('/'))
145
+ // if (source === undefined) { return notFound(moduleMap) }
146
+
147
+ // const compileResult = compile(source)
148
+ // if (compileResult[0] === 'error') { return error(['compilation error', compileResult[1]])(moduleMap) }
149
+
150
+ // const moduleFunction = compileResult[1]
151
+
152
+ // moduleMap = moduleMapInterface.insert(moduleIdStr)(['building'])(moduleMap)
153
+
154
+ // const [[type, exportsOrError], [newModuleMap, requireMap]] = moduleFunction(require_)([moduleMap, map.empty])
155
+ // moduleMap = newModuleMap
156
+
157
+ // {
158
+ // const m = moduleMapInterface.at(moduleIdStr)(moduleMap)
159
+ // if (m === undefined ) { throw 'm === undefined' }
160
+ // if (m[0] !== 'building') { return [m, moduleMap] }
161
+ // }
162
+
163
+ // /** @type {module_.State} */
164
+ // const result = type === 'error' ?
165
+ // ['error', ['runtime error', exportsOrError]] :
166
+ // ['ok', {
167
+ // exports: exportsOrError,
168
+ // requireMap: object.fromMap(requireMap)
169
+ // }]
170
+
171
+ // return [result, moduleMapInterface.insert(moduleIdStr)(result)(moduleMap)]
172
+ // }
173
+ // }
174
+
120
175
  module.exports = {
121
176
  /** @readonly */
122
177
  getOrBuild,
@@ -11,8 +11,7 @@ const object = require('../../types/object')
11
11
  /**
12
12
  * @typedef {|
13
13
  * readonly['ok', Module] |
14
- * readonly['error', Error] |
15
- * readonly['building']
14
+ * readonly['error', Error]
16
15
  * } State
17
16
  */
18
17
 
@@ -34,13 +33,13 @@ const object = require('../../types/object')
34
33
 
35
34
  /**
36
35
  * @typedef {{
37
- * readonly packageId: string
36
+ * readonly package: string
38
37
  * readonly path: readonly string[]
39
38
  * }} Id
40
39
  */
41
40
 
42
41
  /** @type {(id: Id) => string} */
43
- const idToString = ({ packageId, path }) => `${packageId}/${path.join('/')}`
42
+ const idToString = id => `${id.package}/${id.path.join('/')}`
44
43
 
45
44
  module.exports = {
46
45
  /** @readonly */
@@ -89,7 +89,7 @@ const mapDependency = d => ([external, internal]) => {
89
89
 
90
90
  /**
91
91
  * @typedef {{
92
- * readonly packageId: string,
92
+ * readonly package: string,
93
93
  * readonly items: Items,
94
94
  * readonly dir: boolean,
95
95
  * }} Path
@@ -105,7 +105,7 @@ const parseGlobal = d => dir => items => {
105
105
  const v = variants([undefined, items])
106
106
  const r = list.first(undefined)(list.filterMap(mapDependency(d))(v))
107
107
  if (r === undefined) { return undefined }
108
- return { packageId: r[0], items: list.toArray(r[1]), dir }
108
+ return { package: r[0], items: list.toArray(r[1]), dir }
109
109
  }
110
110
 
111
111
  /**
@@ -119,14 +119,13 @@ const parse = packageId => dependencies => local => path => {
119
119
  const parsed = parseLocal(local)(path)
120
120
  if (parsed === undefined) { return undefined }
121
121
  const {external, dir, items } = parsed
122
- if (!external) { return { packageId, items, dir } }
122
+ if (!external) { return { package: packageId, items, dir } }
123
123
  return parseGlobal(dependencies)(dir)(items)
124
124
  }
125
125
 
126
126
  /**
127
127
  * @typedef {{
128
- * readonly package: string
129
- * readonly file: string
128
+ * readonly id: module_.Id
130
129
  * readonly source: string
131
130
  * }| undefined} Result
132
131
  */
@@ -144,12 +143,12 @@ const parseAndFind = packageGet => packageId => local => path => {
144
143
  if (currentPack === undefined) { return undefined }
145
144
  const p = parse(packageId)(currentPack.dependency)(local)(path)
146
145
  if (p === undefined) { return undefined }
147
- const pack = packageGet(p.packageId)
146
+ const pack = packageGet(p.package)
148
147
  if (pack === undefined) { return undefined }
149
148
  /** @type {(file: string) => Result } */
150
149
  const tryFile = file => {
151
150
  const source = pack.file(file)
152
- return source === undefined ? undefined : { package: p.packageId, file, source }
151
+ return source === undefined ? undefined : { id: { package: p.package, path: file.split('/') }, source }
153
152
  }
154
153
  const file = p.items.join('/')
155
154
  const indexJs = list.join('/')(list.concat(p.items)(['index.js']))
@@ -59,20 +59,20 @@ const stringify = g => {
59
59
  if (_.parseGlobal(d => at(d)({ b: 'x' }))(false)(['d']) !== undefined) { throw 'error' }
60
60
  {
61
61
  const result = stringify(_.parseGlobal(d => at(d)({ b: 'x' }))(false)(['b']))
62
- if (result !== '{"packageId":"x","items":[],"dir":false}') { throw result }
62
+ if (result !== '{"package":"x","items":[],"dir":false}') { throw result }
63
63
  }
64
64
  if (_.parseGlobal(d => at(d)({ 'b/r': 'x' }))(false)(['b']) !== undefined) { throw 'error' }
65
65
  {
66
66
  const result = stringify(_.parseGlobal(d => at(d)({ 'b/r': 'x' }))(false)(['b', 'r']))
67
- if (result !== '{"packageId":"x","items":[],"dir":false}') { throw result }
67
+ if (result !== '{"package":"x","items":[],"dir":false}') { throw result }
68
68
  }
69
69
  {
70
70
  const result = stringify(_.parseGlobal(d => at(d)({ 'b/r': 'x' }))(false)(['b', 'r', 'd', 't']))
71
- if (result !== '{"packageId":"x","items":["d","t"],"dir":false}') { throw result }
71
+ if (result !== '{"package":"x","items":["d","t"],"dir":false}') { throw result }
72
72
  }
73
73
  {
74
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 }
75
+ if (result !== '{"package":"x","items":["d","t"],"dir":true}') { throw result }
76
76
  }
77
77
  }
78
78
 
@@ -85,7 +85,7 @@ const stringify = g => {
85
85
  }
86
86
  }
87
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 }
88
+ if (result !== '{"id":{"package":"","path":["a","c"]},"source":"return \\"a/c\\""}') { throw result }
89
89
  }
90
90
 
91
91
  {
@@ -109,31 +109,33 @@ const stringify = g => {
109
109
  }
110
110
  {
111
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 }
112
+ if (result !== '{"id":{"package":"node_modules/z","path":["a","c","index.js"]},"source":"return \\"a/c\\""}') {
113
+ throw result
114
+ }
113
115
  }
114
116
  {
115
117
  const result = stringify(_.parseAndFind(p => at(p)(packages))('')('a/b')('../..'))
116
- if (result !== '{"package":"","file":"index.js","source":"return \\"index.js\\""}') { throw result }
118
+ if (result !== '{"id":{"package":"","path":["index.js"]},"source":"return \\"index.js\\""}') { throw result }
117
119
  }
118
120
  {
119
121
  const result = stringify(_.parseAndFind(p => at(p)(packages))('')('')('./x'))
120
- if (result !== '{"package":"","file":"x.js","source":"return \\"x.js\\""}') { throw result }
122
+ if (result !== '{"id":{"package":"","path":["x.js"]},"source":"return \\"x.js\\""}') { throw result }
121
123
  }
122
124
  {
123
125
  const result = stringify(_.parseAndFind(p => at(p)(packages))('')('')('./x.js'))
124
- if (result !== '{"package":"","file":"x.js","source":"return \\"x.js\\""}') { throw result }
126
+ if (result !== '{"id":{"package":"","path":["x.js"]},"source":"return \\"x.js\\""}') { throw result }
125
127
  }
126
128
  {
127
129
  const result = stringify(_.parseAndFind(p => at(p)(packages))('')('')('./x/'))
128
- if (result !== '{"package":"","file":"x/index.js","source":"return \\"x/index.js\\""}') { throw result }
130
+ if (result !== '{"id":{"package":"","path":["x","index.js"]},"source":"return \\"x/index.js\\""}') { throw result }
129
131
  }
130
132
  {
131
133
  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 }
134
+ if (result !== '{"id":{"package":"","path":["x","index.js"]},"source":"return \\"x/index.js\\""}') { throw result }
133
135
  }
134
136
  {
135
137
  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 }
138
+ if (result !== '{"id":{"package":"","path":["x","index.js"]},"source":"return \\"x/index.js\\""}') { throw result }
137
139
  }
138
140
  }
139
141
 
@@ -157,11 +159,11 @@ const stringify = g => {
157
159
  }
158
160
  {
159
161
  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 }
162
+ if (result !== '{"id":{"package":"node_modules/z/a","path":["c.js"]},"source":"return \\"c.js\\""}') { throw result }
161
163
  }
162
164
  {
163
165
  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 }
166
+ if (result !== '{"id":{"package":"node_modules/z/a","path":["c","index.js"]},"source":"return \\"c/index.js\\""}') { throw result }
165
167
  }
166
168
  }
167
169
 
@@ -185,5 +187,5 @@ const stringify = g => {
185
187
  }
186
188
  }
187
189
  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 }
190
+ if (result !== '{"id":{"package":"node_modules/z/a/c","path":["index.js"]},"source":"return \\"a/c\\""}') { throw result }
189
191
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.314",
3
+ "version": "0.0.318",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  /**
8
- * Postfix Compose function.
8
+ * A postfix compose function.
9
9
  *
10
10
  * @type {<I, X>(g: Func<I, X>) => <O>(f: Func<X, O>) => Func<I, O>}
11
11
  */
@@ -22,6 +22,6 @@ module.exports = {
22
22
  identity,
23
23
  /** @readonly */
24
24
  compose,
25
- /** @reeadonly */
25
+ /** @readonly */
26
26
  flip,
27
- }
27
+ }