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