1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 #ifndef SkScript2_DEFINED 9 #define SkScript2_DEFINED 10 11 #include "SkOperand2.h" 12 #include "SkStream.h" 13 #include "SkTDArray.h" 14 #include "SkTDArray_Experimental.h" 15 #include "SkTDict.h" 16 #include "SkTDStack.h" 17 18 typedef SkLongArray(SkString*) SkTDStringArray; 19 20 class SkAnimateMaker; 21 class SkScriptCallBack; 22 23 class SkScriptEngine2 { 24 public: 25 enum Error { 26 kNoError, 27 kArrayIndexOutOfBounds, 28 kCouldNotFindReferencedID, 29 kFunctionCallFailed, 30 kMemberOpFailed, 31 kPropertyOpFailed 32 }; 33 34 enum Attrs { 35 kConstant, 36 kVariable 37 }; 38 39 SkScriptEngine2(SkOperand2::OpType returnType); 40 ~SkScriptEngine2(); 41 bool convertTo(SkOperand2::OpType , SkScriptValue2* ); 42 bool evaluateScript(const char** script, SkScriptValue2* value); 43 void forget(SkOpArray* array); getError()44 Error getError() { return fError; } getReturnType()45 SkOperand2::OpType getReturnType() { return fReturnType; } track(SkOpArray * array)46 void track(SkOpArray* array) { 47 SkASSERT(fTrackArray.find(array) < 0); 48 *fTrackArray.append() = array; } track(SkString * string)49 void track(SkString* string) { 50 SkASSERT(fTrackString.find(string) < 0); 51 *fTrackString.append() = string; 52 } 53 static bool ConvertTo(SkScriptEngine2* , SkOperand2::OpType toType, SkScriptValue2* value); 54 static SkScalar IntToScalar(int32_t ); 55 static bool ValueToString(const SkScriptValue2& value, SkString* string); 56 57 enum Op { // used by tokenizer attribute table 58 kUnassigned, 59 kAdd, 60 kBitAnd, 61 kBitNot, 62 kBitOr, 63 kDivide, 64 kEqual, 65 kFlipOps, 66 kGreaterEqual, 67 kLogicalAnd, 68 kLogicalNot, 69 kLogicalOr, 70 kMinus, 71 kModulo, 72 kMultiply, 73 kShiftLeft, 74 kShiftRight, // signed 75 kSubtract, 76 kXor, 77 // following not in attribute table 78 kArrayOp, 79 kElse, 80 kIf, 81 kParen, 82 kLastLogicalOp, 83 kArtificialOp = 0x20 84 }; 85 86 enum TypeOp { // generated by tokenizer 87 kNop, // should never get generated 88 kAccumulatorPop, 89 kAccumulatorPush, 90 kAddInt, 91 kAddScalar, 92 kAddString, // string concat 93 kArrayIndex, 94 kArrayParam, 95 kArrayToken, 96 kBitAndInt, 97 kBitNotInt, 98 kBitOrInt, 99 kBoxToken, 100 kCallback, 101 kDivideInt, 102 kDivideScalar, 103 kDotOperator, 104 kElseOp, 105 kEnd, 106 kEqualInt, 107 kEqualScalar, 108 kEqualString, 109 kFunctionCall, 110 kFlipOpsOp, 111 kFunctionToken, 112 kGreaterEqualInt, 113 kGreaterEqualScalar, 114 kGreaterEqualString, 115 kIfOp, 116 kIntToScalar, 117 kIntToScalar2, 118 kIntToString, 119 kIntToString2, 120 kIntegerAccumulator, 121 kIntegerOperand, 122 kLogicalAndInt, 123 kLogicalNotInt, 124 kLogicalOrInt, 125 kMemberOp, 126 kMinusInt, 127 kMinusScalar, 128 kModuloInt, 129 kModuloScalar, 130 kMultiplyInt, 131 kMultiplyScalar, 132 kPropertyOp, 133 kScalarAccumulator, 134 kScalarOperand, 135 kScalarToInt, 136 kScalarToInt2, 137 kScalarToString, 138 kScalarToString2, 139 kShiftLeftInt, 140 kShiftRightInt, // signed 141 kStringAccumulator, 142 kStringOperand, 143 kStringToInt, 144 kStringToScalar, 145 kStringToScalar2, 146 kStringTrack, 147 kSubtractInt, 148 kSubtractScalar, 149 kToBool, 150 kUnboxToken, 151 kUnboxToken2, 152 kXorInt, 153 kLastTypeOp 154 }; 155 156 enum OpBias { 157 kNoBias, 158 kTowardsNumber = 0, 159 kTowardsString 160 }; 161 162 protected: 163 164 enum BraceStyle { 165 // kStructBrace, 166 kArrayBrace, 167 kFunctionBrace 168 }; 169 170 enum AddTokenRegister { 171 kAccumulator, 172 kOperand 173 }; 174 175 enum ResultIsBoolean { 176 kResultIsNotBoolean, 177 kResultIsBoolean 178 }; 179 180 struct OperatorAttributes { 181 unsigned int fLeftType : 3; // SkOpType union, but only lower values 182 unsigned int fRightType : 3; // SkOpType union, but only lower values 183 OpBias fBias : 1; 184 ResultIsBoolean fResultIsBoolean : 1; 185 }; 186 187 struct Branch { BranchBranch188 Branch() { 189 } 190 BranchBranch191 Branch(Op op, int depth, unsigned offset) : fOffset(offset), fOpStackDepth(depth), fOperator(op), 192 fPrimed(kIsNotPrimed), fDone(kIsNotDone) { 193 } 194 195 enum Primed { 196 kIsNotPrimed, 197 kIsPrimed 198 }; 199 200 enum Done { 201 kIsNotDone, 202 kIsDone, 203 }; 204 205 unsigned fOffset : 16; // offset in generated stream where branch needs to go 206 int fOpStackDepth : 7; // depth when operator was found 207 Op fOperator : 6; // operand which generated branch 208 mutable Primed fPrimed : 1; // mark when next instruction generates branch 209 Done fDone : 1; // mark when branch is complete primeBranch210 void prime() { fPrimed = kIsPrimed; } 211 void resolve(SkDynamicMemoryWStream* , size_t offset); 212 }; 213 214 static const OperatorAttributes gOpAttributes[]; 215 static const signed char gPrecedence[]; 216 static const TypeOp gTokens[]; 217 void addToken(TypeOp ); 218 void addTokenConst(SkScriptValue2* , AddTokenRegister , SkOperand2::OpType , TypeOp ); 219 void addTokenInt(int ); 220 void addTokenScalar(SkScalar ); 221 void addTokenString(const SkString& ); 222 void addTokenValue(const SkScriptValue2& , AddTokenRegister ); 223 int arithmeticOp(char ch, char nextChar, bool lastPush); 224 bool convertParams(SkTDArray<SkScriptValue2>* , 225 const SkOperand2::OpType* paramTypes, int paramTypeCount); convertToString(SkOperand2 * operand,SkOperand2::OpType type)226 void convertToString(SkOperand2* operand, SkOperand2::OpType type) { 227 SkScriptValue2 scriptValue; 228 scriptValue.fOperand = *operand; 229 scriptValue.fType = type; 230 convertTo(SkOperand2::kString, &scriptValue); 231 *operand = scriptValue.fOperand; 232 } 233 bool evaluateDot(const char*& script); 234 bool evaluateDotParam(const char*& script, const char* field, size_t fieldLength); 235 bool functionParams(const char** scriptPtr, SkTDArray<SkScriptValue2>* params); 236 size_t getTokenOffset(); 237 SkOperand2::OpType getUnboxType(SkOperand2 scriptValue); 238 bool handleArrayIndexer(const char** scriptPtr); 239 bool handleFunction(const char** scriptPtr); 240 bool handleMember(const char* field, size_t len, void* object); 241 bool handleMemberFunction(const char* field, size_t len, void* object, 242 SkTDArray<SkScriptValue2>* params); 243 bool handleProperty(); 244 bool handleUnbox(SkScriptValue2* scriptValue); 245 bool innerScript(const char** scriptPtr, SkScriptValue2* value); 246 int logicalOp(char ch, char nextChar); 247 void processLogicalOp(Op op); 248 bool processOp(); 249 void resolveBranch(Branch& ); 250 // void setAnimateMaker(SkAnimateMaker* maker) { fMaker = maker; } 251 SkDynamicMemoryWStream fStream; 252 SkDynamicMemoryWStream* fActiveStream; 253 SkTDStack<BraceStyle> fBraceStack; // curly, square, function paren 254 SkTDStack<Branch> fBranchStack; // logical operators, slot to store forward branch 255 SkLongArray(SkScriptCallBack*) fCallBackArray; 256 SkTDStack<Op> fOpStack; 257 SkTDStack<SkScriptValue2> fValueStack; 258 // SkAnimateMaker* fMaker; 259 SkLongArray(SkOpArray*) fTrackArray; 260 SkTDStringArray fTrackString; 261 const char* fToken; // one-deep stack 262 size_t fTokenLength; 263 SkOperand2::OpType fReturnType; 264 Error fError; 265 SkOperand2::OpType fAccumulatorType; // tracking for code generation 266 SkBool fBranchPopAllowed; 267 SkBool fConstExpression; 268 SkBool fOperandInUse; 269 private: 270 #ifdef SK_DEBUG 271 public: 272 void decompile(const unsigned char* , size_t ); 273 static void UnitTest(); 274 static void ValidateDecompileTable(); 275 #endif 276 }; 277 278 #ifdef SK_DEBUG 279 280 struct SkScriptNAnswer2 { 281 const char* fScript; 282 SkOperand2::OpType fType; 283 int32_t fIntAnswer; 284 SkScalar fScalarAnswer; 285 const char* fStringAnswer; 286 }; 287 288 #endif 289 290 291 #endif // SkScript2_DEFINED 292 293