jaydata
Version:
Cross-platform HTML5 data-management, JavaScript Language Query (JSLQ) support for OData, SQLite, WebSQL, IndexedDB, YQL and Facebook (packaged for Node.JS)
166 lines (158 loc) • 9.23 kB
JavaScript
'use strict';
var _index = require('../../TypeSystem/index.js');
var _index2 = _interopRequireDefault(_index);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
_index2.default.Class.define('$data.Expressions.ExpressionBuilder', null, null, {
constructor: function constructor(context) {
this.context = context;
},
_isLambdaParam: function _isLambdaParam(name) {
var p = this.context.lambdaParams;
for (var i = 0; i < p.length; i++) {
if (p[i] == name) return true;
}
return false;
},
_isParam: function _isParam(name) {
return this.context.paramContext[name] != undefined;
},
_isParamRoot: function _isParamRoot(name) {
return this.context.paramsName == name;
},
Build: function Build(node, expNode) {
var n;
switch (node.arity) {
case "infix":
if ("(" == node.value) n = this.BuildMethodCall(node, expNode);else if ("." == node.value) n = this.BuildMember(node, expNode);else if (["===", "==", "!==", "!=", ">", "<", ">=", "<="].indexOf(node.value) >= 0) n = this.BuildEquality(node, expNode);else if (["&&", "||"].indexOf(node.value) >= 0) n = this.BuildBinary(node, expNode);else if (["+", "-", "*", "/", "%"].indexOf(node.value) >= 0) n = this.BuildBinary(node, expNode);else if ("[" == node.value) n = this.BuildArrayAccess(node, expNode);else _index.Guard.raise("Value of infix node isn't implemented: " + node.value);
break;
case "prefix":
if (["+", "-", "!"].indexOf(node.value) >= 0) n = this.BuildUnary(node, expNode);else if (["++", "--"].indexOf(node.value) >= 0) n = this.BuildIncDec(node, expNode);else if ("{" == node.value /* && "object" == node.type*/) //TODO: check the second condition necessity
n = this.BuildNewExpression(node, expNode);else _index.Guard.raise("Value of prefix node isn't implemented: " + node.value);
break;
case "suffix":
if (["++", "--"].indexOf(node.value) >= 0) n = this.BuildIncDec(node, expNode);else _index.Guard.raise("Value of suffix node isn't implemented: " + node.value);
break;
case "string":
case "number":
n = this.BuildLiteral(node, expNode); //TODO: more arity to literal?
break;
case "ternary":
if (node.value == "?") n = this.BuildDecision(node, expNode);else _index.Guard.raise("Value of ternary node isn't implemented: " + node.value);
break;
case null:
case undefined:
if (node.type == "boolean" && (node.value == "true" || node.value == "false")) n = this.BuildBoolLiteral(node, expNode);else n = this.BuildVariable(node, expNode);
break;
default:
_index.Guard.raise("Arity isn't implemented: " + node.arity);
}
return n;
},
BuildNewExpression: function BuildNewExpression(node, expNode) {
var newExpression = _index2.default.Expressions.ExpressionNodeTypes.NewExpressionNode.create(true, []);
var n = node.first;
for (var i = 0; i < n.length; i++) {
newExpression.values.push(this.Build(n[i], newExpression));
}return newExpression;
},
BuildLiteral: function BuildLiteral(node, expNode) {
return _index2.default.Expressions.ExpressionNodeTypes.LiteralExpressionNode.create(true, node.arity, node.value);
},
BuildBoolLiteral: function BuildBoolLiteral(node, expNode) {
return _index2.default.Expressions.ExpressionNodeTypes.LiteralExpressionNode.create(true, node.type, node.value == "true" ? true : false);
},
BuildVariable: function BuildVariable(node, expNode) {
if (!node.first) {
if (expNode.type == MEMBERACCESS) {
var subType;
if (this._isLambdaParam(node.value)) subType = "LAMBDAPARAM";else if (this._isParamRoot(node.value)) subType = "PARAMETERROOT";else if (this._isParam(node.value)) subType = "PARAMETER";else subType = "PROPERTY";
} else {
if (this._isLambdaParam(node.value)) subType = "LAMBDAPARAM";else if (this._isParamRoot(node.value)) subType = "PARAMETERROOT";else if (this._isParam(node.value)) subType = "PARAMETER";else if (_index2.default.__global[node.value] != undefined) subType = "GLOBALOBJECT";else _index.Guard.raise(new _index.Exception("Unknown variable in '" + this.context.operation + "' operation. The variable isn't referenced in the parameter context and it's not a global variable: '" + node.value + "'.", "InvalidOperation", { operationName: this.context.operation, missingParameterName: node.value }));
}
return _index2.default.Expressions.ExpressionNodeTypes.VariableExpressionNode.create(true, node.value, subType);
}
var left = _index2.default.Expressions.ExpressionNodeTypes.LiteralExpressionNode.create(true, "name", node.value);
var jsonAssign = _index2.default.Expressions.ExpressionNodeTypes.JsonAssignExpressionNode.create(true);
var right = this.Build(node.first, jsonAssign);
//left.parent = jsonAssign;
jsonAssign.left = left;
jsonAssign.right = right;
left.JSONASSIGN = true;
right.JSONASSIGN = true;
return jsonAssign;
},
BuildMember: function BuildMember(node, expNode) {
if (node.value != "." || node.arity != "infix") {
if (node.type == "string") {
//TODO: more types?
return _index2.default.Expressions.ExpressionNodeTypes.LiteralExpressionNode.create(true, node.arity, node.value);
}
return _index2.default.Expressions.ExpressionNodeTypes.MemberAccessExpressionNode.create(true, null, node.value);
}
var result = _index2.default.Expressions.ExpressionNodeTypes.MemberAccessExpressionNode.create(true);
var expression = this.Build(node.first, result);
var member = this.Build(node.second, result);
result.expression = expression;
result.member = member;
return result;
},
BuildUnary: function BuildUnary(node, expNode) {
var result = _index2.default.Expressions.ExpressionNodeTypes.UnaryExpressionNode.create(true, node.value);
result.operand = this.Build(node.first, result);
return result;
},
BuildIncDec: function BuildIncDec(node, expNode) {
var result = _index2.default.Expressions.ExpressionNodeTypes.IncDecExpressionNode.create(true, node.value, null, node.arity == "suffix");
result.operand = this.Build(node.first, result);
return result;
},
BuildBinary: function BuildBinary(node, expNode) {
if (!node.first) _index.Guard.raise("Cannot build binary: node.first is null");
if (!node.second) _index.Guard.raise("Cannot build binary: node.second is null");
var result = _index2.default.Expressions.ExpressionNodeTypes.BinaryExpressionNode.create(true, node.value);
result.left = this.Build(node.first, result);
result.right = this.Build(node.second, result);
return result;
},
BuildEquality: function BuildEquality(node, expNode) {
var result = _index2.default.Expressions.ExpressionNodeTypes.EqualityExpressionNode.create(true, node.value);
result.left = this.Build(node.first, result);
result.right = this.Build(node.second, result);
return result;
},
BuildDecision: function BuildDecision(node, expNode) {
var result = _index2.default.Expressions.ExpressionNodeTypes.DecisionExpressionNode.create(true);
result.expression = this.Build(node.first, result);
result.left = this.Build(node.second, result);
result.right = this.Build(node.third, result);
return result;
},
BuildMethodCall: function BuildMethodCall(node, expNode) {
var result = _index2.default.Expressions.ExpressionNodeTypes.MethodcallExpressionNode.create(true);
if (node.first.type == "function") {
//-- object's function
result.object = this.Build(node.first.first, result);
result.method = node.first.second.value;
} else {
//-- global function
if (node.first.type != null) _index.Guard.raise("Cannot build MethodCall because type is " + type);
result.object = null;
result.method = node.first.value;
}
var argNodes = node.second;
var args = [];
for (var i = 0; i < argNodes.length; i++) {
var arg = argNodes[i];
args[i] = this.Build(arg, result);
}
result.args = args;
return result;
},
BuildArrayAccess: function BuildArrayAccess(node, expNode) {
// { type:ARRAYACCESS, executable:true, array:, index: }
var result = _index2.default.Expressions.ExpressionNodeTypes.ArrayAccessExpressionNode.create(true);
result.array = this.Build(node.first, result);
result.index = this.Build(node.second, result);
return result;
}
}, null);