Support debug names for actors (any JSON term)

This commit is contained in:
Tony Garnock-Jones 2016-05-18 16:51:51 -04:00
parent 6160012576
commit fba4aaa6b4
5 changed files with 52 additions and 23 deletions

View File

@ -42,9 +42,15 @@ var forEachChild = (function () {
return forEachChild;
})();
function buildActor(constructorES5, block) {
function buildActor(constructorES5, nameExpOpt, block) {
var nameExpStr;
if (nameExpOpt.numChildren === 1) {
nameExpStr = ', ' + nameExpOpt.asES5;
} else {
nameExpStr = '';
}
return 'Syndicate.Actor.spawnActor(new '+constructorES5+', '+
'function() ' + block.asES5 + ');';
'function() ' + block.asES5 + nameExpStr + ');';
}
function buildFacet(facetBlock, transitionBlock) {
@ -79,11 +85,11 @@ function buildCaseEvent(eventPattern, body) {
}
var modifiedSourceActions = {
ActorStatement_noConstructor: function(_actor, block) {
return buildActor('Object()', block);
ActorStatement_noConstructor: function(_actor, _namedOpt, nameExpOpt, block) {
return buildActor('Object()', nameExpOpt, block);
},
ActorStatement_withConstructor: function(_actor, ctorExp, block) {
return buildActor(ctorExp.asES5, block);
ActorStatement_withConstructor: function(_actor, ctorExp, _namedOpt, nameExpOpt, block) {
return buildActor(ctorExp.asES5, nameExpOpt, block);
},
DataspaceStatement_ground: function(_ground, _dataspace, maybeId, block) {

View File

@ -14,7 +14,7 @@ assertion type ready(what);
assertion type entry(key, val);
ground dataspace {
actor {
actor named 'listener' {
react {
assert ready("listener");
on asserted entry($key, _) {
@ -31,7 +31,7 @@ ground dataspace {
}
}
actor {
actor named 'other-listener' {
react {
assert ready('other-listener');
during entry($key, _) {
@ -56,7 +56,7 @@ ground dataspace {
}
}
actor {
actor named 'driver' {
react until {
case asserted ready("listener") {
react until {

View File

@ -16,8 +16,8 @@ Syndicate <: ES5 {
FunctionBodyBlock = "{" FunctionBody "}" // odd that this isn't in es5.ohm somewhere
ActorStatement
= actor CallExpression FunctionBodyBlock -- withConstructor
| actor FunctionBodyBlock -- noConstructor
= actor CallExpression (named Expression<withIn>)? FunctionBodyBlock -- withConstructor
| actor (named Expression<withIn>)? FunctionBodyBlock -- noConstructor
DataspaceStatement
= ground dataspace identifier? FunctionBodyBlock -- ground
@ -82,6 +82,7 @@ Syndicate <: ES5 {
ground = "ground" ~identifierPart
message = "message" ~identifierPart
metalevel = "metalevel" ~identifierPart
named = "named" ~identifierPart
on = "on" ~identifierPart
react = "react" ~identifierPart
retracted = "retracted" ~identifierPart

View File

@ -10,11 +10,11 @@ var Util = require('./util.js');
//---------------------------------------------------------------------------
function spawnActor(state, bootFn) {
Dataspace.spawn(new Actor(state, bootFn));
function spawnActor(state, bootFn, optName) {
Dataspace.spawn(new Actor(state, bootFn, optName));
}
function Actor(state, bootFn) {
function Actor(state, bootFn, optName) {
this.state = state;
this.facets = Immutable.Set();
this.mux = new Mux.Mux();
@ -22,6 +22,10 @@ function Actor(state, bootFn) {
this.knowledge = Trie.emptyTrie;
this.pendingActions = [];
if (typeof optName !== 'undefined') {
this.name = optName;
}
this.boot = function() {
var self = this;
withCurrentFacet(null, function () {

View File

@ -113,17 +113,32 @@ Dataspace.exitDataspace = function () {
Dataspace.enqueueAction(terminateDataspace());
};
Dataspace.inertBehavior = {
handleEvent: function (e) {}
Dataspace.inertBehavior = function (oldBehavior) {
var b = { handleEvent: function (e) {} };
if ('name' in oldBehavior) {
b.name = oldBehavior.name;
}
return b;
};
// Instance methods
Dataspace.prototype.debugName = function (pid) {
var p = this.processTable.get(pid, null);
if (p === null) {
return '(dead)[' + pid + ']';
}
if ('name' in p.behavior) {
return JSON.stringify(p.behavior.name) + '[' + pid + ']';
}
return '(anon)[' + pid + ']';
};
Dataspace.prototype.asChild = function (pid, f, omitLivenessCheck) {
var self = this;
var p = this.processTable.get(pid, null);
if (!omitLivenessCheck && (p === null)) {
console.warn("Dataspace.asChild eliding invocation of dead process", pid);
console.warn("Dataspace.asChild eliding invocation of dead process", this.debugName(pid));
return;
}
@ -141,15 +156,17 @@ Dataspace.prototype.asChild = function (pid, f, omitLivenessCheck) {
Dataspace.prototype.kill = function (pid, exn) {
if (exn) {
if (exn.stack) {
console.error("Process crashed", pid, exn, exn.stack);
console.error("Process crashed", this.debugName(pid), exn, exn.stack);
} else {
console.error("Process crashed", pid, exn);
console.error("Process crashed", this.debugName(pid), exn);
}
} else if (Dataspace.noisy) {
console.log("Process exiting", pid);
console.log("Process exiting", this.debugName(pid));
}
var p = this.processTable.get(pid);
this.processTable = this.processTable.set(pid, { behavior: Dataspace.inertBehavior });
this.processTable = this.processTable.set(pid, {
behavior: Dataspace.inertBehavior(p.behavior)
});
if (p) {
if (p.behavior.trapexit) {
this.asChild(pid, function () { return p.behavior.trapexit(exn); }, true);
@ -234,7 +251,8 @@ Dataspace.prototype.interpretAction = function (pid, action) {
case 'message':
if (Patch.observe.isClassOf(action.message)) {
console.warn('Process ' + pid + ' send message containing query', action.message);
console.warn('Process ' + this.debugName(pid) + ' sent message containing query',
action.message);
}
if (pid !== 'meta' && Patch.atMeta.isClassOf(action.message)) {
Dataspace.send(action.message[0]);
@ -262,7 +280,7 @@ Dataspace.prototype.interpretAction = function (pid, action) {
case 'terminate':
var oldMux = this.mux.shallowCopy();
this.deliverPatches(oldMux, this.mux.removeStream(pid));
if (Dataspace.noisy) console.log("Process exit complete", pid);
if (Dataspace.noisy) console.log("Process exit complete", this.debugName(pid));
this.processTable = this.processTable.remove(pid);
return true;