#pragma once #include "stdafx.h" #include #include #include #include #include "../Utilities/SimpleLock.h" #include "DebuggerTypes.h" class Debugger; enum EvalOperators : int64_t { //Binary operators Multiplication = 20000000000, Division = 20000000001, Modulo = 20000000002, Addition = 20000000003, Substration = 20000000004, ShiftLeft = 20000000005, ShiftRight = 20000000006, SmallerThan = 20000000007, SmallerOrEqual = 20000000008, GreaterThan = 20000000009, GreaterOrEqual = 20000000010, Equal = 20000000011, NotEqual = 20000000012, BinaryAnd = 20000000013, BinaryXor = 20000000014, BinaryOr = 20000000015, LogicalAnd = 20000000016, LogicalOr = 20000000017, //Unary operators Plus = 20000000050, Minus = 20000000051, BinaryNot = 20000000052, LogicalNot = 20000000053, AbsoluteAddress = 20000000054, //Used to read ram address Bracket = 20000000060, //Read byte Braces = 20000000061, //Read word //Special value, not used as an operator Parenthesis = 20000000100, }; enum EvalValues : int64_t { RegA = 20000000100, RegX = 20000000101, RegY = 20000000102, RegSP = 20000000103, RegPS = 20000000104, RegPC = 20000000105, RegOpPC = 20000000106, PpuFrameCount = 20000000107, PpuCycle = 20000000108, PpuScanline = 20000000109, Nmi = 20000000110, Irq = 20000000111, Value = 20000000112, Address = 20000000113, IsWrite = 20000000115, IsRead = 20000000116, PreviousOpPC = 20000000117, Sprite0Hit = 20000000118, SpriteOverflow = 20000000119, VerticalBlank = 20000000120, Branched = 20000000121, RegPS_Carry = 20000000122, RegPS_Zero = 20000000123, RegPS_Interrupt = 20000000124, RegPS_Decimal = 20000000125, RegPS_Overflow = 20000000126, RegPS_Negative = 20000000127, FirstLabelIndex = 20000002000, }; enum EvalResultType : int32_t { Numeric = 0, Boolean = 1, Invalid = 2, DivideBy0 = 3, OutOfScope = 4 }; class StringHasher { public: size_t operator()(const std::string& t) const { //Quick hash for expressions - most are likely to have different lengths, and not expecting dozens of breakpoints, either, so this should be fine. return t.size(); } }; struct ExpressionData { std::vector RpnQueue; std::vector Labels; }; class ExpressionEvaluator { private: static const vector _binaryOperators; static const vector _binaryPrecedence; static const vector _unaryOperators; static const vector _unaryPrecedence; static const std::unordered_set _operators; std::unordered_map _cache; SimpleLock _cacheLock; int64_t operandStack[1000]; Debugger* _debugger; bool IsOperator(string token, int &precedence, bool unaryOperator); EvalOperators GetOperator(string token, bool unaryOperator); bool CheckSpecialTokens(string expression, size_t &pos, string &output, ExpressionData &data); string GetNextToken(string expression, size_t &pos, ExpressionData &data, bool &success, bool previousTokenIsOp); bool ProcessSpecialOperator(EvalOperators evalOp, std::stack &opStack, std::stack &precedenceStack, vector &outputQueue); bool ToRpn(string expression, ExpressionData &data); int32_t PrivateEvaluate(string expression, DebugState &state, EvalResultType &resultType, OperationInfo &operationInfo, bool &success); ExpressionData* PrivateGetRpnList(string expression, bool& success); public: ExpressionEvaluator(Debugger* debugger); int32_t Evaluate(ExpressionData &data, DebugState &state, EvalResultType &resultType, OperationInfo &operationInfo); int32_t Evaluate(string expression, DebugState &state, EvalResultType &resultType, OperationInfo &operationInfo); ExpressionData GetRpnList(string expression, bool &success); bool Validate(string expression); #if _DEBUG void RunTests(); #endif };