nisp
Version:
A language that for easily build cross-language language
102 lines (101 loc) • 2.91 kB
JavaScript
;
exports.__esModule = true;
var utils_1 = require("./utils");
// To safely mark a function as macro function
function macro(fn) {
return Object.defineProperty(fn, 'macro', {
configurable: false,
value: true
});
}
exports.macro = macro;
function apply(fn, ctx) {
if (fn.macro)
return fn(ctx);
var args = [], len = ctx.ast.length;
for (var i = 1; i < len; i++) {
args[i - 1] = arg(ctx, i);
}
return fn.apply(ctx, args);
}
/**
* Get nth argument value
*/
function arg(ctx, index) {
return nisp({
ast: ctx.ast[index],
sandbox: ctx.sandbox,
env: ctx.env,
parent: ctx,
index: index
});
}
exports.arg = arg;
var NispError = (function () {
function NispError(msg, stack) {
this.name = 'NispError';
this.stack = stack;
this.message = msg;
}
NispError.prototype.toString = function () {
return "NispError: " + this.message + "\n" +
"stack: " + JSON.stringify(this.stack, null, 4);
};
return NispError;
}());
exports.NispError = NispError;
/**
* Throw error with stack info
*/
exports.error = function (ctx, msg) {
var stack = [];
var node = ctx;
var max = 100;
while (node && max-- > 0) {
stack.push(node.ast[0], node.index);
node = node.parent;
}
throw new NispError(msg, stack);
};
function nisp(ctx) {
if (!ctx)
exports.error(ctx, "ctx is required");
var sandbox = ctx.sandbox, ast = ctx.ast;
if (!sandbox)
exports.error(ctx, "sandbox is required");
if (utils_1.isArray(ast)) {
if (ast.length === 0)
return;
var action = arg(ctx, 0);
if (utils_1.isFunction(action)) {
return apply(action, ctx);
}
if (action in sandbox) {
var fn = sandbox[action];
return utils_1.isFunction(fn) ? apply(fn, ctx) : fn;
}
else {
exports.error(ctx, "function \"" + action + "\" is undefined");
}
}
else {
return ast;
}
}
/**
* Eval an nisp ast
* @param {any} ast The abstract syntax tree of nisp.
* It's a common flaw that array cannot carry plain data,
* such as `['foo', [1,2]]`, The `1` will be treat as a function name.
* So it's recommended to use object to carry plain data,
* such as translate the example to `['foo', { data: [1, 2] }]`.
* @param {Sandbox} sandbox The interface to the real world.
* It defined functions to reduce the data of each expression.
* @param {any} env The system space of the vm.
* @param {any} parent Parent context, it is used to back trace the execution stack.
*/
function default_1(ast, sandbox, env, parent, index) {
if (index === void 0) { index = 0; }
return nisp({ ast: ast, sandbox: sandbox, env: env, parent: parent, index: index });
}
exports["default"] = default_1;