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, size_t offset) 192 : fOffset(SkToU16(offset)), fOpStackDepth(depth), fOperator(op) 193 , fPrimed(kIsNotPrimed), fDone(kIsNotDone) { 194 } 195 196 enum Primed { 197 kIsNotPrimed, 198 kIsPrimed 199 }; 200 201 enum Done { 202 kIsNotDone, 203 kIsDone, 204 }; 205 206 unsigned fOffset : 16; // offset in generated stream where branch needs to go 207 int fOpStackDepth : 7; // depth when operator was found 208 Op fOperator : 6; // operand which generated branch 209 mutable Primed fPrimed : 1; // mark when next instruction generates branch 210 Done fDone : 1; // mark when branch is complete primeBranch211 void prime() { fPrimed = kIsPrimed; } 212 void resolve(SkDynamicMemoryWStream* , size_t offset); 213 }; 214 215 static const OperatorAttributes gOpAttributes[]; 216 static const signed char gPrecedence[]; 217 static const TypeOp gTokens[]; 218 void addToken(TypeOp ); 219 void addTokenConst(SkScriptValue2* , AddTokenRegister , SkOperand2::OpType , TypeOp ); 220 void addTokenInt(int ); 221 void addTokenScalar(SkScalar ); 222 void addTokenString(const SkString& ); 223 void addTokenValue(const SkScriptValue2& , AddTokenRegister ); 224 int arithmeticOp(char ch, char nextChar, bool lastPush); 225 bool convertParams(SkTDArray<SkScriptValue2>* , 226 const SkOperand2::OpType* paramTypes, int paramTypeCount); convertToString(SkOperand2 * operand,SkOperand2::OpType type)227 void convertToString(SkOperand2* operand, SkOperand2::OpType type) { 228 SkScriptValue2 scriptValue; 229 scriptValue.fOperand = *operand; 230 scriptValue.fType = type; 231 convertTo(SkOperand2::kString, &scriptValue); 232 *operand = scriptValue.fOperand; 233 } 234 bool evaluateDot(const char*& script); 235 bool evaluateDotParam(const char*& script, const char* field, size_t fieldLength); 236 bool functionParams(const char** scriptPtr, SkTDArray<SkScriptValue2>* params); 237 size_t getTokenOffset(); 238 SkOperand2::OpType getUnboxType(SkOperand2 scriptValue); 239 bool handleArrayIndexer(const char** scriptPtr); 240 bool handleFunction(const char** scriptPtr); 241 bool handleMember(const char* field, size_t len, void* object); 242 bool handleMemberFunction(const char* field, size_t len, void* object, 243 SkTDArray<SkScriptValue2>* params); 244 bool handleProperty(); 245 bool handleUnbox(SkScriptValue2* scriptValue); 246 bool innerScript(const char** scriptPtr, SkScriptValue2* value); 247 int logicalOp(char ch, char nextChar); 248 void processLogicalOp(Op op); 249 bool processOp(); 250 void resolveBranch(Branch& ); 251 // void setAnimateMaker(SkAnimateMaker* maker) { fMaker = maker; } 252 SkDynamicMemoryWStream fStream; 253 SkDynamicMemoryWStream* fActiveStream; 254 SkTDStack<BraceStyle> fBraceStack; // curly, square, function paren 255 SkTDStack<Branch> fBranchStack; // logical operators, slot to store forward branch 256 SkLongArray(SkScriptCallBack*) fCallBackArray; 257 SkTDStack<Op> fOpStack; 258 SkTDStack<SkScriptValue2> fValueStack; 259 // SkAnimateMaker* fMaker; 260 SkLongArray(SkOpArray*) fTrackArray; 261 SkTDStringArray fTrackString; 262 const char* fToken; // one-deep stack 263 size_t fTokenLength; 264 SkOperand2::OpType fReturnType; 265 Error fError; 266 SkOperand2::OpType fAccumulatorType; // tracking for code generation 267 SkBool fBranchPopAllowed; 268 SkBool fConstExpression; 269 SkBool fOperandInUse; 270 private: 271 #ifdef SK_DEBUG 272 public: 273 void decompile(const unsigned char* , size_t ); 274 static void UnitTest(); 275 static void ValidateDecompileTable(); 276 #endif 277 }; 278 279 #ifdef SK_DEBUG 280 281 struct SkScriptNAnswer2 { 282 const char* fScript; 283 SkOperand2::OpType fType; 284 int32_t fIntAnswer; 285 SkScalar fScalarAnswer; 286 const char* fStringAnswer; 287 }; 288 289 #endif 290 291 292 #endif // SkScript2_DEFINED 293