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, unsigned offset) : fOffset(offset), fOpStackDepth(depth), fOperator(op),
192            fPrimed(kIsNotPrimed), fDone(kIsNotDone) {
193        }
194
195        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;
269private:
270#ifdef SK_DEBUG
271public:
272    void decompile(const unsigned char* , size_t );
273    static void UnitTest();
274    static void ValidateDecompileTable();
275#endif
276};
277
278#ifdef SK_DEBUG
279
280struct SkScriptNAnswer2 {
281    const char* fScript;
282    SkOperand2::OpType fType;
283    int32_t fIntAnswer;
284    SkScalar fScalarAnswer;
285    const char* fStringAnswer;
286};
287
288#endif
289
290
291#endif // SkScript2_DEFINED
292