theprogrammablemind 7.1.4-beta.3
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/client.js +1473 -0
- package/index.js +27 -0
- package/lines.js +61 -0
- package/package.json +63 -0
- package/readme +132 -0
- package/src/config.js +2129 -0
- package/src/digraph.js +110 -0
- package/src/flatten.js +143 -0
- package/src/generators.js +282 -0
- package/src/helpers.js +216 -0
- package/src/semantics.js +293 -0
- package/src/unflatten.js +128 -0
package/src/digraph.js
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
const toA = (edge) => {
|
2
|
+
if (Array.isArray(edge)) {
|
3
|
+
return edge
|
4
|
+
} else {
|
5
|
+
return [edge.child, edge.parent]
|
6
|
+
}
|
7
|
+
}
|
8
|
+
|
9
|
+
class Digraph {
|
10
|
+
// edges maybe either [child, parent] or { child, parent }
|
11
|
+
constructor (edges = []) {
|
12
|
+
this.edges = edges
|
13
|
+
}
|
14
|
+
|
15
|
+
/*
|
16
|
+
edges () {
|
17
|
+
return this.edges
|
18
|
+
}
|
19
|
+
*/
|
20
|
+
acdcs (s, from, to) {
|
21
|
+
const todo = [s]
|
22
|
+
const seen = new Set([s])
|
23
|
+
const acdcs = new Set([])
|
24
|
+
while (todo.length > 0) {
|
25
|
+
const n = todo.pop()
|
26
|
+
this.edges.forEach((e) => {
|
27
|
+
e = toA(e)
|
28
|
+
if (e[from] === n) {
|
29
|
+
acdcs.add(e[to])
|
30
|
+
if (!seen.has(e[to])) {
|
31
|
+
todo.push(e[to])
|
32
|
+
seen.add(e[to])
|
33
|
+
}
|
34
|
+
}
|
35
|
+
})
|
36
|
+
}
|
37
|
+
return acdcs
|
38
|
+
}
|
39
|
+
|
40
|
+
isA (low, high) {
|
41
|
+
if (low === high) {
|
42
|
+
return true
|
43
|
+
}
|
44
|
+
return this.ancestors(low).has(high)
|
45
|
+
}
|
46
|
+
|
47
|
+
lessThan (low, high) {
|
48
|
+
if (low === high) {
|
49
|
+
return false
|
50
|
+
}
|
51
|
+
return this.ancestors(low).has(high)
|
52
|
+
}
|
53
|
+
|
54
|
+
descendants (s) {
|
55
|
+
return this.acdcs(s, 1, 0)
|
56
|
+
}
|
57
|
+
|
58
|
+
ancestors (s) {
|
59
|
+
return this.acdcs(s, 0, 1)
|
60
|
+
}
|
61
|
+
|
62
|
+
minima (nodes) {
|
63
|
+
let minima = new Set(nodes)
|
64
|
+
const ancestors = new Set([])
|
65
|
+
nodes.forEach((node) => {
|
66
|
+
this.ancestors(node).forEach((n) => ancestors.add(n))
|
67
|
+
})
|
68
|
+
ancestors.forEach((n) => minima.delete(n))
|
69
|
+
if (minima.size === 0) {
|
70
|
+
// all unrelated
|
71
|
+
minima = new Set(nodes)
|
72
|
+
}
|
73
|
+
return minima
|
74
|
+
}
|
75
|
+
|
76
|
+
maxima (nodes) {
|
77
|
+
const maxima = new Set(nodes)
|
78
|
+
const descendants = new Set([])
|
79
|
+
nodes.forEach((node) => {
|
80
|
+
this.descendants(node).forEach((n) => descendants.add(n))
|
81
|
+
})
|
82
|
+
descendants.forEach((n) => maxima.delete(n))
|
83
|
+
return maxima
|
84
|
+
}
|
85
|
+
|
86
|
+
add (child, parent) {
|
87
|
+
this.edges.push([child, parent])
|
88
|
+
}
|
89
|
+
|
90
|
+
addList (l) {
|
91
|
+
for (let i = 1; i < l.length; ++i) {
|
92
|
+
this.edges.push([l[i - 1], l[i]])
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
order (todo) {
|
97
|
+
const ordered = []
|
98
|
+
while (todo.length > 0) {
|
99
|
+
const nodes = this.minima(todo)
|
100
|
+
todo = todo.filter((e) => !nodes.has(e))
|
101
|
+
for (const node of nodes) {
|
102
|
+
ordered.push(node)
|
103
|
+
}
|
104
|
+
// ordered = ordered.concat([...nodes])
|
105
|
+
}
|
106
|
+
return ordered
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
module.exports = Digraph
|
package/src/flatten.js
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
const { isArray, isObject, isCompound } = require('./helpers')
|
2
|
+
const _ = require('lodash')
|
3
|
+
|
4
|
+
const DEBUG = (...args) => {
|
5
|
+
// DEBUG(...args)
|
6
|
+
}
|
7
|
+
|
8
|
+
const flattens = (markers, contexts) => {
|
9
|
+
let flats = []
|
10
|
+
for (const context of contexts) {
|
11
|
+
// const [more, _] = flatten(markers, context)
|
12
|
+
const more = flatten(markers, context)[0]
|
13
|
+
flats = flats.concat(more)
|
14
|
+
}
|
15
|
+
return flats
|
16
|
+
}
|
17
|
+
|
18
|
+
const accumulate = (accumulator, nexts) => {
|
19
|
+
const accumulatorPrime = []
|
20
|
+
for (const current of accumulator) {
|
21
|
+
for (const next of nexts) {
|
22
|
+
const nextCurrent = _.clone(current)
|
23
|
+
nextCurrent.push(next)
|
24
|
+
accumulatorPrime.push(nextCurrent)
|
25
|
+
}
|
26
|
+
}
|
27
|
+
return accumulatorPrime
|
28
|
+
}
|
29
|
+
|
30
|
+
const cartesianHelper = (accumulator, b, ...c) => {
|
31
|
+
if (b) {
|
32
|
+
return cartesianHelper(accumulate(accumulator, b), ...c)
|
33
|
+
} else {
|
34
|
+
return accumulator
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
const cartesian = (...factors) => {
|
39
|
+
return cartesianHelper([[]], ...factors)
|
40
|
+
}
|
41
|
+
|
42
|
+
const zip = (a1, a2) => {
|
43
|
+
return a1.map(function (value, index) {
|
44
|
+
return [value, a2[index]]
|
45
|
+
})
|
46
|
+
}
|
47
|
+
|
48
|
+
const flattenListHelper = (markers, values) => {
|
49
|
+
const flats = []
|
50
|
+
let wasFlattened = false
|
51
|
+
let singles = []
|
52
|
+
for (const value of values) {
|
53
|
+
if (!isCompound(value)) {
|
54
|
+
singles.push(value)
|
55
|
+
} else {
|
56
|
+
const [more, wf] = flatten(markers, value)
|
57
|
+
if (wf) {
|
58
|
+
wasFlattened = wasFlattened || wf
|
59
|
+
flats.push(more)
|
60
|
+
} else {
|
61
|
+
singles = singles.concat(more)
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
// product does weirdness with only choice
|
67
|
+
if (!wasFlattened) {
|
68
|
+
return [[singles], wasFlattened]
|
69
|
+
} else {
|
70
|
+
const results = []
|
71
|
+
for (const flat of cartesian(...flats)) {
|
72
|
+
results.push(singles.concat(flat))
|
73
|
+
}
|
74
|
+
return [results, wasFlattened]
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
// returns (list, wasFlattened)
|
79
|
+
const flatten = (markers, value) => {
|
80
|
+
if (isArray(value)) {
|
81
|
+
return flattenListHelper(markers, value)
|
82
|
+
}
|
83
|
+
|
84
|
+
const marker = value.marker
|
85
|
+
let properties = value
|
86
|
+
|
87
|
+
// if you want to pull up conj properties fix this to do to the other part
|
88
|
+
// split = marker in markers
|
89
|
+
const split = markers.includes(marker)
|
90
|
+
if (split) {
|
91
|
+
if ('value' in properties) {
|
92
|
+
return [properties.value, true]
|
93
|
+
} else {
|
94
|
+
return [[value], false]
|
95
|
+
}
|
96
|
+
}
|
97
|
+
|
98
|
+
const keys = []
|
99
|
+
const valuess = []
|
100
|
+
const unchanged = {}
|
101
|
+
DEBUG('properties', JSON.stringify(properties, null, 2))
|
102
|
+
for (const key in properties) {
|
103
|
+
let wf = false
|
104
|
+
let values
|
105
|
+
// if isinstance(properties[key], Context) {
|
106
|
+
if (isObject(properties[key])) {
|
107
|
+
const context = properties[key];
|
108
|
+
[values, wf] = flatten(markers, context)
|
109
|
+
// } else if (isinstance(properties[key], list)) {
|
110
|
+
} else if (isArray(properties[key])) {
|
111
|
+
[values, wf] = flattenListHelper(markers, properties[key])
|
112
|
+
} else {
|
113
|
+
values = [properties[key]]
|
114
|
+
}
|
115
|
+
|
116
|
+
if (wf) {
|
117
|
+
keys.push(key)
|
118
|
+
valuess.push(values)
|
119
|
+
} else {
|
120
|
+
unchanged[key] = values[0]
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
const propertiess = []
|
125
|
+
DEBUG('-----------> valuess', JSON.stringify(valuess))
|
126
|
+
DEBUG('-----------> cartesian(valuess)', JSON.stringify(cartesian(valuess)))
|
127
|
+
// for (let values of itertools.product(*valuess)) {
|
128
|
+
const cp = cartesian(...valuess)
|
129
|
+
DEBUG('-----------> cp', JSON.stringify(cp))
|
130
|
+
for (const values of cartesian(...valuess)) {
|
131
|
+
// properties = copy.deepcopy(unchanged)
|
132
|
+
properties = _.cloneDeep(unchanged)
|
133
|
+
// for key, value in zip(keys, values) {
|
134
|
+
for (const [key, value] of zip(keys, values)) {
|
135
|
+
properties[key] = value
|
136
|
+
}
|
137
|
+
propertiess.push(properties)
|
138
|
+
}
|
139
|
+
|
140
|
+
return [propertiess, valuess.length > 0]
|
141
|
+
}
|
142
|
+
|
143
|
+
module.exports = { flattens, flatten, cartesian, accumulate }
|
@@ -0,0 +1,282 @@
|
|
1
|
+
const { args: contextArgs, normalizeGenerator } = require('./helpers')
|
2
|
+
const Lines = require('../lines')
|
3
|
+
const sortJson = require('sort-json')
|
4
|
+
const helpers = require('./helpers')
|
5
|
+
|
6
|
+
class Generator {
|
7
|
+
// constructor ({ match, apply, uuid, index, km, priority, notes }) {
|
8
|
+
constructor (generator) {
|
9
|
+
generator = normalizeGenerator(generator)
|
10
|
+
const { match, apply, uuid, index, km, priority, where, notes, debug } = generator
|
11
|
+
this.match = match
|
12
|
+
this._apply = apply
|
13
|
+
this.uuid = uuid
|
14
|
+
this.index = index
|
15
|
+
this.km = km
|
16
|
+
this.priority = priority || 0
|
17
|
+
this.notes = notes
|
18
|
+
this.where = where
|
19
|
+
this.callId = debug
|
20
|
+
}
|
21
|
+
|
22
|
+
getAPI (config) {
|
23
|
+
if (config && config.getAPI) {
|
24
|
+
return config.getAPI(this.uuid)
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
getAPIs (config) {
|
29
|
+
if (config && config._api && config._api.multiApi) {
|
30
|
+
return config._api.apis
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
toLabel () {
|
35
|
+
const where = this.where ? `where: "${this.where}"` : ''
|
36
|
+
if (!this.km) {
|
37
|
+
return where
|
38
|
+
}
|
39
|
+
return `KM '${this.km}' ordinal: ${this.index} ${where}`
|
40
|
+
}
|
41
|
+
|
42
|
+
toString () {
|
43
|
+
return `Generator(${this.match}, ${this._apply})`
|
44
|
+
}
|
45
|
+
|
46
|
+
matches (baseArgs, objects, context, hierarchy, config, options = {}) {
|
47
|
+
if (objects && objects.namespaced) {
|
48
|
+
objects = objects.namespaced[this.uuid]
|
49
|
+
}
|
50
|
+
// return this.match({ ...args, args: contextArgs(context, hierarchy), objects, global: objects, hierarchy, context, api: this.getAPI(config) })
|
51
|
+
const callId = baseArgs.calls.current()
|
52
|
+
const moreArgs = {
|
53
|
+
uuid: this.uuid,
|
54
|
+
args: contextArgs(context, hierarchy),
|
55
|
+
objects,
|
56
|
+
global: objects,
|
57
|
+
// hierarchy,
|
58
|
+
context,
|
59
|
+
callId,
|
60
|
+
api: this.getAPI(config),
|
61
|
+
apis: this.getAPIs(config)
|
62
|
+
}
|
63
|
+
const args = Object.assign({}, baseArgs, moreArgs)
|
64
|
+
// return this.match(args)
|
65
|
+
const matches = this.match(args)
|
66
|
+
if ((matches && (options.debug || {}).match)
|
67
|
+
||
|
68
|
+
callId == this.callId) {
|
69
|
+
debugger; // next line is the matcher
|
70
|
+
this.match(args)
|
71
|
+
}
|
72
|
+
return matches
|
73
|
+
}
|
74
|
+
|
75
|
+
apply (baseArgs, objects, g, gs, context, hierarchy, config, response, log, options = {}) {
|
76
|
+
if (!log) {
|
77
|
+
throw 'generators.apply argument log is required'
|
78
|
+
}
|
79
|
+
|
80
|
+
// this.getAPI(config)
|
81
|
+
let n = (id) => id
|
82
|
+
if (config && 'nsToString' in config) {
|
83
|
+
n = (id) => config.nsToString(id)
|
84
|
+
}
|
85
|
+
if (objects && objects.namespaced) {
|
86
|
+
objects = objects.namespaced[this.uuid]
|
87
|
+
}
|
88
|
+
const km = (name) => config.getConfig(name)
|
89
|
+
const callId = baseArgs.calls.current()
|
90
|
+
const moreArgs = {
|
91
|
+
callId,
|
92
|
+
uuid: this.uuid,
|
93
|
+
// km,
|
94
|
+
args: contextArgs(context, hierarchy),
|
95
|
+
objects,
|
96
|
+
log,
|
97
|
+
global:
|
98
|
+
objects,
|
99
|
+
g,
|
100
|
+
n,
|
101
|
+
hierarchy,
|
102
|
+
context,
|
103
|
+
uuid: this.uuid,
|
104
|
+
gs,
|
105
|
+
config,
|
106
|
+
response,
|
107
|
+
api: this.getAPI(config),
|
108
|
+
apis: this.getAPIs(config)
|
109
|
+
}
|
110
|
+
const args = Object.assign({}, baseArgs, moreArgs)
|
111
|
+
// if (this.callId) {
|
112
|
+
// greg
|
113
|
+
/*
|
114
|
+
if (callId == 'call11' && this.callId) {
|
115
|
+
debugger;
|
116
|
+
}
|
117
|
+
*/
|
118
|
+
if ((options.debug || {}).apply
|
119
|
+
||
|
120
|
+
callId == this.callId) {
|
121
|
+
debugger
|
122
|
+
}
|
123
|
+
return this._apply(args)
|
124
|
+
}
|
125
|
+
}
|
126
|
+
|
127
|
+
class Generators {
|
128
|
+
constructor (generators, logs = []) {
|
129
|
+
generators = (generators || []).map((generator) => {
|
130
|
+
if (generator instanceof Generator) {
|
131
|
+
return generator
|
132
|
+
} else {
|
133
|
+
return new Generator(generator)
|
134
|
+
}
|
135
|
+
})
|
136
|
+
this.defaults = []
|
137
|
+
const priorityToGenerators = {}
|
138
|
+
const add = (priority, value) => {
|
139
|
+
if (!priorityToGenerators[priority]) {
|
140
|
+
priorityToGenerators[priority] = []
|
141
|
+
}
|
142
|
+
priorityToGenerators[priority].push(value)
|
143
|
+
}
|
144
|
+
for (const generator of generators) {
|
145
|
+
const priority = generator.priority
|
146
|
+
add(priority, generator)
|
147
|
+
}
|
148
|
+
this.generators = []
|
149
|
+
for (const key of Object.keys(priorityToGenerators).sort()) {
|
150
|
+
this.generators = this.generators.concat(priorityToGenerators[key])
|
151
|
+
}
|
152
|
+
// this.generators = generators
|
153
|
+
this.logs = logs
|
154
|
+
};
|
155
|
+
|
156
|
+
// assumed - properties added to contexts before the generators are called. For setting paraphrase property
|
157
|
+
apply (args, contexts, assumed = {}, options = {}) {
|
158
|
+
const config = args.config
|
159
|
+
const objects = args.objects
|
160
|
+
const hierarchy = args.hierarchy
|
161
|
+
const response = args.response
|
162
|
+
if (Array.isArray(contexts)) {
|
163
|
+
// no-op
|
164
|
+
} else if (typeof contexts === 'object') {
|
165
|
+
contexts = [contexts]
|
166
|
+
} else {
|
167
|
+
return String(contexts)
|
168
|
+
}
|
169
|
+
|
170
|
+
const contextsPrime = []
|
171
|
+
for (const icontext in contexts) {
|
172
|
+
let context = contexts[icontext]
|
173
|
+
context = Object.assign({}, context, assumed)
|
174
|
+
// let context_prime = JSON.stringify(context);
|
175
|
+
let contextPrime = context
|
176
|
+
let applied = false
|
177
|
+
const stack = args.calls.push()
|
178
|
+
for (let igenerator = 0; igenerator < this.generators.length; ++igenerator) {
|
179
|
+
const generator = this.generators[igenerator]
|
180
|
+
if (generator.matches(args, objects, context, hierarchy, config, options)) {
|
181
|
+
const g = (context, options) => {
|
182
|
+
const r = this.apply(args, context, Object.assign({}, ((options||{}).assumed || {}), assumed), options)
|
183
|
+
if (Array.isArray(r)) {
|
184
|
+
return r.join(' ')
|
185
|
+
} else {
|
186
|
+
return r
|
187
|
+
}
|
188
|
+
}
|
189
|
+
const log = (message) => { this.logs.push(message) }
|
190
|
+
// this.logs.push(`Generators: applied ${generator.toString()}\n to\n ${JSON.stringify(context)}`)
|
191
|
+
let errorMessage = 'The apply function did not return a value'
|
192
|
+
try {
|
193
|
+
contextPrime = generator.apply(args, objects, g, args.gs, context, hierarchy, config, response, log)
|
194
|
+
} catch( e ) {
|
195
|
+
// the next if handle this
|
196
|
+
contextPrime = null
|
197
|
+
if (e.stack && e.message) {
|
198
|
+
errorMessage = `Error applying generator '${generator.notes}'. Error is ${e.toString()} stack is ${e.stack}. Generator is ${generator.toString()}`
|
199
|
+
} else if (e.error) {
|
200
|
+
errorMessage = `Error applying generator '${generator.notes}'. Error is ${e.error.join()}. Generator is ${generator.toString()}`
|
201
|
+
} else {
|
202
|
+
errorMessage = e.toString()
|
203
|
+
}
|
204
|
+
}
|
205
|
+
if (!contextPrime && contextPrime !== '') {
|
206
|
+
const widths = [10, 10, 90]
|
207
|
+
const lines = new Lines(widths)
|
208
|
+
lines.setElement(0, 0, 'Generator')
|
209
|
+
const source = `${generator.km}/#${generator.index}`
|
210
|
+
lines.setElement(0, 2, `ERROR while applying (${source}) ${generator.toLabel()}`)
|
211
|
+
lines.newRow()
|
212
|
+
lines.setElement(0, 2, generator.toString())
|
213
|
+
lines.newRow()
|
214
|
+
lines.setElement(0, 1, 'TO')
|
215
|
+
lines.setElement(0, 2, `(HASHCODE ${helpers.hashCode(JSON.stringify(sortJson(context, { depth: 25 })))})`)
|
216
|
+
lines.setElement(1, 2, JSON.stringify(sortJson(context, { depth: 25 }), null, 2))
|
217
|
+
lines.newRow()
|
218
|
+
lines.setElement(0, 1, 'STACK')
|
219
|
+
lines.setElement(0, 2, stack)
|
220
|
+
lines.newRow()
|
221
|
+
lines.setElement(0, 1, 'DEBUG')
|
222
|
+
lines.setElement(0, 2, `To debug this use args.callId == '${args.calls.current()}'`)
|
223
|
+
lines.newRow()
|
224
|
+
lines.setElement(0, 1, 'ERROR')
|
225
|
+
lines.setElement(0, 2, errorMessage)
|
226
|
+
this.logs.push(lines.toString())
|
227
|
+
const message = `ERROR while applying (${source}) ${generator.toLabel()}\n to\n ${JSON.stringify(context, null, 2)}.\n${errorMessage}'`
|
228
|
+
// this.logs.push(message)
|
229
|
+
// return [message]
|
230
|
+
args.calls.pop()
|
231
|
+
throw { error: [message], logs: this.logs }
|
232
|
+
}
|
233
|
+
if (((config || {}).config || {}).debug) {
|
234
|
+
const widths = [10, 10, 90]
|
235
|
+
const lines = new Lines(widths)
|
236
|
+
lines.setElement(0, 0, 'Generator')
|
237
|
+
if (generator.index > -1 && generator.km) {
|
238
|
+
// lines.setElement(0, 2, `KM '${generator.km}' ordinal: ${generator.index}`)
|
239
|
+
lines.setElement(0, 2, generator.toLabel())
|
240
|
+
}
|
241
|
+
lines.newRow()
|
242
|
+
lines.setElement(0, 1, 'APPLIED')
|
243
|
+
lines.setElement(0, 2, generator.toLabel())
|
244
|
+
lines.newRow()
|
245
|
+
lines.setElement(0, 2, generator.toString())
|
246
|
+
lines.newRow()
|
247
|
+
lines.setElement(0, 1, 'RESULT')
|
248
|
+
lines.setElement(0, 2, contextPrime)
|
249
|
+
lines.newRow()
|
250
|
+
lines.setElement(0, 1, 'STACK')
|
251
|
+
lines.setElement(0, 2, stack)
|
252
|
+
lines.newRow()
|
253
|
+
lines.newRow()
|
254
|
+
lines.setElement(0, 1, 'DEBUG')
|
255
|
+
lines.setElement(0, 2, `To debug this use args.callId == '${args.calls.current()}'`)
|
256
|
+
lines.setElement(0, 1, 'TO')
|
257
|
+
lines.setElement(0, 2, `(HASHCODE ${helpers.hashCode(JSON.stringify(sortJson(context, { depth: 25 })))})`)
|
258
|
+
lines.setElement(1, 2, JSON.stringify(sortJson(context, { depth: 25 }), null, 2))
|
259
|
+
this.logs.push(lines.toString())
|
260
|
+
}
|
261
|
+
applied = true
|
262
|
+
break
|
263
|
+
}
|
264
|
+
}
|
265
|
+
args.calls.pop()
|
266
|
+
if (!applied && ((config || {}).config || {}).debug) {
|
267
|
+
const widths = [10, 10, 90]
|
268
|
+
const lines = new Lines(widths)
|
269
|
+
lines.setElement(0, 0, 'Generator')
|
270
|
+
lines.setElement(0, 2, 'No generator applied')
|
271
|
+
lines.newRow()
|
272
|
+
lines.setElement(0, 1, 'TO')
|
273
|
+
lines.setElement(0, 2, JSON.stringify(context, null, 2))
|
274
|
+
this.logs.push(lines.toString())
|
275
|
+
}
|
276
|
+
contextsPrime.push(contextPrime)
|
277
|
+
}
|
278
|
+
return contextsPrime
|
279
|
+
}
|
280
|
+
}
|
281
|
+
|
282
|
+
module.exports = { Generator, Generators, normalizeGenerator }
|