UNPKG

jaydata

Version:

Cross-platform HTML5 data-management, JavaScript Language Query (JSLQ) support for OData, SQLite, WebSQL, IndexedDB, YQL and Facebook (packaged for Node.JS)

543 lines (502 loc) 25.8 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; var _index = require('../../TypeSystem/index.js'); var _index2 = _interopRequireDefault(_index); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } (0, _index.$C)('$data.Expressions.CodeParser', null, null, { constructor: function constructor(scopeContext) { ///<signature> ///<param name="scopeContext" type="$data.Expressions.EntityContext" /> ///</signature> ///<signature> ///</signature> this.scopeContext = scopeContext; this.lambdaParams = []; }, log: function log(logInfo) { if (this.scopeContext) this.scopeContext.log(logInfo); }, parseExpression: function parseExpression(code, resolver) { ///<signature> ///<summary>Parses the provided code and returns a parser result with parser information</summary> ///<param name="code" type="string">The JavaScript code to parse &#10;ex: "function (a,b,c) { return a + b /c }"</param> ///<param name="resolver" type="string">The ParameterResolver class that resolves vaiable and parameteres references</param> ///<returns type="$data.Expressions.ExpressionParserResult" /> ///</signature> if ((typeof code === 'undefined' ? 'undefined' : _typeof(code)) === 'object') { code = ''; } var result = { success: true, errorMessage: '', errorDetails: '' }; ///<var name="AST" type="Date" /> //console.log(code.toString()); if (_index2.default.Acorn) { //console.log('using acorn.js'); return { success: true, expression: this.ParserBuild(_index2.default.Acorn.parse('(' + code.toString() + ')').body[0]), errors: [] }; } else if (_index2.default.Esprima) { //console.log('using esprima.js'); return { success: true, expression: this.ParserBuild(_index2.default.Esprima.parse('(' + code.toString() + ')').body[0]), errors: [] }; } else { //console.log('using JayLint'); var AST = _index2.default.ASTParser.parseCode(code); this.log({ event: "AST", data: AST }); if (!AST.success) { return { success: false, error: "ASTParser error", errorMessage: AST.errors ? JSON.stringify(AST.errors) : "could not get code" }; } var b = this.Build2(AST.tree.first[0]); result = { success: true, expression: b, errors: AST.errors }; return result; } }, createExpression: function createExpression(code, resolver) { ///<signature> ///<summary>Parses the provided code and returns a JavaScript code expression tree</summary> ///<param name="code" type="string">The JavaScript code to parse &#10;ex: "a + b /c"</param> ///<param name="resolver" type="string">The ParameterResolver class that resolves vaiable and parameteres references</param> ///<returns type="$data.Expressions.ExpressionParserResult" /> ///</signature> ///<signature> ///<summary>Parses the provided code and returns a JavaScript code expression tree</summary> ///<param name="code" type="Function">The JavaScript function to parse &#10;ex: "function (a,b,c) { return a + b /c }"</param> ///<param name="resolver" type="string">The ParameterResolver class that resolves vaiable and parameteres references</param> ///<returns type="$data.Expressions.ExpressionParserResult" /> ///</signature> var result = this.parseExpression(code, resolver); if (!result.success) { _index.Guard.raise("ExpressionParserError: " + result.errorMessage); } return result.expression; }, ParserBuild: function ParserBuild(node) { //console.log(node); return this['Parser' + node.type](node); }, ParserExpressionStatement: function ParserExpressionStatement(node) { return this.ParserBuild(node.expression); }, ParserBlockStatement: function ParserBlockStatement(node) { return this.ParserBuild(node.body[0]); }, ParserReturnStatement: function ParserReturnStatement(node) { return this.ParserBuild(node.argument); }, ParserMemberExpression: function ParserMemberExpression(node) { return new _index2.default.Expressions.PropertyExpression(this.ParserBuild(node.object), new _index2.default.Expressions.ConstantExpression(node.property.name || node.property.value, _typeof(node.property.name || node.property.value))); }, ParserIdentifier: function ParserIdentifier(node) { return this.ParserParameter(node, this.lambdaParams.indexOf(node.name) > -1 ? _index2.default.Expressions.ExpressionType.LambdaParameterReference : _index2.default.Expressions.ExpressionType.ParameterReference); }, ParserObjectExpression: function ParserObjectExpression(node) { var props = new Array(node.properties.length); for (var i = 0; i < node.properties.length; i++) { props[i] = this.ParserProperty(node.properties[i]); } return new _index2.default.Expressions.ObjectLiteralExpression(props); }, ParserArrayExpression: function ParserArrayExpression(node) { var items = new Array(node.elements.length); for (var i = 0; i < node.elements.length; i++) { items[i] = this.ParserBuild(node.elements[i]); } return new _index2.default.Expressions.ArrayLiteralExpression(items); }, ParserProperty: function ParserProperty(node) { return new _index2.default.Expressions.ObjectFieldExpression(node.key.name, this.ParserBuild(node.value)); }, ParserArrowFunctionExpression: function ParserArrowFunctionExpression(node) { return this.ParserFunctionExpression(node); }, ParserFunctionExpression: function ParserFunctionExpression(node) { var params = new Array(node.params.length); for (var i = 0; i < node.params.length; i++) { if (i === 0 || _index2.default.defaults.parameterResolutionCompatibility) { this.lambdaParams.push(node.params[i].name); params[i] = this.ParserParameter(node.params[i], _index2.default.Expressions.ExpressionType.LambdaParameter); } else { params[i] = this.ParserParameter(node.params[i], _index2.default.Expressions.ExpressionType.Parameter); } params[i].owningFunction = result; } var result = new _index2.default.Expressions.FunctionExpression(node.id ? node.id.name : node.id, params, this.ParserBuild(node.body)); return result; }, ParserParameter: function ParserParameter(node, nodeType) { var result = new _index2.default.Expressions.ParameterExpression(node.name, null, nodeType); if (nodeType == _index2.default.Expressions.ExpressionType.LambdaParameterReference) { result.paramIndex = this.lambdaParams.indexOf(node.name); } return result; }, ParserLogicalExpression: function ParserLogicalExpression(node) { return this.ParserBinaryExpression(node); }, ParserOperators: { value: { "==": { expressionType: _index2.default.Expressions.ExpressionType.Equal, type: "boolean", implementation: function implementation(a, b) { return a == b; } }, "===": { expressionType: _index2.default.Expressions.ExpressionType.EqualTyped, type: "boolean", implementation: function implementation(a, b) { return a === b; } }, "!=": { expressionType: _index2.default.Expressions.ExpressionType.NotEqual, type: "boolean", implementation: function implementation(a, b) { return a != b; } }, "!==": { expressionType: _index2.default.Expressions.ExpressionType.NotEqualTyped, type: "boolean", implementation: function implementation(a, b) { return a !== b; } }, ">": { expressionType: _index2.default.Expressions.ExpressionType.GreaterThen, type: "boolean", implementation: function implementation(a, b) { return a > b; } }, ">=": { expressionType: _index2.default.Expressions.ExpressionType.GreaterThenOrEqual, type: "boolean", implementation: function implementation(a, b) { return a >= b; } }, "<=": { expressionType: _index2.default.Expressions.ExpressionType.LessThenOrEqual, type: "boolean", implementation: function implementation(a, b) { return a <= b; } }, "<": { expressionType: _index2.default.Expressions.ExpressionType.LessThen, type: "boolean", implementation: function implementation(a, b) { return a < b; } }, "&&": { expressionType: _index2.default.Expressions.ExpressionType.And, type: "boolean", implementation: function implementation(a, b) { return a && b; } }, "||": { expressionType: _index2.default.Expressions.ExpressionType.Or, type: "boolean", implementation: function implementation(a, b) { return a || b; } }, "&": { expressionType: _index2.default.Expressions.ExpressionType.AndBitwise, type: "number", implementation: function implementation(a, b) { return a & b; } }, "|": { expressionType: _index2.default.Expressions.ExpressionType.OrBitwise, type: "number", implementation: function implementation(a, b) { return a | b; } }, "+": { expressionType: _index2.default.Expressions.ExpressionType.Add, type: "number", implementation: function implementation(a, b) { return a + b; } }, "-": { expressionType: _index2.default.Expressions.ExpressionType.Subtract, type: "number", implementation: function implementation(a, b) { return a - b; } }, "/": { expressionType: _index2.default.Expressions.ExpressionType.Divide, type: "number", implementation: function implementation(a, b) { return a / b; } }, "%": { expressionType: _index2.default.Expressions.ExpressionType.Modulo, type: "number", implementation: function implementation(a, b) { return a % b; } }, "*": { expressionType: _index2.default.Expressions.ExpressionType.Multiply, type: "number", implementation: function implementation(a, b) { return a * b; } }, "[": { expressionType: _index2.default.Expressions.ExpressionType.ArrayIndex, type: "number", implementation: function implementation(a, b) { return a[b]; } }, "in": { expressionType: _index2.default.Expressions.ExpressionType.In, type: 'boolean', implementation: function implementation(a, b) { return a in b; } } } }, ParserUnaryOperators: { value: { "+": { arity: "prefix", expressionType: _index2.default.Expressions.ExpressionType.Positive, type: "number", implementation: function implementation(operand) { return +operand; } }, "-": { arity: "prefix", expressionType: _index2.default.Expressions.ExpressionType.Negative, type: "number", implementation: function implementation(operand) { return -operand; } }, "++true": { arity: "prefix", expressionType: _index2.default.Expressions.ExpressionType.Increment, type: "number", implementation: function implementation(operand) { return ++operand; } }, "--true": { arity: "prefix", expressionType: _index2.default.Expressions.ExpressionType.Decrement, type: "number", implementation: function implementation(operand) { return --operand; } }, "++false": { arity: "suffix", expressionType: _index2.default.Expressions.ExpressionType.Increment, type: "number", implementation: function implementation(operand) { return operand++; } }, "!": { arity: "prefix", expressionType: _index2.default.Expressions.ExpressionType.Not, type: "boolean", implementation: function implementation(operand) { return !operand; } }, "--false": { arity: "suffix", expressionType: _index2.default.Expressions.ExpressionType.Decrement, type: "number", implementation: function implementation(operand) { return operand--; } } } }, ParserUnaryExpression: function ParserUnaryExpression(node) { return new _index2.default.Expressions.UnaryExpression(this.ParserBuild(node.argument), this.ParserUnaryOperators[node.operator], this.ParserUnaryOperators[node.operator].expressionType); }, ParserUpdateExpression: function ParserUpdateExpression(node) { return new _index2.default.Expressions.UnaryExpression(this.ParserBuild(node.argument), this.ParserUnaryOperators[node.operator + node.prefix], this.ParserUnaryOperators[node.operator + node.prefix].nodeType); }, ParserBinaryExpression: function ParserBinaryExpression(node) { return new _index2.default.Expressions.SimpleBinaryExpression(this.ParserBuild(node.left), this.ParserBuild(node.right), this.ParserOperators[node.operator].expressionType, node.operator, this.ParserOperators[node.operator].type); }, ParserThisExpression: function ParserThisExpression(node) { return new _index2.default.Expressions.ThisExpression(); }, ParserLiteral: function ParserLiteral(node) { return new _index2.default.Expressions.ConstantExpression(node.value, _typeof(node.value)); }, ParserCallExpression: function ParserCallExpression(node) { var method = this.ParserBuild(node.callee); var args = new Array(node.arguments.length); for (var i = 0; i < node.arguments.length; i++) { args[i] = this.ParserBuild(node.arguments[i]); } var member; var expression; switch (true) { case method instanceof _index2.default.Expressions.PropertyExpression: expression = method.expression; member = method.member; break; case method instanceof _index2.default.Expressions.ParameterExpression: expression = new _index2.default.Expressions.ConstantExpression(null, _typeof(null)); member = method; break; } return new _index2.default.Expressions.CallExpression(expression, member, args); } /*, Build2: function (node) { ///<param name="node" type="Lint" /> ///<returns type="$data.Expressions.ExpressionNode" /> var n; switch (node.arity) { case "number": case "string": n = this.BuildConstant(node); break; case "prefix": switch (node.value) { case "{": n = this.BuildObjectLiteral(node); break; case "[": n = this.BuildArrayLiteral(node); break; case $data.unaryOperators.resolve(node.value): n = this.BuildUnary(node); break; //TODO: default case } break; case "suffix": switch (node.value) { case $data.unaryOperators.resolve(node.value): n = this.BuildUnary(node); break; default: Guard.raise("Unknown suffix: " + node.value); } break; case "infix": switch (node.value) { case "[": n = this.BuildArray(node); break; case $data.binaryOperators.resolve(node.value): n = this.BuildSimpleBinary(node); break; case "function": Guard.raise("Unexpected function arity"); case "(": n = this.BuildCall(node); break; case ".": n = this.BuildProperty(node); break; default: debugger; //TODO: remove debugger, throw exception or break } break; case "statement": switch (node.value) { case "function": n = this.BuildFunction(node); //TODO: consider adding break } break; default: switch (node.value) { case "function": n = this.BuildFunction(node); break; case "true": case "false": case "null": n = this.BuildConstant(node); break; case "this": n = this.BuildThis(node); break; default: n = this.BuildParameter(node); break; } } return n; }, BuildThis: function (node) { var result = Container.createThisExpression(); return result; }, BuildConstant: function (node) { ///<param name="node" type="ConstantASTNode" /> var value = node.value; var type = node.type; if (node.reserved === true) { switch (node.value) { case "true": value = true; type = typeof true; break; case "false": value = false; type = typeof false; break; case "null": value = null; type = typeof null; break; //TODO: missing default case } } var result = new $data.Expressions.ConstantExpression(value, type); return result; }, BuildFunctionParameter: function (node) { }, BuildArray: function (node) { switch (node.second.type) { case "string": return this.BuildProperty(node); case "number": default: return this.BuildSimpleBinary(node); } }, BuildParameter: function (node) { ///<param name="node" type="ParameterASTNode" /> ///<returns type="$data.Expressions.ParameterExpression" /> var paramName = node.value; //TODO //var paramType = this.resolver.resolveParameterType(node); var nodeType = node.funct ? $data.Expressions.ExpressionType.LambdaParameter : this.lambdaParams.indexOf(node.value) > -1 ? $data.Expressions.ExpressionType.LambdaParameterReference : $data.Expressions.ExpressionType.Parameter; var result = new $data.Expressions.ParameterExpression(node.value, null, nodeType); if (nodeType == $data.Expressions.ExpressionType.LambdaParameterReference) { result.paramIndex = this.lambdaParams.indexOf(node.value); } return result; }, BuildArrayLiteral: function(node) { var self = this; var items = node.first.map(function (item) { return self.Build2(item); }); var result = new $data.Expressions.ArrayLiteralExpression(items); return result; }, BuildObjectLiteral: function (node) { var self = this; var fields = node.first.map(function (item) { var eItem = self.Build2(item.first); var result = new $data.Expressions.ObjectFieldExpression(item.value, eItem); return result; }); var result = new $data.Expressions.ObjectLiteralExpression(fields); return result; }, BuildFunction: function (node) { ///<param name="node" type="FunctionASTNode"/> ///<returns type="$data.Expressions.FunctionExpression" /> var self = this; var paramStack = []; var params = node.first && node.first.map(function (paramNode) { //paramStack.push(paramNode.value); this.lambdaParams.push(paramNode.value); return self.BuildParameter(paramNode); }, this); params = params || []; //skipping return for convenience //Possible we should raise an error as predicates and selectors can //not be code blocks just expressions var hasReturn = node.block.length == 0 ? false : node.block[0].value === "return" ? true : false; var body = (node.block.length > 0) ? this.Build2(hasReturn ? node.block[0].first : node.block[0]) : null; paramStack.forEach(function () { this.lambdaParams.pop(); }, this); var result = new $data.Expressions.FunctionExpression(node.value, params, body); params.forEach(function (param) { param.owningFunction = result; }); //TODO place on prototyope result.name = node.name; return result; }, BuildCall: function (node) { var self = this; var method = self.Build2(node.first); var args = node.second.map(function (exp) { return self.Build2(exp); }); var member; var expression; switch(true){ case method instanceof $data.Expressions.PropertyExpression: expression = method.expression; member = method.member; break; case method instanceof $data.Expressions.ParameterExpression: expression = Container.createConstantExpression(null, typeof null); member = method; break; //TODO: missing default case } var result = Container.createCallExpression(expression, member, args); return result; }, BuildProperty: function (node) { ///<summary>Builds a PropertyExpression from the AST node</summary> ///<param name="node" type="MemberAccessASTNode" /> ///<returns type="$data.Expressions.PropertyExpression" /> var expression = this.Build2(node.first); //TODO //var type = expression.type; //var member = type.getMemberDefinition() //TODO how to not if????? var member; if (node.second.identifier) { member = new $data.Expressions.ConstantExpression(node.second.value, "string"); } else { member = this.Build2(node.second); } var result = new $data.Expressions.PropertyExpression(expression, member); return result; }, BuildUnary: function(node) { var operator = $data.unaryOperators.getOperator(node.value, node.arity); var nodeType = operator.expressionType; var operand = this.Build2(node.first); var result = new $data.Expressions.UnaryExpression(operand, operator, nodeType); return result; }, BuildSimpleBinary: function (node) { ///<param name="node" type="LintInflixNode" /> var operator = $data.binaryOperators.getOperator(node.value); var nodeType = operator.expressionType; var left = this.Build2(node.first || node.left); var right = this.Build2(node.second || node.right); var result = new $data.Expressions.SimpleBinaryExpression(left, right, nodeType, node.value, operator.type); return result; } //Build: function (node, expNode) { // var n; // switch (node.arity) { // case "ternary": // if (node.value == "?") // n = this.BuildDecision(node, expNode); // else // Guard.raise("Value of ternary node isn't implemented: " + node.value); // break; // case null: // default: // Guard.raise("Arity isn't implemented: " + node.arity); // } // return n; //},*/ }); exports.default = _index2.default; module.exports = exports['default'];