Syndicate/js HLL Ohm-based compiler.
This commit is contained in:
parent
fbbad85b04
commit
3785cebdf2
|
@ -24,6 +24,7 @@
|
|||
"browserify": "^13.0.0",
|
||||
"mocha": "^2.4.5",
|
||||
"expect.js": "^0.3.1",
|
||||
"immutable": "^3.7.6"
|
||||
"immutable": "^3.7.6",
|
||||
"ohm-js": "cdglabs/ohm"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
'use strict';
|
||||
|
||||
var Immutable = require('immutable');
|
||||
var Network = require('./network.js').Network;
|
||||
var Mux = require('./mux.js');
|
||||
var Patch = require('./patch.js');
|
||||
var Route = require('./route.js');
|
||||
var Util = require('./util.js');
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
function spawnActor(state, bootFn) {
|
||||
Network.spawn(new Actor(state, bootFn));
|
||||
}
|
||||
|
||||
function Actor(state, bootFn) {
|
||||
this.state = state;
|
||||
this.facets = Immutable.Set();
|
||||
this.mux = new Mux.Mux();
|
||||
|
||||
this.boot = function() {
|
||||
bootFn.call(this.state);
|
||||
};
|
||||
}
|
||||
|
||||
Actor.prototype.handleEvent = function(e) {
|
||||
this.facets.forEach(function (f) {
|
||||
f.handleEvent(e);
|
||||
});
|
||||
};
|
||||
|
||||
Actor.prototype.addFacet = function(facet) {
|
||||
this.facets = this.facets.add(facet);
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
function createFacet() {
|
||||
return new Facet(Network.activeBehavior());
|
||||
}
|
||||
|
||||
function Facet(actor) {
|
||||
this.actor = actor;
|
||||
this.endpoints = Immutable.Map();
|
||||
}
|
||||
|
||||
Facet.prototype.handleEvent = function(e) {
|
||||
var facet = this;
|
||||
this.endpoints.forEach(function(endpoint) {
|
||||
endpoint.handlerFn.call(facet.actor.state, e);
|
||||
});
|
||||
this.refresh();
|
||||
};
|
||||
|
||||
Facet.prototype.addAssertion = function(assertionFn) {
|
||||
return this.addEndpoint(new Endpoint(assertionFn, function(e) {}));
|
||||
};
|
||||
|
||||
Facet.prototype.onEvent = function(isTerminal, eventType, subscriptionFn, projectionFn, handlerFn) {
|
||||
var facet = this;
|
||||
return this.addEndpoint(new Endpoint(subscriptionFn, function(e) {
|
||||
var proj = projectionFn.call(facet.actor.state);
|
||||
var spec = Patch.prependAtMeta(proj.assertion, proj.metalevel);
|
||||
|
||||
switch (e.type) {
|
||||
case 'message':
|
||||
if (eventType === 'message') {
|
||||
var match = Route.matchPattern(e.message, spec);
|
||||
// console.log(match);
|
||||
if (match) {
|
||||
if (isTerminal) { facet.terminate(); }
|
||||
Util.kwApply(handlerFn, facet.actor.state, match);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'stateChange':
|
||||
{
|
||||
var objects;
|
||||
switch (eventType) {
|
||||
case 'asserted':
|
||||
objects = Route.projectObjects(e.patch.added, Route.compileProjection(spec));
|
||||
break;
|
||||
case 'retracted':
|
||||
objects = Route.projectObjects(e.patch.removed, Route.compileProjection(spec));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (objects) {
|
||||
if (isTerminal) { facet.terminate(); }
|
||||
// console.log(objects.toArray());
|
||||
objects.forEach(function (o) { Util.kwApply(handlerFn, facet.actor.state, o); });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}));
|
||||
};
|
||||
|
||||
Facet.prototype.addEndpoint = function(endpoint) {
|
||||
var patch = endpoint.subscriptionFn.call(this.actor.state);
|
||||
var r = this.actor.mux.addStream(patch);
|
||||
this.endpoints = this.endpoints.set(r.pid, endpoint);
|
||||
Network.stateChange(r.deltaAggregate);
|
||||
return this; // for chaining
|
||||
};
|
||||
|
||||
Facet.prototype.refresh = function() {
|
||||
var facet = this;
|
||||
var aggregate = Patch.emptyPatch;
|
||||
this.endpoints.forEach(function(endpoint, eid) {
|
||||
var patch =
|
||||
Patch.retract(Syndicate.__).andThen(endpoint.subscriptionFn.call(facet.actor.state));
|
||||
var r = facet.actor.mux.updateStream(eid, patch);
|
||||
aggregate = aggregate.andThen(r.deltaAggregate);
|
||||
});
|
||||
Network.stateChange(aggregate);
|
||||
};
|
||||
|
||||
Facet.prototype.completeBuild = function() {
|
||||
this.actor.addFacet(this);
|
||||
};
|
||||
|
||||
Facet.prototype.terminate = function() {
|
||||
var facet = this;
|
||||
var aggregate = Patch.emptyPatch;
|
||||
this.endpoints.forEach(function(endpoint, eid) {
|
||||
var r = facet.actor.mux.removeStream(eid);
|
||||
aggregate = aggregate.andThen(r.deltaAggregate);
|
||||
});
|
||||
Network.stateChange(aggregate);
|
||||
this.endpoints = Immutable.Map();
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
function Endpoint(subscriptionFn, handlerFn) {
|
||||
this.subscriptionFn = subscriptionFn;
|
||||
this.handlerFn = handlerFn;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
module.exports.spawnActor = spawnActor;
|
||||
module.exports.createFacet = createFacet;
|
|
@ -0,0 +1,342 @@
|
|||
// Compile ES5+Syndicate to plain ES5.
|
||||
|
||||
'use strict';
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
var ohm = require('ohm-js');
|
||||
var ES5 = require('ohm-js/examples/ecmascript/es5.js');
|
||||
|
||||
var grammarSource = fs.readFileSync(path.join(__dirname, 'syndicate.ohm')).toString();
|
||||
var grammar = ohm.grammar(grammarSource, { ES5: ES5.grammar });
|
||||
var semantics = grammar.extendSemantics(ES5.semantics);
|
||||
|
||||
var gensym_start = Math.floor(new Date() * 1);
|
||||
var gensym_counter = 0;
|
||||
function gensym(label) {
|
||||
return '_' + (label || 'g') + gensym_start + '_' + (gensym_counter++);
|
||||
}
|
||||
|
||||
var forEachChild = (function () {
|
||||
function flattenIterNodes(nodes, acc) {
|
||||
for (var i = 0; i < nodes.length; ++i) {
|
||||
if (nodes[i].isIteration()) {
|
||||
flattenIterNodes(nodes[i].children, acc);
|
||||
} else {
|
||||
acc.push(nodes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function compareByInterval(node, otherNode) {
|
||||
return node.interval.startIdx - otherNode.interval.startIdx;
|
||||
}
|
||||
|
||||
function forEachChild(children, f) {
|
||||
var nodes = [];
|
||||
flattenIterNodes(children, nodes);
|
||||
nodes.sort(compareByInterval).forEach(f);
|
||||
}
|
||||
|
||||
return forEachChild;
|
||||
})();
|
||||
|
||||
function buildActor(constructorES5, block) {
|
||||
return 'Syndicate.Actor.spawnActor(new '+constructorES5+', '+
|
||||
'function() {' + block.asES5 + '});';
|
||||
}
|
||||
|
||||
function buildFacet(facetBlock, transitionBlock) {
|
||||
return 'Syndicate.Actor.createFacet()' +
|
||||
(facetBlock ? facetBlock.asES5 : '') +
|
||||
(transitionBlock ? transitionBlock.asES5 : '') +
|
||||
'.completeBuild();';
|
||||
}
|
||||
|
||||
function buildOnEvent(isTerminal, eventType, subscription, projection, bindings, body) {
|
||||
return '\n.onEvent(' + isTerminal + ', ' + JSON.stringify(eventType) + ', ' +
|
||||
subscription + ', ' + projection +
|
||||
', (function(' + bindings.join(', ') + ') ' + body + '))';
|
||||
}
|
||||
|
||||
var modifiedSourceActions = {
|
||||
ActorStatement_noConstructor: function(_actor, block) {
|
||||
return buildActor('Object()', block);
|
||||
},
|
||||
ActorStatement_withConstructor: function(_actor, ctorExp, block) {
|
||||
return buildActor(ctorExp.asES5, block);
|
||||
},
|
||||
|
||||
NetworkStatement_ground: function(_ground, _network, block) {
|
||||
return 'new Syndicate.Ground(function () ' + block.asES5 + ').startStepping();';
|
||||
},
|
||||
NetworkStatement_normal: function(_network, block) {
|
||||
return 'Syndicate.Network.spawn(new Network(function () ' + block.asES5 + '));';
|
||||
},
|
||||
|
||||
ActorFacetStatement_state: function(_state, facetBlock, _until, transitionBlock) {
|
||||
return buildFacet(facetBlock, transitionBlock);
|
||||
},
|
||||
ActorFacetStatement_until: function(_until, transitionBlock) {
|
||||
return buildFacet(null, transitionBlock);
|
||||
},
|
||||
ActorFacetStatement_forever: function(_forever, facetBlock) {
|
||||
return buildFacet(facetBlock, null);
|
||||
},
|
||||
|
||||
AssertionTypeDeclarationStatement: function(_assertion,
|
||||
_type,
|
||||
typeName,
|
||||
_leftParen,
|
||||
formalsRaw,
|
||||
_rightParen,
|
||||
_maybeEquals,
|
||||
maybeLabel,
|
||||
_maybeSc)
|
||||
{
|
||||
var formals = formalsRaw.asSyndicateStructureArguments;
|
||||
var label = maybeLabel.numChildren === 1
|
||||
? maybeLabel.children[0].interval.contents
|
||||
: JSON.stringify(typeName.interval.contents);
|
||||
var fragments = [];
|
||||
fragments.push(
|
||||
'var ' + typeName.asES5 + ' = (function() {',
|
||||
' var $SyndicateMeta$ = {',
|
||||
' label: ' + label + ',',
|
||||
' arguments: ' + JSON.stringify(formals),
|
||||
' };',
|
||||
' return function ' + typeName.asES5 + '(' + formalsRaw.asES5 + ') {',
|
||||
' return {');
|
||||
formals.forEach(function(f) {
|
||||
fragments.push(' ' + JSON.stringify(f) + ': ' + f + ',');
|
||||
});
|
||||
fragments.push(
|
||||
' "$SyndicateMeta$": $SyndicateMeta$',
|
||||
' };',
|
||||
' };',
|
||||
'})();');
|
||||
return fragments.join('\n');
|
||||
},
|
||||
|
||||
SendMessageStatement: function(_colons, expr, sc) {
|
||||
return 'Syndicate.Network.send(' + expr.asES5 + ')' + sc.interval.contents;
|
||||
},
|
||||
|
||||
FacetBlock: function(_leftParen, init, situations, done, _rightParen) {
|
||||
return (init ? init.asES5 : '') + situations.asES5.join('') + (done ? done.asES5 : '');
|
||||
},
|
||||
FacetStateTransitionBlock: function(_leftParen, transitions, _rightParen) {
|
||||
return transitions.asES5;
|
||||
},
|
||||
|
||||
FacetInitBlock: function(_init, block) {
|
||||
return '\n.addInitBlock((function() ' + block.asES5 + '))';
|
||||
},
|
||||
FacetDoneBlock: function(_done, block) {
|
||||
return '\n.addDoneBlock((function() ' + block.asES5 + '))';
|
||||
},
|
||||
|
||||
FacetSituation_assert: function(_assert, expr, _sc) {
|
||||
return '\n.addAssertion(' + buildSubscription([expr], 'assert', 'pattern') + ')';
|
||||
},
|
||||
FacetSituation_event: function(_on, eventPattern, block) {
|
||||
return buildOnEvent(false,
|
||||
eventPattern.eventType,
|
||||
eventPattern.subscription,
|
||||
eventPattern.projection,
|
||||
eventPattern.bindings,
|
||||
block.asES5);
|
||||
},
|
||||
FacetSituation_during: function(_during, pattern, facetBlock) {
|
||||
return buildOnEvent(false,
|
||||
'asserted',
|
||||
pattern.subscription,
|
||||
pattern.projection,
|
||||
pattern.bindings,
|
||||
'{ Syndicate.Actor.createFacet()' +
|
||||
facetBlock.asES5 +
|
||||
buildOnEvent(true,
|
||||
'retracted',
|
||||
pattern.instantiatedSubscription,
|
||||
'null',
|
||||
[],
|
||||
'{}') +
|
||||
'.completeBuild(); }');
|
||||
},
|
||||
|
||||
FacetStateTransition_withContinuation: function(_case, eventPattern, block) {
|
||||
return buildOnEvent(true,
|
||||
eventPattern.eventType,
|
||||
eventPattern.subscription,
|
||||
eventPattern.projection,
|
||||
eventPattern.bindings,
|
||||
block.asES5);
|
||||
},
|
||||
FacetStateTransition_noContinuation: function(_case, eventPattern, _sc) {
|
||||
return buildOnEvent(true,
|
||||
eventPattern.eventType,
|
||||
eventPattern.subscription,
|
||||
eventPattern.projection,
|
||||
eventPattern.bindings,
|
||||
'');
|
||||
}
|
||||
};
|
||||
|
||||
semantics.extendAttribute('modifiedSource', modifiedSourceActions);
|
||||
|
||||
semantics.addAttribute('asSyndicateStructureArguments', {
|
||||
FormalParameterList: function(formals) {
|
||||
return formals.asIteration().asSyndicateStructureArguments;
|
||||
},
|
||||
identifier: function(_name) {
|
||||
return this.interval.contents;
|
||||
}
|
||||
});
|
||||
|
||||
semantics.addAttribute('eventType', {
|
||||
FacetEventPattern_messageEvent: function(_kw, _pattern) { return 'message'; },
|
||||
FacetEventPattern_assertedEvent: function(_kw, _pattern) { return 'asserted'; },
|
||||
FacetEventPattern_retractedEvent: function(_kw, _pattern) { return 'retracted'; }
|
||||
});
|
||||
|
||||
function buildSubscription(children, patchMethod, mode) {
|
||||
var fragments = [];
|
||||
fragments.push('(function() { var _ = Syndicate.__; return ');
|
||||
if (patchMethod) {
|
||||
fragments.push('Syndicate.Patch.' + patchMethod + '(');
|
||||
} else {
|
||||
fragments.push('{ assertion: ');
|
||||
}
|
||||
children.forEach(function (c) { c.buildSubscription(fragments, mode); });
|
||||
if (patchMethod) {
|
||||
fragments.push(', ');
|
||||
} else {
|
||||
fragments.push(', metalevel: ');
|
||||
}
|
||||
children.forEach(function (c) { fragments.push(c.metalevel) });
|
||||
if (patchMethod) {
|
||||
fragments.push(')');
|
||||
} else {
|
||||
fragments.push(' }');
|
||||
}
|
||||
fragments.push('; })');
|
||||
return fragments.join('');
|
||||
}
|
||||
|
||||
semantics.addAttribute('subscription', {
|
||||
_default: function(children) {
|
||||
return buildSubscription(children, 'sub', 'pattern');
|
||||
}
|
||||
});
|
||||
|
||||
semantics.addAttribute('instantiatedSubscription', {
|
||||
_default: function(children) {
|
||||
return buildSubscription(children, 'sub', 'instantiated');
|
||||
}
|
||||
});
|
||||
|
||||
semantics.addAttribute('projection', {
|
||||
_default: function(children) {
|
||||
return buildSubscription(children, null, 'projection');
|
||||
}
|
||||
});
|
||||
|
||||
semantics.addAttribute('metalevel', {
|
||||
FacetEventPattern_messageEvent: function(_kw, p) { return p.metalevel; },
|
||||
FacetEventPattern_assertedEvent: function(_kw, p) { return p.metalevel; },
|
||||
FacetEventPattern_retractedEvent: function(_kw, p) { return p.metalevel; },
|
||||
|
||||
FacetPattern_withMetalevel: function(_expr, _kw, metalevel) {
|
||||
return metalevel.interval.contents;
|
||||
},
|
||||
FacetPattern_noMetalevel: function(_expr) {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
semantics.addOperation('buildSubscription(acc,mode)', {
|
||||
FacetEventPattern_messageEvent: function(_kw, pattern) {
|
||||
pattern.buildSubscription(this.args.acc, this.args.mode);
|
||||
},
|
||||
FacetEventPattern_assertedEvent: function(_kw, pattern) {
|
||||
pattern.buildSubscription(this.args.acc, this.args.mode);
|
||||
},
|
||||
FacetEventPattern_retractedEvent: function(_kw, pattern) {
|
||||
pattern.buildSubscription(this.args.acc, this.args.mode);
|
||||
},
|
||||
|
||||
FacetPattern: function (v) {
|
||||
v.children[0].buildSubscription(this.args.acc, this.args.mode); // both branches!
|
||||
},
|
||||
|
||||
identifier: function(_name) {
|
||||
var i = this.interval.contents;
|
||||
if (i[0] === '$') {
|
||||
switch (this.args.mode) {
|
||||
case 'pattern': this.args.acc.push('_'); break;
|
||||
case 'instantiated': this.args.acc.push(i.slice(1)); break;
|
||||
case 'projection': this.args.acc.push('(Syndicate._$(' + JSON.stringify(i.slice(1)) + '))'); break;
|
||||
default: throw new Error('Unexpected buildSubscription mode ' + this.args.mode);
|
||||
}
|
||||
} else {
|
||||
this.args.acc.push(i);
|
||||
}
|
||||
},
|
||||
_terminal: function() {
|
||||
this.args.acc.push(this.interval.contents);
|
||||
},
|
||||
_nonterminal: function(children) {
|
||||
var self = this;
|
||||
forEachChild(children, function (c) {
|
||||
c.buildSubscription(self.args.acc, self.args.mode);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
semantics.addAttribute('bindings', {
|
||||
_default: function(children) {
|
||||
var result = [];
|
||||
this.pushBindings(result);
|
||||
return result;
|
||||
}
|
||||
});
|
||||
|
||||
semantics.addOperation('pushBindings(accumulator)', {
|
||||
identifier: function(_name) {
|
||||
var i = this.interval.contents;
|
||||
if (i[0] === '$') {
|
||||
this.args.accumulator.push(i.slice(1));
|
||||
}
|
||||
},
|
||||
_terminal: function () {},
|
||||
_nonterminal: function(children) {
|
||||
var self = this;
|
||||
children.forEach(function (c) { c.pushBindings(self.args.accumulator); });
|
||||
}
|
||||
})
|
||||
|
||||
function compileExtendedSource(inputSource) {
|
||||
var parseResult = grammar.match(inputSource);
|
||||
if (parseResult.failed()) console.error(parseResult.message);
|
||||
return parseResult.succeeded() && semantics(parseResult).asES5;
|
||||
}
|
||||
|
||||
function compileAndPrint(inputSource) {
|
||||
var translatedSource = compileExtendedSource(inputSource);
|
||||
if (translatedSource) {
|
||||
console.log('"use strict";');
|
||||
console.log(translatedSource);
|
||||
}
|
||||
}
|
||||
|
||||
if (process.argv.length < 3 || process.argv[2] === '-') {
|
||||
var inputSource = '';
|
||||
process.stdin.resume();
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.on('data', function(buf) { inputSource += buf; });
|
||||
process.stdin.on('end', function() { compileAndPrint(inputSource); });
|
||||
} else {
|
||||
var inputSource = fs.readFileSync(process.argv[2]).toString();
|
||||
compileAndPrint(inputSource);
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
// node src/compiler.js src/demo-bankaccount.js | node
|
||||
|
||||
var Syndicate = require('./src/main.js');
|
||||
|
||||
assertion type account(balance);
|
||||
assertion type deposit(amount);
|
||||
|
||||
ground network {
|
||||
actor {
|
||||
this.balance = 0;
|
||||
|
||||
forever {
|
||||
assert account(this.balance);
|
||||
on message deposit($amount) {
|
||||
this.balance += amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
actor {
|
||||
forever {
|
||||
on asserted account($balance) {
|
||||
console.log("Balance is now", balance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
actor {
|
||||
until {
|
||||
case asserted Syndicate.observe(deposit(_)) {
|
||||
:: deposit(+100);
|
||||
:: deposit(-30);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -42,7 +42,7 @@ copyKeys(['emptyPatch',
|
|||
module.exports.Patch);
|
||||
|
||||
module.exports.Ground = require("./ground.js").Ground;
|
||||
// module.exports.Actor = require("./actor.js").Actor;
|
||||
module.exports.Actor = require("./actor.js");
|
||||
// module.exports.Spy = require("./spy.js").Spy;
|
||||
// module.exports.WakeDetector = require("./wake-detector.js").WakeDetector;
|
||||
|
||||
|
|
|
@ -52,6 +52,12 @@ Network.activePid = function () {
|
|||
return Network.stack.last().activePid;
|
||||
};
|
||||
|
||||
Network.activeBehavior = function () {
|
||||
var entry = Network.stack.last();
|
||||
var p = entry.network.processTable.get(entry.activePid);
|
||||
return p ? p.behavior : null;
|
||||
};
|
||||
|
||||
Network.withNetworkStack = function (stack, f) {
|
||||
var oldStack = Network.stack;
|
||||
Network.stack = stack;
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
// Syntactic extensions to ES5 for Syndicate/js. See compiler.js for
|
||||
// the rest of the translator.
|
||||
|
||||
Syndicate <: ES5 {
|
||||
//---------------------------------------------------------------------------
|
||||
// Extensions to expressions.
|
||||
|
||||
Statement
|
||||
+= ActorStatement
|
||||
| NetworkStatement
|
||||
| ActorFacetStatement
|
||||
| AssertionTypeDeclarationStatement
|
||||
| SendMessageStatement
|
||||
|
||||
ActorStatement
|
||||
= actor CallExpression Block -- withConstructor
|
||||
| actor Block -- noConstructor
|
||||
|
||||
NetworkStatement
|
||||
= ground network Block -- ground
|
||||
| network Block -- normal
|
||||
|
||||
ActorFacetStatement
|
||||
= state FacetBlock until FacetStateTransitionBlock -- state
|
||||
| until FacetStateTransitionBlock -- until
|
||||
| forever FacetBlock -- forever
|
||||
|
||||
AssertionTypeDeclarationStatement
|
||||
= assertion type identifier "(" FormalParameterList ")" ("=" stringLiteral)? #(sc)
|
||||
|
||||
SendMessageStatement = "::" Expression<withIn> #(sc)
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Ongoing event handlers.
|
||||
|
||||
FacetBlock = "{" FacetInitBlock? FacetSituation* FacetDoneBlock? "}"
|
||||
FacetStateTransitionBlock = "{" FacetStateTransition* "}"
|
||||
|
||||
FacetInitBlock = init Block
|
||||
FacetDoneBlock = done Block
|
||||
|
||||
FacetSituation
|
||||
= assert FacetPattern #(sc) -- assert
|
||||
| on FacetEventPattern Block -- event
|
||||
| during FacetPattern FacetBlock -- during
|
||||
|
||||
FacetEventPattern
|
||||
= message FacetPattern -- messageEvent
|
||||
| asserted FacetPattern -- assertedEvent
|
||||
| retracted FacetPattern -- retractedEvent
|
||||
|
||||
FacetStateTransition
|
||||
= case FacetEventPattern Block -- withContinuation
|
||||
| case FacetEventPattern #(sc) -- noContinuation
|
||||
|
||||
FacetPattern
|
||||
= LeftHandSideExpression metalevel decimalIntegerLiteral -- withMetalevel
|
||||
| LeftHandSideExpression -- noMetalevel
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Keywords. We don't add them to the "keyword" production because
|
||||
// we don't want to make them unavailable to programs as
|
||||
// identifiers.
|
||||
|
||||
actor = "actor" ~identifierPart
|
||||
assert = "assert" ~identifierPart
|
||||
asserted = "asserted" ~identifierPart
|
||||
assertion = "assertion" ~identifierPart
|
||||
done = "done" ~identifierPart
|
||||
during = "during" ~identifierPart
|
||||
forever = "forever" ~identifierPart
|
||||
ground = "ground" ~identifierPart
|
||||
init = "init" ~identifierPart
|
||||
message = "message" ~identifierPart
|
||||
metalevel = "metalevel" ~identifierPart
|
||||
network = "network" ~identifierPart
|
||||
on = "on" ~identifierPart
|
||||
retracted = "retracted" ~identifierPart
|
||||
state = "state" ~identifierPart
|
||||
type = "type" ~identifierPart
|
||||
until = "until" ~identifierPart
|
||||
}
|
Loading…
Reference in New Issue