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