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
293