• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
~SkScriptRuntime()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 
executeTokens(unsigned char * opCode)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 	}
308 	} while (true);
309 done:
310 	fRunStack.push(operand[0]);
311 	return true;
312 }
313 
getResult(SkOperand2 * result)314 bool SkScriptRuntime::getResult(SkOperand2* result) {
315 	if (fRunStack.count() == 0)
316 		return false;
317 	fRunStack.pop(result);
318 	return true;
319 }
320 
track(SkOpArray * array)321 void SkScriptRuntime::track(SkOpArray* array) {
322 	SkASSERT(fTrackArray.find(array) < 0);
323 	*fTrackArray.append() = array;
324 }
325 
track(SkString * string)326 void SkScriptRuntime::track(SkString* string) {
327 	SkASSERT(fTrackString.find(string) < 0);
328 	*fTrackString.append() = string;
329 }
330 
untrack(SkOpArray * array)331 void SkScriptRuntime::untrack(SkOpArray* array) {
332 	int index = fTrackArray.find(array);
333 	SkASSERT(index >= 0);
334 	fTrackArray.begin()[index] = NULL;
335 }
336 
untrack(SkString * string)337 void SkScriptRuntime::untrack(SkString* string) {
338 	int index = fTrackString.find(string);
339 	SkASSERT(index >= 0);
340 	fTrackString.begin()[index] = NULL;
341 }
342 
343