@naanlang/naan 1.2.0 → 1.3.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 (41) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +1 -1
  3. package/bin/index.js +5 -2
  4. package/dist/env_web.js +11 -1
  5. package/dist/naan.min.js +5 -5
  6. package/frameworks/browser/https_request.nlg +2 -0
  7. package/frameworks/browser/sworker.js +23 -23
  8. package/frameworks/browser/terminals.nlg +132 -20
  9. package/frameworks/browser/workers.nlg +4 -1
  10. package/frameworks/browser/ws_client.nlg +9 -3
  11. package/frameworks/client/apiclient.nlg +8 -6
  12. package/frameworks/client/psm_client.nlg +4 -4
  13. package/frameworks/client/relaycon.nlg +5 -1
  14. package/frameworks/common/common.nlg +10 -4
  15. package/frameworks/node/apiserver.nlg +190 -4
  16. package/frameworks/node/worker.nlg +112 -10
  17. package/frameworks/node/ws_client.nlg +10 -3
  18. package/frameworks/project/build.nlg +13 -11
  19. package/frameworks/project/projects.nlg +7 -5
  20. package/frameworks/running/executors.nlg +124 -34
  21. package/frameworks/running/taskexec.nlg +5 -1
  22. package/lib/browser/env_web.js +17 -7
  23. package/lib/browser/env_webworker.js +22 -3
  24. package/lib/core/naanlib.js +5 -5
  25. package/lib/env_node.js +15 -4
  26. package/lib/env_nodeworker.js +21 -1
  27. package/package.json +8 -5
  28. package/plugins/serviceAws/aws/aws-sdk-node.min.js +2 -2
  29. package/plugins/serviceAws/aws/aws-sdk.min.js +3 -2
  30. package/plugins/serviceAws/aws_dynamo.nlg +19 -19
  31. package/plugins/serviceAws/dbt_aws.nlg +1 -1
  32. package/plugins/serviceYC/generic_api.yaml +36 -0
  33. package/plugins/serviceYC/naanide-relay-index.js +148 -0
  34. package/plugins/serviceYC/serviceYC.nlg +60 -0
  35. package/plugins/serviceYC/yc_apigateway.nlg +205 -0
  36. package/plugins/serviceYC/yc_function.nlg +163 -0
  37. package/plugins/serviceYC/yc_vm.nlg +207 -0
  38. package/test/test_02_context.nlg +1 -1
  39. package/test/test_03_jsinterop.nlg +2 -2
  40. package/test/test_05_strings.nlg +7 -4
  41. package/test/test_07_lingo.nlg +1 -1
@@ -52,19 +52,28 @@ closure ExecutorBase(track, type, name, local exec) {
52
52
  }
53
53
 
54
54
  // execReceived
55
- // THe specified message was received from the instance, so signal it.
55
+ // The specified message was received from the instance, so signal it.
56
56
 
