mirror of https://gitee.com/bigwinds/arangodb
defer evaluation of logical operators
This commit is contained in:
parent
56054d3e66
commit
8277e7582c
|
@ -1939,28 +1939,30 @@ static void ProcessUnaryPlus (TRI_aql_codegen_js_t* const generator,
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief generate code for binary and (a && b)
|
/// @brief generate code for binary and (a && b)
|
||||||
|
/// this passes two functions to the operator for lazy evaluation
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static void ProcessBinaryAnd (TRI_aql_codegen_js_t* const generator,
|
static void ProcessBinaryAnd (TRI_aql_codegen_js_t* const generator,
|
||||||
const TRI_aql_node_t* const node) {
|
const TRI_aql_node_t* const node) {
|
||||||
ScopeOutput(generator, "aql.LOGICAL_AND(");
|
ScopeOutput(generator, "aql.LOGICAL_AND_FN(function () {\nreturn ");
|
||||||
ProcessNode(generator, TRI_AQL_NODE_MEMBER(node, 0));
|
ProcessNode(generator, TRI_AQL_NODE_MEMBER(node, 0));
|
||||||
ScopeOutput(generator, ", ");
|
ScopeOutput(generator, "}, function () {\nreturn ");
|
||||||
ProcessNode(generator, TRI_AQL_NODE_MEMBER(node, 1));
|
ProcessNode(generator, TRI_AQL_NODE_MEMBER(node, 1));
|
||||||
ScopeOutput(generator, ")");
|
ScopeOutput(generator, "})");
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief generate code for binary or (a || b)
|
/// @brief generate code for binary or (a || b)
|
||||||
|
/// this passes two functions to the operator for lazy evaluation
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static void ProcessBinaryOr (TRI_aql_codegen_js_t* const generator,
|
static void ProcessBinaryOr (TRI_aql_codegen_js_t* const generator,
|
||||||
const TRI_aql_node_t* const node) {
|
const TRI_aql_node_t* const node) {
|
||||||
ScopeOutput(generator, "aql.LOGICAL_OR(");
|
ScopeOutput(generator, "aql.LOGICAL_OR_FN(function () {\nreturn ");
|
||||||
ProcessNode(generator, TRI_AQL_NODE_MEMBER(node, 0));
|
ProcessNode(generator, TRI_AQL_NODE_MEMBER(node, 0));
|
||||||
ScopeOutput(generator, ", ");
|
ScopeOutput(generator, "}, function () {\nreturn ");
|
||||||
ProcessNode(generator, TRI_AQL_NODE_MEMBER(node, 1));
|
ProcessNode(generator, TRI_AQL_NODE_MEMBER(node, 1));
|
||||||
ScopeOutput(generator, ")");
|
ScopeOutput(generator, "})");
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -2125,13 +2127,13 @@ static void ProcessBinaryIn (TRI_aql_codegen_js_t* const generator,
|
||||||
|
|
||||||
static void ProcessTernary (TRI_aql_codegen_js_t* const generator,
|
static void ProcessTernary (TRI_aql_codegen_js_t* const generator,
|
||||||
const TRI_aql_node_t* const node) {
|
const TRI_aql_node_t* const node) {
|
||||||
ScopeOutput(generator, "aql.TERNARY_OPERATOR(");
|
ScopeOutput(generator, "aql.TERNARY_OPERATOR_FN(");
|
||||||
ProcessNode(generator, TRI_AQL_NODE_MEMBER(node, 0));
|
ProcessNode(generator, TRI_AQL_NODE_MEMBER(node, 0));
|
||||||
ScopeOutput(generator, ", ");
|
ScopeOutput(generator, ", function () { \nreturn ");
|
||||||
ProcessNode(generator, TRI_AQL_NODE_MEMBER(node, 1));
|
ProcessNode(generator, TRI_AQL_NODE_MEMBER(node, 1));
|
||||||
ScopeOutput(generator, ", ");
|
ScopeOutput(generator, "}, function () {\nreturn ");
|
||||||
ProcessNode(generator, TRI_AQL_NODE_MEMBER(node, 2));
|
ProcessNode(generator, TRI_AQL_NODE_MEMBER(node, 2));
|
||||||
ScopeOutput(generator, ")");
|
ScopeOutput(generator, "})");
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -1064,6 +1064,26 @@ function TERNARY_OPERATOR (condition, truePart, falsePart) {
|
||||||
return falsePart;
|
return falsePart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief execute ternary operator
|
||||||
|
///
|
||||||
|
/// the condition operand must be a boolean value, returns either the truepart
|
||||||
|
/// or the falsepart
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function TERNARY_OPERATOR_FN (condition, truePart, falsePart) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
if (TYPEWEIGHT(condition) !== TYPEWEIGHT_BOOL) {
|
||||||
|
THROW(INTERNAL.errors.ERROR_QUERY_INVALID_LOGICAL_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (condition) {
|
||||||
|
return truePart();
|
||||||
|
}
|
||||||
|
return falsePart();
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief perform logical and
|
/// @brief perform logical and
|
||||||
///
|
///
|
||||||
|
@ -1108,6 +1128,60 @@ function LOGICAL_OR (lhs, rhs) {
|
||||||
return rhs;
|
return rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief perform logical and
|
||||||
|
///
|
||||||
|
/// both operands must be boolean values, returns a boolean, uses short-circuit
|
||||||
|
/// evaluation
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function LOGICAL_AND_FN (lhs, rhs) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var l = lhs();
|
||||||
|
if (TYPEWEIGHT(l) !== TYPEWEIGHT_BOOL) {
|
||||||
|
THROW(INTERNAL.errors.ERROR_QUERY_INVALID_LOGICAL_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! l) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var r = rhs();
|
||||||
|
if (TYPEWEIGHT(r) !== TYPEWEIGHT_BOOL) {
|
||||||
|
THROW(INTERNAL.errors.ERROR_QUERY_INVALID_LOGICAL_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief perform logical or
|
||||||
|
///
|
||||||
|
/// both operands must be boolean values, returns a boolean, uses short-circuit
|
||||||
|
/// evaluation
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function LOGICAL_OR_FN (lhs, rhs) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var l = lhs();
|
||||||
|
if (TYPEWEIGHT(l) !== TYPEWEIGHT_BOOL) {
|
||||||
|
THROW(INTERNAL.errors.ERROR_QUERY_INVALID_LOGICAL_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var r = rhs();
|
||||||
|
if (TYPEWEIGHT(r) !== TYPEWEIGHT_BOOL) {
|
||||||
|
THROW(INTERNAL.errors.ERROR_QUERY_INVALID_LOGICAL_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief perform logical negation
|
/// @brief perform logical negation
|
||||||
///
|
///
|
||||||
|
@ -4002,8 +4076,11 @@ exports.GET_DOCUMENTS_SKIPLIST = GET_DOCUMENTS_SKIPLIST;
|
||||||
exports.GET_DOCUMENTS_SKIPLIST_LIST = GET_DOCUMENTS_SKIPLIST_LIST;
|
exports.GET_DOCUMENTS_SKIPLIST_LIST = GET_DOCUMENTS_SKIPLIST_LIST;
|
||||||
exports.COLLECTIONS = COLLECTIONS;
|
exports.COLLECTIONS = COLLECTIONS;
|
||||||
exports.TERNARY_OPERATOR = TERNARY_OPERATOR;
|
exports.TERNARY_OPERATOR = TERNARY_OPERATOR;
|
||||||
|
exports.TERNARY_OPERATOR_FN = TERNARY_OPERATOR_FN;
|
||||||
exports.LOGICAL_AND = LOGICAL_AND;
|
exports.LOGICAL_AND = LOGICAL_AND;
|
||||||
exports.LOGICAL_OR = LOGICAL_OR;
|
exports.LOGICAL_OR = LOGICAL_OR;
|
||||||
|
exports.LOGICAL_AND_FN = LOGICAL_AND_FN;
|
||||||
|
exports.LOGICAL_OR_FN = LOGICAL_OR_FN;
|
||||||
exports.LOGICAL_NOT = LOGICAL_NOT;
|
exports.LOGICAL_NOT = LOGICAL_NOT;
|
||||||
exports.RELATIONAL_EQUAL = RELATIONAL_EQUAL;
|
exports.RELATIONAL_EQUAL = RELATIONAL_EQUAL;
|
||||||
exports.RELATIONAL_UNEQUAL = RELATIONAL_UNEQUAL;
|
exports.RELATIONAL_UNEQUAL = RELATIONAL_UNEQUAL;
|
||||||
|
|
|
@ -238,18 +238,35 @@ function ahuacatlLogicalTestSuite () {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
testBinaryAndShortCircuit1 : function () {
|
testBinaryAndShortCircuit1 : function () {
|
||||||
// TODO: FIXME
|
var expected = [ false ];
|
||||||
// var expected = [ false ];
|
var actual = getQueryResults("RETURN false && FAIL('this will fail')");
|
||||||
// var actual = getQueryResults("RETURN false && FAIL('this will fail')");
|
assertEqual(expected, actual);
|
||||||
//assertEqual(expected, actual);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief test binary and, short circuit evaluation
|
/// @brief test binary or, short circuit evaluation
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
testBinaryAndShortCircuit2 : function () {
|
testBinaryAndShortCircuit2 : function () {
|
||||||
assertException(function() { getQueryResults("RETURN false && FAIL('this will fail')"); });
|
assertException(function() { getQueryResults("RETURN true && FAIL('this will fail')"); });
|
||||||
|
},
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief test binary or, short circuit evaluation
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
testBinaryOrShortCircuit1 : function () {
|
||||||
|
var expected = [ true ];
|
||||||
|
var actual = getQueryResults("RETURN true || FAIL('this will fail')");
|
||||||
|
assertEqual(expected, actual);
|
||||||
|
},
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief test binary or, short circuit evaluation
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
testBinaryOrShortCircuit2 : function () {
|
||||||
|
assertException(function() { getQueryResults("RETURN false || FAIL('this will fail')"); });
|
||||||
},
|
},
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
Loading…
Reference in New Issue