slang_rs_reflection.h revision 6315f76e3cc6ff2d012d1183a0b030d4ff0dc808
1#ifndef _SLANG_COMPILER_RS_REFLECTION_H
2#define _SLANG_COMPILER_RS_REFLECTION_H
3
4#include <map>
5#include <vector>
6#include <string>
7#include <cassert>
8#include <fstream>
9#include <iostream>
10
11#include "llvm/ADT/StringExtras.h"
12
13#include "slang_rs_export_type.h"
14
15namespace slang {
16
17  class RSContext;
18  class RSExportVar;
19  class RSExportFunc;
20
21class RSReflection {
22 private:
23  const RSContext *mRSContext;
24
25  std::string mLastError;
26  inline void setError(const std::string &Error) { mLastError = Error; }
27
28  class Context {
29   private:
30    static const char *const ApacheLicenseNote;
31
32    static const char *const Import[];
33
34    bool mVerbose;
35
36    std::string mInputRSFile;
37
38    std::string mPackageName;
39    std::string mResourceId;
40
41    std::string mClassName;
42
43    std::string mLicenseNote;
44
45    std::string mIndent;
46
47    int mPaddingFieldIndex;
48
49    int mNextExportVarSlot;
50    int mNextExportFuncSlot;
51
52    // A mapping from a field in a record type to its index in the rsType
53    // instance. Only used when generates TypeClass (ScriptField_*).
54    typedef std::map<const RSExportRecordType::Field*, unsigned> FieldIndexMapTy;
55    FieldIndexMapTy mFieldIndexMap;
56    // Field index of current processing TypeClass.
57    unsigned mFieldIndex;
58
59    inline void clear() {
60      mClassName = "";
61      mIndent = "";
62      mPaddingFieldIndex = 1;
63      mNextExportVarSlot = 0;
64      mNextExportFuncSlot = 0;
65      return;
66    }
67
68   public:
69    typedef enum {
70      AM_Public,
71      AM_Protected,
72      AM_Private
73    } AccessModifier;
74
75    bool mUseStdout;
76    mutable std::ofstream mOF;
77
78    static const char *AccessModifierStr(AccessModifier AM);
79
80    Context(const std::string &InputRSFile,
81            const std::string &PackageName,
82            const std::string &ResourceId,
83            bool UseStdout)
84        : mVerbose(true),
85          mInputRSFile(InputRSFile),
86          mPackageName(PackageName),
87          mResourceId(ResourceId),
88          mLicenseNote(ApacheLicenseNote),
89          mUseStdout(UseStdout) {
90      clear();
91      return;
92    }
93
94    inline std::ostream &out() const {
95      return ((mUseStdout) ? std::cout : mOF);
96    }
97    inline std::ostream &indent() const {
98      out() << mIndent;
99      return out();
100    }
101
102    inline void incIndentLevel() {
103      mIndent.append(4, ' ');
104      return;
105    }
106
107    inline void decIndentLevel() {
108      assert(getIndentLevel() > 0 && "No indent");
109      mIndent.erase(0, 4);
110      return;
111    }
112
113    inline int getIndentLevel() {
114      return (mIndent.length() >> 2);
115    }
116
117    inline int getNextExportVarSlot() {
118      return mNextExportVarSlot++;
119    }
120
121    inline int getNextExportFuncSlot() {
122      return mNextExportFuncSlot++;
123    }
124
125    // Will remove later due to field name information is not necessary for
126    // C-reflect-to-Java
127    inline std::string createPaddingField() {
128      return "#padding_" + llvm::itostr(mPaddingFieldIndex++);
129    }
130
131    inline void setLicenseNote(const std::string &LicenseNote) {
132      mLicenseNote = LicenseNote;
133    }
134
135    bool startClass(AccessModifier AM,
136                    bool IsStatic,
137                    const std::string &ClassName,
138                    const char *SuperClassName,
139                    std::string &ErrorMsg);
140    void endClass();
141
142    void startFunction(AccessModifier AM,
143                       bool IsStatic,
144                       const char *ReturnType,
145                       const std::string &FunctionName,
146                       int Argc, ...);
147
148    typedef std::vector<std::pair<std::string, std::string> > ArgTy;
149    void startFunction(AccessModifier AM,
150                       bool IsStatic,
151                       const char *ReturnType,
152                       const std::string &FunctionName,
153                       const ArgTy &Args);
154    void endFunction();
155
156    void startBlock(bool ShouldIndent = false);
157    void endBlock();
158
159    inline const std::string &getPackageName() const { return mPackageName; }
160    inline const std::string &getClassName() const { return mClassName; }
161    inline const std::string &getResourceId() const { return mResourceId; }
162
163    void startTypeClass(const std::string &ClassName);
164    void endTypeClass();
165
166    inline void incFieldIndex() {
167      mFieldIndex++;
168    }
169
170    inline void resetFieldIndex() {
171      mFieldIndex = 0;
172    }
173
174    inline void addFieldIndexMapping(const RSExportRecordType::Field *F) {
175      assert((mFieldIndexMap.find(F) == mFieldIndexMap.end()) &&
176             "Nested structure never occurs in C language.");
177      mFieldIndexMap.insert(std::make_pair(F, mFieldIndex));
178    }
179
180    inline unsigned getFieldIndex(const RSExportRecordType::Field *F) const {
181      FieldIndexMapTy::const_iterator I = mFieldIndexMap.find(F);
182      assert((I != mFieldIndexMap.end()) &&
183             "Requesting field is out of scope.");
184      return I->second;
185    }
186
187    inline void clearFieldIndexMap() {
188      mFieldIndexMap.clear();
189    }
190  };
191
192  bool openScriptFile(Context &C,
193                      const std::string &ClassName,
194                      std::string &ErrorMsg);
195  bool genScriptClass(Context &C,
196                      const std::string &ClassName,
197                      std::string &ErrorMsg);
198  void genScriptClassConstructor(Context &C);
199
200  void genInitBoolExportVariable(Context &C,
201                                 const std::string &VarName,
202                                 const clang::APValue &Val);
203  void genInitPrimitiveExportVariable(Context &C,
204                                      const std::string &VarName,
205                                      const clang::APValue &Val);
206  void genInitExportVariable(Context &C,
207                             const RSExportType *ET,
208                             const std::string &VarName,
209                             const clang::APValue &Val);
210  void genExportVariable(Context &C, const RSExportVar *EV);
211  void genPrimitiveTypeExportVariable(Context &C, const RSExportVar *EV);
212  void genPointerTypeExportVariable(Context &C, const RSExportVar *EV);
213  void genVectorTypeExportVariable(Context &C, const RSExportVar *EV);
214  void genRecordTypeExportVariable(Context &C, const RSExportVar *EV);
215  void genGetExportVariable(Context &C,
216                            const std::string &TypeName,
217                            const std::string &VarName);
218
219  void genExportFunction(Context &C,
220                         const RSExportFunc *EF);
221
222  bool genTypeClass(Context &C,
223                    const RSExportRecordType *ERT,
224                    std::string &ErrorMsg);
225  bool genTypeItemClass(Context &C,
226                        const RSExportRecordType *ERT,
227                        std::string &ErrorMsg);
228  void genTypeClassConstructor(Context &C,
229                               const RSExportRecordType *ERT);
230  void genTypeClassCopyToArray(Context &C,
231                               const RSExportRecordType *ERT);
232  void genTypeClassItemSetter(Context &C,
233                              const RSExportRecordType *ERT);
234  void genTypeClassItemGetter(Context &C, const RSExportRecordType *ERT);
235  void genTypeClassComponentSetter(Context &C, const RSExportRecordType *ERT);
236  void genTypeClassComponentGetter(Context &C, const RSExportRecordType *ERT);
237  void genTypeClassCopyAll(Context &C, const RSExportRecordType *ERT);
238
239  void genBuildElement(Context &C,
240                       const RSExportRecordType *ERT,
241                       const char *RenderScriptVar);
242  void genAddElementToElementBuilder(Context &C,
243                                     const RSExportType *ERT,
244                                     const std::string &VarName,
245                                     const char *ElementBuilderName,
246                                     const char *RenderScriptVar);
247  void genAddPaddingToElementBuiler(Context &C,
248                                    int PaddingSize,
249                                    const char *ElementBuilderName,
250                                    const char *RenderScriptVar);
251
252  bool genCreateFieldPacker(Context &C,
253                            const RSExportType *T,
254                            const char *FieldPackerName);
255  void genPackVarOfType(Context &C,
256                        const RSExportType *T,
257                        const char *VarName,
258                        const char *FieldPackerName);
259  void genNewItemBufferIfNull(Context &C, const char *Index);
260  void genNewItemBufferPackerIfNull(Context &C);
261
262 public:
263  explicit RSReflection(const RSContext *Context)
264      : mRSContext(Context),
265        mLastError("") {
266    return;
267  }
268
269  bool reflect(const char *OutputPackageName,
270               const std::string &InputFileName,
271               const std::string &OutputBCFileName);
272
273  inline const char *getLastError() const {
274    if (mLastError.empty())
275      return NULL;
276    else
277      return mLastError.c_str();
278  }
279};  // class RSReflection
280
281}   // namespace slang
282
283#endif  // _SLANG_COMPILER_RS_REFLECTION_H
284