mirror of https://github.com/axmolengine/axmol.git
286 lines
7.9 KiB
C++
286 lines
7.9 KiB
C++
#ifndef SkScript2_DEFINED
|
|
#define SkScript2_DEFINED
|
|
|
|
#include "SkOperand2.h"
|
|
#include "SkStream.h"
|
|
#include "SkTDArray.h"
|
|
#include "SkTDArray_Experimental.h"
|
|
#include "SkTDict.h"
|
|
#include "SkTDStack.h"
|
|
|
|
typedef SkLongArray(SkString*) SkTDStringArray;
|
|
|
|
class SkAnimateMaker;
|
|
class SkScriptCallBack;
|
|
|
|
class SkScriptEngine2 {
|
|
public:
|
|
enum Error {
|
|
kNoError,
|
|
kArrayIndexOutOfBounds,
|
|
kCouldNotFindReferencedID,
|
|
kFunctionCallFailed,
|
|
kMemberOpFailed,
|
|
kPropertyOpFailed
|
|
};
|
|
|
|
enum Attrs {
|
|
kConstant,
|
|
kVariable
|
|
};
|
|
|
|
SkScriptEngine2(SkOperand2::OpType returnType);
|
|
~SkScriptEngine2();
|
|
bool convertTo(SkOperand2::OpType , SkScriptValue2* );
|
|
bool evaluateScript(const char** script, SkScriptValue2* value);
|
|
void forget(SkOpArray* array);
|
|
Error getError() { return fError; }
|
|
SkOperand2::OpType getReturnType() { return fReturnType; }
|
|
void track(SkOpArray* array) {
|
|
SkASSERT(fTrackArray.find(array) < 0);
|
|
*fTrackArray.append() = array; }
|
|
void track(SkString* string) {
|
|
SkASSERT(fTrackString.find(string) < 0);
|
|
*fTrackString.append() = string;
|
|
}
|
|
static bool ConvertTo(SkScriptEngine2* , SkOperand2::OpType toType, SkScriptValue2* value);
|
|
static SkScalar IntToScalar(int32_t );
|
|
static bool ValueToString(const SkScriptValue2& value, SkString* string);
|
|
|
|
enum Op { // used by tokenizer attribute table
|
|
kUnassigned,
|
|
kAdd,
|
|
kBitAnd,
|
|
kBitNot,
|
|
kBitOr,
|
|
kDivide,
|
|
kEqual,
|
|
kFlipOps,
|
|
kGreaterEqual,
|
|
kLogicalAnd,
|
|
kLogicalNot,
|
|
kLogicalOr,
|
|
kMinus,
|
|
kModulo,
|
|
kMultiply,
|
|
kShiftLeft,
|
|
kShiftRight, // signed
|
|
kSubtract,
|
|
kXor,
|
|
// following not in attribute table
|
|
kArrayOp,
|
|
kElse,
|
|
kIf,
|
|
kParen,
|
|
kLastLogicalOp,
|
|
kArtificialOp = 0x20
|
|
};
|
|
|
|
enum TypeOp { // generated by tokenizer
|
|
kNop, // should never get generated
|
|
kAccumulatorPop,
|
|
kAccumulatorPush,
|
|
kAddInt,
|
|
kAddScalar,
|
|
kAddString, // string concat
|
|
kArrayIndex,
|
|
kArrayParam,
|
|
kArrayToken,
|
|
kBitAndInt,
|
|
kBitNotInt,
|
|
kBitOrInt,
|
|
kBoxToken,
|
|
kCallback,
|
|
kDivideInt,
|
|
kDivideScalar,
|
|
kDotOperator,
|
|
kElseOp,
|
|
kEnd,
|
|
kEqualInt,
|
|
kEqualScalar,
|
|
kEqualString,
|
|
kFunctionCall,
|
|
kFlipOpsOp,
|
|
kFunctionToken,
|
|
kGreaterEqualInt,
|
|
kGreaterEqualScalar,
|
|
kGreaterEqualString,
|
|
kIfOp,
|
|
kIntToScalar,
|
|
kIntToScalar2,
|
|
kIntToString,
|
|
kIntToString2,
|
|
kIntegerAccumulator,
|
|
kIntegerOperand,
|
|
kLogicalAndInt,
|
|
kLogicalNotInt,
|
|
kLogicalOrInt,
|
|
kMemberOp,
|
|
kMinusInt,
|
|
kMinusScalar,
|
|
kModuloInt,
|
|
kModuloScalar,
|
|
kMultiplyInt,
|
|
kMultiplyScalar,
|
|
kPropertyOp,
|
|
kScalarAccumulator,
|
|
kScalarOperand,
|
|
kScalarToInt,
|
|
kScalarToInt2,
|
|
kScalarToString,
|
|
kScalarToString2,
|
|
kShiftLeftInt,
|
|
kShiftRightInt, // signed
|
|
kStringAccumulator,
|
|
kStringOperand,
|
|
kStringToInt,
|
|
kStringToScalar,
|
|
kStringToScalar2,
|
|
kStringTrack,
|
|
kSubtractInt,
|
|
kSubtractScalar,
|
|
kToBool,
|
|
kUnboxToken,
|
|
kUnboxToken2,
|
|
kXorInt,
|
|
kLastTypeOp
|
|
};
|
|
|
|
enum OpBias {
|
|
kNoBias,
|
|
kTowardsNumber = 0,
|
|
kTowardsString
|
|
};
|
|
|
|
protected:
|
|
|
|
enum BraceStyle {
|
|
// kStructBrace,
|
|
kArrayBrace,
|
|
kFunctionBrace
|
|
};
|
|
|
|
enum AddTokenRegister {
|
|
kAccumulator,
|
|
kOperand
|
|
};
|
|
|
|
enum ResultIsBoolean {
|
|
kResultIsNotBoolean,
|
|
kResultIsBoolean
|
|
};
|
|
|
|
struct OperatorAttributes {
|
|
unsigned int fLeftType : 3; // SkOpType union, but only lower values
|
|
unsigned int fRightType : 3; // SkOpType union, but only lower values
|
|
OpBias fBias : 1;
|
|
ResultIsBoolean fResultIsBoolean : 1;
|
|
};
|
|
|
|
struct Branch {
|
|
Branch() {
|
|
}
|
|
|
|
Branch(Op op, int depth, unsigned offset) : fOffset(offset), fOpStackDepth(depth), fOperator(op),
|
|
fPrimed(kIsNotPrimed), fDone(kIsNotDone) {
|
|
}
|
|
|
|
enum Primed {
|
|
kIsNotPrimed,
|
|
kIsPrimed
|
|
};
|
|
|
|
enum Done {
|
|
kIsNotDone,
|
|
kIsDone,
|
|
};
|
|
|
|
unsigned fOffset : 16; // offset in generated stream where branch needs to go
|
|
int fOpStackDepth : 7; // depth when operator was found
|
|
Op fOperator : 6; // operand which generated branch
|
|
mutable Primed fPrimed : 1; // mark when next instruction generates branch
|
|
Done fDone : 1; // mark when branch is complete
|
|
void prime() { fPrimed = kIsPrimed; }
|
|
void resolve(SkDynamicMemoryWStream* , size_t offset);
|
|
};
|
|
|
|
static const OperatorAttributes gOpAttributes[];
|
|
static const signed char gPrecedence[];
|
|
static const TypeOp gTokens[];
|
|
void addToken(TypeOp );
|
|
void addTokenConst(SkScriptValue2* , AddTokenRegister , SkOperand2::OpType , TypeOp );
|
|
void addTokenInt(int );
|
|
void addTokenScalar(SkScalar );
|
|
void addTokenString(const SkString& );
|
|
void addTokenValue(const SkScriptValue2& , AddTokenRegister );
|
|
int arithmeticOp(char ch, char nextChar, bool lastPush);
|
|
bool convertParams(SkTDArray<SkScriptValue2>* ,
|
|
const SkOperand2::OpType* paramTypes, int paramTypeCount);
|
|
void convertToString(SkOperand2* operand, SkOperand2::OpType type) {
|
|
SkScriptValue2 scriptValue;
|
|
scriptValue.fOperand = *operand;
|
|
scriptValue.fType = type;
|
|
convertTo(SkOperand2::kString, &scriptValue);
|
|
*operand = scriptValue.fOperand;
|
|
}
|
|
bool evaluateDot(const char*& script);
|
|
bool evaluateDotParam(const char*& script, const char* field, size_t fieldLength);
|
|
bool functionParams(const char** scriptPtr, SkTDArray<SkScriptValue2>* params);
|
|
size_t getTokenOffset();
|
|
SkOperand2::OpType getUnboxType(SkOperand2 scriptValue);
|
|
bool handleArrayIndexer(const char** scriptPtr);
|
|
bool handleFunction(const char** scriptPtr);
|
|
bool handleMember(const char* field, size_t len, void* object);
|
|
bool handleMemberFunction(const char* field, size_t len, void* object,
|
|
SkTDArray<SkScriptValue2>* params);
|
|
bool handleProperty();
|
|
bool handleUnbox(SkScriptValue2* scriptValue);
|
|
bool innerScript(const char** scriptPtr, SkScriptValue2* value);
|
|
int logicalOp(char ch, char nextChar);
|
|
void processLogicalOp(Op op);
|
|
bool processOp();
|
|
void resolveBranch(Branch& );
|
|
// void setAnimateMaker(SkAnimateMaker* maker) { fMaker = maker; }
|
|
SkDynamicMemoryWStream fStream;
|
|
SkDynamicMemoryWStream* fActiveStream;
|
|
SkTDStack<BraceStyle> fBraceStack; // curly, square, function paren
|
|
SkTDStack<Branch> fBranchStack; // logical operators, slot to store forward branch
|
|
SkLongArray(SkScriptCallBack*) fCallBackArray;
|
|
SkTDStack<Op> fOpStack;
|
|
SkTDStack<SkScriptValue2> fValueStack;
|
|
// SkAnimateMaker* fMaker;
|
|
SkLongArray(SkOpArray*) fTrackArray;
|
|
SkTDStringArray fTrackString;
|
|
const char* fToken; // one-deep stack
|
|
size_t fTokenLength;
|
|
SkOperand2::OpType fReturnType;
|
|
Error fError;
|
|
SkOperand2::OpType fAccumulatorType; // tracking for code generation
|
|
SkBool fBranchPopAllowed;
|
|
SkBool fConstExpression;
|
|
SkBool fOperandInUse;
|
|
private:
|
|
#ifdef SK_DEBUG
|
|
public:
|
|
void decompile(const unsigned char* , size_t );
|
|
static void UnitTest();
|
|
static void ValidateDecompileTable();
|
|
#endif
|
|
};
|
|
|
|
#ifdef SK_DEBUG
|
|
|
|
struct SkScriptNAnswer2 {
|
|
const char* fScript;
|
|
SkOperand2::OpType fType;
|
|
int32_t fIntAnswer;
|
|
SkScalar fScalarAnswer;
|
|
const char* fStringAnswer;
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
#endif // SkScript2_DEFINED
|
|
|