@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.
- package/LICENSE.md +21 -0
- package/README.md +46 -0
- package/dist/env_web.js +431 -0
- package/dist/naan.min.js +73 -0
- package/frameworks/browser/browser.nlg +30 -0
- package/frameworks/browser/pouchdb/pouchdb.min.js +7 -0
- package/frameworks/browser/spark-md5/spark-md5.min.js +1 -0
- package/frameworks/browser/sworker.js +192 -0
- package/frameworks/browser/terminals.nlg +787 -0
- package/frameworks/browser/workers.nlg +386 -0
- package/frameworks/client/apiclient.nlg +183 -0
- package/frameworks/client/client.nlg +29 -0
- package/frameworks/client/psm_client.nlg +572 -0
- package/frameworks/common/common.nlg +464 -0
- package/frameworks/common/preferences.nlg +131 -0
- package/frameworks/common/repltools.nlg +100 -0
- package/frameworks/common/watching.nlg +97 -0
- package/frameworks/node/apiserver.nlg +399 -0
- package/frameworks/node/filesystem.nlg +1012 -0
- package/frameworks/node/gitter.nlg +234 -0
- package/frameworks/node/node.nlg +81 -0
- package/frameworks/node/psm_server.nlg +465 -0
- package/frameworks/node/worker.nlg +560 -0
- package/frameworks/project/build.nlg +1229 -0
- package/frameworks/project/jszip.js +30 -0
- package/frameworks/project/jszip.nlg +87 -0
- package/frameworks/project/proj_cliser.nlg +139 -0
- package/frameworks/project/proj_console.nlg +137 -0
- package/frameworks/project/proj_folder.nlg +143 -0
- package/frameworks/project/proj_lambda.nlg +137 -0
- package/frameworks/project/proj_static.nlg +138 -0
- package/frameworks/project/project.nlg +29 -0
- package/frameworks/project/projects.nlg +587 -0
- package/frameworks/project/uglifyjs.js +1 -0
- package/frameworks/project/uglifyjs.nlg +79 -0
- package/frameworks/running/debugcom.nlg +163 -0
- package/frameworks/running/debugnub.nlg +565 -0
- package/frameworks/running/debugutil.nlg +510 -0
- package/frameworks/running/executors.nlg +767 -0
- package/frameworks/running/running.nlg +151 -0
- package/frameworks/running/sourcecode.nlg +346 -0
- package/frameworks/running/taskexec.nlg +196 -0
- package/frameworks/storage/dbt_pouch.nlg +773 -0
- package/frameworks/storage/file_manager.nlg +772 -0
- package/frameworks/storage/psm.nlg +326 -0
- package/frameworks/storage/psm_dbtables.nlg +814 -0
- package/frameworks/storage/resources.nlg +445 -0
- package/frameworks/storage/storage.nlg +52 -0
- package/lib/browser/env_web.js +431 -0
- package/lib/browser/env_webworker.js +146 -0
- package/lib/browser/require.js +1653 -0
- package/lib/core/naanlib.js +73 -0
- package/lib/env_node.js +282 -0
- package/lib/env_nodeworker.js +165 -0
- package/lib/node_repl.js +25 -0
- package/lib/node_repl_init.nlg +52 -0
- package/package.json +13 -0
- package/plugins/gitClient/clientops.nlg +317 -0
- package/plugins/gitClient/gitClient.nlg +63 -0
- package/plugins/gitClient/gitutils.nlg +1331 -0
- package/plugins/gitClient/minimatch.js +945 -0
- package/plugins/gitClient/minimatch_license.txt +15 -0
- package/plugins/gitClient/minimatch_readme.md +208 -0
- package/plugins/nodeLib/nodeLib.nlg +26 -0
- package/plugins/nodeLib/node_cp.nlg +65 -0
- package/plugins/nodeLib/node_fs.nlg +137 -0
- package/plugins/nodeLib/node_https.nlg +172 -0
- package/plugins/nodeLib/node_util.nlg +180 -0
- package/plugins/serviceAws/aws/aws-sdk.min.js +88 -0
- package/plugins/serviceAws/aws/lambda_rest_index.js +122 -0
- package/plugins/serviceAws/aws/lambda_rest_init.nlg +58 -0
- package/plugins/serviceAws/aws/lambda_ws_index.js +498 -0
- package/plugins/serviceAws/aws/lambda_ws_init.nlg +49 -0
- package/plugins/serviceAws/aws_cloudwatchlogs.nlg +122 -0
- package/plugins/serviceAws/aws_cognito.nlg +76 -0
- package/plugins/serviceAws/aws_dynamo.nlg +509 -0
- package/plugins/serviceAws/aws_lambda.nlg +95 -0
- package/plugins/serviceAws/aws_s3.nlg +134 -0
- package/plugins/serviceAws/aws_utils.nlg +86 -0
- package/plugins/serviceAws/dbt_aws.nlg +769 -0
- package/plugins/serviceAws/lambda_naan_control.nlg +175 -0
- package/plugins/serviceAws/psm_aws.nlg +258 -0
- package/plugins/serviceAws/serviceAws.nlg +38 -0
- package/plugins/serviceGitHub/gitops.nlg +522 -0
- package/plugins/serviceGitHub/psm_github.nlg +205 -0
- package/plugins/serviceGitHub/serviceGitHub.nlg +65 -0
- package/plugins/serviceGitLab/gitops.nlg +528 -0
- package/plugins/serviceGitLab/psm_gitlab.nlg +205 -0
- package/plugins/serviceGitLab/serviceGitLab.nlg +65 -0
- package/test/harness.nlg +312 -0
- package/test/node_test.js +33 -0
- package/test/test_01_core.nlg +768 -0
- package/test/test_02_context.nlg +269 -0
- package/test/test_03_jsinterop.nlg +137 -0
- package/test/test_04_numerics.nlg +450 -0
- package/test/test_05_strings.nlg +63 -0
- package/test/test_06_lingoparse.nlg +500 -0
- 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
|
+
} ();
|