blob: 33e2af7fee7c9ec46c856d26988926880eeab765 [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
rmistry@google.comd6176b02012-08-23 18:14:13 +0000191 Branch(Op op, int depth, unsigned offset) : fOffset(offset), fOpStackDepth(depth), fOperator(op),
192 fPrimed(kIsNotPrimed), fDone(kIsNotDone) {
193 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000194
rmistry@google.comd6176b02012-08-23 18:14:13 +0000195 enum Primed {
196 kIsNotPrimed,
197 kIsPrimed
198 };
199
200 enum Done {
201 kIsNotDone,
202 kIsDone,
203 };
204
205 unsigned fOffset : 16; // offset in generated stream where branch needs to go
206 int fOpStackDepth : 7; // depth when operator was found
207 Op fOperator : 6; // operand which generated branch
208 mutable Primed fPrimed : 1; // mark when next instruction generates branch
209 Done fDone : 1; // mark when branch is complete
210 void prime() { fPrimed = kIsPrimed; }
211 void resolve(SkDynamicMemoryWStream* , size_t offset);
212 };
213
214 static const OperatorAttributes gOpAttributes[];
215 static const signed char gPrecedence[];
216 static const TypeOp gTokens[];
217 void addToken(TypeOp );
218 void addTokenConst(SkScriptValue2* , AddTokenRegister , SkOperand2::OpType , TypeOp );
219 void addTokenInt(int );
220 void addTokenScalar(SkScalar );
221 void addTokenString(const SkString& );
222 void addTokenValue(const SkScriptValue2& , AddTokenRegister );
223 int arithmeticOp(char ch, char nextChar, bool lastPush);
224 bool convertParams(SkTDArray<SkScriptValue2>* ,
225 const SkOperand2::OpType* paramTypes, int paramTypeCount);
226 void convertToString(SkOperand2* operand, SkOperand2::OpType type) {
227 SkScriptValue2 scriptValue;
228 scriptValue.fOperand = *operand;
229 scriptValue.fType = type;
230 convertTo(SkOperand2::kString, &scriptValue);
231 *operand = scriptValue.fOperand;
232 }
233 bool evaluateDot(const char*& script);
234 bool evaluateDotParam(const char*& script, const char* field, size_t fieldLength);
235 bool functionParams(const char** scriptPtr, SkTDArray<SkScriptValue2>* params);
236 size_t getTokenOffset();
237 SkOperand2::OpType getUnboxType(SkOperand2 scriptValue);
238 bool handleArrayIndexer(const char** scriptPtr);
239 bool handleFunction(const char** scriptPtr);
240 bool handleMember(const char* field, size_t len, void* object);
241 bool handleMemberFunction(const char* field, size_t len, void* object,
242 SkTDArray<SkScriptValue2>* params);
243 bool handleProperty();
244 bool handleUnbox(SkScriptValue2* scriptValue);
245 bool innerScript(const char** scriptPtr, SkScriptValue2* value);
246 int logicalOp(char ch, char nextChar);
247 void processLogicalOp(Op op);
248 bool processOp();
249 void resolveBranch(Branch& );
250// void setAnimateMaker(SkAnimateMaker* maker) { fMaker = maker; }
251 SkDynamicMemoryWStream fStream;
252 SkDynamicMemoryWStream* fActiveStream;
253 SkTDStack<BraceStyle> fBraceStack; // curly, square, function paren
254 SkTDStack<Branch> fBranchStack; // logical operators, slot to store forward branch
255 SkLongArray(SkScriptCallBack*) fCallBackArray;
256 SkTDStack<Op> fOpStack;
257 SkTDStack<SkScriptValue2> fValueStack;
258// SkAnimateMaker* fMaker;
259 SkLongArray(SkOpArray*) fTrackArray;
260 SkTDStringArray fTrackString;
261 const char* fToken; // one-deep stack
262 size_t fTokenLength;
263 SkOperand2::OpType fReturnType;
264 Error fError;
265 SkOperand2::OpType fAccumulatorType; // tracking for code generation
266 SkBool fBranchPopAllowed;
267 SkBool fConstExpression;
268 SkBool fOperandInUse;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000269private:
270#ifdef SK_DEBUG
271public:
rmistry@google.comd6176b02012-08-23 18:14:13 +0000272 void decompile(const unsigned char* , size_t );
273 static void UnitTest();
274 static void ValidateDecompileTable();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000275#endif
276};
277
278#ifdef SK_DEBUG
279
280struct SkScriptNAnswer2 {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000281 const char* fScript;
282 SkOperand2::OpType fType;
283 int32_t fIntAnswer;
284 SkScalar fScalarAnswer;
285 const char* fStringAnswer;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000286};
287
288#endif
289
290
291#endif // SkScript2_DEFINED