ion
Version:
ion language ========================
321 lines • 13.1 kB
JavaScript
void (function(){var _ion_runtime_Factory_ = function(module,exports,require){'use strict';
var ion = require('../');
var Literal = require('./Literal');
var Expression = require('./Expression');
var Factory = ion.defineClass({
name: 'Factory',
properties: {
runtime: './OperationExpression',
createRuntime: {
writable: true,
value: function (context, ast) {
var properties = ion.clone(ast);
properties.context = context;
properties.factory = this;
var type = require(this.runtime);
return ion.patch.combine(new type(properties), { ast: ast });
}
},
canCache: {
writable: true,
value: function (ast) {
return false;
}
},
toCode: {
writable: true,
value: function (ast) {
if (ast.type === 'BinaryExpression') {
return toCode(ast.left) + ast.operator + toCode(ast.right);
}
return '(' + JSON.stringify(ast) + ')';
}
}
}
});
Factory;
var lookup = {
type: {
UndoStatement: ion.patch.combine(new Factory(), { runtime: './UndoStatement' }),
VariableDeclaration: ion.patch.combine(new Factory(), { runtime: './VariableDeclaration' }),
ThisExpression: ion.patch.combine(new Factory(), {
createRuntime: function (context, ast) {
var expression = context.getVariable('this');
if (ast.deep) {
expression.deep = true;
}
return expression;
},
toCode: function (ast) {
return 'this';
}
}),
Identifier: ion.patch.combine(new Factory(), {
createRuntime: function (context, ast) {
var expression = context.getVariable(ast);
if (ast.deep) {
expression.deep = true;
}
return expression;
},
canCache: function (ast) {
return true;
},
toCode: function (ast) {
return ast.name;
}
}),
Function: ion.patch.combine(new Factory(), {
createRuntime: function (context, ast) {
var value = ast.value;
if (ast.context) {
value = value(context);
}
return new Literal({ value: value });
}
}),
Template: ion.patch.combine(new Factory(), { runtime: './Template' }),
Literal: ion.patch.combine(new Factory(), {
runtime: './Literal',
canCache: function (ast) {
return true;
},
toCode: function (ast) {
return JSON.stringify(ast.value);
}
}),
Property: ion.patch.combine(new Factory(), { runtime: './Property' }),
IfStatement: ion.patch.combine(new Factory(), { runtime: './IfStatement' }),
BlockStatement: ion.patch.combine(new Factory(), { runtime: './BlockStatement' }),
ReturnStatement: ion.patch.combine(new Factory(), { runtime: './ReturnStatement' }),
ObjectExpression: ion.patch.combine(new Factory(), { runtime: './ObjectExpression' }),
ArrayExpression: ion.patch.combine(new Factory(), { runtime: './ArrayExpression' }),
ExpressionStatement: ion.patch.combine(new Factory(), { runtime: './ExpressionStatement' }),
ForOfStatement: ion.patch.combine(new Factory(), { runtime: './ForInOfStatement' }),
ForInStatement: ion.patch.combine(new Factory(), { runtime: './ForInOfStatement' }),
MemberExpression: ion.patch.combine(new Factory(), {
runtime: './MemberExpression',
canCache: function (ast) {
return canCache(ast.object) && canCache(ast.property);
},
toCode: function (ast) {
if (ast.computed) {
return '' + toCode(ast.object) + '[' + toCode(ast.property) + ']';
} else {
return '' + toCode(ast.object) + '.' + toCode(ast.property);
}
}
}),
CallExpression: ion.patch.combine(new Factory(), { runtime: './CallExpression' }),
NewExpression: ion.patch.combine(new Factory(), { runtime: './CallExpression' }),
UnaryExpression: {
operator: {
'!': ion.patch.combine(new Factory(), {
evaluate: function (a) {
return !a;
}
}),
'typeof': ion.patch.combine(new Factory(), {
evaluate: function (a) {
return typeof a;
}
}),
'void': ion.patch.combine(new Factory(), {
evaluate: function (a) {
return void a;
}
}),
'-': ion.patch.combine(new Factory(), {
evaluate: function (a) {
return -a;
}
}),
'+': ion.patch.combine(new Factory(), {
evaluate: function (a) {
return +a;
}
}),
'~': ion.patch.combine(new Factory(), {
evaluate: function (a) {
return ~a;
}
}),
'?': ion.patch.combine(new Factory(), {
evaluate: function (a) {
return a != null;
}
})
}
},
ConditionalExpression: ion.patch.combine(new Factory(), { runtime: './ConditionalExpression' }),
BinaryExpression: {
operator: {
'*': ion.patch.combine(new Factory(), {
evaluate: function (left, right) {
return left * right;
}
}),
'/': ion.patch.combine(new Factory(), {
evaluate: function (left, right) {
return left / right;
}
}),
'%': ion.patch.combine(new Factory(), {
evaluate: function (left, right) {
return left % right;
}
}),
'+': ion.patch.combine(new Factory(), {
evaluate: function (left, right) {
return left + right;
}
}),
'-': ion.patch.combine(new Factory(), {
evaluate: function (left, right) {
return left - right;
}
}),
'&&': ion.patch.combine(new Factory(), {
evaluate: function (left, right) {
return left && right;
}
}),
'||': ion.patch.combine(new Factory(), {
evaluate: function (left, right) {
return left || right;
}
}),
'&': ion.patch.combine(new Factory(), {
evaluate: function (left, right) {
return left & right;
}
}),
'|': ion.patch.combine(new Factory(), {
evaluate: function (left, right) {
return left | right;
}
}),
'==': ion.patch.combine(new Factory(), {
evaluate: function (left, right) {
return left == right;
}
}),
'!=': ion.patch.combine(new Factory(), {
evaluate: function (left, right) {
return left != right;
}
}),
'===': ion.patch.combine(new Factory(), {
evaluate: function (left, right) {
return left === right;
}
}),
'!==': ion.patch.combine(new Factory(), {
evaluate: function (left, right) {
return left !== right;
}
}),
'<': ion.patch.combine(new Factory(), {
evaluate: function (left, right) {
return left < right;
}
}),
'>': ion.patch.combine(new Factory(), {
evaluate: function (left, right) {
return left > right;
}
}),
'<=': ion.patch.combine(new Factory(), {
evaluate: function (left, right) {
return left <= right;
}
}),
'>=': ion.patch.combine(new Factory(), {
evaluate: function (left, right) {
return left >= right;
}
})
}
}
}
};
function getFactory(ast, step) {
if (step == null)
step = lookup;
for (var key in step) {
var values = step[key];
var nodeValue = ast[key];
var next = values[nodeValue];
if (next != null) {
if (next.constructor === Factory) {
return next;
}
return getFactory(ast, next);
}
}
return null;
}
var canCache = exports.canCache = function (ast) {
if (ast != null) {
var factory = getFactory(ast);
if (factory != null) {
return factory.canCache(ast);
}
}
return false;
}, toCode = exports.toCode = function (ast) {
if (ast != null) {
var code = ast._toCode;
if (!(code != null)) {
var factory = getFactory(ast);
if (factory != null) {
code = factory.toCode(ast);
}
if (code != null && typeof ast === 'object') {
Object.defineProperty(ast, '_toCode', { value: code });
}
}
return code;
}
return JSON.stringify(ast);
}, createRuntime = exports.createRuntime = function (context, ast) {
if (typeof (ast != null ? ast.type : void 0) !== 'string') {
ast = {
type: 'Literal',
value: ast
};
}
var factory = getFactory(ast);
if (!(factory != null)) {
throw new Error('Factory not found for ast:\n' + JSON.stringify(ast, null, ' '));
}
return factory.createRuntime(context, ast);
}, test = exports.test = function () {
var factory = getFactory({
type: 'BinaryExpression',
operator: '>',
left: {
type: 'Literal',
value: 1
},
right: {
type: 'Literal',
value: 2
}
});
if (!(factory === lookup.type.BinaryExpression.operator['>']))
throw new Error('Assertion Failed: (factory is lookup.type.BinaryExpression.operator[">"])');
if (!(lookup.type.BinaryExpression.operator['>'] != null))
throw new Error('Assertion Failed: (lookup.type.BinaryExpression.operator[">"]?)');
};
}
if (typeof require === 'function') {
if (require.register)
require.register('ion/runtime/Factory',_ion_runtime_Factory_);
else
_ion_runtime_Factory_.call(this, module, exports, require);
}
else {
_ion_runtime_Factory_.call(this);
}
}).call(this)