OLD | NEW |
| (Empty) |
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 / dictionar
ies | |
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 valu
e? | |
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 < fTrackStri
ng.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 = (SkScriptCa
llBackFunction*) 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 = (SkScriptCallBa
ckMember*) callBack; | |
96 if (callBackMember->invoke(ref, operand[0].fObject, &ope
rand[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 = (SkScriptCa
llBackProperty*) callBack; | |
105 if (callBackProperty->getResult(ref, &operand[0])== fals
e) { | |
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(Sk
Scalar)); | |
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 = (SkScriptCallBack
Convert*) 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 = (SkScriptCallBa
ckConvert*) 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 pr
edicate) | |
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 == SkScrip
tEngine2::kIntToString2) | |
185 strPtr->appendS32(operand[op - SkScriptEngine2::
kIntToString].fS32); | |
186 else | |
187 strPtr->appendScalar(operand[op - SkScriptEngine
2::kScalarToString].fScalar); | |
188 operand[0].fString = strPtr; | |
189 } break; | |
190 case SkScriptEngine2::kIntToScalar: | |
191 case SkScriptEngine2::kIntToScalar2: | |
192 operand[0].fScalar = SkScriptEngine2::IntToScalar(operan
d[op - SkScriptEngine2::kIntToScalar].fS32); | |
193 break; | |
194 case SkScriptEngine2::kStringToInt: | |
195 if (SkParse::FindS32(operand[0].fString->c_str(), &opera
nd[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::kStringTo
Scalar].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, (*oper
and[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_NaN3
2 : | |
234 operand[0].fS32 > 0 ? SK_MaxS32 : -SK_Ma
xS32; | |
235 else | |
236 if (operand[1].fS32 != 0) // throw error on divide by ze
ro? | |
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 ? S
K_ScalarNaN : | |
242 operand[0].fScalar > 0 ? SK_ScalarMax :
-SK_ScalarMax; | |
243 else | |
244 operand[0].fScalar = SkScalarDiv(operand[0].fSca
lar, 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].fScal
ar; | |
251 break; | |
252 case SkScriptEngine2::kEqualString: | |
253 operand[0].fS32 = *operand[0].fString == *operand[1].fSt
ring; | |
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].fScal
ar; | |
260 break; | |
261 case SkScriptEngine2::kGreaterEqualString: | |
262 operand[0].fS32 = strcmp(operand[0].fString->c_str(), op
erand[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, ope
rand[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, ope
rand[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 | |
314 bool SkScriptRuntime::getResult(SkOperand2* result) { | |
315 if (fRunStack.count() == 0) | |
316 return false; | |
317 fRunStack.pop(result); | |
318 return true; | |
319 } | |
320 | |
321 void SkScriptRuntime::track(SkOpArray* array) { | |
322 SkASSERT(fTrackArray.find(array) < 0); | |
323 *fTrackArray.append() = array; | |
324 } | |
325 | |
326 void SkScriptRuntime::track(SkString* string) { | |
327 SkASSERT(fTrackString.find(string) < 0); | |
328 *fTrackString.append() = string; | |
329 } | |
330 | |
331 void SkScriptRuntime::untrack(SkOpArray* array) { | |
332 int index = fTrackArray.find(array); | |
333 SkASSERT(index >= 0); | |
334 fTrackArray.begin()[index] = NULL; | |
335 } | |
336 | |
337 void SkScriptRuntime::untrack(SkString* string) { | |
338 int index = fTrackString.find(string); | |
339 SkASSERT(index >= 0); | |
340 fTrackString.begin()[index] = NULL; | |
341 } | |
342 | |
OLD | NEW |