namespace EightBit { namespace Files { namespace Symbols { public class IdentifiableSection : Section { public int ID { get; private set; } protected IdentifiableSection() => _ = this._integer_keys.Add("id"); public override void Parse(Parser parent, Dictionary entries) { base.Parse(parent, entries); this.ID = this.TakeInteger("id"); } #region Foreign key constraints #region Generic FK access protected static T TakeReference(int key, List? from) where T : IdentifiableSection { ArgumentNullException.ThrowIfNull(from); var identifiable = from[key]; ArgumentOutOfRangeException.ThrowIfNotEqual(identifiable.ID, key, nameof(key)); return identifiable; } protected T TakeReference(string key, List? from) where T : IdentifiableSection => TakeReference(this.TakeInteger(key), from); protected T? MaybeTakeReference(string key, List? from) where T : IdentifiableSection { var id = this.MaybeTakeInteger(key); return id == null ? null : TakeReference(id.Value, from); } protected List TakeReferences(string key, List? from) where T : IdentifiableSection { ArgumentNullException.ThrowIfNull(from); List returned = []; var ids = this.MaybeTakeMultiple(key); if (ids != null) { foreach (var id in ids) { returned.Add(from[id]); } } return returned; } #endregion #region Specific FK access protected Module TakeModuleReference(string key = "mod") => this.TakeReference(key, this._parent?.Modules); protected File TakeFileReference(string key = "file") => this.TakeReference(key, this._parent?.Files); protected Type TakeTypeReference(string key = "type") => this.TakeReference(key, this._parent?.Types); protected Segment TakeSegmentReference(string key = "seg") => this.TakeReference(key, this._parent?.Segments); protected Scope TakeScopeReference(string key = "scope") => this.TakeReference(key, this._parent?.Scopes); protected Scope? MaybeTakeParentReference(string key = "parent") => this.MaybeTakeReference(key, this._parent?.Scopes); protected Symbol? MaybeTakeSymbolReference(string key = "sym") => this.MaybeTakeReference(key, this._parent?.Symbols); protected List TakeSpanReferences(string key = "span") => this.TakeReferences(key, this._parent?.Spans); protected List TakeLineReferences(string key) => this.TakeReferences(key, this._parent?.Lines); #endregion #endregion } } } }