1 
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  */
8 #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 
18 typedef SkLongArray(SkString*) SkTDStringArray;
19 
20 class SkAnimateMaker;
21 class SkScriptCallBack;
22 
23 class SkScriptEngine2 {
24 public:
25     enum Error {
26         kNoError,
27         kArrayIndexOutOfBounds,
28         kCouldNotFindReferencedID,
29         kFunctionCallFailed,
30         kMemberOpFailed,
31         kPropertyOpFailed
32     };
33 
34     enum Attrs {
35         kConstant,
36         kVariable
37     };
38 
39     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);
getError()44     Error getError() { return fError; }
getReturnType()45     SkOperand2::OpType getReturnType() { return fReturnType; }
track(SkOpArray * array)46     void track(SkOpArray* array) {
47         SkASSERT(fTrackArray.find(array) < 0);
48         *fTrackArray.append() = array; }
track(SkString * string)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);
56 
57     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,
77 // following not in attribute table
78         kArrayOp,
79         kElse,
80         kIf,
81         kParen,
82         kLastLogicalOp,
83         kArtificialOp = 0x20
84     };
85 
86     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     };
155 
156     enum OpBias {
157         kNoBias,
158         kTowardsNumber = 0,
159         kTowardsString
160     };
161 
162 protected:
163 
164     enum BraceStyle {
165     //    kStructBrace,
166         kArrayBrace,
167         kFunctionBrace
168     };
169 
170     enum AddTokenRegister {
171         kAccumulator,
172         kOperand
173     };
174 
175     enum ResultIsBoolean {
176         kResultIsNotBoolean,
177         kResultIsBoolean
178     };
179 
180     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     };
186 
187     struct Branch {
BranchBranch188         Branch() {
189         }
190 
BranchBranch191         Branch(Op op, int depth, size_t offset)
192             : fOffset(SkToU16(offset)), fOpStackDepth(depth), fOperator(op)
193             , fPrimed(kIsNotPrimed), fDone(kIsNotDone) {
194         }
195 
196         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
primeBranch211         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);
convertToString(SkOperand2 * operand,SkOperand2::OpType type)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;
270 private:
271 #ifdef SK_DEBUG
272 public:
273     void decompile(const unsigned char* , size_t );
274     static void UnitTest();
275     static void ValidateDecompileTable();
276 #endif
277 };
278 
279 #ifdef SK_DEBUG
280 
281 struct SkScriptNAnswer2 {
282     const char* fScript;
283     SkOperand2::OpType fType;
284     int32_t fIntAnswer;
285     SkScalar fScalarAnswer;
286     const char* fStringAnswer;
287 };
288 
289 #endif
290 
291 
292 #endif // SkScript2_DEFINED
293