using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using miew.Concurrency; using miew.Debugging; namespace agree { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Type in the type hierarchy. This hierarchy is a fully-connected directed-acyclic graph (DAG) where each type /// supports zero or more features that may be arbitrarily constrained to be any type in the hierarchy. /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public sealed partial class Type : GlbDag { public Type(TypeMgr tm, String name, List<BaseFeatConstraint> bfc) : base(tm, name, bfc) { } public static Type MakeTopType(TypeMgr tm, String name) { Type t = new Type(tm, name, null); t.m_id = TypeMgr.TopId; t._definition = tm.TopTfs; t._expanded = tm.TopTfs; return t; } public bool IsTop { get { return this == tm.TopType; } } /// <summary> /// if a type has authored constraints then, when it is the result of a unification meet /// and is not the same as either type, it must go through the extra step of /// being made well-formed. It is not sufficient to check HasLocalFeatures because /// a type can further constraint features that it did not introduce /// </summary> public bool HasConstraints { get { return (m_flags & Flags.HasConstraints) > 0; } } /// <summary> /// 'Atomic' types have no appropriate features in their inclusive subgraph (Copestake 2001 p.68) /// We term featureless types "bare." For example, *top* is not atomic, despite being bare. /// </summary> public bool IsAtomic { get { return (m_flags & Flags.Atomic) > 0; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] HashSet<int> _feat_gather = null; public FeatureConfig fc = FeatureConfig.Empty; public override Type InstanceType { get { return this; } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public void AddLocalFeature(int i_feat) { if ((m_flags & Flags.LoadedNonLocalFeatures) > 0) throw new Exception("Cannot add local features because parent features have already been calculated."); (_feat_gather = _feat_gather ?? new HashSet<int>()).Add(i_feat); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Internal use only. Implements lazy loading of parent features. /// Assumes local features have already been added to m_appropriate_features for the parent types, so this should /// be called for all types according to topological order. /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// internal void AddNonLocalFeatures() { if ((m_flags & Flags.HasAnyFeatures) > 0) { foreach (Type par in Parents) { if ((par.m_flags & Flags.LoadedNonLocalFeatures) == 0) throw new Exception("Incorrect topological order while calculating inherited features."); if (par.fc.Count > 0) { _feat_gather = _feat_gather ?? new HashSet<int>(); _feat_gather.UnionWith(par.fc); } } /// Set the order for which features of this type are enumerated. /// Observation: unification failures tend to happen in more common types, as opposed to more obscure ones. /// Reverse this ordering and you'll see. /// We use the following order to unify the features of a type, i.e. according to the topological order of /// their introducing type. fc = tm.fcm.Get(this, _feat_gather); _feat_gather = null; } m_flags |= Flags.LoadedNonLocalFeatures; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <returns> /// 'false' if the specified feature does not exist or is not appropriate for this type. /// </returns> //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public bool HasFeature(int i_feat) { int[] arr = fc.rg_fix; for (int i = 0; i < arr.Length; i++) if (arr[i] == i_feat) return true; return false; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public override Tfs EnsureExpanded(out bool f_did) { f_did = false; Tfs _tmp, _new; if ((_tmp = _expanded) != null) return _tmp; if (!HasAnyFeatures) return _expanded = Definition; Stopwatch stopw = Stopwatch.StartNew(); TargetTfs tt = Unification.ExpandType(this); if (tt == null) throw new TfsException("Error expanding type '{0}': could not unify with its constraint or parents.", this.Name); if ((_tmp = _expanded) != null) return _tmp; int ec = tt.EdgeCount; if (ec == 0) _new = new BareTfs(tt.Type); //else if (ec < 12) // _new = new TinyTfs(tt); else _new = tt.ToArrayTfs(); _new.Name = Name + " - Expanded"; if ((_tmp = _expanded) != null) return _tmp; Interlocked.Add(ref tm.ms_expand, (int)stopw.ElapsedMilliseconds); if ((_tmp = Interlocked.CompareExchange(ref _expanded, _new, null)) != null) return _tmp; f_did = true; return _new; } }; }