/// <summary>
        /// Returns true if the given method is an AQL function
        /// and thus shouldn't be evaluated
        /// </summary>
        private static bool IsAqlFunction(MethodInfo method)
        {
            ArangoFunctionAttribute attribute = method
                                                .GetCustomAttribute <ArangoFunctionAttribute>();

            return(attribute != null);
        }
 public AqlFunctionExpression(
     ArangoFunctionAttribute attribute,
     List <AqlExpression> arguments
     ) : this(attribute.FunctionName, arguments)
 {
 }
        private AqlExpression VisitCall(MethodCallExpression node)
        {
            AqlExpression        instance = Visit(node.Object);
            List <AqlExpression> args     = node.Arguments
                                            .Select(Visit)
                                            .ToList();

            // === handle arango functions ===

            ArangoFunctionAttribute attribute = node.Method
                                                .GetCustomAttribute <ArangoFunctionAttribute>();

            if (attribute != null)
            {
                return(new AqlFunctionExpression(attribute, args));
            }

            // === intercept indexing on JSON objects and arrays ===

            if (possibleIndexerMethods.Contains(node.Method) &&
                args.Count == 1)
            {
                return(new AqlMemberAccessExpression(
                           instance,
                           args[0]
                           ));
            }

            // === handle JSON object construction ===

            // if we call .Add on a JsonObject instance
            if (node.Object?.Type == typeof(JsonObject) &&
                node.Method.Name == "Add")
            {
                // start construction
                if (instance is AqlConstantExpression constant)
                {
                    instance = new AqlJsonObjectExpression(constant.Value);
                }

                // continue construction
                if (instance is AqlJsonObjectExpression obj)
                {
                    return(obj.CallAddViaArgs(args));
                }
            }

            // === handle JSON array construction ===

            // if we call .Add on a JsonArray instance
            if (node.Object?.Type == typeof(JsonArray) &&
                node.Method.Name == "Add")
            {
                // start construction
                if (instance is AqlConstantExpression constant)
                {
                    instance = new AqlJsonArrayExpression(constant.Value);
                }

                // continue construction
                if (instance is AqlJsonArrayExpression arr)
                {
                    return(arr.CallAddViaArgs(args));
                }
            }

            // === expression is invalid ===

            throw new AqlParsingException(
                      $"Expression uses parameters in method '{node.Method}'" +
                      ", but this method cannot be translated to AQL"
                      );
        }