1/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
14==============================================================================*/
15
16#ifndef TENSORFLOW_PYTHON_UTIL_FUNCTION_PARAMETER_CANONICALIZER_H_
17#define TENSORFLOW_PYTHON_UTIL_FUNCTION_PARAMETER_CANONICALIZER_H_
18
19#include <Python.h>
20
21#include <vector>
22
23#include "absl/types/span.h"
24#include "tensorflow/python/lib/core/safe_pyobject_ptr.h"
25
26namespace tensorflow {
27
28// A class that Canonicalizes Python arg & kwargs parameters.
29class FunctionParameterCanonicalizer {
30 public:
31 // `arg_names` is a list of argument names, and `defaults` is default PyObject
32 // instances for arguments. `default` is aligned to the end.
33 FunctionParameterCanonicalizer(absl::Span<const char*> arg_names,
34 absl::Span<PyObject*> defaults);
35
36 // Returns the total number of arguments.
37 ABSL_MUST_USE_RESULT
38 int GetArgSize() const { return interned_arg_names_.size(); }
39
40 // Canonicalizes `args` and `kwargs` by the spec specified at construction.
41 // It's written to `result`. Returns `true` if Canonicalization was
42 // successful, and `false` otherwise. When it fails, it also sets CPython
43 // error status.
44 // This function does not update reference counter of any Python objects.
45 // `PyObject*`s in `result` are borrowed references from `args`, `kwargs`, and
46 // possibly `defaults_`, and will be only valid if `args` and `kwargs` are
47 // still alive.
48 ABSL_MUST_USE_RESULT
49 ABSL_ATTRIBUTE_HOT
50 bool Canonicalize(PyObject* args, PyObject* kwargs,
51 absl::Span<PyObject*> result);
52
53 private:
54 // Simple linear search of `name` in `interned_arg_names`. If found, returns
55 // the index. If not found, returns `interned_arg_names.size()`.
56 ABSL_MUST_USE_RESULT
57 ABSL_ATTRIBUTE_HOT
58 std::size_t InternedArgNameLinearSearch(PyObject* name);
59
60 // Check if `interned_arg_names_` is unique.
61 bool AreInternedArgNamesUnique();
62
63 // TODO(kkb): Use one `std::vector` and two `absl:Span`s instead to improve
64 // cache locality.
65 std::vector<Safe_PyObjectPtr> interned_arg_names_;
66 std::vector<Safe_PyObjectPtr> defaults_;
67 const int positional_args_size_;
68};
69
70} // namespace tensorflow
71
72#endif // TENSORFLOW_PYTHON_UTIL_FUNCTION_PARAMETER_CANONICALIZER_H_
73