@naanlang/naan 1.0.0

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.
Files changed (98) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +46 -0
  3. package/dist/env_web.js +431 -0
  4. package/dist/naan.min.js +73 -0
  5. package/frameworks/browser/browser.nlg +30 -0
  6. package/frameworks/browser/pouchdb/pouchdb.min.js +7 -0
  7. package/frameworks/browser/spark-md5/spark-md5.min.js +1 -0
  8. package/frameworks/browser/sworker.js +192 -0
  9. package/frameworks/browser/terminals.nlg +787 -0
  10. package/frameworks/browser/workers.nlg +386 -0
  11. package/frameworks/client/apiclient.nlg +183 -0
  12. package/frameworks/client/client.nlg +29 -0
  13. package/frameworks/client/psm_client.nlg +572 -0
  14. package/frameworks/common/common.nlg +464 -0
  15. package/frameworks/common/preferences.nlg +131 -0
  16. package/frameworks/common/repltools.nlg +100 -0
  17. package/frameworks/common/watching.nlg +97 -0
  18. package/frameworks/node/apiserver.nlg +399 -0
  19. package/frameworks/node/filesystem.nlg +1012 -0
  20. package/frameworks/node/gitter.nlg +234 -0
  21. package/frameworks/node/node.nlg +81 -0
  22. package/frameworks/node/psm_server.nlg +465 -0
  23. package/frameworks/node/worker.nlg +560 -0
  24. package/frameworks/project/build.nlg +1229 -0
  25. package/frameworks/project/jszip.js +30 -0
  26. package/frameworks/project/jszip.nlg +87 -0
  27. package/frameworks/project/proj_cliser.nlg +139 -0
  28. package/frameworks/project/proj_console.nlg +137 -0
  29. package/frameworks/project/proj_folder.nlg +143 -0
  30. package/frameworks/project/proj_lambda.nlg +137 -0
  31. package/frameworks/project/proj_static.nlg +138 -0
  32. package/frameworks/project/project.nlg +29 -0
  33. package/frameworks/project/projects.nlg +587 -0
  34. package/frameworks/project/uglifyjs.js +1 -0
  35. package/frameworks/project/uglifyjs.nlg +79 -0
  36. package/frameworks/running/debugcom.nlg +163 -0
  37. package/frameworks/running/debugnub.nlg +565 -0
  38. package/frameworks/running/debugutil.nlg +510 -0
  39. package/frameworks/running/executors.nlg +767 -0
  40. package/frameworks/running/running.nlg +151 -0
  41. package/frameworks/running/sourcecode.nlg +346 -0
  42. package/frameworks/running/taskexec.nlg +196 -0
  43. package/frameworks/storage/dbt_pouch.nlg +773 -0
  44. package/frameworks/storage/file_manager.nlg +772 -0
  45. package/frameworks/storage/psm.nlg +326 -0
  46. package/frameworks/storage/psm_dbtables.nlg +814 -0
  47. package/frameworks/storage/resources.nlg +445 -0
  48. package/frameworks/storage/storage.nlg +52 -0
  49. package/lib/browser/env_web.js +431 -0
  50. package/lib/browser/env_webworker.js +146 -0
  51. package/lib/browser/require.js +1653 -0
  52. package/lib/core/naanlib.js +73 -0
  53. package/lib/env_node.js +282 -0
  54. package/lib/env_nodeworker.js +165 -0
  55. package/lib/node_repl.js +25 -0
  56. package/lib/node_repl_init.nlg +52 -0
  57. package/package.json +13 -0
  58. package/plugins/gitClient/clientops.nlg +317 -0
  59. package/plugins/gitClient/gitClient.nlg +63 -0
  60. package/plugins/gitClient/gitutils.nlg +1331 -0
  61. package/plugins/gitClient/minimatch.js +945 -0
  62. package/plugins/gitClient/minimatch_license.txt +15 -0
  63. package/plugins/gitClient/minimatch_readme.md +208 -0
  64. package/plugins/nodeLib/nodeLib.nlg +26 -0
  65. package/plugins/nodeLib/node_cp.nlg +65 -0
  66. package/plugins/nodeLib/node_fs.nlg +137 -0
  67. package/plugins/nodeLib/node_https.nlg +172 -0
  68. package/plugins/nodeLib/node_util.nlg +180 -0
  69. package/plugins/serviceAws/aws/aws-sdk.min.js +88 -0
  70. package/plugins/serviceAws/aws/lambda_rest_index.js +122 -0
  71. package/plugins/serviceAws/aws/lambda_rest_init.nlg +58 -0
  72. package/plugins/serviceAws/aws/lambda_ws_index.js +498 -0
  73. package/plugins/serviceAws/aws/lambda_ws_init.nlg +49 -0
  74. package/plugins/serviceAws/aws_cloudwatchlogs.nlg +122 -0
  75. package/plugins/serviceAws/aws_cognito.nlg +76 -0
  76. package/plugins/serviceAws/aws_dynamo.nlg +509 -0
  77. package/plugins/serviceAws/aws_lambda.nlg +95 -0
  78. package/plugins/serviceAws/aws_s3.nlg +134 -0
  79. package/plugins/serviceAws/aws_utils.nlg +86 -0
  80. package/plugins/serviceAws/dbt_aws.nlg +769 -0
  81. package/plugins/serviceAws/lambda_naan_control.nlg +175 -0
  82. package/plugins/serviceAws/psm_aws.nlg +258 -0
  83. package/plugins/serviceAws/serviceAws.nlg +38 -0
  84. package/plugins/serviceGitHub/gitops.nlg +522 -0
  85. package/plugins/serviceGitHub/psm_github.nlg +205 -0
  86. package/plugins/serviceGitHub/serviceGitHub.nlg +65 -0
  87. package/plugins/serviceGitLab/gitops.nlg +528 -0
  88. package/plugins/serviceGitLab/psm_gitlab.nlg +205 -0
  89. package/plugins/serviceGitLab/serviceGitLab.nlg +65 -0
  90. package/test/harness.nlg +312 -0
  91. package/test/node_test.js +33 -0
  92. package/test/test_01_core.nlg +768 -0
  93. package/test/test_02_context.nlg +269 -0
  94. package/test/test_03_jsinterop.nlg +137 -0
  95. package/test/test_04_numerics.nlg +450 -0
  96. package/test/test_05_strings.nlg +63 -0
  97. package/test/test_06_lingoparse.nlg +500 -0
  98. package/test/test_07_lingo.nlg +623 -0
