Home | History | Annotate | Download | only in animator
      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