michael@0: michael@0: /* michael@0: * Copyright 2006 The Android Open Source Project michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: michael@0: #ifndef SkScript_DEFINED michael@0: #define SkScript_DEFINED michael@0: michael@0: #include "SkOperand.h" michael@0: #include "SkIntArray.h" michael@0: #include "SkTDict.h" michael@0: #include "SkTDStack.h" michael@0: michael@0: class SkAnimateMaker; michael@0: michael@0: class SkScriptEngine { michael@0: public: michael@0: enum Error { michael@0: kNoError, michael@0: kArrayIndexOutOfBounds, michael@0: kCouldNotFindReferencedID, michael@0: kDotOperatorExpectsObject, michael@0: kErrorInArrrayIndex, michael@0: kErrorInFunctionParameters, michael@0: kExpectedArray, michael@0: kExpectedBooleanExpression, michael@0: kExpectedFieldName, michael@0: kExpectedHex, michael@0: kExpectedIntForConditionOperator, michael@0: kExpectedNumber, michael@0: kExpectedNumberForArrayIndex, michael@0: kExpectedOperator, michael@0: kExpectedToken, michael@0: kExpectedTokenBeforeDotOperator, michael@0: kExpectedValue, michael@0: kHandleMemberFailed, michael@0: kHandleMemberFunctionFailed, michael@0: kHandleUnboxFailed, michael@0: kIndexOutOfRange, michael@0: kMismatchedArrayBrace, michael@0: kMismatchedBrackets, michael@0: kNoFunctionHandlerFound, michael@0: kPrematureEnd, michael@0: kTooManyParameters, michael@0: kTypeConversionFailed, michael@0: kUnterminatedString michael@0: }; michael@0: michael@0: enum SkOpType { michael@0: kNoType, michael@0: kInt = 1, michael@0: kScalar = 2, michael@0: kString = 4, michael@0: kArray = 8, michael@0: kObject = 16 michael@0: // kStruct = 32 michael@0: }; michael@0: michael@0: typedef bool (*_boxCallBack)(void* userStorage, SkScriptValue* result); michael@0: typedef bool (*_functionCallBack)(const char* func, size_t len, SkTDArray& params, michael@0: void* userStorage, SkScriptValue* result); michael@0: typedef bool (*_memberCallBack)(const char* member, size_t len, void* object, michael@0: void* userStorage, SkScriptValue* result); michael@0: typedef bool (*_memberFunctionCallBack)(const char* member, size_t len, void* object, michael@0: SkTDArray& params, void* userStorage, SkScriptValue* result); michael@0: // typedef bool (*_objectToStringCallBack)(void* object, void* userStorage, SkScriptValue* result); michael@0: typedef bool (*_propertyCallBack)(const char* prop, size_t len, void* userStorage, SkScriptValue* result); michael@0: typedef bool (*_unboxCallBack)(void* userStorage, SkScriptValue* result); michael@0: SkScriptEngine(SkOpType returnType); michael@0: ~SkScriptEngine(); michael@0: void boxCallBack(_boxCallBack func, void* userStorage); michael@0: bool convertTo(SkDisplayTypes , SkScriptValue* ); michael@0: bool evaluateScript(const char** script, SkScriptValue* value); michael@0: void forget(SkTypedArray* array); michael@0: void functionCallBack(_functionCallBack func, void* userStorage); michael@0: Error getError() const { return fError; } michael@0: #ifdef SK_DEBUG michael@0: bool getErrorString(SkString* err) const; michael@0: #endif michael@0: void memberCallBack(_memberCallBack , void* userStorage); michael@0: void memberFunctionCallBack(_memberFunctionCallBack , void* userStorage); michael@0: // void objectToStringCallBack(_objectToStringCallBack , void* userStorage); michael@0: void propertyCallBack(_propertyCallBack prop, void* userStorage); michael@0: void track(SkTypedArray* array); michael@0: void track(SkString* string); michael@0: void unboxCallBack(_unboxCallBack func, void* userStorage); michael@0: static bool ConvertTo(SkScriptEngine* , SkDisplayTypes toType, SkScriptValue* value); michael@0: static SkScalar IntToScalar(int32_t ); michael@0: static SkDisplayTypes ToDisplayType(SkOpType type); michael@0: static SkOpType ToOpType(SkDisplayTypes type); michael@0: static bool ValueToString(SkScriptValue value, SkString* string); michael@0: michael@0: enum CallBackType { michael@0: kBox, michael@0: kFunction, michael@0: kMember, michael@0: kMemberFunction, michael@0: // kObjectToString, michael@0: kProperty, michael@0: kUnbox michael@0: }; michael@0: michael@0: struct UserCallBack { michael@0: CallBackType fCallBackType; michael@0: void* fUserStorage; michael@0: union { michael@0: _boxCallBack fBoxCallBack; michael@0: _functionCallBack fFunctionCallBack; michael@0: _memberCallBack fMemberCallBack; michael@0: _memberFunctionCallBack fMemberFunctionCallBack; michael@0: // _objectToStringCallBack fObjectToStringCallBack; michael@0: _propertyCallBack fPropertyCallBack; michael@0: _unboxCallBack fUnboxCallBack; michael@0: }; michael@0: }; michael@0: michael@0: enum SkOp { michael@0: kUnassigned, michael@0: kAdd, michael@0: kAddInt = kAdd, michael@0: kAddScalar, michael@0: kAddString, // string concat michael@0: kArrayOp, michael@0: kBitAnd, michael@0: kBitNot, michael@0: kBitOr, michael@0: kDivide, michael@0: kDivideInt = kDivide, michael@0: kDivideScalar, michael@0: kElse, michael@0: kEqual, michael@0: kEqualInt = kEqual, michael@0: kEqualScalar, michael@0: kEqualString, michael@0: kFlipOps, michael@0: kGreaterEqual, michael@0: kGreaterEqualInt = kGreaterEqual, michael@0: kGreaterEqualScalar, michael@0: kGreaterEqualString, michael@0: kIf, michael@0: kLogicalAnd, michael@0: kLogicalNot, michael@0: kLogicalOr, michael@0: kMinus, michael@0: kMinusInt = kMinus, michael@0: kMinusScalar, michael@0: kModulo, michael@0: kModuloInt = kModulo, michael@0: kModuloScalar, michael@0: kMultiply, michael@0: kMultiplyInt = kMultiply, michael@0: kMultiplyScalar, michael@0: kParen, michael@0: kShiftLeft, michael@0: kShiftRight, // signed michael@0: kSubtract, michael@0: kSubtractInt = kSubtract, michael@0: kSubtractScalar, michael@0: kXor, michael@0: kArtificialOp = 0x40 michael@0: }; michael@0: michael@0: enum SkOpBias { michael@0: kNoBias, michael@0: kTowardsNumber = 0, michael@0: kTowardsString michael@0: }; michael@0: michael@0: protected: michael@0: michael@0: struct SkOperatorAttributes { michael@0: unsigned int fLeftType : 3; // SkOpType, but only lower values michael@0: unsigned int fRightType : 3; // SkOpType, but only lower values michael@0: SkOpBias fBias : 1; michael@0: }; michael@0: michael@0: struct SkSuppress { // !!! could be compressed to a long michael@0: SkOp fOperator; // operand which enabled suppression michael@0: int fOpStackDepth; // depth when suppression operator was found michael@0: SkBool8 fSuppress; // set if suppression happens now, as opposed to later michael@0: SkBool8 fElse; // set on the : half of ? : michael@0: }; michael@0: michael@0: static const SkOperatorAttributes gOpAttributes[]; michael@0: static const signed char gPrecedence[]; michael@0: int arithmeticOp(char ch, char nextChar, bool lastPush); michael@0: void commonCallBack(CallBackType type, UserCallBack& callBack, void* userStorage); michael@0: bool convertParams(SkTDArray&, const SkFunctionParamType* , michael@0: int paramTypeCount); michael@0: void convertToString(SkOperand& operand, SkDisplayTypes type) { michael@0: SkScriptValue scriptValue; michael@0: scriptValue.fOperand = operand; michael@0: scriptValue.fType = type; michael@0: convertTo(SkType_String, &scriptValue); michael@0: operand = scriptValue.fOperand; michael@0: } michael@0: bool evaluateDot(const char*& script, bool suppressed); michael@0: bool evaluateDotParam(const char*& script, bool suppressed, const char* field, size_t fieldLength); michael@0: bool functionParams(const char** scriptPtr, SkTDArray& params); michael@0: bool handleArrayIndexer(const char** scriptPtr, bool suppressed); michael@0: bool handleBox(SkScriptValue* value); michael@0: bool handleFunction(const char** scriptPtr, bool suppressed); michael@0: bool handleMember(const char* field, size_t len, void* object); michael@0: bool handleMemberFunction(const char* field, size_t len, void* object, SkTDArray& params); michael@0: // bool handleObjectToString(void* object); michael@0: bool handleProperty(bool suppressed); michael@0: bool handleUnbox(SkScriptValue* scriptValue); michael@0: bool innerScript(const char** scriptPtr, SkScriptValue* value); michael@0: int logicalOp(char ch, char nextChar); michael@0: Error opError(); michael@0: bool processOp(); michael@0: void setAnimateMaker(SkAnimateMaker* maker) { fMaker = maker; } michael@0: bool setError(Error , const char* pos); michael@0: enum SkBraceStyle { michael@0: // kStructBrace, michael@0: kArrayBrace, michael@0: kFunctionBrace michael@0: }; michael@0: michael@0: #if 0 michael@0: SkIntArray(SkBraceStyle) fBraceStack; // curly, square, function paren michael@0: SkIntArray(SkOp) fOpStack; michael@0: SkIntArray(SkOpType) fTypeStack; michael@0: SkTDOperandArray fOperandStack; michael@0: SkTDArray fSuppressStack; michael@0: #else michael@0: SkTDStack fBraceStack; // curly, square, function paren michael@0: SkTDStack fOpStack; michael@0: SkTDStack fTypeStack; michael@0: SkTDStack fOperandStack; michael@0: SkTDStack fSuppressStack; michael@0: #endif michael@0: SkAnimateMaker* fMaker; michael@0: SkTDTypedArrayArray fTrackArray; michael@0: SkTDStringArray fTrackString; michael@0: const char* fToken; // one-deep stack michael@0: size_t fTokenLength; michael@0: SkTDArray fUserCallBacks; michael@0: SkOpType fReturnType; michael@0: Error fError; michael@0: int fErrorPosition; michael@0: private: michael@0: friend class SkTypedArray; michael@0: #ifdef SK_SUPPORT_UNITTEST michael@0: public: michael@0: static void UnitTest(); michael@0: #endif michael@0: }; michael@0: michael@0: #ifdef SK_SUPPORT_UNITTEST michael@0: michael@0: struct SkScriptNAnswer { michael@0: const char* fScript; michael@0: SkDisplayTypes fType; michael@0: int32_t fIntAnswer; michael@0: SkScalar fScalarAnswer; michael@0: const char* fStringAnswer; michael@0: }; michael@0: michael@0: #endif michael@0: michael@0: #endif // SkScript_DEFINED