1
0
Fork 0

defer evaluation of logical operators

This commit is contained in:
Jan Steemann 2014-01-10 10:58:30 +01:00
parent 56054d3e66
commit 8277e7582c
3 changed files with 112 additions and 16 deletions

View File

@ -1939,28 +1939,30 @@ static void ProcessUnaryPlus (TRI_aql_codegen_js_t* const generator,
////////////////////////////////////////////////////////////////////////////////
/// @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,
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));
ScopeOutput(generator, ", ");
ScopeOutput(generator, "}, function () {\nreturn ");
ProcessNode(generator, TRI_AQL_NODE_MEMBER(node, 1));
ScopeOutput(generator, ")");
ScopeOutput(generator, "})");
}
////////////////////////////////////////////////////////////////////////////////
/// @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,
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));
ScopeOutput(generator, ", ");
ScopeOutput(generator, "}, function () {\nreturn ");
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,
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));
ScopeOutput(generator, ", ");
ScopeOutput(generator, ", function () { \nreturn ");
ProcessNode(generator, TRI_AQL_NODE_MEMBER(node, 1));
ScopeOutput(generator, ", ");
ScopeOutput(generator, "}, function () {\nreturn ");
ProcessNode(generator, TRI_AQL_NODE_MEMBER(node, 2));
ScopeOutput(generator, ")");
ScopeOutput(generator, "})");
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -1064,6 +1064,26 @@ function TERNARY_OPERATOR (condition, truePart, 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
///
@ -1108,6 +1128,60 @@ function LOGICAL_OR (lhs, 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
///
@ -4002,8 +4076,11 @@ exports.GET_DOCUMENTS_SKIPLIST = GET_DOCUMENTS_SKIPLIST;
exports.GET_DOCUMENTS_SKIPLIST_LIST = GET_DOCUMENTS_SKIPLIST_LIST;
exports.COLLECTIONS = COLLECTIONS;
exports.TERNARY_OPERATOR = TERNARY_OPERATOR;
exports.TERNARY_OPERATOR_FN = TERNARY_OPERATOR_FN;
exports.LOGICAL_AND = LOGICAL_AND;
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.RELATIONAL_EQUAL = RELATIONAL_EQUAL;
exports.RELATIONAL_UNEQUAL = RELATIONAL_UNEQUAL;

View File

@ -238,18 +238,35 @@ function ahuacatlLogicalTestSuite () {
////////////////////////////////////////////////////////////////////////////////
testBinaryAndShortCircuit1 : function () {
// TODO: FIXME
// var expected = [ false ];
// var actual = getQueryResults("RETURN false && FAIL('this will fail')");
//assertEqual(expected, actual);
var expected = [ false ];
var actual = getQueryResults("RETURN false && FAIL('this will fail')");
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test binary and, short circuit evaluation
/// @brief test binary or, short circuit evaluation
////////////////////////////////////////////////////////////////////////////////
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')"); });
},
////////////////////////////////////////////////////////////////////////////////