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