slang_rs_reflection.h revision 66aa299de2b5e0b0c7bfae7628e29a3961247aed
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      resetFieldIndex();
92      clearFieldIndexMap();
93      return;
94    }
95
96    inline std::ostream &out() const {
97      return ((mUseStdout) ? std::cout : mOF);
98    }
99    inline std::ostream &indent() const {
100      out() << mIndent;
101      return out();
102    }
103
104    inline void incIndentLevel() {
105      mIndent.append(4, ' ');
106      return;
107    }
108
109    inline void decIndentLevel() {
110      assert(getIndentLevel() > 0 && "No indent");
111      mIndent.erase(0, 4);
112      return;
113    }
114
115    inline int getIndentLevel() {
116      return (mIndent.length() >> 2);
117    }
118
119    inline int getNextExportVarSlot() {
120      return mNextExportVarSlot++;
121    }
122
123    inline int getNextExportFuncSlot() {
124      return mNextExportFuncSlot++;
125    }
126
127    // Will remove later due to field name information is not necessary for
128    // C-reflect-to-Java
129    inline std::string createPaddingField() {
130      return "#padding_" + llvm::itostr(mPaddingFieldIndex++);
131    }
132
133    inline void setLicenseNote(const std::string &LicenseNote) {
134      mLicenseNote = LicenseNote;
135    }
136
137    bool startClass(AccessModifier AM,
138                    bool IsStatic,
139                    const std::string &ClassName,
140                    const char *SuperClassName,
141                    std::string &ErrorMsg);
142    void endClass();
143
144    void startFunction(AccessModifier AM,
145                       bool IsStatic,
146                       const char *ReturnType,
147                       const std::string &FunctionName,
148                       int Argc, ...);
149
150    typedef std::vector<std::pair<std::string, std::string> > ArgTy;
151    void startFunction(AccessModifier AM,
152                       bool IsStatic,
153                       const char *ReturnType,
154                       const std::string &FunctionName,
155                       const ArgTy &Args);
156    void endFunction();
157
158    void startBlock(bool ShouldIndent = false);
159    void endBlock();
160
161    inline const std::string &getPackageName() const { return mPackageName; }
162    inline const std::string &getClassName() const { return mClassName; }
163    inline const std::string &getResourceId() const { return mResourceId; }
164
165    void startTypeClass(const std::string &ClassName);
166    void endTypeClass();
167
168    inline void incFieldIndex() {
169      mFieldIndex++;
170    }
171
172    inline void resetFieldIndex() {
173      mFieldIndex = 0;
174    }
175
176    inline void addFieldIndexMapping(const RSExportRecordType::Field *F) {
177      assert((mFieldIndexMap.find(F) == mFieldIndexMap.end()) &&
178             "Nested structure never occurs in C language.");
179      mFieldIndexMap.insert(std::make_pair(F, mFieldIndex));
180    }
181
182    inline unsigned getFieldIndex(const RSExportRecordType::Field *F) const {
183      FieldIndexMapTy::const_iterator I = mFieldIndexMap.find(F);
184      assert((I != mFieldIndexMap.end()) &&
185             "Requesting field is out of scope.");
186      return I->second;
187    }
188
189    inline void clearFieldIndexMap() {
190      mFieldIndexMap.clear();
191    }
192  };
193
194  bool openScriptFile(Context &C,
195                      const std::string &ClassName,
196                      std::string &ErrorMsg);
197  bool genScriptClass(Context &C,
198                      const std::string &ClassName,
199                      std::string &ErrorMsg);
200  void genScriptClassConstructor(Context &C);
201
202  void genInitBoolExportVariable(Context &C,
203                                 const std::string &VarName,
204                                 const clang::APValue &Val);
205  void genInitPrimitiveExportVariable(Context &C,
206                                      const std::string &VarName,
207                                      const clang::APValue &Val);
208  void genInitExportVariable(Context &C,
209                             const RSExportType *ET,
210                             const std::string &VarName,
211                             const clang::APValue &Val);
212  void genExportVariable(Context &C, const RSExportVar *EV);
213  void genPrimitiveTypeExportVariable(Context &C, const RSExportVar *EV);
214  void genPointerTypeExportVariable(Context &C, const RSExportVar *EV);
215  void genVectorTypeExportVariable(Context &C, const RSExportVar *EV);
216  void genRecordTypeExportVariable(Context &C, const RSExportVar *EV);
217  void genGetExportVariable(Context &C,
218                            const std::string &TypeName,
219                            const std::string &VarName);
220
221  void genExportFunction(Context &C,
222                         const RSExportFunc *EF);
223
224  bool genTypeClass(Context &C,
225                    const RSExportRecordType *ERT,
226                    std::string &ErrorMsg);
227  bool genTypeItemClass(Context &C,
228                        const RSExportRecordType *ERT,
229                        std::string &ErrorMsg);
230  void genTypeClassConstructor(Context &C,
231                               const RSExportRecordType *ERT);
232  void genTypeClassCopyToArray(Context &C,
233                               const RSExportRecordType *ERT);
234  void genTypeClassItemSetter(Context &C,
235                              const RSExportRecordType *ERT);
236  void genTypeClassItemGetter(Context &C, const RSExportRecordType *ERT);
237  void genTypeClassComponentSetter(Context &C, const RSExportRecordType *ERT);
238  void genTypeClassComponentGetter(Context &C, const RSExportRecordType *ERT);
239  void genTypeClassCopyAll(Context &C, const RSExportRecordType *ERT);
240
241  void genBuildElement(Context &C,
242                       const RSExportRecordType *ERT,
243                       const char *RenderScriptVar);
244  void genAddElementToElementBuilder(Context &C,
245                                     const RSExportType *ERT,
246                                     const std::string &VarName,
247                                     const char *ElementBuilderName,
248                                     const char *RenderScriptVar);
249  void genAddPaddingToElementBuiler(Context &C,
250                                    int PaddingSize,
251                                    const char *ElementBuilderName,
252                                    const char *RenderScriptVar);
253
254  bool genCreateFieldPacker(Context &C,
255                            const RSExportType *T,
256                            const char *FieldPackerName);
257  void genPackVarOfType(Context &C,
258                        const RSExportType *T,
259                        const char *VarName,
260                        const char *FieldPackerName);
261  void genNewItemBufferIfNull(Context &C, const char *Index);
262  void genNewItemBufferPackerIfNull(Context &C);
263
264 public:
265  explicit RSReflection(const RSContext *Context)
266      : mRSContext(Context),
267        mLastError("") {
268    return;
269  }
270
271  bool reflect(const char *OutputPackageName,
272               const std::string &InputFileName,
273               const std::string &OutputBCFileName);
274
275  inline const char *getLastError() const {
276    if (mLastError.empty())
277      return NULL;
278    else
279      return mLastError.c_str();
280  }
281};  // class RSReflection
282
283}   // namespace slang
284
285#endif  // _SLANG_COMPILER_RS_REFLECTION_H
286