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
18typedef SkLongArray(SkString*) SkTDStringArray;
19
20class SkAnimateMaker;
21class SkScriptCallBack;
22
23class SkScriptEngine2 {
24public:
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);
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);
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
162protected:
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 {
188        Branch() {
189        }
190
191        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
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;
270private:
271#ifdef SK_DEBUG
272public:
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
281struct 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