static TRI_aql_node_t* OptimiseUnaryArithmeticOperation (TRI_aql_context_t* const context, TRI_aql_node_t* node) { TRI_aql_node_t* operand = TRI_AQL_NODE_MEMBER(node, 0); assert(node->_type == TRI_AQL_NODE_OPERATOR_UNARY_PLUS || node->_type == TRI_AQL_NODE_OPERATOR_UNARY_MINUS); if (!operand || !TRI_IsConstantValueNodeAql(operand)) { return node; } if (!TRI_IsNumericValueNodeAql(operand)) { TRI_SetErrorContextAql(context, TRI_ERROR_QUERY_INVALID_ARITHMETIC_VALUE, NULL); return node; } if (node->_type == TRI_AQL_NODE_OPERATOR_UNARY_PLUS) { // + number => number node = operand; } else if (node->_type == TRI_AQL_NODE_OPERATOR_UNARY_MINUS) { // - number => eval! node = TRI_CreateNodeValueDoubleAql(context, - TRI_GetNumericNodeValueAql(operand)); if (node == NULL) { TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL); } } return node; }
TRI_aql_node_t* TRI_JsonNodeAql (TRI_aql_context_t* const context, const TRI_json_t* const json) { TRI_aql_node_t* node = NULL; char* value; switch (json->_type) { case TRI_JSON_UNUSED: break; case TRI_JSON_NULL: node = TRI_CreateNodeValueNullAql(context); break; case TRI_JSON_BOOLEAN: node = TRI_CreateNodeValueBoolAql(context, json->_value._boolean); break; case TRI_JSON_NUMBER: node = TRI_CreateNodeValueDoubleAql(context, json->_value._number); break; case TRI_JSON_STRING: value = TRI_RegisterStringAql(context, json->_value._string.data, strlen(json->_value._string.data), true); node = TRI_CreateNodeValueStringAql(context, value); break; case TRI_JSON_LIST: { size_t i; size_t n; node = TRI_CreateNodeListAql(context); n = json->_value._objects._length; for (i = 0; i < n; ++i) { TRI_json_t* subJson; TRI_aql_node_t* member; subJson = (TRI_json_t*) TRI_AtVector(&json->_value._objects, i); assert(subJson); member = TRI_JsonNodeAql(context, subJson); if (member) { TRI_PushBackVectorPointer(&node->_members, (void*) member); } else { TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL); return NULL; } } break; } case TRI_JSON_ARRAY: { size_t i; size_t n; node = TRI_CreateNodeArrayAql(context); n = json->_value._objects._length; for (i = 0; i < n; i += 2) { TRI_json_t* nameJson; TRI_json_t* valueJson; TRI_aql_node_t* member; TRI_aql_node_t* valueNode; char* name; // json_t containing the array element name nameJson = (TRI_json_t*) TRI_AtVector(&json->_value._objects, i); assert(nameJson); assert(nameJson->_value._string.data); name = TRI_RegisterStringAql(context, nameJson->_value._string.data, strlen(nameJson->_value._string.data), false); if (! name) { TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL); return NULL; } // json_t containing the array element value valueJson = (TRI_json_t*) TRI_AtVector(&json->_value._objects, i + 1); assert(valueJson); valueNode = TRI_JsonNodeAql(context, valueJson); if (! valueNode) { TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL); return NULL; } member = TRI_CreateNodeArrayElementAql(context, name, valueNode); if (member) { TRI_PushBackVectorPointer(&node->_members, (void*) member); } else { TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL); return NULL; } } break; } } if (! node) { TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL); } return node; }
static TRI_aql_node_t* OptimiseBinaryArithmeticOperation (TRI_aql_context_t* const context, TRI_aql_node_t* node) { TRI_aql_node_t* lhs = TRI_AQL_NODE_MEMBER(node, 0); TRI_aql_node_t* rhs = TRI_AQL_NODE_MEMBER(node, 1); bool isEligibleLhs; bool isEligibleRhs; double value; if (!lhs || !rhs) { return node; } isEligibleLhs = TRI_IsConstantValueNodeAql(lhs); isEligibleRhs = TRI_IsConstantValueNodeAql(rhs); if (isEligibleLhs && !TRI_IsNumericValueNodeAql(lhs)) { // node is not a numeric value => error TRI_SetErrorContextAql(context, TRI_ERROR_QUERY_INVALID_ARITHMETIC_VALUE, NULL); return node; } if (isEligibleRhs && !TRI_IsNumericValueNodeAql(rhs)) { // node is not a numeric value => error TRI_SetErrorContextAql(context, TRI_ERROR_QUERY_INVALID_ARITHMETIC_VALUE, NULL); return node; } if (!isEligibleLhs || !isEligibleRhs) { return node; } assert(node->_type == TRI_AQL_NODE_OPERATOR_BINARY_PLUS || node->_type == TRI_AQL_NODE_OPERATOR_BINARY_MINUS || node->_type == TRI_AQL_NODE_OPERATOR_BINARY_TIMES || node->_type == TRI_AQL_NODE_OPERATOR_BINARY_DIV || node->_type == TRI_AQL_NODE_OPERATOR_BINARY_MOD); if (node->_type == TRI_AQL_NODE_OPERATOR_BINARY_PLUS) { value = TRI_GetNumericNodeValueAql(lhs) + TRI_GetNumericNodeValueAql(rhs); } else if (node->_type == TRI_AQL_NODE_OPERATOR_BINARY_MINUS) { value = TRI_GetNumericNodeValueAql(lhs) - TRI_GetNumericNodeValueAql(rhs); } else if (node->_type == TRI_AQL_NODE_OPERATOR_BINARY_TIMES) { value = TRI_GetNumericNodeValueAql(lhs) * TRI_GetNumericNodeValueAql(rhs); } else if (node->_type == TRI_AQL_NODE_OPERATOR_BINARY_DIV) { if (TRI_GetNumericNodeValueAql(rhs) == 0.0) { // division by zero TRI_SetErrorContextAql(context, TRI_ERROR_QUERY_DIVISION_BY_ZERO, NULL); return node; } value = TRI_GetNumericNodeValueAql(lhs) / TRI_GetNumericNodeValueAql(rhs); } else if (node->_type == TRI_AQL_NODE_OPERATOR_BINARY_MOD) { if (TRI_GetNumericNodeValueAql(rhs) == 0.0) { // division by zero TRI_SetErrorContextAql(context, TRI_ERROR_QUERY_DIVISION_BY_ZERO, NULL); return node; } value = fmod(TRI_GetNumericNodeValueAql(lhs), TRI_GetNumericNodeValueAql(rhs)); } else { value = 0.0; } node = TRI_CreateNodeValueDoubleAql(context, value); if (!node) { TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL); return NULL; } LOG_TRACE("optimised away binary arithmetic operation"); return node; }