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