@@ -0,0 +1,151 @@
1
+ /*
2
+ * running.nlg
3
+ * Naanlib/frameworks/running
4
+ *
5
+ * Root compoment for running execution instances.
6
+ *
7
+ * column positioning: // // !
8
+ *
9
+ * Copyright (c) 2021 by Richard C. Zulch
10
+ *
11
+ */
12
+
13
+
14
+ /*
15
+ * rootproc
16
+ *
17
+ * Return the root procdef of the specified procdef.
18
+ *
19
+ */
20
+
21
+ function rootproc(procdef, local parent) {
22
+ loop { // can only find out proc
23
+ parent = procdef.1@\.parent
24
+ if !parent
25
+ break
26
+ procdef = parent.proc
27
+ }
28
+ procdef
29
+ };
30
+
31
+
32
+ /*
33
+ * baseproc
34
+ *
35
+ * Return the base procdef if a closure or macro, or the procedure symbol itself otherwise.
36
+ * The base is the original procedure from which a closure or macro is instantiated.
37
+ *
38
+ */
39
+
40
+ function baseproc(procdef) {
41
+ if procdef.1@\.base.proc
42
+ { }
43
+ else
44
+ procdef
45
+ };
46
+
47
+
48
+ /*
49
+ * pathmatch
50
+ *
51
+ * Given a parent symbol and a tuple of child procedure symbols within it, return the child
52
+ * procedure named by the path in the tuple.
53
+ *
54
+ */
55
+
56
+ function pathmatch(parent, path, local segment) {
57
+ if empty(path)
58
+ return (parent)
59
+ segment = tostring(pop(path))
60
+ for child in parent@\.children
61
+ if tostring(child) == segment
62
+ return (pathmatch(child, path))
63
+ false
64
+ };
65
+
66
+
67
+ /*
68
+ * procpath
69
+ *
70
+ * Return a tuple of parent prcoedure symbols for the specified child procedure. Note that this
71
+ * path includes the parent but pathmatch above requires the parent as a separate argument.
72
+ *
73
+ */
74
+
75
+ function procpath(procdef, local path) {
76
+ loop {
77
+ push(procdef.1, path)
78
+ parent = procdef.1@\.parent
79
+ if !parent
80
+ break
81
+ procdef = parent.proc
82
+ }
83
+ path
84
+ };
85
+
86
+
87
+ /*
88
+ * procname
89
+ *
90
+ * Return the full name of possibly-nested procedure.
91
+ *
92
+ */
93
+
94
+ function procname(name, local parent) {
95
+ parent = name@\.parent
96
+ name = tostring(name)
97
+ if parent
98
+ procname(parent).concat(".", name)
99
+ else
100
+ name
101
+ };
102
+
103
+
104
+ /*
105
+ * procstring
106
+ *
107
+ * Return a string representing a procedure and its parameters.
108
+ * Options:
109
+ * {
110
+ * fullname: true // list name path for nested procedures
111
+ * namespace: true // prepend name with namespace
112
+ * }
113
+ *
114
+ */
115
+
116
+ function procstring(procdef, options, local name, output, parm) {
117
+ if options.fullname || !defined(options, `fullname)
118
+ name = procname(procdef.1) // default is full name
119
+ else
120
+ name = procdef.1
121
+ if options.namespace || !defined(options, `namespace) // default includes namespace
122
+ name = procdef.1.namespace.tostring.concat("::", name)
123
+ if !procdef.2 || !car(procdef.2)
124
+ return (tostring(procdef.0).concat(" ", name, "()"))
125
+ if atom(procdef.2)
126
+ return (tostring(procdef.0).concat(" ", name, " ", procdef.2))
127
+ output = tostring(procdef.0).concat(" ", name, "(")
128
+ for parm in procdef.2 {
129
+ if !parm
130
+ break
131
+ output = output.concat(parm, ", ") }
132
+ output = output.slice(0,-2)
133
+ output.concat(")")
134
+ }
135
+
136
+
137
+ /*
138
+ * runnInit
139
+ *
140
+ * Initialize the module.
141
+ *
142
+ */
143
+
144
+ function runnInit(local manifest) {
145
+ manifest = `(rootproc, baseproc, pathmatch, procpath, procname, procstring, runnInit)
146
+
147
+ build(module.id, "running", closure(modobj, compobj) {
148
+ require("../common").LiveImport()
149
+ compobj.manifest = manifest
150
+ })
151
+ } ();
@@ -0,0 +1,346 @@
1
+ /*
2
+ * sourcecode.nlg
3
+ *
4
+ * Source code manager for debugging.
5
+ *
6
+ * column positioning: // // !
7
+ *
8
+ * Copyright (c) 2021 by Richard C. Zulch
9
+ *
10
+ */
11
+
12
+
13
+ /*
14
+ * CodeManager
15
+ *
16
+ * Manage source code for debugging, with caching, tuple/location conversion, etc. The caller
17
+ * can provide a manifest and get a CodeComposite object that tracks source code and tuple locations
18
+ * within it. Creation options are:
19
+ * {
20
+ * cacheSize: <integer> // number of unparser instances to cache
21
+ * }
22
+ *
23
+ */
24
+
25
+ closure CodeManager(options, local coman, cache)
26
+ {
27
+ coman = modlist().CLI.exports.Utils(options)
28
+ coman.independent = new(nonce) // caches are ephemeral
29
+
30
+ // composite
31
+ //
32
+ // Return a code composite for the specified list of symbols.
33
+ //
34
+ coman.composite = function composite(manifest) {
35
+ CodeComposite(coman, manifest)
36
+ }
37
+
38
+ // component
39
+ //
40
+ // Return a code composite for the specified module and component, or false if not found.
41
+ // This will return an "independent" component if it was already created by procComponent.
42
+ //
43
+ coman.component = function component(modname, compname, local component) {
44
+ component = modlist()[modname].components[compname]
45
+ if !component
46
+ return (coman.independent[modname.concat(":-:", compname)])
47
+ CodeComposite(coman, component.manifest, modname, compname)
48
+ }
49
+
50
+ // procComponent
51
+ //
52
+ // Return a code composite for the specified procedure definition. If the module / component
53
+ // cannot be identified then this returns an independent "component". A complexity here is that
54
+ // we always do source operations from the original base procedure of a closure or macro, not the
55
+ // instantiated derivations. This allows us to cache only one copy of the unparser for all the
56
+ // instances, but also prevents a GC problem if you unparse an active closure with a lot of state
57
+ // and then cache it. Turns out these can be very large.
58
+ //
59
+ coman.procComponent = function procComponent(procdef, local sym, mod, modname, compname, component) {
60
+ procdef = baseproc(rootproc(procdef)) // only work with the bases, not instances
61
+ sym = procdef.1
62
+ mod = module.owner.findModule(sym.namespace)
63
+ for `(compname, component) in mod.components
64
+ if member(sym, component.manifest)
65
+ return (CodeComposite(coman, component.manifest, mod.id, compname))
66
+ if sym == car(sym.proc.1)
67
+ sym = car(sym.proc.1) // use interned symbol
68
+ if string(mod.id)
69
+ modname = mod.id
70
+ else
71
+ modname = "<".concat(sym.namespace.tostring, ">") // create independent module
72
+ compname = "<".concat(sym, ">") // create independent component
73
+ coman.independent[modname.concat(":-:", compname)] = CodeComposite(coman, sym, modname, compname)
74
+ }
75
+
76
+ // parseExprs
77
+ //
78
+ // Parse an array of text expressions and return a corresponding array of result tuples with
79
+ // standard `(error, expr) format. The optional locals are symbols to provide context.
80
+ //
81
+ coman.parseExprs = function parseExprs(texts, locals,
82
+ local output, text, source, registry, dialect, error, expr)
83
+ {
84
+ output = []
85
+ for text in texts {
86
+ if !string(text) || text == "" {
87
+ output.push(false)
88
+ continue
89
+ }
90
+ try {
91
+ source = new(textstream, text.concat(" ;")) // avoid EOF
92
+ if locals
93
+ source.setsymbols(locals)
94
+ registry = modlist().Lib.exports.Registry // dialect registry
95
+ dialect = registry.findName(registry.dialects().0) // ### default dialecct
96
+ output.push(dialect.parse(source))
97
+ } catch {
98
+ if true {
99
+ output.push(list(exception))
100
+ }
101
+ }
102
+ }
103
+ output
104
+ }
105
+
106
+ // cacheAdd
107
+ //
108
+ // Add a CodeComposite to our cache. If we really wanted to be fancy we'd have more than one
109
+ // entry, but then we'd need to design an invalidation strategy and the big win here is stepping
110
+ // within the same component--the common case.
111
+
112
+ coman.cacheAdd = function cacheAdd(cocode, manifest, local item, mandefs) {
113
+ for item in manifest
114
+ push(item.proc, mandefs)
115
+ cacne = new(nonce)
116
+ cache.modname = cocode.modname
117
+ cache.compname = cocode.compname
118
+ cache.mandefs = mandefs
119
+ cache.cocode = cocode
120
+ cache
121
+ }
122
+
123
+ // cachGet
124
+ //
125
+ // Get a CodeComposite from our cache, or false.
126
+
127
+ coman.cachGet = function cachGet(cocode, manifest, local entry, item, mandefs) {
128
+ if cache.modname != cocode.modname || cache.compname != cocode.compname || cache.manifest != manifest
129
+ return (false)
130
+ for item in manifest
131
+ push(item.proc, mandefs)
132
+ if cache.mandefs === mandefs
133
+ cache.cocode
134
+ else
135
+ false
136
+ }
137
+
138
+ // finis
139
+ coman
140
+ };
141
+
142
+
143
+ /*
144
+ * CodeComposite
145
+ *
146
+ * Return a code composite for the specified manifest. The composite generates a header and then
147
+ * unparses each of the procedures in order, keeping track of the line ranges. Methods retrieve the
148
+ * source text and allow conversions from a tuple in a procedure to the code location of the tuple in
149
+ * the text. This is most useful for displaying the entire manifest in a scrolling view of lines and
150
+ * finding locations in the view for tuples found on the callstack.
151
+ *
152
+ */
153
+
154
+ closure CodeComposite(coman, manifest, modname, compname, local cocode)
155
+ {
156
+ cocode = new(object, this)
157
+ cocode.modname = modname
158
+ cocode.compname = compname
159
+ if symbol(manifest) && atom(manifest) {
160
+ manifest = list(manifest)
161
+ cocode.unlisted = true // not in any component
162
+ }
163
+ if coman.cachGet(cocode)
164
+ return
165
+ coman.cacheAdd(cocode)
166
+
167
+ // lineCount
168
+ //
169
+ // Count the lines (actually line endings) in a text string. If the string does not end with
170
+ // newline then the partial line afterwards is not counted.
171
+ //
172
+ function lineCount(str) {
173
+ str.length - str.replace(RegExp("\n", "g"), "").length // credit: https://stackoverflow.com/users/2037832/chris-jr
174
+ }
175
+
176
+ // populate
177
+ //
178
+ // Populate the composite from the specified manifest, if needed. Each element has the
179
+ // following structure:
180
+ // {
181
+ // startno: <integer> // first line number in composite, zero-based
182
+ // item: <symbol> // symbol in manifest
183
+ // text: <string> // text of item, including any procedure
184
+ // offset: <integer> // number of lines in element text preceding unparse
185
+ // linecount: <integer> // total linecount of item
186
+ // }
187
+ //
188
+ function populate(local lineno, output, item, comment, prop, element) {
189
+ if cocode.elements
190
+ return // already populated
191
+ cocode.elements = []
192
+ lineno = 0
193
+ for item in manifest {
194
+ output = ""
195
+ comment = item@\.sourcemap.comments.0 // first comment for item
196
+ if comment.0 != 0 || comment.1 != -1
197
+ output = output.concat("/*\n", // make our own header comment
198
+ " * ", item.tostring, "\n",
199
+ " * \n"
200
+ " */\n\n")
201
+ if car(item) !== item
202
+ output = output.concat(item, " = ", coman.unparser(car(item)).string(), ";\n\n")
203
+ comment = output
204
+ for prop in item@* {
205
+ if !prop.startsWith(".")
206
+ output = output.concat("@", prop, " = ", coman.unparser(item@[prop]).string(), ";\n")
207
+ }
208
+ if comment != output
209
+ output = output.concat("\n") // must have output properties
210
+ element = {
211
+ startno: lineno
212
+ item: item
213
+ text: output
214
+ offset: lineCount(output) // number of lines preceding procedure, if any
215
+ }
216
+ if item.proc
217
+ element.text = output.concat(coman.unparser(item.proc).string(), "\n\n")
218
+ element.linecount = lineCount(element.text)
219
+ cocode.elements.push(element)
220
+ lineno += element.linecount
221
+ }
222
+ }
223
+
224
+ // findproc
225
+ //
226
+ // Find the element for the specified procedure definition. ### Eventually this should find
227
+ // the procedure in the item value or item properties.
228
+ //
229
+ function findproc(procdef, local element) {
230
+ for element in cocode.elements
231
+ if element.item.proc === procdef || element.item.proc.1 == procdef.1
232
+ return (element)
233
+ false
234
+ }
235
+
236
+ // findline
237
+ //
238
+ // Find the element for the specified text line number.
239
+ //
240
+ function findline(lineno, local elem, prev) {
241
+ for elem in cocode.elements
242
+ if elem.startno >= lineno
243
+ break
244
+ else
245
+ prev = elem
246
+ prev
247
+ }
248
+
249
+ // string
250
+ //
251
+ // Return the total text string of the composite.
252
+ //
253
+ cocode.string = function string(local output, elem) {
254
+ populate()
255
+ output = ""
256
+ for elem in cocode.elements
257
+ output = output.concat(elem.text)
258
+ output
259
+ }
260
+
261
+ // textpos
262
+ //
263
+ // Return the text position for the specified procedure/task. The return value is a
264
+ // dictionary with a tuple key and first/last fields defined, each a tuple of row and column.
265
+ // One of the complexities here is that an instantiated closure nested in a parent procedure is
266
+ // not listed in the parent's child procedures because it's a 1:N mapping. This checks if the
267
+ // base of the root matches the original procedure definition, and if needed computes the task
268
+ // context within the original root, base procedure.
269
+ //
270
+ cocode.textpos = function textpos(procdef, task,
271
+ local baserootdef, element, lineoff, unpar, path, baseprocdef, taskpath, location) {
272
+ populate()
273
+ baserootdef = baseproc(rootproc(procdef)) // work with base
274
+ element = findproc(baserootdef)
275
+ if element {
276
+ lineoff = element.startno + element.offset
277
+ unpar = coman.unparser(baserootdef)
278
+ if baserootdef !== procdef { // nested and/or instantiated...
279
+ path = procpath(procdef) // procnames path within root
280
+ baseprocdef = pathmatch(baserootdef.1, cdr(path)).proc // base peer to desired procdef
281
+ taskpath = tuplepath(procdef, task) // indexes path within original procdef
282
+ task = apply(`., list(baseprocdef, taskpath)) // base peer to desired task
283
+ }
284
+ location = unpar.findtuple(task)
285
+ {
286
+ first: list(location.first.0 + lineoff, location.first.1)
287
+ last: list(location.last.0 + lineoff, location.last.1)
288
+ line: unpar.string(location.first, list(location.first.0))
289
+ }
290
+ }
291
+ }
292
+
293
+ // findbreak
294
+ //
295
+ // Return a procdef and task for the zero-based (line, col) text position. This returns a
296
+ // dictionary with the actual text location with the procedure/task to target:
297
+ // {
298
+ // first: (line, col)
299
+ // last: (line, col)
300
+ // proc: <procdef>
301
+ // task: <task-tuple>
302
+ // }
303
+ //
304
+ cocode.findbreak = function findbreak(lineno, column, local element, lineoff, output, unpar, result) {
305
+ populate()
306
+ element = findline(lineno)
307
+ lineoff = element.startno + element.offset
308
+ if element {
309
+ output = {
310
+ proc: element.item.proc
311
+ task: cdddr(element.item.proc)
312
+ first: list(lineoff, 0)
313
+ last: list(lineoff, 1)
314
+ }
315
+ unpar = coman.unparser(element.item.proc)
316
+ result = unpar.findbreak(list(lineno-lineoff, column))
317
+ if result {
318
+ output.first = list(result.first.0 + lineoff, result.first.1)
319
+ output.last = list(result.last.0 + lineoff, result.last.1)
320
+ output.task = result.tuple
321
+ output.line = unpar.string(result.first, list(result.first.0))
322
+ }
323
+ output
324
+ }
325
+ }
326
+
327
+ // finis
328
+ cocode
329
+ };
330
+
331
+
332
+ /*
333
+ * codeInit
334
+ *
335
+ * Initialize the component.
336
+ *
337
+ */
338
+
339
+ function codeInit(local manifest) {
340
+ manifest = `(CodeManager, CodeComposite, codeInit)
341
+ Naan.module.build(module.id, "sourcecode", function(modobj, compobj) {
342
+ require("./running.nlg")
343
+ compobj.manifest = manifest
344
+ modobj.exports.CodeManager = CodeManager
345
+ })
346
+ } ();
@@ -0,0 +1,196 @@
1
+ /*
2
+ * taskexec.nlg
3
+ *
4
+ * Task execution for workers.
5
+ *
6
+ * column positioning: // // !
7
+ *
8
+ * Copyright (c) 2021 by Richard C. Zulch
9
+ *
10
+ */
11
+
12
+
13
+ /*
14
+ * taskDispatcher
15
+ *
16
+ * Create a dispatcher for remote evaluation. The replier argument is a function that accepts
17
+ * outgoing messages. The return value is a closure that processes incomming messages. This code is
18
+ * a peer to ExecutorContext in executors.nlg.
19
+ *
20
+ */
21
+
22
+ closure taskDispatcher(replier, local contexts, gohome, util) {
23
+ contexts = { }
24
+ gohome = makeActivator()
25
+ util = modlist().Util.exports
26
+ closure(data, local reply, restorens, expr, roots, proc, args, result) {
27
+ reply = {
28
+ xmsg: "error"
29
+ xid: data.xid
30
+ error: "unknown operation"
31
+ }
32
+ try {
33
+ restorens = makeActivator()
34
+ if data.xmsg == "xstart"
35
+ reply = { xmsg: "xready" } // ready to accept messages
36
+ else if data.xmsg == "register" {
37
+ //
38
+ // register a new context to default namespace
39
+ //
40
+ gohome()
41
+ context = contexts[data.contextID] = { // register new context
42
+ namespace: nsactive()
43
+ activator: gohome
44
+ }
45
+ restorens()
46
+ reply.xmsg = "registered"
47
+ reply.contextID = data.contextID
48
+ reply.error = undefined
49
+ reply.nsname = context.namespace.tostring
50
+ }
51
+ else if data.xmsg == "eval" {
52
+ //
53
+ // evaluate an expression in the context's namespace
54
+ //
55
+ context = contexts[data.contextID]
56
+ if !context
57
+ reply.error = "unknown context"
58
+ else if !context.namespace
59
+ reply.error = "namespace missing"
60
+ else {
61
+ context.activator()
62
+ reply.xmsg = "evaluated"
63
+ reply.contextID = data.contextID
64
+ expr = util.pkgLoad(data.expr, {
65
+ intern: true // intern symbols
66
+ localroots: true // make roots local if needed to intern
67
+ execute: true // execute auto-running procedures
68
+ })
69
+ expr = caar(expr)
70
+ reply.error = undefined
71
+ if expr {
72
+ expr = evalactive(expr)
73
+ if data.get
74
+ roots = new(data.get).map(function(sym){ // new() to get symbol from compress
75
+ compress(sym)
76
+ })
77
+ if roots
78
+ roots = cons(`expr, totuple(roots))
79
+ else
80
+ roots = `(expr)
81
+ reply.result = util.pkgSave(`expr, roots, {
82
+ nsignore: true // don't report namespace errors
83
+ comments: true }) // include comments
84
+ if context.namespace !== nsactive().0
85
+ { // evaluation changed namespace
86
+ context.namespace = nsactive().0
87
+ context.activator = makeActivator()
88
+ }
89
+ }
90
+ }
91
+ }
92
+ else if data.xmsg == "rpc" {
93
+ //
94
+ // call an RPC in the context's namespace
95
+ //
96
+ context = contexts[data.contextID]
97
+ if !context
98
+ reply.error = "unknown context"
99
+ else if !context.namespace
100
+ reply.error = "namespace missing"
101
+ else {
102
+ context.activator()
103
+ reply.xmsg = "executed"
104
+ reply.contextID = data.contextID
105
+ if data.args && !(args = new(data.args).totuple)
106
+ reply.error = "invalid arguments"
107
+ else if !string(data.proc)
108
+ reply.error = "invalid procedure"
109
+ else {
110
+ proc = compress(data.proc)
111
+ reply.error = undefined
112
+ reply.result = apply(proc, args)
113
+ if context.namespace !== nsactive().0
114
+ { // evaluation changed namespace
115
+ context.namespace = nsactive().0
116
+ context.activator = makeActivator()
117
+ }
118
+ }
119
+ }
120
+ }
121
+ else
122
+ call(onMessageHook, data)
123
+ } catch {
124
+ if true {
125
+ if tuple(exception)
126
+ result = exception.toarray.map(function(x){tostring(x)}).join(" - ")
127
+ else
128
+ result = tostring(exception)
129
+ reply.error = "exception: ".concat(result)
130
+ }
131
+ } finally {
132
+ restorens()
133
+ }
134
+ replier(reply)
135
+ }
136
+ };
137
+
138
+
139
+ /*
140
+ * TaskExecutor
141
+ *
142
+ * Install an executor for remote evaluation in worker threads. This uses the OnMessage protocol
143
+ * available in the env_xxx.js Naan controllers. The return value is false if OnMessage is not there
144
+ * or true on success.
145
+ *
146
+ */
147
+
148
+ closure TaskExecutor() {
149
+
150
+ // taskInstall
151
+ // Install the taskDispatcher, and reload on state load.
152
+ //
153
+ function taskInstall() {
154
+ if !js.t.OnMessage
155
+ return (false) // false if not a worker
156
+ js.t.OnMessage(taskDispatcher(js.t.ReplyMessage))
157
+ }()
158
+ LoadNotify(taskInstall)
159
+
160
+ // finis
161
+
162
+ true
163
+ };
164
+
165
+
166
+ /*
167
+ * TaskOnMessageHook
168
+ *
169
+ * OK, this is a kludge, but you call this function to specify a handler proc when a message
170
+ * comes in that we don't understand.
171
+ *
172
+ */
173
+
174
+ function TaskOnMessageHook(hook) {
175
+ onMessageHook = hook
176
+ };
177
+
178
+
179
+ /*
180
+ * taxInit
181
+ *
182
+ * Initialize the component.
183
+ *
184
+ */
185
+
186
+ function taxInit(local manifest) {
187
+
188
+ manifest = `(taskDispatcher, TaskExecutor, TaskOnMessageHook, taxInit)
189
+
190
+ Naan.module.build(module.id, "taskexec", function(modobj, compobj) {
191
+ require("./running.nlg").LiveImport()
192
+ compobj.manifest = manifest
193
+ modobj.exports.TaskExecutor = TaskExecutor
194
+ modobj.exports.TaskOnMessageHook = TaskOnMessageHook
195
+ })
196
+ } ();