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