/* Copyright (c) Microsoft Corporation. Licensed under the MIT License. */ /* Copyright (c) Microsoft Corporation. Licensed under the MIT License. */ /*************************************************************************** Author: ShonK Project: Kauai Reviewed: Copyright (c) Microsoft Corporation Script compiler declarations. ***************************************************************************/ #ifndef SCRCOM_H #define SCRCOM_H /*************************************************************************** Opcodes for scripts - these are the opcodes that can actually exist in script. They don't necessarily map directly to the compiler's notion of an operator. ***************************************************************************/ //if you change this enum, bump the version numbers below enum { opNil, //ops that act on variables come first kopPushLocVar, kopPopLocVar, kopPushThisVar, kopPopThisVar, kopPushGlobalVar, kopPopGlobalVar, kopPushRemoteVar, kopPopRemoteVar, kopMinArray = 0x80, kopPushLocArray = kopMinArray, kopPopLocArray, kopPushThisArray, kopPopThisArray, kopPushGlobalArray, kopPopGlobalArray, kopPushRemoteArray, kopPopRemoteArray, kopLimArray, kopLimVarSccb = kopLimArray, //ops that just act on the stack - no variables // for the comments below, a is the top value on the execution stack // b is the next to top value on the stack, and c is next on the stack kopAdd = 0x100, // addition: b + a kopSub, // subtraction: b - a kopMul, // multiplication: b * a kopDiv, // integer division: b / a kopMod, // mod: b % a kopNeg, // unary negation: -a kopInc, // unary increment: a + 1 kopDec, // unary decrement: a - 1 kopShr, // shift right: b >> a kopShl, // shift left: b << a kopBOr, // bitwise or: b | a kopBAnd, // bitwise and: b & a kopBXor, // bitwise exclusive or: b ^ a kopBNot, // unary bitwise not: ~a kopLXor, // logical exclusive or: (b != 0) != (a != 0) kopLNot, // unary logical not: !a kopEq, // equality: b == a kopNe, // not equal: b != a kopGt, // greater than: b > a kopLt, // less than: b < a kopGe, // greater or equal: b >= a kopLe, // less or equal: b <= a kopAbs, // unary absolute value: LwAbs(a) kopRnd, // a random number between 0 and a - 1 (inclusive) kopMulDiv, // a * b / c without loss of precision kopDup, // duplicates the top value kopPop, // discards the top value kopSwap, // swaps the top two values kopRot, // rotates b values by a (c is placed a slots deeper in the stack) kopRev, // reverses the next a slots on the stack kopDupList, // duplicates the next a slots on the stack kopPopList, // pops the next a slots on the stack kopRndList, // picks one of the next a stack values at random kopSelect, // picks the b'th entry among the next a stack values kopGoEq, // if (b == a) jumps to label c kopGoNe, // if (b != a) jumps to label c kopGoGt, // if (b > a) jumps to label c kopGoLt, // if (b < a) jumps to label c kopGoGe, // if (b >= a) jumps to label c kopGoLe, // if (b <= a) jumps to label c kopGoZ, // if (a == 0) jumps to label b kopGoNz, // if (a != 0) jumps to label b kopGo, // jumps to label a kopExit, // terminates the script kopReturn, // terminates the script with return value a kopSetReturn, // sets the return value to a kopShuffle, // shuffles the numbers 0,1,..,a-1 for calls to NextCard kopShuffleList, // shuffles the top a values for calls to NextCard kopNextCard, // returns the next value from the shuffled values // when all values have been used, the values are reshuffled kopMatch, // a is a count of pairs, b is the key, c is the default value // if b matches the first of any of the a pairs, the second // value of the pair is pushed. if not, c is pushed. kopPause, // pause the script (can be resumed later from C code) kopCopyStr, // copy a string within the registry kopMoveStr, // move a string within the registry kopNukeStr, // delete a string from the registry kopMergeStrs, // merge a string table into the registry kopScaleTime, // scale the application clock kopNumToStr, // convert a number to a decimal string kopStrToNum, // convert a string to a number kopConcatStrs, // concatenate two strings kopLenStr, // return the number of characters in the string kopCopySubStr, // copy a piece of the string kopLimSccb }; // structure to map a string to an opcode (post-fix) struct SZOP { long op; PSZ psz; }; // structure to map a string to an opcode and argument information (in-fix) struct AROP { long op; PSZ psz; long clwFixed; //number of fixed arguments long clwVar; //number of arguments per variable group long cactMinVar; //minimum number of variable groups bool fVoid; //return a value? }; // script version numbers // if you bump these, also bump the numbers in scrcomg.h const short kswCurSccb = 0xA; //this version const short kswBackSccb = 0xA; //we can be read back to this version const short kswMinSccb = 0xA; //we can read back to this version // high byte of a label value const byte kbLabel = 0xCC; /*************************************************************************** Run-time variable name. The first 8 characters of the name are significant. These 8 characters are packed into lu2 and the low 2 bytes of lu1, so clients can store the info in 6 bytes. The high 2 bytes of lu1 are used for array subscripts. ***************************************************************************/ struct RTVN { ulong lu1; ulong lu2; void SetFromStn(PSTN pstn); void GetStn(PSTN pstn); }; /*************************************************************************** The script compiler base class. ***************************************************************************/ typedef class SCCB *PSCCB; #define SCCB_PAR BASE #define kclsSCCB 'SCCB' class SCCB : public SCCB_PAR { RTCLASS_DEC ASSERT MARKMEM protected: enum { fsccNil = 0, fsccWantVoid = 1, fsccTop = 2 }; PLEXB _plexb; // the lexer PSCPT _pscpt; // the script we're building PGL _pgletnTree; // expression tree (in-fix only) PGL _pgletnStack; // token stack for building expression tree (in-fix only) PGL _pglcstd; // control structure stack (in-fix only) PGST _pgstNames; // encountered names (in-fix only) PGST _pgstLabel; // encountered labels, sorted, extra long is label value PGST _pgstReq; // label references, extra long is address of reference long _ilwOpLast; // address of the last opcode long _lwLastLabel; // for internal temporary labels bool _fError: 1; // whether an error has occured during compiling bool _fForceOp: 1; // when pushing a constant, make sure the last long // is an opcode (because a label references this loc) bool _fHitEnd: 1; // we've exhausted our input stream long _ttEnd; // stop compiling when we see this PMSNK _pmsnk; // the message sink - for error reporting when compiling bool _FInit(PLEXB plexb, bool fInFix, PMSNK pmsnk); void _Free(void); // general compilation methods void _PushLw(long lw); void _PushString(PSTN pstn); void _PushOp(long op); void _EndOp(void); void _PushVarOp(long op, RTVN *prtvn); bool _FFindLabel(PSTN pstn, long *plwLoc); void _AddLabel(PSTN pstn); void _PushLabelRequest(PSTN pstn); void _AddLabelLw(long lw); void _PushLabelRequestLw(long lw); virtual void _ReportError(PSZ psz); virtual short _SwCur(void); virtual short _SwBack(void); virtual short _SwMin(void); virtual bool _FGetTok(PTOK ptok); // post-fix compiler routines virtual void _CompilePost(void); long _OpFromStnRgszop(PSTN pstn, SZOP *prgszop); virtual long _OpFromStn(PSTN pstn); bool _FGetStnFromOpRgszop(long op, PSTN pstn, SZOP *prgszop); virtual bool _FGetStnFromOp(long op, PSTN pstn); // in-fix compiler routines virtual void _CompileIn(void); bool _FResolveToOpl(long opl, long oplMin, long *pietn); void _EmitCode(long ietnTop, ulong grfscc, long *pclwArg); void _EmitVarAccess(long ietn, RTVN *prtvn, long *popPush, long *popPop, long *pclwStack); virtual bool _FGetOpFromName(PSTN pstn, long *pop, long *pclwFixed, long *pclwVar, long *pcactMinVar, bool *pfVoid); bool _FGetArop(PSTN pstn, AROP *prgarop, long *pop, long *pclwFixed, long *pclwVar, long *pcactMinVar, bool *pfVoid); void _PushLabelRequestIetn(long ietn); void _AddLabelIetn(long ietn); void _PushOpFromName(long ietn, ulong grfscc, long clwArg); void _GetIstnNameFromIetn(long ietn, long *pistn); void _GetRtvnFromName(long istn, RTVN *prtvn); bool _FKeyWord(PSTN pstn); void _GetStnFromIstn(long istn, PSTN pstn); void _AddNameRef(PSTN pstn, long *pistn); long _CstFromName(long ietn); void _BeginCst(long cst, long ietn); bool _FHandleCst(long ietn); bool _FAddToTree(struct ETN *petn, long *pietn); bool _FConstEtn(long ietn, long *plw); bool _FCombineConstValues(long op, long lw1, long lw2, long *plw); void _SetDepth(struct ETN *petn, bool fCommute = fFalse); void _PushStringIstn(long istn); public: SCCB(void); ~SCCB(void); virtual PSCPT PscptCompileLex(PLEXB plexb, bool fInFix, PMSNK pmsnk, long ttEnd = ttNil); virtual PSCPT PscptCompileFil(PFIL pfil, bool fInFix, PMSNK pmsnk); virtual PSCPT PscptCompileFni(FNI *pfni, bool fInFix, PMSNK pmsnk); virtual bool FDisassemble(PSCPT pscpt, PMSNK pmsnk, PMSNK pmsnkError = pvNil); }; #endif //!SCRCOM_H