From 0621b9ed1dd5cc3f69635e1f29ddd5eecdd24449 Mon Sep 17 00:00:00 2001 From: Adrian Conlon <98398945+AdrianConlon@users.noreply.github.com> Date: Wed, 18 Sep 2024 11:19:41 +0100 Subject: [PATCH] More symbols improvements --- M6502/M6502.Symbols/File.cs | 6 +-- M6502/M6502.Symbols/Information.cs | 2 +- M6502/M6502.Symbols/Line.cs | 2 +- M6502/M6502.Symbols/Module.cs | 2 +- M6502/M6502.Symbols/Parser.cs | 44 +++++++++++++++---- .../ReflectedSectionProperties.cs | 11 +++++ M6502/M6502.Symbols/Scope.cs | 2 +- M6502/M6502.Symbols/Section.cs | 9 ++++ .../SectionEnumerationAttribute.cs | 2 +- .../SectionReferenceAttribute.cs | 2 +- .../SectionReferencesAttribute.cs | 2 +- M6502/M6502.Symbols/Segment.cs | 2 +- M6502/M6502.Symbols/Span.cs | 2 +- M6502/M6502.Symbols/Symbol.cs | 2 +- M6502/M6502.Symbols/Type.cs | 2 +- M6502/M6502.Symbols/Version.cs | 2 +- 16 files changed, 70 insertions(+), 24 deletions(-) diff --git a/M6502/M6502.Symbols/File.cs b/M6502/M6502.Symbols/File.cs index 7906919..53bb87f 100644 --- a/M6502/M6502.Symbols/File.cs +++ b/M6502/M6502.Symbols/File.cs @@ -5,13 +5,13 @@ namespace Symbols { // file id=0,name="sudoku.s",size=9141,mtime=0x6027C7F0,mod=0 - public class File(Parser container) : NamedSection(container) + public sealed class File(Parser container) : NamedSection(container) { [SectionProperty("size")] public int Size => this.TakeInteger("size"); - [SectionProperty("mtime", hexadecimal: true)] - public long ModificationTime => this.TakeLong("mtime"); + [SectionProperty("mtime")] + public DateTime ModificationTime => this.TakeDateTime("mtime"); [SectionReference("mod")] public Symbols.Module Module => this.TakeModuleReference(); diff --git a/M6502/M6502.Symbols/Information.cs b/M6502/M6502.Symbols/Information.cs index b10e92c..cd095bc 100644 --- a/M6502/M6502.Symbols/Information.cs +++ b/M6502/M6502.Symbols/Information.cs @@ -5,7 +5,7 @@ namespace Symbols { //info csym = 0, file = 3, lib = 0, line = 380, mod = 1, scope = 12, seg = 8, span = 356, sym = 61, type = 3 - public class Information : Section + public sealed class Information : Section { public Information(Parser container) : base(container) diff --git a/M6502/M6502.Symbols/Line.cs b/M6502/M6502.Symbols/Line.cs index 73a4f09..0548dc5 100644 --- a/M6502/M6502.Symbols/Line.cs +++ b/M6502/M6502.Symbols/Line.cs @@ -5,7 +5,7 @@ namespace Symbols { // line id = 268, file = 1, line = 60, type = 2, count = 1, span = 286 + 195 - public class Line(Parser container) : IdentifiableSection(container) + public sealed class Line(Parser container) : IdentifiableSection(container) { [SectionReference("file")] public Symbols.File File => this.TakeFileReference(); diff --git a/M6502/M6502.Symbols/Module.cs b/M6502/M6502.Symbols/Module.cs index 66680d9..86f4796 100644 --- a/M6502/M6502.Symbols/Module.cs +++ b/M6502/M6502.Symbols/Module.cs @@ -5,7 +5,7 @@ namespace Symbols { // mod id=0,name="sudoku.o",file=0 - public class Module(Parser container) : NamedSection(container) + public sealed class Module(Parser container) : NamedSection(container) { [SectionReference("file")] public Symbols.File File => this.TakeFileReference(); diff --git a/M6502/M6502.Symbols/Parser.cs b/M6502/M6502.Symbols/Parser.cs index 0a9eee8..ed1a740 100644 --- a/M6502/M6502.Symbols/Parser.cs +++ b/M6502/M6502.Symbols/Parser.cs @@ -31,7 +31,7 @@ { get { - if (_files == null) + if (this._files == null) { this.ExtractFiles(); } @@ -44,7 +44,7 @@ { get { - if (_lines == null) + if (this._lines == null) { this.ExtractLines(); } @@ -57,7 +57,7 @@ { get { - if (_modules == null) + if (this._modules == null) { this.ExtractModules(); } @@ -70,7 +70,7 @@ { get { - if (_segments == null) + if (this._segments == null) { this.ExtractSegments(); } @@ -83,7 +83,7 @@ { get { - if (_spans == null) + if (this._spans == null) { this.ExtractSpans(); } @@ -96,7 +96,7 @@ { get { - if (_scopes == null) + if (this._scopes == null) { this.ExtractScopes(); } @@ -109,7 +109,7 @@ { get { - if (_symbols == null) + if (this._symbols == null) { this.ExtractSymbols(); } @@ -122,7 +122,7 @@ { get { - if (_types == null) + if (this._types == null) { this.ExtractTypes(); } @@ -440,11 +440,20 @@ if (key is "version") { + if (this._version != null) + { + throw new InvalidOperationException("Verson object has already been parsed"); + } this._version = new(this); this._version.Parse(BuildDictionary(parts)); + this.VerifyVersion(); } else if (key is "info") { + if (this._information != null) + { + throw new InvalidOperationException("Information object has already been parsed"); + } this._information = new(this); this._information.Parse(BuildDictionary(parts)); } @@ -502,7 +511,24 @@ return dictionary; } -#endregion + + private void VerifyVersion() + { + if (this._version == null) + { + throw new InvalidOperationException("Version has not yet been parsed"); + } + + var major = this._version?.Major; + var minor = this._version?.Minor; + var valid = major == 2 && minor == 0; + if (!valid) + { + throw new InvalidOperationException($"Unknown symbol file version: {major}.{minor}"); + } + } + + #endregion } } } diff --git a/M6502/M6502.Symbols/ReflectedSectionProperties.cs b/M6502/M6502.Symbols/ReflectedSectionProperties.cs index 318c441..3996cf7 100644 --- a/M6502/M6502.Symbols/ReflectedSectionProperties.cs +++ b/M6502/M6502.Symbols/ReflectedSectionProperties.cs @@ -15,6 +15,7 @@ public HashSet HexIntegerKeys { get; } = []; public HashSet LongKeys { get; } = []; public HashSet HexLongKeys { get; } = []; + public HashSet DateTimeKeys { get; } = []; public HashSet MultipleKeys { get; } = []; public ReflectedSectionProperties(System.Type type) @@ -83,6 +84,12 @@ Debug.Assert(added, $"<{key}> already has an entry"); } + public void AddDateTimeKey(string key) + { + var added = this.DateTimeKeys.Add(key); + Debug.Assert(added, $"<{key}> already has an entry"); + } + private void ProcessSectionPropertyAttribute(System.Type originalType, SectionPropertyAttribute attribute) { var key = attribute.Key; @@ -135,6 +142,10 @@ this.AddLongKey(key); } } + else if (type == typeof(DateTime) || type == typeof(Nullable)) + { + this.AddDateTimeKey(key); + } else { throw new NotImplementedException($"Property type <{type}> has not been implemented"); diff --git a/M6502/M6502.Symbols/Scope.cs b/M6502/M6502.Symbols/Scope.cs index eb6b2fb..c85db77 100644 --- a/M6502/M6502.Symbols/Scope.cs +++ b/M6502/M6502.Symbols/Scope.cs @@ -7,7 +7,7 @@ //scope id = 0, name = "", mod = 0, size = 1137, span = 355 + 354 //scope id = 1, name = "stack", mod = 0, type = scope, size = 7, parent = 0, span = 15 //scope id = 7, name = "print_box_break_vertical", mod = 0, type = scope, size = 6, parent = 0, sym = 33, span = 72 - public class Scope(Parser container) : NamedSection(container) + public sealed class Scope(Parser container) : NamedSection(container) { [SectionReference("mod")] public Symbols.Module Module => this.TakeModuleReference(); diff --git a/M6502/M6502.Symbols/Section.cs b/M6502/M6502.Symbols/Section.cs index d95f95d..1d358d6 100644 --- a/M6502/M6502.Symbols/Section.cs +++ b/M6502/M6502.Symbols/Section.cs @@ -12,12 +12,14 @@ public class Section { protected static readonly Dictionary _sectionPropertiesCache = []; + protected static readonly DateTime _unixEpoch = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); protected readonly Parser _container; protected readonly Dictionary _strings = []; protected readonly Dictionary _integers = []; protected readonly Dictionary _longs = []; + protected readonly Dictionary _dateTimes = []; protected readonly Dictionary> _multiples = []; protected ReflectedSectionProperties SectionProperties @@ -80,6 +82,10 @@ { this._longs.Add(key, ExtractHexLong(value)); } + else if (this.SectionProperties.DateTimeKeys.Contains(key)) + { + this._dateTimes.Add(key, ExtractDateTime(value)); + } else if (this.SectionProperties.MultipleKeys.Contains(key)) { this._multiples.Add(key, ExtractCompoundInteger(value)); @@ -92,11 +98,13 @@ protected int? MaybeTakeInteger(string key) => this._integers.TryGetValue(key, out var value) ? value : null; protected long? MaybeTakeLong(string key) => this._longs.TryGetValue(key, out var value) ? value : null; + protected DateTime? MaybeTakeDateTime(string key) => this._dateTimes.TryGetValue(key, out var value) ? value : null; protected string? MaybeTakeString(string key) => this._strings.TryGetValue(key, out var value) ? value : null; protected List? MaybeTakeMultiple(string key) => this._multiples.TryGetValue(key, out var value) ? value : null; protected int TakeInteger(string key) => this.MaybeTakeInteger(key) ?? throw new ArgumentOutOfRangeException(nameof(key), key, "Missing integer entry in section"); protected long TakeLong(string key) => this.MaybeTakeLong(key) ?? throw new ArgumentOutOfRangeException(nameof(key), key, "Missing long integer entry in section"); + protected DateTime TakeDateTime(string key) => this.MaybeTakeDateTime(key) ?? throw new ArgumentOutOfRangeException(nameof(key), key, "Missing DateTime entry in section"); protected string TakeString(string key) => this.MaybeTakeString(key) ?? throw new ArgumentOutOfRangeException(nameof(key), key, "Missing string entry in section"); protected List TakeMultiple(string key) => this.MaybeTakeMultiple(key) ?? throw new ArgumentOutOfRangeException(nameof(key), key, "Missing multiple entry in section"); @@ -110,6 +118,7 @@ protected static long ExtractHexLong(string value) => ExtractHexValue(value); protected static int ExtractInteger(string value) => ExtractNumericValue(value); protected static long ExtractLong(string value) => ExtractNumericValue(value); + protected static DateTime ExtractDateTime(string value) => _unixEpoch.AddSeconds(ExtractHexLong(value)); protected static string[] ExtractCompoundString(string value) => value.Split('+'); protected static List ExtractCompoundInteger(string value) diff --git a/M6502/M6502.Symbols/SectionEnumerationAttribute.cs b/M6502/M6502.Symbols/SectionEnumerationAttribute.cs index f9b0625..1d9aa7a 100644 --- a/M6502/M6502.Symbols/SectionEnumerationAttribute.cs +++ b/M6502/M6502.Symbols/SectionEnumerationAttribute.cs @@ -5,7 +5,7 @@ namespace Symbols { [AttributeUsage(AttributeTargets.Property)] - internal class SectionEnumerationAttribute(string key) : SectionPropertyAttribute(key, enumeration: true) + internal sealed class SectionEnumerationAttribute(string key) : SectionPropertyAttribute(key, enumeration: true) { } } diff --git a/M6502/M6502.Symbols/SectionReferenceAttribute.cs b/M6502/M6502.Symbols/SectionReferenceAttribute.cs index b50eb82..72f8e2e 100644 --- a/M6502/M6502.Symbols/SectionReferenceAttribute.cs +++ b/M6502/M6502.Symbols/SectionReferenceAttribute.cs @@ -5,7 +5,7 @@ namespace Symbols { [AttributeUsage(AttributeTargets.Property)] - internal class SectionReferenceAttribute(string key) : SectionPropertyAttribute(key, type: typeof(int)) + internal sealed class SectionReferenceAttribute(string key) : SectionPropertyAttribute(key, type: typeof(int)) { } } diff --git a/M6502/M6502.Symbols/SectionReferencesAttribute.cs b/M6502/M6502.Symbols/SectionReferencesAttribute.cs index 58e6275..1071600 100644 --- a/M6502/M6502.Symbols/SectionReferencesAttribute.cs +++ b/M6502/M6502.Symbols/SectionReferencesAttribute.cs @@ -5,7 +5,7 @@ namespace Symbols { [AttributeUsage(AttributeTargets.Property)] - internal class SectionReferencesAttribute(string key) : SectionPropertyAttribute(key, many: true) + internal sealed class SectionReferencesAttribute(string key) : SectionPropertyAttribute(key, many: true) { } } diff --git a/M6502/M6502.Symbols/Segment.cs b/M6502/M6502.Symbols/Segment.cs index 6c5d3ac..e161519 100644 --- a/M6502/M6502.Symbols/Segment.cs +++ b/M6502/M6502.Symbols/Segment.cs @@ -5,7 +5,7 @@ namespace Symbols { // seg id=1,name="RODATA",start=0x00F471,size=0x0000,addrsize=absolute,type=ro,oname="sudoku.65b",ooffs=1137 - public class Segment(Parser container) : NamedSection(container) + public sealed class Segment(Parser container) : NamedSection(container) { [SectionProperty("start", hexadecimal: true)] public int Start => this.TakeInteger("start"); diff --git a/M6502/M6502.Symbols/Span.cs b/M6502/M6502.Symbols/Span.cs index a29b087..d16590b 100644 --- a/M6502/M6502.Symbols/Span.cs +++ b/M6502/M6502.Symbols/Span.cs @@ -5,7 +5,7 @@ namespace Symbols { //span id = 351, seg = 7, start = 0, size = 2, type = 2 - public class Span(Parser container) : IdentifiableSection(container) + public sealed class Span(Parser container) : IdentifiableSection(container) { [SectionReference("seg")] public Symbols.Segment Segment => this.TakeSegmentReference(); diff --git a/M6502/M6502.Symbols/Symbol.cs b/M6502/M6502.Symbols/Symbol.cs index 5648377..28c0b0f 100644 --- a/M6502/M6502.Symbols/Symbol.cs +++ b/M6502/M6502.Symbols/Symbol.cs @@ -7,7 +7,7 @@ using System.Collections.Generic; // sym id = 16, name = "solve", addrsize = absolute, size = 274, scope = 0, def = 94,ref=144+17+351,val=0xF314,seg=6,type=lab - public class Symbol(Parser container) : NamedSection(container) + public sealed class Symbol(Parser container) : NamedSection(container) { [SectionEnumeration("addrsize")] public string AddressSize => this.TakeString("addrsize"); diff --git a/M6502/M6502.Symbols/Type.cs b/M6502/M6502.Symbols/Type.cs index 2039e7c..35ac06a 100644 --- a/M6502/M6502.Symbols/Type.cs +++ b/M6502/M6502.Symbols/Type.cs @@ -5,7 +5,7 @@ namespace Symbols { // type id = 0, val = "800920" - public class Type(Parser container) : IdentifiableSection(container) + public sealed class Type(Parser container) : IdentifiableSection(container) { [SectionProperty("val")] public string Value => this.TakeString("val"); diff --git a/M6502/M6502.Symbols/Version.cs b/M6502/M6502.Symbols/Version.cs index 3e08c2d..659e8c7 100644 --- a/M6502/M6502.Symbols/Version.cs +++ b/M6502/M6502.Symbols/Version.cs @@ -5,7 +5,7 @@ namespace Symbols { //version major = 2, minor = 0 - public class Version(Parser container) : Section(container) + public sealed class Version(Parser container) : Section(container) { [SectionProperty("major")] public int Major => this.TakeInteger("major");