static TRI_aql_node_t* OptimiseConstantFilter (TRI_aql_node_t* const node) { if (TRI_GetBooleanNodeValueAql(node)) { // filter expression is always true => remove it LOG_TRACE("optimised away constant (true) filter"); return TRI_GetDummyNopNodeAql(); } // filter expression is always false => invalidate surrounding scope(s) LOG_TRACE("optimised away scope"); return TRI_GetDummyReturnEmptyNodeAql(); }
static TRI_aql_node_t* OptimiseFor (TRI_aql_statement_walker_t* const walker, TRI_aql_node_t* node) { TRI_aql_node_t* expression = TRI_AQL_NODE_MEMBER(node, 1); if (expression->_type == TRI_AQL_NODE_LIST) { // for statement with a list expression if (expression->_members._length == 0) { // list is empty => we can eliminate the for statement LOG_TRACE("optimised away empty for loop"); return TRI_GetDummyReturnEmptyNodeAql(); } } return node; }
size_t TRI_InvalidateStatementListAql (TRI_aql_statement_list_t* const list, const size_t position) { size_t i, n; size_t start; size_t scopes; size_t ignoreScopes; assert(list); assert(position >= 0); n = list->_statements._length; // walk the scope from the specified position backwards until we find the start of the scope scopes = 1; ignoreScopes = 0; i = position; while (true) { TRI_aql_node_t* node = StatementAt(list, i); TRI_aql_node_type_e type = node->_type; list->_statements._buffer[i] = TRI_GetDummyNopNodeAql(); start = i; if (type == TRI_AQL_NODE_SCOPE_START) { // node is a scope start TRI_aql_scope_t* scope = (TRI_aql_scope_t*) TRI_AQL_NODE_DATA(node); if (ignoreScopes > 0) { // this is an inner, parallel scope that we can ignore --ignoreScopes; } else { if (scope->_type != TRI_AQL_SCOPE_FOR_NESTED) { // we have reached the scope and need to stop break; } scopes++; } } else if (type == TRI_AQL_NODE_SCOPE_END) { // we found the end of another scope // we must remember how many other scopes we passed ignoreScopes++; } if (i-- == 0) { break; } } assert(ignoreScopes == 0); // remove from position forwards to scope end i = position; while (true) { TRI_aql_node_t* node = StatementAt(list, i); TRI_aql_node_type_e type = node->_type; list->_statements._buffer[i] = TRI_GetDummyNopNodeAql(); if (type == TRI_AQL_NODE_SCOPE_START) { ++scopes; } else if (type == TRI_AQL_NODE_SCOPE_END) { assert(scopes > 0); if (--scopes == 0) { break; } } if (++i == n) { break; } } list->_statements._buffer[start] = TRI_GetDummyReturnEmptyNodeAql(); return start + 1; }
size_t TRI_InvalidateStatementListAql (TRI_aql_statement_list_t* const list, const size_t position) { size_t i, n; size_t start; size_t scopes; assert(list); assert(position >= 0); n = list->_statements._length; // remove from position backwards to scope start scopes = 1; i = position; while (true) { TRI_aql_node_t* node = StatementAt(list, i); TRI_aql_node_type_e type = node->_type; list->_statements._buffer[i] = TRI_GetDummyNopNodeAql(); start = i; if (type == TRI_AQL_NODE_SCOPE_START) { TRI_aql_scope_t* scope = (TRI_aql_scope_t*) TRI_AQL_NODE_DATA(node); if (scope->_type != TRI_AQL_SCOPE_FOR_NESTED) { break; } scopes++; } if (i-- == 0) { break; } } // remove from position forwards to scope end i = position; while (true) { TRI_aql_node_t* node = StatementAt(list, i); TRI_aql_node_type_e type = node->_type; list->_statements._buffer[i] = TRI_GetDummyNopNodeAql(); if (type == TRI_AQL_NODE_SCOPE_START) { ++scopes; } else if (type == TRI_AQL_NODE_SCOPE_END) { assert(scopes > 0); if (--scopes == 0) { break; } } if (++i == n) { break; } } list->_statements._buffer[start] = TRI_GetDummyReturnEmptyNodeAql(); return start + 1; }