// group variable public LuaValueDataBase EvaluateComplexTerminal() { if (TryTakeToken("(")) { LuaValueDataBase value = EvaluateOr(); if (value as LuaValueDataError != null) { return(value); } if (!TryTakeToken(")")) { return(Report("Failed to find ')' after '('")); } return(EvaluatePostExpressions(value)); } string name = TryParseIdentifier(); if (name == null) { return(Report("Failed to find variable name")); } var result = LookupVariable(name); if (result as LuaValueDataError != null) { return(result); } return(EvaluatePostExpressions(result)); }
public LuaValueDataNumber CoerceToNumber(LuaValueDataBase value) { var valueAsNumber = value as LuaValueDataNumber; if (valueAsNumber != null) { return(valueAsNumber); } var valueAsString = value as LuaValueDataString; if (valueAsString != null) { if (!double.TryParse(valueAsString.value, out double result)) { return(null); } if ((double)(int)result == result) { return(new LuaValueDataNumber(result)); } return(new LuaValueDataNumber(result)); } return(null); }
public bool CoerceToBool(LuaValueDataBase value) { LuaValueDataNil asNilValue = value as LuaValueDataNil; LuaValueDataBool asBoolValue = value as LuaValueDataBool; // 'nil' and 'false' are false, everything else is 'true' return(asNilValue != null ? false : (asBoolValue != null ? asBoolValue.value : true)); }
// + - public LuaValueDataBase EvaluateAdditive() { LuaValueDataBase lhs = EvaluateMultiplicative(); if (lhs as LuaValueDataError != null) { return(lhs); } string token = TryTakeOneOfTokens(new[] { "+", "-" }); if (token != null) { var lhsAsNumber = CoerceToNumber(lhs); if (lhsAsNumber == null) { return(Report("lhs of a numeric binary operator must be a number")); } LuaValueDataBase rhs = EvaluateMultiplicative(); if (rhs as LuaValueDataError != null) { return(rhs); } var rhsAsNumber = CoerceToNumber(rhs); if (rhsAsNumber == null) { return(Report("rhs of a '+' binary operator must be a number")); } if (token == "+") { if (lhsAsNumber.extendedType == LuaHelpers.GetIntegerNumberExtendedType() && rhsAsNumber.extendedType == LuaHelpers.GetIntegerNumberExtendedType()) { return(new LuaValueDataNumber((int)lhsAsNumber.value + (int)rhsAsNumber.value)); } return(new LuaValueDataNumber(lhsAsNumber.value + rhsAsNumber.value)); } if (token == "-") { if (lhsAsNumber.extendedType == LuaHelpers.GetIntegerNumberExtendedType() && rhsAsNumber.extendedType == LuaHelpers.GetIntegerNumberExtendedType()) { return(new LuaValueDataNumber((int)lhsAsNumber.value - (int)rhsAsNumber.value)); } return(new LuaValueDataNumber(lhsAsNumber.value - rhsAsNumber.value)); } } return(lhs); }
public override bool LuaCompare(LuaValueDataBase rhs) { var rhsAsMe = rhs as LuaValueDataError; if (rhsAsMe == null) { return(false); } return(value == rhsAsMe.value); }
public override bool LuaCompare(LuaValueDataBase rhs) { var rhsAsMe = rhs as LuaValueDataThread; if (rhsAsMe == null) { return(false); } return(targetAddress == rhsAsMe.targetAddress); }
public override bool LuaCompare(LuaValueDataBase rhs) { var rhsAsMe = rhs as LuaValueDataNil; if (rhsAsMe == null) { return(false); } return(true); }
public LuaValueDataBase LookupTableValueMember(LuaValueDataBase value, string name) { var table = value as LuaValueDataTable; if (table == null) { return(Report("Value is not a table")); } return(LookupTableMember(table.value, name)); }
public LuaValueDataBase Report(LuaValueDataBase value, string error) { var errorValue = value as LuaValueDataError; if (errorValue != null) { return(new LuaValueDataError(errorValue.value + ", " + error)); } return(Report(error)); }
// * / public LuaValueDataBase EvaluateMultiplicative() { LuaValueDataBase lhs = EvaluateUnary(); if (lhs as LuaValueDataError != null) { return(lhs); } string token = TryTakeOneOfTokens(new[] { "*", "/" }); if (token != null) { var lhsAsNumber = CoerceToNumber(lhs); if (lhsAsNumber == null) { return(Report("lhs of a numeric binary operator must be a number")); } LuaValueDataBase rhs = EvaluateUnary(); if (rhs as LuaValueDataError != null) { return(rhs); } var rhsAsNumber = CoerceToNumber(rhs); if (rhsAsNumber == null) { return(Report("rhs of a numeric binary operator must be a number")); } if (token == "*") { if (lhsAsNumber.extendedType == LuaHelpers.GetIntegerNumberExtendedType() && rhsAsNumber.extendedType == LuaHelpers.GetIntegerNumberExtendedType()) { return(new LuaValueDataNumber((int)lhsAsNumber.value * (int)rhsAsNumber.value)); } return(new LuaValueDataNumber(lhsAsNumber.value * rhsAsNumber.value)); } if (token == "/") { // Always floating-point return(new LuaValueDataNumber(lhsAsNumber.value / rhsAsNumber.value)); } } return(lhs); }
public LuaValueDataBase EvaluateAssignment(bool allowSideEffects) { LuaValueDataBase lhs = EvaluateOr(); if (lhs as LuaValueDataError != null) { return(lhs); } if (TryTakeToken("=")) { LuaValueDataBase rhs = EvaluateOr(); if (rhs as LuaValueDataError != null) { return(rhs); } if (!allowSideEffects) { var error = Report("Expression has side-effects"); error.evaluationFlags |= DkmEvaluationResultFlags.UnflushedSideEffects; return(error); } // lhs must be an l-value if (lhs.tagAddress == 0 || lhs.originalAddress == 0) { return(Report("lhs value cannot be modified")); } // Try to update the value if (!LuaHelpers.TryWriteValue(process, stackFrame, inspectionSession, lhs.tagAddress, lhs.originalAddress, rhs, out string errorText)) { return(Report(errorText)); } rhs.evaluationFlags |= DkmEvaluationResultFlags.SideEffect; return(rhs); } return(lhs); }
// .. public LuaValueDataBase EvaluateConcatenation() { LuaValueDataBase lhs = EvaluateAdditive(); if (lhs as LuaValueDataError != null) { return(lhs); } if (TryTakeToken("..")) { LuaValueDataBase rhs = EvaluateAdditive(); if (rhs as LuaValueDataError != null) { return(rhs); } var lhsAsNumber = lhs as LuaValueDataNumber; var lhsAsString = lhs as LuaValueDataString; if (lhsAsNumber == null && lhsAsString == null) { return(Report("lhs of a concatenation operator must be a number or a string")); } var rhsAsNumber = rhs as LuaValueDataNumber; var rhsAsString = rhs as LuaValueDataString; if (rhsAsNumber == null && rhsAsString == null) { return(Report("rhs of a concatenation operator must be a number or a string")); } string lhsString = lhsAsNumber != null ? (lhsAsNumber.extendedType == LuaHelpers.GetIntegerNumberExtendedType() ? $"{(int)lhsAsNumber.value}" : $"{lhsAsNumber.value}") : lhsAsString.value; string rhsString = rhsAsNumber != null ? (rhsAsNumber.extendedType == LuaHelpers.GetIntegerNumberExtendedType() ? $"{(int)rhsAsNumber.value}" : $"{rhsAsNumber.value}") : rhsAsString.value; return(new LuaValueDataString(lhsString + rhsString)); } return(lhs); }
public LuaValueDataBase Evaluate(string expression, bool allowSideEffects) { this.expression = expression; this.pos = 0; LuaValueDataBase value = EvaluateAssignment(allowSideEffects); if (value as LuaValueDataError != null) { return(value); } SkipSpace(); if (pos < expression.Length) { return(Report(value, $"Failed to fully parse at '{expression.Substring(pos)}'")); } return(value); }
// not - public LuaValueDataBase EvaluateUnary() { if (TryTakeNamedToken("not")) { LuaValueDataBase lhs = EvaluateUnary(); if (lhs as LuaValueDataError != null) { return(lhs); } return(new LuaValueDataBool(!CoerceToBool(lhs))); } if (TryTakeToken("-")) { LuaValueDataBase lhs = EvaluateUnary(); if (lhs as LuaValueDataError != null) { return(lhs); } var lhsAsNumber = CoerceToNumber(lhs); if (lhsAsNumber == null) { return(Report("value of the unary '-' operator must be a number")); } if (lhsAsNumber.extendedType == LuaHelpers.GetIntegerNumberExtendedType()) { return(new LuaValueDataNumber(-(int)lhsAsNumber.value)); } return(new LuaValueDataNumber(-lhsAsNumber.value)); } return(EvaluateTerminal()); }
// or public LuaValueDataBase EvaluateOr() { LuaValueDataBase lhs = EvaluateAnd(); if (lhs as LuaValueDataError != null) { return(lhs); } if (TryTakeNamedToken("or")) { LuaValueDataBase rhs = EvaluateAnd(); if (rhs as LuaValueDataError != null) { return(rhs); } return(new LuaValueDataBool(CoerceToBool(lhs) || CoerceToBool(rhs))); } return(lhs); }
// and public LuaValueDataBase EvaluateAnd() { LuaValueDataBase lhs = EvaluateComparisons(); if (lhs as LuaValueDataError != null) { return(lhs); } if (TryTakeNamedToken("and")) { LuaValueDataBase rhs = EvaluateComparisons(); if (rhs as LuaValueDataError != null) { return(rhs); } return(new LuaValueDataBool(CoerceToBool(lhs) && CoerceToBool(rhs))); } return(lhs); }
internal static DkmEvaluationResult EvaluateDataAtLuaValue(DkmInspectionContext inspectionContext, DkmStackWalkFrame stackFrame, string name, string fullName, LuaValueDataBase luaValue, DkmEvaluationResultFlags flags, DkmEvaluationResultAccessType access, DkmEvaluationResultStorageType storage) { var process = stackFrame.Process; if (luaValue == null) { return(DkmFailedEvaluationResult.Create(inspectionContext, stackFrame, name, fullName, "Null pointer access", DkmEvaluationResultFlags.Invalid, null)); } string value = EvaluateValueAtLuaValue(process, luaValue, inspectionContext.Radix, out string editableValue, ref flags, out DkmDataAddress dataAddress, out string type); if (value == null) { return(DkmFailedEvaluationResult.Create(inspectionContext, stackFrame, name, fullName, "Failed to read value", DkmEvaluationResultFlags.Invalid, null)); } DkmEvaluationResultCategory category = DkmEvaluationResultCategory.Data; DkmEvaluationResultTypeModifierFlags typeModifiers = DkmEvaluationResultTypeModifierFlags.None; var dataItem = new LuaEvaluationDataItem { address = luaValue.originalAddress, type = type, fullName = fullName, luaValueData = luaValue }; return(DkmSuccessEvaluationResult.Create(inspectionContext, stackFrame, name, fullName, flags, value, editableValue, type, category, access, storage, typeModifiers, dataAddress, null, null, dataItem)); }
internal static string EvaluateValueAtAddress(DkmProcess process, ulong address, uint radix, out string editableValue, ref DkmEvaluationResultFlags flags, out DkmDataAddress dataAddress, out string type, out LuaValueDataBase luaValueData) { editableValue = null; dataAddress = null; type = "unknown"; luaValueData = LuaHelpers.ReadValue(process, address); if (luaValueData == null) { return(null); } return(EvaluateValueAtLuaValue(process, luaValueData, radix, out editableValue, ref flags, out dataAddress, out type)); }
internal static string EvaluateValueAtLuaValue(DkmProcess process, LuaValueDataBase valueBase, uint radix, out string editableValue, ref DkmEvaluationResultFlags flags, out DkmDataAddress dataAddress, out string type) { editableValue = null; dataAddress = null; type = "unknown"; if (valueBase == null) { return(null); } if (valueBase as LuaValueDataNil != null) { type = "nil"; flags |= DkmEvaluationResultFlags.IsBuiltInType | DkmEvaluationResultFlags.ReadOnly; return("nil"); } if (valueBase as LuaValueDataBool != null) { var value = valueBase as LuaValueDataBool; type = "bool"; if (value.value) { flags |= DkmEvaluationResultFlags.IsBuiltInType | DkmEvaluationResultFlags.Boolean | DkmEvaluationResultFlags.BooleanTrue; editableValue = $"{value.value}"; return("true"); } else { flags |= DkmEvaluationResultFlags.IsBuiltInType | DkmEvaluationResultFlags.Boolean; editableValue = $"{value.value}"; return("false"); } } if (valueBase as LuaValueDataLightUserData != null) { var value = valueBase as LuaValueDataLightUserData; type = "user_data"; flags |= DkmEvaluationResultFlags.IsBuiltInType; editableValue = $"{value.value}"; return($"0x{value.value:x}"); } if (valueBase as LuaValueDataNumber != null) { var value = valueBase as LuaValueDataNumber; if (value.extendedType == LuaHelpers.GetIntegerNumberExtendedType()) { type = "int"; flags |= DkmEvaluationResultFlags.IsBuiltInType; editableValue = $"{value.value}"; if (radix == 16) { return($"0x{(int)value.value:x8}"); } return($"{value.value}"); } else { type = "double"; flags |= DkmEvaluationResultFlags.IsBuiltInType; editableValue = $"{value.value}"; return($"{value.value}"); } } if (valueBase as LuaValueDataString != null) { var value = valueBase as LuaValueDataString; type = value.extendedType == LuaExtendedType.ShortString ? "short_string" : "long_string"; flags |= DkmEvaluationResultFlags.IsBuiltInType | DkmEvaluationResultFlags.RawString; editableValue = $"{value.value}"; dataAddress = DkmDataAddress.Create(process.GetNativeRuntimeInstance(), value.targetAddress, null); return($"0x{value.targetAddress:x} \"{value.value}\""); } if (valueBase as LuaValueDataTable != null) { var value = valueBase as LuaValueDataTable; type = "table"; flags |= DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.Expandable; var arrayElementCount = value.value.GetArrayElementCount(process); var nodeElementCount = value.value.GetNodeElementCount(process); if (arrayElementCount != 0 && nodeElementCount != 0) { return($"0x{value.targetAddress:x} table [{arrayElementCount} element(s) and {nodeElementCount} key(s)]"); } if (arrayElementCount != 0) { return($"0x{value.targetAddress:x} table [{arrayElementCount} element(s)]"); } if (nodeElementCount != 0) { return($"0x{value.targetAddress:x} table [{nodeElementCount} key(s)]"); } if (!value.value.HasMetaTable()) { flags &= ~DkmEvaluationResultFlags.Expandable; return($"0x{value.targetAddress:x} table [empty]"); } return($"0x{value.targetAddress:x} table"); } if (valueBase as LuaValueDataLuaFunction != null) { var value = valueBase as LuaValueDataLuaFunction; type = "lua_function"; flags |= DkmEvaluationResultFlags.IsBuiltInType | DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.Expandable; return($"0x{value.targetAddress:x}"); } if (valueBase as LuaValueDataExternalFunction != null) { var value = valueBase as LuaValueDataExternalFunction; type = "c_function"; flags |= DkmEvaluationResultFlags.IsBuiltInType | DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.Expandable; return($"0x{value.targetAddress:x}"); } if (valueBase as LuaValueDataExternalClosure != null) { var value = valueBase as LuaValueDataExternalClosure; type = "c_closure"; flags |= DkmEvaluationResultFlags.IsBuiltInType | DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.Expandable; return($"0x{value.targetAddress:x}"); } if (valueBase as LuaValueDataUserData != null) { var value = valueBase as LuaValueDataUserData; type = "user_data"; flags |= DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.Expandable; return($"0x{value.targetAddress:x}"); } if (valueBase as LuaValueDataThread != null) { var value = valueBase as LuaValueDataThread; type = "thread"; flags |= DkmEvaluationResultFlags.IsBuiltInType | DkmEvaluationResultFlags.ReadOnly; return($"0x{value.targetAddress:x}"); } return(null); }
public LuaValueDataBase EvaluatePostExpressions(LuaValueDataBase value) { if (TryTakeToken(".") || TryTakeToken(":")) { string name = TryParseIdentifier(); if (name == null) { return(Report("Failed to find member name")); } if (value is LuaValueDataTable table) { value = LookupTableMember(table.value, name); } else if (value is LuaValueDataUserData userData) { if (userData.value.metaTable != null) { value = LookupTableMember(userData.value.metaTable, name); } } if (value as LuaValueDataError != null) { return(value); } return(EvaluatePostExpressions(value)); } if (TryTakeToken("[")) { var table = value as LuaValueDataTable; if (table == null) { return(Report("Value is not a table")); } var index = EvaluateOr(); if (index as LuaValueDataError != null) { return(index); } if (process == null) { return(Report("Can't load table - process memory is not available")); } // Check array index var indexAsNumber = index as LuaValueDataNumber; if (indexAsNumber != null && indexAsNumber.extendedType == LuaHelpers.GetIntegerNumberExtendedType()) { int result = (int)indexAsNumber.value; if (result > 0 && result - 1 < table.value.GetArrayElementCount(process)) { if (!TryTakeToken("]")) { return(Report("Failed to find ']' after '['")); } var arrayElements = table.value.GetArrayElements(process); return(EvaluatePostExpressions(arrayElements[result - 1])); } } foreach (var element in table.value.GetNodeKeys(process)) { var elementKey = element.LoadKey(process, table.value.batchNodeElementData); if (elementKey.GetType() != index.GetType()) { continue; } if (elementKey.LuaCompare(index)) { if (!TryTakeToken("]")) { return(Report("Failed to find ']' after '['")); } return(EvaluatePostExpressions(element.LoadValue(process, table.value.batchNodeElementData))); } } return(Report($"Failed to find key '{index.AsSimpleDisplayString(10)}' in table")); } return(value); }
// not - # public LuaValueDataBase EvaluateUnary() { if (TryTakeNamedToken("not")) { LuaValueDataBase lhs = EvaluateUnary(); if (lhs as LuaValueDataError != null) { return(lhs); } return(new LuaValueDataBool(!CoerceToBool(lhs))); } if (TryTakeToken("-")) { LuaValueDataBase lhs = EvaluateUnary(); if (lhs as LuaValueDataError != null) { return(lhs); } var lhsAsNumber = CoerceToNumber(lhs); if (lhsAsNumber == null) { return(Report("value of the unary '-' operator must be a number")); } if (lhsAsNumber.extendedType == LuaHelpers.GetIntegerNumberExtendedType()) { return(new LuaValueDataNumber(-(int)lhsAsNumber.value)); } return(new LuaValueDataNumber(-lhsAsNumber.value)); } if (TryTakeToken("#")) { LuaValueDataBase lhs = EvaluateUnary(); if (lhs as LuaValueDataError != null) { return(lhs); } if (process == null) { return(Report("Can't load value - process memory is not available")); } if (lhs is LuaValueDataTable table) { return(new LuaValueDataNumber(table.value.arraySize)); } if (lhs is LuaValueDataString str) { return(new LuaValueDataNumber(str.value.Length)); } return(Report("Value is not a table or a string")); } return(EvaluateTerminal()); }
public abstract bool LuaCompare(LuaValueDataBase rhs);
// < > <= >= == ~= public LuaValueDataBase EvaluateComparisons() { LuaValueDataBase lhs = EvaluateConcatenation(); if (lhs as LuaValueDataError != null) { return(lhs); } string token = TryTakeOneOfTokens(new[] { "<=", ">=", "==", "~=", "<", ">" }); if (token != null) { LuaValueDataBase rhs = EvaluateConcatenation(); if (rhs as LuaValueDataError != null) { return(rhs); } if (token == "==") { if (lhs.GetType() != rhs.GetType()) { return(new LuaValueDataBool(false)); } return(new LuaValueDataBool(lhs.LuaCompare(rhs))); } if (token == "~=") { if (lhs.GetType() != rhs.GetType()) { return(new LuaValueDataBool(true)); } return(new LuaValueDataBool(!lhs.LuaCompare(rhs))); } // Other relational operators can only be applied to numbers and strings var lhsAsNumber = lhs as LuaValueDataNumber; var lhsAsString = lhs as LuaValueDataString; if (lhsAsNumber == null && lhsAsString == null) { return(Report("lhs of a comparison operator must be a number or a string")); } var rhsAsNumber = rhs as LuaValueDataNumber; var rhsAsString = rhs as LuaValueDataString; if (rhsAsNumber == null && rhsAsString == null) { return(Report("rhs of a comparison operator must be a number or a string")); } if (lhsAsNumber != null) { if (rhsAsNumber == null) { return(Report("lhs of a comparison operator is number but rhs is a string")); } if (token == "<=") { return(new LuaValueDataBool(lhsAsNumber.value <= rhsAsNumber.value)); } if (token == ">=") { return(new LuaValueDataBool(lhsAsNumber.value >= rhsAsNumber.value)); } if (token == "<") { return(new LuaValueDataBool(lhsAsNumber.value < rhsAsNumber.value)); } if (token == ">") { return(new LuaValueDataBool(lhsAsNumber.value > rhsAsNumber.value)); } } else { if (rhsAsString == null) { return(Report("lhs of a comparison operator is string but rhs is a number")); } if (token == "<=") { return(new LuaValueDataBool(lhsAsString.value.CompareTo(rhsAsString.value) <= 0)); } if (token == ">=") { return(new LuaValueDataBool(lhsAsString.value.CompareTo(rhsAsString.value) >= 0)); } if (token == "<") { return(new LuaValueDataBool(lhsAsString.value.CompareTo(rhsAsString.value) < 0)); } if (token == ">") { return(new LuaValueDataBool(lhsAsString.value.CompareTo(rhsAsString.value) > 0)); } } } return(lhs); }