es-vm
Version:
A visual machine run in ES env like Node/Browser
82 lines (73 loc) • 1.99 kB
JavaScript
;
const statementClassMap = {};
const error = {
NO_EXECUTE: (symbol) => {
return `The Statement:${symbol} miss prototype.execute.`;
}
};
function linkNode(syntaxNode) {
try {
return new statementClassMap[syntaxNode.SYMBOL](syntaxNode);
} catch (err) {
console.error(syntaxNode);
throw err;
}
}
/**
* Bind statement with a symbol.
* @param {String} $Symbol Statement symbol.
*/
function register(statementClass, symbol, execution = true) {
if (!statementClass.prototype.execute && execution) {
throw new Error(`[ESVM-DEV]: ${error.NO_EXECUTE(symbol)}`);
}
statementClassMap[symbol] = statementClass;
return statementClass;
}
/**
* The most simple statement looks like:
* {
* SYMBOL: <string | used to query how to execute>,
* [POSITION]: {
* [IDENTIFIER]: <string | the line name user assigned>,
* LINE: <unsigned number | the line of statement in the code>,
* [COL]: <unsigned number | the line of statement in the code>
* }, <object | statement position info from syntax tree>
* BODY: {
* [PROPERTIES]
* } <object | >
* }
*
* @class Statement
*/
class Statement {
/**
* @constructor
* @param {Object} [POSITION={}] Position info of the statement.
*/
constructor ({POSITION} = {type: 'native'}) {
this.position = POSITION;
}
/**
* Link each statement node from a syntax tree by statement symbol.
* @param {Object} syntaxNode Statement content.
* @returns {Statement} Statement instance.
*/
linkNode (syntaxNode) {
return linkNode(syntaxNode);
}
/**
* Define execution rule for the statement.
* Operation will be record in a stack.
* @param {Kernel} vm
* @param {Scope} scope
*/
*doExecution($) {
$.vm.pushOperation(this);
const ret = yield* this.execute($);
$.vm.emit('writeback', ret, $.vm);
$.vm.popOperation();
return ret;
}
}
module.exports = {Statement, linkNode, register};