• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #ifndef TENSORFLOW_JAVA_SRC_GEN_CC_SOURCE_WRITER_H_
17 #define TENSORFLOW_JAVA_SRC_GEN_CC_SOURCE_WRITER_H_
18 
19 #include <string>
20 #include <stack>
21 #include <list>
22 #include <set>
23 
24 #include "tensorflow/core/lib/core/stringpiece.h"
25 #include "tensorflow/core/platform/env.h"
26 #include "tensorflow/java/src/gen/cc/java_defs.h"
27 
28 namespace tensorflow {
29 namespace java {
30 
31 // A class for writing Java source code.
32 class SourceWriter {
33  public:
34   SourceWriter();
35 
36   virtual ~SourceWriter();
37 
38   // Indents following lines with white spaces.
39   //
40   // Indentation is cumulative, i.e. the provided tabulation is added to the
41   // current indentation value. If the tabulation is negative, the operation
42   // will outdent the source code, until the indentation reaches 0 again.
43   //
44   // For example, calling Indent(2) twice will indent code with 4 white
45   // spaces. Then calling Indent(-2) will outdent the code back to 2 white
46   // spaces.
47   SourceWriter& Indent(int tab);
48 
49   // Prefixes following lines with provided character(s).
50   //
51   // A common use case of a prefix is for commenting or documenting the code.
52   //
53   // The prefix is written after the indentation, For example, invoking
54   // Indent(2)->Prefix("//") will result in prefixing lines with "  //".
55   //
56   // An empty value ("") will remove any line prefix that was previously set.
57   SourceWriter& Prefix(const char* line_prefix);
58 
59   // Writes a source code snippet.
60   //
61   // The data might potentially contain newline characters, therefore it will
62   // be scanned to ensure that each line is indented and prefixed properly,
63   // making it a bit slower than Append().
64   SourceWriter& Write(const StringPiece& str);
65 
66   // Writes a source code snippet read from a file.
67   //
68   // All lines of the file at the provided path will be read and written back
69   // to the output of this writer in regard of its current attributes (e.g.
70   // the indentation, prefix, etc.)
71   SourceWriter& WriteFromFile(const string& fname, Env* env = Env::Default());
72 
73   // Appends a piece of source code.
74   //
75   // It is expected that no newline character is present in the data provided,
76   // otherwise Write() must be used.
77   SourceWriter& Append(const StringPiece& str);
78 
79   // Appends a type to the current line.
80   //
81   // The type is written in its simple form (i.e. not prefixed by its package)
82   // and followed by any parameter types it has enclosed in brackets (<>).
83   SourceWriter& AppendType(const Type& type);
84 
85   // Appends a newline character.
86   //
87   // Data written after calling this method will start on a new line, in respect
88   // of the current indentation.
89   SourceWriter& EndLine();
90 
91   // Begins a block of source code.
92   //
93   // This method appends a new opening brace to the current data and indent the
94   // next lines according to Google Java Style Guide. The block can optionally
95   // be preceded by an expression (e.g. Append("if(true)").BeginBlock();)
96   SourceWriter& BeginBlock(const string& expression = "");
97 
98   // Ends the current block of source code.
99   //
100   // This method appends a new closing brace to the current data and outdent the
101   // next lines back to the margin used before BeginBlock() was invoked.
102   SourceWriter& EndBlock();
103 
104   // Begins to write a method.
105   //
106   // This method outputs the signature of the Java method from the data passed
107   // in the 'method' parameter and starts a new block. Modifiers are also passed
108   // in parameter to define the access scope of this method and, optionally,
109   // a Javadoc.
110   SourceWriter& BeginMethod(const Method& method, int modifiers,
111                             const Javadoc* javadoc = nullptr);
112 
113   // Ends the current method.
114   //
115   // This method ends the block of code that has begun when invoking
116   // BeginMethod() prior to this.
117   SourceWriter& EndMethod();
118 
119   // Begins to write the main type of a source file.
120   //
121   // This method outputs the declaration of the Java type from the data passed
122   // in the 'type' parameter and starts a new block. Modifiers are also passed
123   // in parameter to define the access scope of this type and, optionally,
124   // a Javadoc.
125   //
126   // If not null, all types found in the 'extra_dependencies' list will be
127   // imported before declaring the new type.
128   SourceWriter& BeginType(const Type& type, int modifiers,
129                           const std::list<Type>* extra_dependencies = nullptr,
130                           const Javadoc* javadoc = nullptr);
131 
132   // Begins to write a new inner type.
133   //
134   // This method outputs the declaration of the Java type from the data passed
135   // in the 'type' parameter and starts a new block. Modifiers are also passed
136   // in parameter to define the accesses and the scope of this type and,
137   // optionally, a Javadoc.
138   SourceWriter& BeginInnerType(const Type& type, int modifiers,
139                                const Javadoc* javadoc = nullptr);
140 
141   // Ends the current type.
142   //
143   // This method ends the block of code that has begun when invoking
144   // BeginType() or BeginInnerType() prior to this.
145   SourceWriter& EndType();
146 
147   // Writes a variable as fields of a type.
148   //
149   // This method must be called within the definition of a type (see BeginType()
150   // or BeginInnerType()). Modifiers are also be passed in parameter to define
151   // the accesses and the scope of this field and, optionally, a Javadoc.
152   SourceWriter& WriteField(const Variable& field, int modifiers,
153                            const Javadoc* javadoc = nullptr);
154 
155  protected:
156   virtual void DoAppend(const StringPiece& str) = 0;
157 
158  private:
159   // A utility base class for visiting elements of a type.
160   class TypeVisitor {
161    public:
162     virtual ~TypeVisitor() = default;
163     void Visit(const Type& type);
164 
165    protected:
166     virtual void DoVisit(const Type& type) = 0;
167   };
168 
169   // A utility class for keeping track of declared generics in a given scope.
170   class GenericNamespace : public TypeVisitor {
171    public:
172     GenericNamespace() = default;
GenericNamespace(const GenericNamespace * parent)173     explicit GenericNamespace(const GenericNamespace* parent)
174       : generic_names_(parent->generic_names_) {}
declared_types()175     std::list<const Type*> declared_types() {
176       return declared_types_;
177     }
178    protected:
179     virtual void DoVisit(const Type& type);
180 
181    private:
182     std::list<const Type*> declared_types_;
183     std::set<string> generic_names_;
184   };
185 
186   // A utility class for collecting a list of import statements to declare.
187   class TypeImporter : public TypeVisitor {
188    public:
TypeImporter(const string & current_package)189     explicit TypeImporter(const string& current_package)
190       : current_package_(current_package) {}
191     virtual ~TypeImporter() = default;
imports()192     const std::set<string> imports() {
193       return imports_;
194     }
195    protected:
196     virtual void DoVisit(const Type& type);
197 
198    private:
199     string current_package_;
200     std::set<string> imports_;
201   };
202 
203   string left_margin_;
204   string line_prefix_;
205   bool newline_ = true;
206   std::stack<GenericNamespace*> generic_namespaces_;
207 
208   SourceWriter& WriteModifiers(int modifiers);
209   SourceWriter& WriteJavadoc(const Javadoc& javadoc);
210   SourceWriter& WriteAnnotations(const std::list<Annotation>& annotations);
211   SourceWriter& WriteGenerics(const std::list<const Type*>& generics);
212   GenericNamespace* PushGenericNamespace(int modifiers);
213   void PopGenericNamespace();
214 };
215 
216 // A writer that outputs source code into a file.
217 //
218 // Note: the writer does not acquire the ownership of the file being passed in
219 // parameter.
220 class SourceFileWriter : public SourceWriter {
221  public:
SourceFileWriter(WritableFile * file)222   explicit SourceFileWriter(WritableFile* file) : file_(file) {}
223   virtual ~SourceFileWriter() = default;
224 
225  protected:
DoAppend(const StringPiece & str)226   void DoAppend(const StringPiece& str) override {
227     TF_CHECK_OK(file_->Append(str));
228   }
229 
230  private:
231   WritableFile* file_;
232 };
233 
234 // A writer that outputs source code into a string buffer.
235 class SourceBufferWriter : public SourceWriter {
236  public:
SourceBufferWriter()237   SourceBufferWriter() : owns_buffer_(true), buffer_(new string()) {}
SourceBufferWriter(string * buffer)238   explicit SourceBufferWriter(string* buffer)
239       : owns_buffer_(false), buffer_(buffer) {}
~SourceBufferWriter()240   virtual ~SourceBufferWriter() {
241     if (owns_buffer_) delete buffer_;
242   }
str()243   const string& str() { return *buffer_; }
244 
245  protected:
DoAppend(const StringPiece & str)246   void DoAppend(const StringPiece& str) override {
247     buffer_->append(str.begin(), str.end());
248   }
249 
250  private:
251   bool owns_buffer_;
252   string* buffer_;
253 };
254 
255 }  // namespace java
256 }  // namespace tensorflow
257 
258 #endif  // TENSORFLOW_JAVA_SRC_GEN_CC_SOURCE_WRITER_H_
259