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