diff --git a/solution/GraphicalDebugging/Debugger.cs b/solution/GraphicalDebugging/Debugger.cs index 0a85d1c..d2d4ba8 100644 --- a/solution/GraphicalDebugging/Debugger.cs +++ b/solution/GraphicalDebugging/Debugger.cs @@ -37,7 +37,7 @@ public bool TryLoadDouble(string name, out double result) { result = 0.0; string castedName = !IsLanguageBasic - ? "(double)" + name + ? "(double)(" + name + ")" : "CType(" + name + ", Double)"; var expr = debugger.GetExpression(castedName); return expr.IsValidValue diff --git a/solution/GraphicalDebugging/ExpressionLoader.cs b/solution/GraphicalDebugging/ExpressionLoader.cs index 5d67933..d13a130 100644 --- a/solution/GraphicalDebugging/ExpressionLoader.cs +++ b/solution/GraphicalDebugging/ExpressionLoader.cs @@ -10,6 +10,7 @@ using System; using System.Collections.Generic; +using System.Runtime.InteropServices.WindowsRuntime; using System.Threading.Tasks; namespace GraphicalDebugging @@ -35,7 +36,7 @@ public enum Kind Container = 0, MultiPoint, TurnsContainer, ValuesContainer, GeometriesContainer, Point, Segment, Box, NSphere, Ray, Line, Linestring, Ring, Polygon, MultiLinestring, MultiPolygon, MultiGeometry, Turn, OtherGeometry, - Variant, Image + Variant, Image, Value }; public delegate void BreakModeEnteredEventHandler(); @@ -111,6 +112,8 @@ private ExpressionLoader(DTE2 dte) loadersCpp.Add(new StdPairPoint.LoaderCreator()); loadersCpp.Add(new StdComplexPoint.LoaderCreator()); + loadersCpp.Add(new StdChronoDuration.LoaderCreator()); + loadersCpp.Add(new BVariant.LoaderCreator()); loadersCpp.Add(new StdArray.LoaderCreator()); @@ -231,7 +234,7 @@ public bool Check(Kind kind) private readonly Kind mKind; } - public class NonValueKindConstraint : IKindConstraint + public class NonValueContainerKindConstraint : IKindConstraint { public bool Check(Kind kind) { @@ -242,7 +245,11 @@ public bool Check(Kind kind) public class DrawableKindConstraint : IKindConstraint { - public bool Check(Kind kind) { return kind != Kind.Container; } + public bool Check(Kind kind) + { + return kind != Kind.Container + && kind != Kind.Value; + } } // IMPORTANT: GeometriesContainer cannot be a Geometry, @@ -254,7 +261,8 @@ public bool Check(Kind kind) return kind != Kind.Container && kind != Kind.ValuesContainer && kind != Kind.GeometriesContainer - && kind != Kind.Image; + && kind != Kind.Image + && kind != Kind.Value; } } @@ -264,7 +272,8 @@ public bool Check(Kind kind) { return kind != Kind.Container && kind != Kind.ValuesContainer - && kind != Kind.Image; + && kind != Kind.Image + && kind != Kind.Value; } } @@ -284,7 +293,7 @@ public bool Check(Kind kind) public static KindConstraint OnlyValuesContainers { get; } = new KindConstraint(Kind.ValuesContainer); public static KindConstraint OnlyMultiPoints { get; } = new KindConstraint(Kind.MultiPoint); public static IndexableKindConstraint OnlyIndexables { get; } = new IndexableKindConstraint(); - public static NonValueKindConstraint OnlyNonValues { get; } = new NonValueKindConstraint(); + public static NonValueContainerKindConstraint OnlyNonValueContainers { get; } = new NonValueContainerKindConstraint(); /// /// Loads debugged variable into ExpressionDrawer.IDrawable and additional @@ -3180,6 +3189,70 @@ public override ExpressionDrawer.IDrawable Load(MemoryReader mreader, Debugger d readonly string pointType; } + // TODO: Add abstract class and derive from it here + // TODO: Add user-defined Calue in ExpressionLoader_UserDefined + class Value : Loader + { + public Value(string memberName, string memberType) + { + this.memberName = memberName; + this.memberType = memberType; + } + + public double Load(MemoryReader mreader, Debugger debugger, string name, string type) + { + // TODO: what if the actual value is NaN? + return debugger.TryLoadDouble(name + "." + memberName, out double result) + ? result + : double.NaN; + } + + public MemoryReader.Converter GetMemoryConverter(MemoryReader mreader, + Debugger debugger, // TODO - remove + string name, + string type) + { + string member = name + "." + memberName; + if (!debugger.GetAddressOffset(name, member, out long memberOffset) + || !debugger.GetTypeSizeof(member, out int memberSize)) + return null; + MemoryReader.ValueConverter memberConverter = mreader.GetNumericConverter(memberType, memberSize); + return memberConverter != null + && debugger.GetTypeSizeof(type, out int sizeOfValue) + && !Debugger.IsInvalidOffset(sizeOfValue, memberOffset) + ? new MemoryReader.StructConverter( + sizeOfValue, + new MemoryReader.Member(memberConverter, (int)memberOffset)) + : null; + } + + private readonly string memberName; + private readonly string memberType; + } + + class StdChronoDuration : Value + { + public class LoaderCreator : ExpressionLoader.ILoaderCreator + { + public bool IsUserDefined() { return false; } + public Kind Kind() { return ExpressionLoader.Kind.Value; } + public Loader Create(Loaders loaders, Debugger debugger, string name, string type, string id) + { + if (id != "std::chrono::duration") + return null; + + List tparams = Util.Tparams(type); + if (tparams.Count < 1) + return null; + + return new StdChronoDuration("_MyRep", tparams[0]); + } + } + + private StdChronoDuration(string memberName, string memberType) : base(memberName, memberType) + {} + } + class ValuesContainer : LoaderR { public class LoaderCreator : ExpressionLoader.ILoaderCreator @@ -3201,17 +3274,19 @@ public Loader Create(Loaders loaders, Debugger debugger, string name, string typ containerLoader.ElementInfo(name, type, out string elName, out string elType); // WARNING: Potentially recursive call, avoid searching for ValuesContainers - Loader l = loaders.FindByType(OnlyNonValues, elName, elType); + Loader l = loaders.FindByType(OnlyNonValueContainers, elName, elType); - return l == null // this is not non-value - ? new ValuesContainer(containerLoader) + return l == null ? new ValuesContainer(containerLoader, null, elType) + : l is Value ? new ValuesContainer(containerLoader, l as Value, elType) : null; } } - private ValuesContainer(ContainerLoader containerLoader) + private ValuesContainer(ContainerLoader containerLoader, Value valueLoader, string valueType) { this.containerLoader = containerLoader; + this.valueLoader = valueLoader; + this.valueType = valueType; } public override Geometry.Traits GetTraits(MemoryReader mreader, Debugger debugger, @@ -3238,34 +3313,38 @@ public List LoadValues(MemoryReader mreader, Debugger debugger, List result = null; if (mreader != null) - LoadMemory(mreader, debugger, name, type, containerLoader, out result, callback); + LoadMemory(mreader, debugger, name, type, out result, callback); if (result == null) - LoadParsed(debugger, name, containerLoader, out result, callback); + LoadParsed(mreader, debugger, name, type, out result, callback); return result; } private void LoadMemory(MemoryReader mreader, Debugger debugger, string name, string type, - ContainerLoader loader, out List result, LoadCallback callback) { result = null; - loader.ElementInfo(name, type, out string elemName, out string elemType); + containerLoader.ElementInfo(name, type, out string elemName, out string elemType); if (!debugger.GetTypeSizeof(elemType, out int valSize)) return; - MemoryReader.ValueConverter + MemoryReader.Converter valueConverter = null; + + if (valueLoader != null) + valueConverter = valueLoader.GetMemoryConverter(mreader, debugger, elemName, elemType); + else valueConverter = mreader.GetNumericConverter(elemType, valSize); + if (valueConverter == null) return; List list = new List(); - bool ok = loader.ForEachMemoryBlock(mreader, debugger, name, type, 0, valueConverter, + bool ok = containerLoader.ForEachMemoryBlock(mreader, debugger, name, type, 0, valueConverter, delegate (double[] values) { foreach (double v in values) @@ -3277,17 +3356,28 @@ private void LoadMemory(MemoryReader mreader, Debugger debugger, result = list; } - private void LoadParsed(Debugger debugger, string name, - ContainerLoader loader, + private void LoadParsed(MemoryReader mreader, Debugger debugger, + string name, string type, out List result, LoadCallback callback) { result = null; List values = new List(); - bool ok = loader.ForEachElement(debugger, name, delegate (string elName) + bool ok = containerLoader.ForEachElement(debugger, name, delegate (string elName) { - if (!debugger.TryLoadDouble(elName, out double value)) - return false; + double value = double.NaN; + if (valueLoader != null) + { + // TODO: what if the actual value is NaN? + value = valueLoader.Load(mreader, debugger, elName, valueType); + if (double.IsNaN(value)) + return false; + } + else // no value loader found, assume it's built-in numeric type + { + if (!debugger.TryLoadDouble(elName, out value)) + return false; + } values.Add(value); return callback(); }); @@ -3297,6 +3387,8 @@ private void LoadParsed(Debugger debugger, string name, } readonly ContainerLoader containerLoader; + readonly Value valueLoader; + readonly string valueType; } // This loader is created manually right now so LoaderCreator is not needed