1 #include "SkScriptRuntime.h" 2 #include "SkScript2.h" 3 #include "SkParse.h" 4 #include "SkScriptCallBack.h" 5 #include "SkString.h" 6 #include "SkOpArray.h" 7 8 // script tokenizer 9 10 // turn text into token string 11 // turn number literals into inline UTF8-style values 12 // process operators to turn standard notation into stack notation 13 14 // defer processing until the tokens can all be resolved 15 // then, turn token strings into indices into the appropriate tables / dictionaries 16 17 // consider: const evaluation? 18 19 // replace script string with script tokens preceeded by special value 20 21 // need second version of script plugins that return private index of found value? 22 // then would need in script index of plugin, private index 23 24 // encode brace stack push/pop as opcodes 25 26 // should token script enocde type where possible? 27 28 // current flow: 29 // strip whitespace 30 // if in array brace [ recurse, continue 31 // if token, handle function, or array, or property (continue) 32 // parse number, continue 33 // parse token, continue 34 // parse string literal, continue 35 // if dot operator, handle dot, continue 36 // if [ , handle array literal or accessor, continue 37 // if ), pop (if function, break) 38 // if ], pop ; if ',' break 39 // handle logical ops 40 // or, handle arithmetic ops 41 // loop 42 43 // !!! things to do 44 // add separate processing loop to advance while suppressed 45 // or, include jump offset to skip suppressed code? 46 47 SkScriptRuntime::~SkScriptRuntime() { 48 for (SkString** stringPtr = fTrackString.begin(); stringPtr < fTrackString.end(); stringPtr++) 49 delete *stringPtr; 50 for (SkOpArray** arrayPtr = fTrackArray.begin(); arrayPtr < fTrackArray.end(); arrayPtr++) 51 delete *arrayPtr; 52 } 53 54 bool SkScriptRuntime::executeTokens(unsigned char* opCode) { 55 SkOperand2 operand[2]; // 1=accumulator and 2=operand 56 SkScriptEngine2::TypeOp op; 57 size_t ref; 58 int index, size; 59 int registerLoad; 60 SkScriptCallBack* callBack SK_INIT_TO_AVOID_WARNING; 61 do { 62 switch ((op = (SkScriptEngine2::TypeOp) *opCode++)) { 63 case SkScriptEngine2::kArrayToken: // create an array 64 operand[0].fArray = new SkOpArray(SkOperand2::kNoType /*fReturnType*/); 65 break; 66 case SkScriptEngine2::kArrayIndex: // array accessor 67 index = operand[1].fS32; 68 if (index >= operand[0].fArray->count()) { 69 fError = kArrayIndexOutOfBounds; 70 return false; 71 } 72 operand[0] = operand[0].fArray->begin()[index]; 73 break; 74 case SkScriptEngine2::kArrayParam: // array initializer, or function param 75 *operand[0].fArray->append() = operand[1]; 76 break; 77 case SkScriptEngine2::kCallback: 78 memcpy(&index, opCode, sizeof(index)); 79 opCode += sizeof(index); 80 callBack = fCallBackArray[index]; 81 break; 82 case SkScriptEngine2::kFunctionCall: { 83 memcpy(&ref, opCode, sizeof(ref)); 84 opCode += sizeof(ref); 85 SkScriptCallBackFunction* callBackFunction = (SkScriptCallBackFunction*) callBack; 86 if (callBackFunction->invoke(ref, operand[0].fArray, /* params */ 87 &operand[0] /* result */) == false) { 88 fError = kFunctionCallFailed; 89 return false; 90 } 91 } break; 92 case SkScriptEngine2::kMemberOp: { 93 memcpy(&ref, opCode, sizeof(ref)); 94 opCode += sizeof(ref); 95 SkScriptCallBackMember* callBackMember = (SkScriptCallBackMember*) callBack; 96 if (callBackMember->invoke(ref, operand[0].fObject, &operand[0]) == false) { 97 fError = kMemberOpFailed; 98 return false; 99 } 100 } break; 101 case SkScriptEngine2::kPropertyOp: { 102 memcpy(&ref, opCode, sizeof(ref)); 103 opCode += sizeof(ref); 104 SkScriptCallBackProperty* callBackProperty = (SkScriptCallBackProperty*) callBack; 105 if (callBackProperty->getResult(ref, &operand[0])== false) { 106 fError = kPropertyOpFailed; 107 return false; 108 } 109 } break; 110 case SkScriptEngine2::kAccumulatorPop: 111 fRunStack.pop(&operand[0]); 112 break; 113 case SkScriptEngine2::kAccumulatorPush: 114 *fRunStack.push() = operand[0]; 115 break; 116 case SkScriptEngine2::kIntegerAccumulator: 117 case SkScriptEngine2::kIntegerOperand: 118 registerLoad = op - SkScriptEngine2::kIntegerAccumulator; 119 memcpy(&operand[registerLoad].fS32, opCode, sizeof(int32_t)); 120 opCode += sizeof(int32_t); 121 break; 122 case SkScriptEngine2::kScalarAccumulator: 123 case SkScriptEngine2::kScalarOperand: 124 registerLoad = op - SkScriptEngine2::kScalarAccumulator; 125 memcpy(&operand[registerLoad].fScalar, opCode, sizeof(SkScalar)); 126 opCode += sizeof(SkScalar); 127 break; 128 case SkScriptEngine2::kStringAccumulator: 129 case SkScriptEngine2::kStringOperand: { 130 SkString* strPtr = new SkString(); 131 track(strPtr); 132 registerLoad = op - SkScriptEngine2::kStringAccumulator; 133 memcpy(&size, opCode, sizeof(size)); 134 opCode += sizeof(size); 135 strPtr->set((char*) opCode, size); 136 opCode += size; 137 operand[registerLoad].fString = strPtr; 138 } break; 139 case SkScriptEngine2::kStringTrack: // call after kObjectToValue 140 track(operand[0].fString); 141 break; 142 case SkScriptEngine2::kBoxToken: { 143 SkOperand2::OpType type; 144 memcpy(&type, opCode, sizeof(type)); 145 opCode += sizeof(type); 146 SkScriptCallBackConvert* callBackBox = (SkScriptCallBackConvert*) callBack; 147 if (callBackBox->convert(type, &operand[0]) == false) 148 return false; 149 } break; 150 case SkScriptEngine2::kUnboxToken: 151 case SkScriptEngine2::kUnboxToken2: { 152 SkScriptCallBackConvert* callBackUnbox = (SkScriptCallBackConvert*) callBack; 153 if (callBackUnbox->convert(SkOperand2::kObject, &operand[0]) == false) 154 return false; 155 } break; 156 case SkScriptEngine2::kIfOp: 157 case SkScriptEngine2::kLogicalAndInt: 158 memcpy(&size, opCode, sizeof(size)); 159 opCode += sizeof(size); 160 if (operand[0].fS32 == 0) 161 opCode += size; // skip to else (or end of if predicate) 162 break; 163 case SkScriptEngine2::kElseOp: 164 memcpy(&size, opCode, sizeof(size)); 165 opCode += sizeof(size); 166 opCode += size; // if true: after predicate, always skip to end of else 167 break; 168 case SkScriptEngine2::kLogicalOrInt: 169 memcpy(&size, opCode, sizeof(size)); 170 opCode += sizeof(size); 171 if (operand[0].fS32 != 0) 172 opCode += size; // skip to kToBool opcode after || predicate 173 break; 174 // arithmetic conversion ops 175 case SkScriptEngine2::kFlipOpsOp: 176 SkTSwap(operand[0], operand[1]); 177 break; 178 case SkScriptEngine2::kIntToString: 179 case SkScriptEngine2::kIntToString2: 180 case SkScriptEngine2::kScalarToString: 181 case SkScriptEngine2::kScalarToString2:{ 182 SkString* strPtr = new SkString(); 183 track(strPtr); 184 if (op == SkScriptEngine2::kIntToString || op == SkScriptEngine2::kIntToString2) 185 strPtr->appendS32(operand[op - SkScriptEngine2::kIntToString].fS32); 186 else 187 strPtr->appendScalar(operand[op - SkScriptEngine2::kScalarToString].fScalar); 188 operand[0].fString = strPtr; 189 } break; 190 case SkScriptEngine2::kIntToScalar: 191 case SkScriptEngine2::kIntToScalar2: 192 operand[0].fScalar = SkScriptEngine2::IntToScalar(operand[op - SkScriptEngine2::kIntToScalar].fS32); 193 break; 194 case SkScriptEngine2::kStringToInt: 195 if (SkParse::FindS32(operand[0].fString->c_str(), &operand[0].fS32) == false) 196 return false; 197 break; 198 case SkScriptEngine2::kStringToScalar: 199 case SkScriptEngine2::kStringToScalar2: 200 if (SkParse::FindScalar(operand[0].fString->c_str(), 201 &operand[op - SkScriptEngine2::kStringToScalar].fScalar) == false) 202 return false; 203 break; 204 case SkScriptEngine2::kScalarToInt: 205 operand[0].fS32 = SkScalarFloor(operand[0].fScalar); 206 break; 207 // arithmetic ops 208 case SkScriptEngine2::kAddInt: 209 operand[0].fS32 += operand[1].fS32; 210 break; 211 case SkScriptEngine2::kAddScalar: 212 operand[0].fScalar += operand[1].fScalar; 213 break; 214 case SkScriptEngine2::kAddString: 215 // if (fTrackString.find(operand[1].fString) < 0) { 216 // operand[1].fString = SkNEW_ARGS(SkString, (*operand[1].fString)); 217 // track(operand[1].fString); 218 // } 219 operand[0].fString->append(*operand[1].fString); 220 break; 221 case SkScriptEngine2::kBitAndInt: 222 operand[0].fS32 &= operand[1].fS32; 223 break; 224 case SkScriptEngine2::kBitNotInt: 225 operand[0].fS32 = ~operand[0].fS32; 226 break; 227 case SkScriptEngine2::kBitOrInt: 228 operand[0].fS32 |= operand[1].fS32; 229 break; 230 case SkScriptEngine2::kDivideInt: 231 SkASSERT(operand[1].fS32 != 0); 232 if (operand[1].fS32 == 0) 233 operand[0].fS32 = operand[0].fS32 == 0 ? SK_NaN32 : 234 operand[0].fS32 > 0 ? SK_MaxS32 : -SK_MaxS32; 235 else 236 if (operand[1].fS32 != 0) // throw error on divide by zero? 237 operand[0].fS32 /= operand[1].fS32; 238 break; 239 case SkScriptEngine2::kDivideScalar: 240 if (operand[1].fScalar == 0) 241 operand[0].fScalar = operand[0].fScalar == 0 ? SK_ScalarNaN : 242 operand[0].fScalar > 0 ? SK_ScalarMax : -SK_ScalarMax; 243 else 244 operand[0].fScalar = SkScalarDiv(operand[0].fScalar, operand[1].fScalar); 245 break; 246 case SkScriptEngine2::kEqualInt: 247 operand[0].fS32 = operand[0].fS32 == operand[1].fS32; 248 break; 249 case SkScriptEngine2::kEqualScalar: 250 operand[0].fS32 = operand[0].fScalar == operand[1].fScalar; 251 break; 252 case SkScriptEngine2::kEqualString: 253 operand[0].fS32 = *operand[0].fString == *operand[1].fString; 254 break; 255 case SkScriptEngine2::kGreaterEqualInt: 256 operand[0].fS32 = operand[0].fS32 >= operand[1].fS32; 257 break; 258 case SkScriptEngine2::kGreaterEqualScalar: 259 operand[0].fS32 = operand[0].fScalar >= operand[1].fScalar; 260 break; 261 case SkScriptEngine2::kGreaterEqualString: 262 operand[0].fS32 = strcmp(operand[0].fString->c_str(), operand[1].fString->c_str()) >= 0; 263 break; 264 case SkScriptEngine2::kToBool: 265 operand[0].fS32 = !! operand[0].fS32; 266 break; 267 case SkScriptEngine2::kLogicalNotInt: 268 operand[0].fS32 = ! operand[0].fS32; 269 break; 270 case SkScriptEngine2::kMinusInt: 271 operand[0].fS32 = -operand[0].fS32; 272 break; 273 case SkScriptEngine2::kMinusScalar: 274 operand[0].fScalar = -operand[0].fScalar; 275 break; 276 case SkScriptEngine2::kModuloInt: 277 operand[0].fS32 %= operand[1].fS32; 278 break; 279 case SkScriptEngine2::kModuloScalar: 280 operand[0].fScalar = SkScalarMod(operand[0].fScalar, operand[1].fScalar); 281 break; 282 case SkScriptEngine2::kMultiplyInt: 283 operand[0].fS32 *= operand[1].fS32; 284 break; 285 case SkScriptEngine2::kMultiplyScalar: 286 operand[0].fScalar = SkScalarMul(operand[0].fScalar, operand[1].fScalar); 287 break; 288 case SkScriptEngine2::kShiftLeftInt: 289 operand[0].fS32 <<= operand[1].fS32; 290 break; 291 case SkScriptEngine2::kShiftRightInt: 292 operand[0].fS32 >>= operand[1].fS32; 293 break; 294 case SkScriptEngine2::kSubtractInt: 295 operand[0].fS32 -= operand[1].fS32; 296 break; 297 case SkScriptEngine2::kSubtractScalar: 298 operand[0].fScalar -= operand[1].fScalar; 299 break; 300 case SkScriptEngine2::kXorInt: 301 operand[0].fS32 ^= operand[1].fS32; 302 break; 303 case SkScriptEngine2::kEnd: 304 goto done; 305 case SkScriptEngine2::kNop: 306 SkASSERT(0); 307 default: 308 break; 309 } 310 } while (true); 311 done: 312 fRunStack.push(operand[0]); 313 return true; 314 } 315 316 bool SkScriptRuntime::getResult(SkOperand2* result) { 317 if (fRunStack.count() == 0) 318 return false; 319 fRunStack.pop(result); 320 return true; 321 } 322 323 void SkScriptRuntime::track(SkOpArray* array) { 324 SkASSERT(fTrackArray.find(array) < 0); 325 *fTrackArray.append() = array; 326 } 327 328 void SkScriptRuntime::track(SkString* string) { 329 SkASSERT(fTrackString.find(string) < 0); 330 *fTrackString.append() = string; 331 } 332 333 void SkScriptRuntime::untrack(SkOpArray* array) { 334 int index = fTrackArray.find(array); 335 SkASSERT(index >= 0); 336 fTrackArray.begin()[index] = NULL; 337 } 338 339 void SkScriptRuntime::untrack(SkString* string) { 340 int index = fTrackString.find(string); 341 SkASSERT(index >= 0); 342 fTrackString.begin()[index] = NULL; 343 } 344 345