57
57
  exec.execReceived = closure execReceived(data, local pending) {
58
58
  pending = exec.pending[data.xid]
59
- if !pending {
59
+ if !pending { // not waiting on message
60
60
  if data.xmsg == "xready"
61
61
  exec.pending.ready = true
62
+ if data.xmsg == "xattention"
63
+ { }
62
64
  return
63
65
  }
64
66
  exec.pending[data.xid] = undefined
65
67
  pending.signal(list(false, data))
66
68
  }
67
69
 
70
+ // execSetStatus
71
+ // Received a status update from the instance.
72
+
73
+ exec.execSetStatus = function execSetStatus(status) {
74
+ exec.xstatus = status
75
+ }
76
+
68
77
  // execFailed
69
78
  // Communication has failed.
70
79
 
@@ -263,21 +272,22 @@ closure ExecutorContext(exec, contextID, local context, util) {
263
272
  *
264
273
  * Allowable options are:
265
274
  * {
266
- * maxcount: <integer> // maximum workers, default 4
267
- * initeval: `(<expr>, <put>, <get>) // initializes each new worker
268
- * basename: <string> // worker label for UI, default "batch"
275
+ * spawnLoc: <string> // e.g. "Local" (default) or "Host"
276
+ * maxcount: <integer> // maximum workers, default 4
277
+ * initeval: `(<expr>, <put>, <get>) // initializes each new worker
278
+ * basename: <string> // worker label for UI, default "batch"
269
279
  * }
270
280
  *
271
281
  */
272
282
 
273
- closure ExecutorParallel(options, local maxcount, basename, parallel, exqueue, crValue) {
283
+ closure ExecutorParallel(track, options, local maxcount, parallel, exqueue, crValue) {
274
284
  global()
285
+ options = merge({
286
+ spawnLoc: "Local"
287
+ maxcount: 4
288
+ basename: "batch"
289
+ }, options)
275
290
  maxcount = options.maxcount
276
- if !maxcount
277
- maxcount = 4 // default is 4 workers
278
- basename = options.basename
279
- if !string(basename)
280
- basename = "batch"
281
291
  exqueue = [] // waiting for execution
282
292
  parallel = new(object, this)
283
293
  parallel.workers = [] // array of worker executors
@@ -288,36 +298,41 @@ closure ExecutorParallel(options, local maxcount, basename, parallel, exqueue, c
288
298
  //
289
299
  // Return the next available worker. If no workers are available and we haven't hit the maximum
290
300
  // then create an additional worker and return it. If we cannot allocate another worker then this
291
- // returns false.
301
+ // returns { wait: true }.
292
302
 
293
303
  closure acquireWorker(local workdex, name, worker, context, result) {
294
304
  if parallel.available.length > 0
295
- return (parallel.available.pop())
305
+ return (list(false, parallel.available.pop()))
296
306
  workdex = parallel.workers.length
297
307
  if workdex >= maxcount
298
- return (false)
308
+ return (list(false, { wait: true }))
299
309
  parallel.workers[workdex] = false // reserve our spot
300
- name = basename.concat("-", workdex+1)
301
- worker = App.nide.track.spawn("Local", name, "ExecutorParallel") // ### App.nide.track.spawn may not exist
302
- if worker.0 { // ### wasting space on workers list
310
+ name = options.basename.concat("-", workdex+1)
311
+ worker = track.spawn(options.spawnLoc, name, {
312
+ workerID: "ExecutorParallel"
313
+ })
314
+ if worker.0 {
315
+ parallel.workers.splice(workdex, 1)
303
316
  debuglog("execParallel: cannot spawn worker:", ErrorString(worker.0))
304
- return (false)
317
+ return (list(worker.0))
305
318
  }
306
319
  worker = worker.1
307
320
  context = worker.context()
308
321
  if context.0 {
309
- debuglog("execParallel: cannot create worker context:", ErrorString(context.0))
322
+ parallel.workers.splice(workdex, 1)
310
323
  worker.destroy()
311
- return (false)
324
+ debuglog("execParallel: cannot create worker context:", ErrorString(context.0))
325
+ return (list(context.0))
312
326
  }
313
327
  context = context.1
314
328
  parallel.workers[workdex] = worker
315
329
  parallel.contexts[worker] = context
316
330
  if tuple(options.initeval) {
317
331
  result = apply(context.eval, options.initeval)
318
- if result.0
319
- debuglog("execParallel: cannot initialize worker", name, ErrorString(result.0)) }
320
- return (worker)
332
+ if result.0 {
333
+ debuglog("execParallel: cannot initialize worker", name, ErrorString(result.0))
334
+ return (list(result.0)) } }
335
+ return (list(false, worker))
321
336
  }
322
337
 
323
338
  // releaseWorker
@@ -337,23 +352,26 @@ closure ExecutorParallel(options, local maxcount, basename, parallel, exqueue, c
337
352
  // don't remove work from the queue until we already have a worker.
338
353
  //
339
354
 
340
- closure execNext(local worker, result) {
355
+ closure execNext(local error, worker, result) {
341
356
  if exqueue.length > 0 {
342
- worker = acquireWorker() // false if none available
343
- if !worker {
344
- if maxcount > 0 && parallel.workers.length == 0 // maxcount zero when being destroyed
345
- throw("execParallel: cannot allocate any workers at all")
346
- return // we're busy, so try again later
357
+ `(error, worker) = acquireWorker()
358
+ if error {
359
+ if maxcount > 0 && parallel.workers.length == 0 {
360
+ exqueue = []
361
+ throw("execParallel: cannot allocate any workers at all") }
362
+ return // one failed, so try again later
347
363
  }
364
+ if worker.wait
365
+ return // we're busy, so try again later
348
366
  future(function(local next, context) {
349
367
  next = exqueue.splice(0, 1).0 // remove oldest entry, from start
350
368
  if !next {
351
369
  releaseWorker(worker) // someone else already processed this
352
370
  return
353
- }
371
+ }
354
372
  context = parallel.contexts[worker]
355
373
  if next.eval
356
- result = apply(context.eval, next.args)
374
+ result = apply(context.eval, next.eval)
357
375
  else if next.proc
358
376
  result = context.rpc(next.proc, next.args)
359
377
  else
@@ -372,7 +390,7 @@ closure ExecutorParallel(options, local maxcount, basename, parallel, exqueue, c
372
390
  //
373
391
 
374
392
  parallel.eval = closure evalf(expr, put, get, local pending) {
375
- if !maxcount
393
+ if maxcount == 0
376
394
  return (crValue) // already destroyed
377
395
  pending = new(nonce)
378
396
  exqueue.push({
@@ -392,13 +410,55 @@ closure ExecutorParallel(options, local maxcount, basename, parallel, exqueue, c
392
410
  evalf(expr, eval(put), eval(get))
393
411
  }
394
412
 
413
+ // exBatch
414
+ //
415
+ // Remote helper to execute a batch function.
416
+ //
417
+
418
+ closure exBatch(expr, local pending) {
419
+ // evaluate the expression in batch mode
420
+ function execbat() {
421
+ try {
422
+ pending.signal(list(false, evalactive(expr)))
423
+ } catch {
424
+ pending.signal(list(Error(exception)))
425
+ }
426
+ }
427
+
428
+ pending = new(nonce)
429
+ exec(list(execbat))
430
+ pending.wait()
431
+ }
432
+
433
+ // batch
434
+ //
435
+ // Execute eval above in a remote in batch mode, waiting until it is complete.
436
+ //
437
+
438
+ parallel.batch = closure batchf(expr, put, get, local result) {
439
+ result = evalf(list(exBatch, list(quote, expr)), `(exBatch).append(put), get)
440
+ if result.0 // unpack our error wrapper
441
+ result
442
+ else
443
+ result.1
444
+ }
445
+
446
+ // batchq
447
+ //
448
+ // Evaluate the specified QUOTED expression in a remote in batch mode.
449
+ //
450
+
451
+ parallel.batchq = macro batchq(expr, put, get) {
452
+ batchf(expr, eval(put), eval(get))
453
+ }
454
+
395
455
  // rpc
396
456
  //
397
457
  // Execute a procedure call in a remote worker.
398
458
  //
399
459
 
400
460
  parallel.rpc = closure rpc(proc, args, local pending) {
401
- if !maxcount
461
+ if maxcount == 0
402
462
  return (crValue) // already destroyed
403
463
  pending = new(nonce)
404
464
  exqueue.push({
@@ -410,13 +470,36 @@ closure ExecutorParallel(options, local maxcount, basename, parallel, exqueue, c
410
470
  pending.wait()
411
471
  }
412
472
 
473
+ // status
474
+ //
475
+ // Report status of workers. Each worker has a dictionary:
476
+ // {
477
+ // state: <string> // "active" or "idle"
478
+ // status: <dict> // like runaverage(1)
479
+ // }
480
+ //
481
+
482
+ parallel.status = function status(local output, worker) {
483
+ output = []
484
+ for worker in parallel.workers {
485
+ output.push({
486
+ name: worker.name
487
+ type: worker.type
488
+ state: if parallel.available.indexOf(worker) >= 0
489
+ "idle" else "active"
490
+ status: worker.xstatus
491
+ })
492
+ }
493
+ output
494
+ }
495
+
413
496
  // destroy
414
497
  //
415
498
  // Destroy the object by destroying the workers and failing pending requests with cancelResult.
416
499
  //
417
500
 
418
501
  parallel.destroy = closure destroy(cancelResult, local worker, next) {
419
- if !maxcount
502
+ if maxcount == 0
420
503
  return (false) // already destroyed
421
504
  crValue = cancelResult
422
505
  maxcount = 0
@@ -542,6 +625,13 @@ closure ExecutorTracker(local xtrak) {
542
625
  } (pop(args), args)
543
626
  }
544
627
 
628
+ // parallel
629
+ // Return a new parallel executor with specified options.
630
+
631
+ xtrak.parallel = function parallel(options) {
632
+ ExecutorParallel(xtrak, options)
633
+ }
634
+
545
635
  xtrak.register(execLambda, "Lambda")
546
636
 
547
637
  // finis
@@ -28,12 +28,16 @@ closure TaskDispatcher(replier, local contexts, gohome, util) {
28
28
  reply = {
29
29
  xmsg: "error"
30
30
  xid: data.xid
31
+ _guid: data._guid || undefined
31
32
  error: "unknown operation"
32
33
  }
33
34
  try {
34
35
  restorens = makeActivator()
35
36
  if data.xmsg == "xstart"
36
- reply = { xmsg: "xready" } // ready to accept messages
37
+ reply = { // ready to accept messages
38
+ xmsg: "xready"
39
+ _guid: data._guid || undefined
40
+ }
37
41
  else if data.xmsg == "register" {
38
42
  //
39
43
  // register a new context to default namespace
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * column positioning: // // !
8
8
  *
9
- * Copyright (c) 2017-2022 by Richard C. Zulch
9
+ * Copyright (c) 2017-2024 by Richard C. Zulch
10
10
  *
11
11
  */
12
12
 
@@ -223,7 +223,17 @@ exports.NaanControllerWeb = function() {
223
223
  }, 1);
224
224
  };
225
225
 
226
+ var replyHook;
227
+ this.OnReplyHook = function OnReplyHook(proc) {
228
+ replyHook = proc;
229
+ return (proc);
230
+ };
231
+
226
232
  this.ReplyMessage = function ReplyMessage(data) { // "remote" -> "local"
233
+ if (replyHook)
234
+ setTimeout(function() {
235
+ replyHook(data);
236
+ }, 1);
227
237
  termlist.forEach(function(term) {
228
238
  if (term.OnMessageOut)
229
239
  term.OnMessageOut(data);
@@ -526,7 +536,7 @@ exports.NaanControllerWeb = function() {
526
536
  statedoc.curversion = kStateCurrentVersion;
527
537
  statedoc.firstver = kStateFirstVersion;
528
538
  statedoc.licensee = "MIT-License";
529
- statedoc.verstring = "1.2.0+1";
539
+ statedoc.verstring = "1.3.0+1";
530
540
  statedoc.date = new Date().toISOString();
531
541
  statedoc.prefs = prefs;
532
542
  statedoc.naan = naanlib.saveState(false); // true to optimize, which is a bit slower
@@ -544,7 +554,7 @@ exports.NaanControllerWeb = function() {
544
554
  || statedoc.firstver > kStateCurrentVersion
545
555
  || statedoc.curversion < kStateFirstVersion
546
556
  || statedoc.licensee != "MIT-License"
547
- || statedoc.verstring != "1.2.0+1")
557
+ || statedoc.verstring != "1.3.0+1")
548
558
  {
549
559
  localStorage.removeItem("NaanState_Hosted");
550
560
  return (false);
@@ -603,7 +613,7 @@ exports.NaanControllerWeb = function() {
603
613
  op: "VsiteOpen",
604
614
  name: vsiteName,
605
615
  naancont: contSelf,
606
- title: vsiteName + " 1.2.0+1"
616
+ title: vsiteName + " 1.3.0+1"
607
617
  });
608
618
  }
609
619
  } catch (e) {
@@ -617,7 +627,7 @@ exports.NaanControllerWeb = function() {
617
627
  op: "VsiteClose",
618
628
  name: vsiteName,
619
629
  naancont: contSelf,
620
- title: vsiteName + " 1.2.0+1"
630
+ title: vsiteName + " 1.3.0+1"
621
631
  });
622
632
  termTextOut("\x1b[90m\x1b[3m".concat("\nwindow closed", "\x1b[0m\n"));
623
633
  }
@@ -632,8 +642,8 @@ exports.NaanControllerWeb = function() {
632
642
  naanlib.banner();
633
643
  var hostpath = naanlib.js.r("path").dirname(window.location.href);
634
644
  naanlib.start({
635
- cmd: 'App.version = "1.2.0+1";;\r\n'
636
- + 'App.cache = "9659b00cb48debdc9726030789336e68";;\r\n'
645
+ cmd: 'App.version = "1.3.0+1";;\r\n'
646
+ + 'App.cache = "49a9b89fb804111a36026df163e15009";;\r\n'
637
647
  + 'Naan.module.requireQuery({ naanver: App.cache });;\r\n'
638
648
  + 'Naan.module.webparse("naan_init.nlg", "' + hostpath + '", { naanver: App.cache });;\r\n'
639
649
  });
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * column positioning: // // !
8
8
  *
9
- * Copyright (c) 2019-2022 by Richard C. Zulch
9
+ * Copyright (c) 2019-2024 by Richard C. Zulch
10
10
  *
11
11
  */
12
12
 
@@ -83,13 +83,27 @@ exports.NaanControllerWebWorker = function NaanControllerWebWorker() {
83
83
  });
84
84
  return (data);
85
85
  };
86
-
86
+
87
87
  var targetListener;
88
88
  targSelf.OnMessage = function OnMessage(proc) {
89
89
  targetListener = proc;
90
90
  return (proc);
91
91
  };
92
-
92
+
93
+ this.DispatchMessage = function DispatchMessage(data) {
94
+ postMessage({ // target is sending a message
95
+ id: "targetsend",
96
+ data: data
97
+ });
98
+ return (data);
99
+ };
100
+
101
+ var targetReceiver;
102
+ targSelf.OnReceive = function OnReceive(proc) {
103
+ targetReceiver = proc;
104
+ return (proc);
105
+ };
106
+
93
107
  targSelf.ReplyDebugger = function ReplyDebugger(data) {
94
108
  postMessage({ // target is sending debug data
95
109
  id: "debugout",
@@ -149,6 +163,11 @@ exports.NaanControllerWebWorker = function NaanControllerWebWorker() {
149
163
  if (debugListener)
150
164
  debugListener(msg.data); // target received a message
151
165
  }
166
+ else if (msg.id == "targetreceive")
167
+ {
168
+ if (targetReceiver)
169
+ targetReceiver(msg.data);
170
+ }
152
171
  };
153
172
 
154
173
  //