diff --git a/arangod/Aql/Ast.cpp b/arangod/Aql/Ast.cpp index 4304c4a55f..b81d5d5d04 100644 --- a/arangod/Aql/Ast.cpp +++ b/arangod/Aql/Ast.cpp @@ -535,7 +535,6 @@ AstNode* Ast::createNodeIterator (char const* variableName, return node; } - //////////////////////////////////////////////////////////////////////////////// /// @brief create an AST null value node //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/Aql/V8Executor.cpp b/arangod/Aql/V8Executor.cpp index 8ecdb53a0e..e73400cb12 100644 --- a/arangod/Aql/V8Executor.cpp +++ b/arangod/Aql/V8Executor.cpp @@ -264,6 +264,21 @@ void V8Executor::generateCodeReference (AstNode const* node) { _buffer->appendText("\"]"); } +//////////////////////////////////////////////////////////////////////////////// +/// @brief generate JavaScript code for a variable +//////////////////////////////////////////////////////////////////////////////// + +void V8Executor::generateCodeVariable (AstNode const* node) { + TRI_ASSERT(node != nullptr); + TRI_ASSERT(node->numMembers() == 0); + + auto variable = static_cast(node->getData()); + + _buffer->appendText("vars[\""); + _buffer->appendJsonEncoded(variable->name.c_str()); + _buffer->appendText("\"]"); +} + //////////////////////////////////////////////////////////////////////////////// /// @brief generate JavaScript code for a full collection access //////////////////////////////////////////////////////////////////////////////// @@ -308,6 +323,78 @@ void V8Executor::generateCodeFunctionCall (AstNode const* node) { _buffer->appendText(")"); } +//////////////////////////////////////////////////////////////////////////////// +/// @brief generate JavaScript code for an expansion (i.e. [*] operator) +//////////////////////////////////////////////////////////////////////////////// + +void V8Executor::generateCodeExpand (AstNode const* node) { + TRI_ASSERT(node != nullptr); + TRI_ASSERT(node->numMembers() == 2); + + _buffer->appendText("(function () { var r = []; return "); + generateCodeNode(node->getMember(0)); + _buffer->appendText(".forEach(function (v) { r.push_back("); + generateCodeNode(node->getMember(1)); + _buffer->appendText("); }); })()"); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief generate JavaScript code for an expansion iterator +//////////////////////////////////////////////////////////////////////////////// + +void V8Executor::generateCodeExpandIterator (AstNode const* node) { + TRI_ASSERT(node != nullptr); + TRI_ASSERT(node->numMembers() == 2); + + // intentionally do not stringify node 0 + generateCodeNode(node->getMember(1)); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief generate JavaScript code for a range (i.e. 1..10) +//////////////////////////////////////////////////////////////////////////////// + +void V8Executor::generateCodeRange (AstNode const* node) { + TRI_ASSERT(node != nullptr); + TRI_ASSERT(node->numMembers() == 2); + + _buffer->appendText("aql.RANGE("); + generateCodeNode(node->getMember(0)); + _buffer->appendText(", "); + generateCodeNode(node->getMember(1)); + _buffer->appendText(")"); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief generate JavaScript code for a named attribute access +//////////////////////////////////////////////////////////////////////////////// + +void V8Executor::generateCodeNamedAccess (AstNode const* node) { + TRI_ASSERT(node != nullptr); + TRI_ASSERT(node->numMembers() == 1); + + _buffer->appendText("aql.DOCUMENT_MEMBER("); + generateCodeNode(node->getMember(0)); + _buffer->appendText(", \""); + _buffer->appendJsonEncoded(node->getStringValue()); + _buffer->appendText("\")"); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief generate JavaScript code for an indexed attribute access +//////////////////////////////////////////////////////////////////////////////// + +void V8Executor::generateCodeIndexedAccess (AstNode const* node) { + TRI_ASSERT(node != nullptr); + TRI_ASSERT(node->numMembers() == 2); + + _buffer->appendText("aql.GET_INDEX("); + generateCodeNode(node->getMember(0)); + _buffer->appendText(", "); + generateCodeNode(node->getMember(1)); + _buffer->appendText(")"); +} + //////////////////////////////////////////////////////////////////////////////// /// @brief generate JavaScript code for a node //////////////////////////////////////////////////////////////////////////////// @@ -358,10 +445,30 @@ void V8Executor::generateCodeNode (AstNode const* node) { case NODE_TYPE_FCALL: generateCodeFunctionCall(node); break; + + case NODE_TYPE_EXPAND: + generateCodeExpand(node); + break; + + case NODE_TYPE_ITERATOR: + generateCodeExpandIterator(node); + break; + + case NODE_TYPE_RANGE: + generateCodeRange(node); + break; case NODE_TYPE_ATTRIBUTE_ACCESS: + generateCodeNamedAccess(node); + break; + case NODE_TYPE_INDEXED_ACCESS: - // TODO: + generateCodeIndexedAccess(node); + break; + + case NODE_TYPE_VARIABLE: + // we're not expecting a variable here + THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); default: // TODO: remove debug output diff --git a/arangod/Aql/V8Executor.h b/arangod/Aql/V8Executor.h index 4058e6c316..c4ba8fd450 100644 --- a/arangod/Aql/V8Executor.h +++ b/arangod/Aql/V8Executor.h @@ -122,6 +122,12 @@ namespace triagens { void generateCodeReference (AstNode const*); +//////////////////////////////////////////////////////////////////////////////// +/// @brief generate JavaScript code for a variable +//////////////////////////////////////////////////////////////////////////////// + + void generateCodeVariable (AstNode const*); + //////////////////////////////////////////////////////////////////////////////// /// @brief generate JavaScript code for a full collection access //////////////////////////////////////////////////////////////////////////////// @@ -134,6 +140,36 @@ namespace triagens { void generateCodeFunctionCall (AstNode const*); +//////////////////////////////////////////////////////////////////////////////// +/// @brief generate JavaScript code for an expansion (i.e. [*] operator) +//////////////////////////////////////////////////////////////////////////////// + + void generateCodeExpand (AstNode const*); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief generate JavaScript code for an expansion iterator +//////////////////////////////////////////////////////////////////////////////// + + void generateCodeExpandIterator (AstNode const*); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief generate JavaScript code for a range (i.e. 1..10) +//////////////////////////////////////////////////////////////////////////////// + + void generateCodeRange (AstNode const*); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief generate JavaScript code for a named attribute access +//////////////////////////////////////////////////////////////////////////////// + + void generateCodeNamedAccess (AstNode const*); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief generate JavaScript code for an indexed attribute access +//////////////////////////////////////////////////////////////////////////////// + + void generateCodeIndexedAccess (AstNode const*); + //////////////////////////////////////////////////////////////////////////////// /// @brief generate JavaScript code for a node ////////////////////////////////////////////////////////////////////////////////