From ef8f9f476b09882cd48469a5321e7d144aa9ed0d Mon Sep 17 00:00:00 2001 From: Adrian Conlon <98398945+AdrianConlon@users.noreply.github.com> Date: Wed, 12 Jun 2024 00:13:30 +0100 Subject: [PATCH] Experiment with FrozenDictionary --- M6502/M6502.Symbols/Parser.cs | 59 +++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/M6502/M6502.Symbols/Parser.cs b/M6502/M6502.Symbols/Parser.cs index 499ab7d..863a4e1 100644 --- a/M6502/M6502.Symbols/Parser.cs +++ b/M6502/M6502.Symbols/Parser.cs @@ -5,6 +5,7 @@ namespace Symbols { using System; + using System.Collections.Frozen; using System.Diagnostics; public sealed class Parser @@ -15,7 +16,8 @@ // Section -> Unique ID list of dictionary entries // Being sorted allows us to verify IDs as they arrive - private readonly Dictionary>> _parsed = []; + private readonly Dictionary>> _parsed_intermediate = []; + private FrozenDictionary>>? _parsed; private Version? _version; private Information? _information; @@ -47,7 +49,7 @@ #region Lookups - public static IEnumerable SelectNameMatching(string name, IEnumerable items) where T : NamedSection => from item in items where item.Name == name select item; + private static IEnumerable SelectNameMatching(string name, IEnumerable items) where T : NamedSection => from item in items where item.Name == name select item; #region Label lookup @@ -74,7 +76,7 @@ } } - public List LookupLabels(int address) => this.Addresses.TryGetValue(address, out var symbols) ? symbols : []; + private List LookupLabels(int address) => this.Addresses.TryGetValue(address, out var symbols) ? symbols : []; public Symbol? LookupLabel(int address) { @@ -82,7 +84,7 @@ return labels.Count > 0 ? labels[0] : null; } - public IEnumerable LookupLabels(string name) => SelectNameMatching(name, this.Labels); + private IEnumerable LookupLabels(string name) => SelectNameMatching(name, this.Labels); public Symbol? LookupLabel(string name) { @@ -117,7 +119,7 @@ } } - public List LookupEquates(int constant) => this.Constants.TryGetValue(constant, out var symbols) ? symbols : []; + private List LookupEquates(int constant) => this.Constants.TryGetValue(constant, out var symbols) ? symbols : []; public Symbol? LookupEquate(int constant) { @@ -129,14 +131,6 @@ #region Scope lookup - public IEnumerable LookupScopes(string name) => SelectNameMatching(name, this.Scopes); - - public Scope? LookupScope(string name) - { - var scopes = this.LookupScopes(name).ToList(); - return scopes.Count > 0 ? scopes[0] : null; - } - private int LocateScope(int address) { var low = 0; @@ -184,7 +178,7 @@ #region Scope evaluation - public static List EvaluateScope(Scope start) + private static List EvaluateScope(Scope start) { var returned = new List(); for (var current = start; current.Parent != null; current = current.Parent) @@ -194,13 +188,13 @@ return returned; } - public static List EvaluateScope(Symbol symbol) => EvaluateScope(symbol.Scope); + private static List EvaluateScope(Symbol symbol) => EvaluateScope(symbol.Scope); #endregion #region Namespace evaluation from scope - public static string BuildNamespace(Symbol symbol) + private static string BuildNamespace(Symbol symbol) { var returned = string.Empty; var scopes = EvaluateScope(symbol); @@ -219,7 +213,7 @@ return returned; } - public static string PrefixNamespace(Symbol? symbol) + private static string PrefixNamespace(Symbol? symbol) { if (symbol is null) { @@ -296,10 +290,16 @@ private void Extract(string key, List into) where T : IdentifiableSection, new() { + if (this._parsed == null) + { + throw new InvalidOperationException("Parsed dictionary has not been frozen"); + } + if (!this._parsed.TryGetValue(key, out var parsed)) { throw new InvalidOperationException($"Debugging section: '{key}' is unavailable"); } + Debug.Assert(into.Count == 0); into.Capacity = parsed.Count; foreach (var element in parsed) @@ -342,6 +342,8 @@ this.ParseLine(line.Split(' ', '\t')); } + this.FreezeParsedData(); + this.ExtractFiles(); this.ExtractLines(); this.ExtractModules(); @@ -356,6 +358,17 @@ this.BuildAddressableScopes(); } + private void FreezeParsedData() + { + var intermediateSections = new Dictionary>>(this._parsed_intermediate.Count); + foreach (var (name, entries) in this._parsed_intermediate) + { + intermediateSections.Add(name, FrozenDictionary.ToFrozenDictionary(entries)); + } + this._parsed = FrozenDictionary.ToFrozenDictionary(intermediateSections); + this._parsed_intermediate.Clear(); + } + private void BuildAddressableScopes() { if (!this.Parsed) @@ -395,10 +408,10 @@ private void Parse(string key, string[] parts) { - if (!this._parsed.TryGetValue(key, out var section)) + if (!this._parsed_intermediate.TryGetValue(key, out var section)) { - this._parsed[key] = []; - section = this._parsed[key]; + this._parsed_intermediate[key] = []; + section = this._parsed_intermediate[key]; } var dictionary = BuildDictionary(parts); @@ -427,9 +440,9 @@ section.Add(identifier, dictionary); } - private static Dictionary BuildDictionary(string[] parts) + private static FrozenDictionary BuildDictionary(string[] parts) { - var dictionary = new Dictionary(); + var dictionary = new Dictionary(parts.Length); foreach (var part in parts) { var definition = part.Split('='); @@ -443,7 +456,7 @@ dictionary[key] = value; } - return dictionary; + return FrozenDictionary.ToFrozenDictionary(dictionary); } #endregion