private void Add(Term t) { if (t.Symbol == unnSymb) { return; } bool wasAdded; Set <Term> bin; switch (t.Symbol.Kind) { case SymbolKind.ConSymb: case SymbolKind.MapSymb: { if (!binMap.TryFindValue(t.Symbol, out bin)) { bin = new Set <Term>(Term.Compare); binMap.Add(t.Symbol, bin); } Term max = null; if (t.Symbol.Kind == SymbolKind.ConSymb) { max = index.MkApply(((ConSymb)t.Symbol).SortSymbol, TermIndex.EmptyArgs, out wasAdded); } else { max = index.MkApply(((MapSymb)t.Symbol).SortSymbol, TermIndex.EmptyArgs, out wasAdded); } if (bin.Contains(max)) { return; } else { bin.Add(t); } break; } case SymbolKind.UserSortSymb: { if (!binMap.TryFindValue(((UserSortSymb)t.Symbol).DataSymbol, out bin)) { bin = new Set <Term>(Term.Compare); binMap.Add(((UserSortSymb)t.Symbol).DataSymbol, bin); bin.Add(t); } else if (!bin.Contains(t)) { bin.Clear(); bin.Add(t); } break; } case SymbolKind.UserCnstSymb: { Contract.Assert(t.Symbol.IsNonVarConstant); if (!binMap.TryFindValue(trueSymb, out bin)) { bin = new Set <Term>(Term.Compare); binMap.Add(trueSymb, bin); } bin.Add(t); break; } case SymbolKind.BaseSortSymb: { var baseSort = ((BaseSortSymb)t.Symbol); var binName = baseSort.SortKind == BaseSortKind.String ? stringSymb : realSymb; if (!binMap.TryFindValue(binName, out bin)) { bin = new Set <Term>(Term.Compare); binMap.Add(binName, bin); } switch (baseSort.SortKind) { case BaseSortKind.String: if (!bin.Contains(t)) { bin.Clear(); bin.Add(t); } break; case BaseSortKind.Real: if (!bin.Contains(t)) { bin.Clear(); bin.Add(t); intervals = null; } break; case BaseSortKind.Integer: if (!bin.Contains(t) && !bin.Contains(index.MkApply(realSymb, TermIndex.EmptyArgs, out wasAdded))) { bin.Remove(index.MkApply(index.SymbolTable.GetSortSymbol(BaseSortKind.Natural), TermIndex.EmptyArgs, out wasAdded)); bin.Remove(index.MkApply(index.SymbolTable.GetSortSymbol(BaseSortKind.PosInteger), TermIndex.EmptyArgs, out wasAdded)); bin.Remove(index.MkApply(index.SymbolTable.GetSortSymbol(BaseSortKind.NegInteger), TermIndex.EmptyArgs, out wasAdded)); bin.Add(t); intervals = null; } break; case BaseSortKind.Natural: if (!bin.Contains(t) && !bin.Contains(index.MkApply(index.SymbolTable.GetSortSymbol(BaseSortKind.Integer), TermIndex.EmptyArgs, out wasAdded)) && !bin.Contains(index.MkApply(realSymb, TermIndex.EmptyArgs, out wasAdded))) { bin.Remove(index.MkApply(index.SymbolTable.GetSortSymbol(BaseSortKind.PosInteger), TermIndex.EmptyArgs, out wasAdded)); bin.Add(t); if (intervals != null && intervals.Count > 0) { BigInteger min, max; intervals.GetExtrema(out min, out max); intervals.Remove(BigInteger.Zero, BigInteger.Max(BigInteger.Zero, max)); } } break; case BaseSortKind.PosInteger: if (!bin.Contains(t) && !bin.Contains(index.MkApply(index.SymbolTable.GetSortSymbol(BaseSortKind.Natural), TermIndex.EmptyArgs, out wasAdded)) && !bin.Contains(index.MkApply(index.SymbolTable.GetSortSymbol(BaseSortKind.Integer), TermIndex.EmptyArgs, out wasAdded)) && !bin.Contains(index.MkApply(realSymb, TermIndex.EmptyArgs, out wasAdded))) { bin.Add(t); if (intervals != null && intervals.Count > 0) { BigInteger min, max; intervals.GetExtrema(out min, out max); intervals.Remove(BigInteger.One, BigInteger.Max(BigInteger.One, max)); } } break; case BaseSortKind.NegInteger: if (!bin.Contains(t) && !bin.Contains(index.MkApply(index.SymbolTable.GetSortSymbol(BaseSortKind.Integer), TermIndex.EmptyArgs, out wasAdded)) && !bin.Contains(index.MkApply(realSymb, TermIndex.EmptyArgs, out wasAdded))) { bin.Add(t); if (intervals != null && intervals.Count > 0) { BigInteger min, max; intervals.GetExtrema(out min, out max); intervals.Remove(BigInteger.Min(min, BigInteger.MinusOne), BigInteger.MinusOne); } } break; default: throw new NotImplementedException(); } break; } case SymbolKind.BaseCnstSymb: { var baseCnst = (BaseCnstSymb)t.Symbol; var binName = baseCnst.CnstKind == CnstKind.String ? stringSymb : realSymb; if (!binMap.TryFindValue(binName, out bin)) { bin = new Set <Term>(Term.Compare); binMap.Add(binName, bin); } switch (baseCnst.CnstKind) { case CnstKind.String: if (!bin.Contains(index.MkApply(index.SymbolTable.GetSortSymbol(BaseSortKind.String), TermIndex.EmptyArgs, out wasAdded))) { bin.Add(t); } break; case CnstKind.Numeric: { var rat = (Rational)baseCnst.Raw; if (bin.Contains(index.MkApply(realSymb, TermIndex.EmptyArgs, out wasAdded))) { } else if (!rat.IsInteger) { bin.Add(t); } else if (bin.Contains(index.MkApply(index.SymbolTable.GetSortSymbol(BaseSortKind.Integer), TermIndex.EmptyArgs, out wasAdded))) { } else if (rat.Sign < 0) { if (!bin.Contains(index.MkApply(index.SymbolTable.GetSortSymbol(BaseSortKind.NegInteger), TermIndex.EmptyArgs, out wasAdded))) { intervals = intervals == null ? new IntIntervals() : intervals; intervals.Add(rat.Numerator, rat.Numerator); } } else if (rat.Sign == 0) { if (!bin.Contains(index.MkApply(index.SymbolTable.GetSortSymbol(BaseSortKind.Natural), TermIndex.EmptyArgs, out wasAdded))) { intervals = intervals == null ? new IntIntervals() : intervals; intervals.Add(rat.Numerator, rat.Numerator); } } else { if (!bin.Contains(index.MkApply(index.SymbolTable.GetSortSymbol(BaseSortKind.Natural), TermIndex.EmptyArgs, out wasAdded)) && !bin.Contains(index.MkApply(index.SymbolTable.GetSortSymbol(BaseSortKind.PosInteger), TermIndex.EmptyArgs, out wasAdded))) { intervals = intervals == null ? new IntIntervals() : intervals; intervals.Add(rat.Numerator, rat.Numerator); } } break; } default: throw new NotImplementedException(); } break; } case SymbolKind.BaseOpSymb: { Contract.Assert(t.Symbol == rngSymb); if (!binMap.TryFindValue(realSymb, out bin)) { bin = new Set <Term>(Term.Compare); binMap.Add(realSymb, bin); } if (!bin.Contains(index.MkApply(realSymb, TermIndex.EmptyArgs, out wasAdded)) && !bin.Contains(index.MkApply(index.SymbolTable.GetSortSymbol(BaseSortKind.Integer), TermIndex.EmptyArgs, out wasAdded))) { var end1 = ((Rational)((BaseCnstSymb)t.Args[0].Symbol).Raw).Numerator; var end2 = ((Rational)((BaseCnstSymb)t.Args[1].Symbol).Raw).Numerator; intervals = intervals == null ? new IntIntervals() : intervals; intervals.Add(end1, end2); BigInteger min, max; intervals.GetExtrema(out min, out max); if (bin.Contains(index.MkApply(index.SymbolTable.GetSortSymbol(BaseSortKind.Natural), TermIndex.EmptyArgs, out wasAdded))) { intervals.Remove(BigInteger.Zero, BigInteger.Max(BigInteger.Zero, max)); } else if (bin.Contains(index.MkApply(index.SymbolTable.GetSortSymbol(BaseSortKind.PosInteger), TermIndex.EmptyArgs, out wasAdded))) { intervals.Remove(BigInteger.One, BigInteger.Max(BigInteger.One, max)); } if (bin.Contains(index.MkApply(index.SymbolTable.GetSortSymbol(BaseSortKind.NegInteger), TermIndex.EmptyArgs, out wasAdded))) { intervals.Remove(BigInteger.Min(BigInteger.MinusOne, min), BigInteger.MinusOne); } } break; } default: throw new InvalidOperationException(); } }
/// <summary> /// Attempts to compute the canonical form. /// </summary> internal bool Canonize(string myName, List <Flag> flags, CancellationToken cancel, Symbol myself = null) { if (typeExpr == null) { return(true); } //// Step 1. Replace all unions with their expansions and all //// Con/Map symbols with their corresponding sorts. var processed = new Set <Symbol>(Symbol.Compare); var stack = new Stack <UserSymbol>(); if (myself != null) { elements.Remove(myself); processed.Add(myself); } foreach (var s in elements) { if (s.Kind == SymbolKind.ConSymb || s.Kind == SymbolKind.MapSymb || s.Kind == SymbolKind.UnnSymb) { processed.Add(s); stack.Push((UserSymbol)s); } } AppFreeCanUnn otherCanUnn; UserSymbol n; while (stack.Count > 0) { n = stack.Pop(); elements.Remove(n); if (n.Kind == SymbolKind.ConSymb) { elements.Add(((ConSymb)n).SortSymbol); } else if (n.Kind == SymbolKind.MapSymb) { elements.Add(((MapSymb)n).SortSymbol); } else if (n.CanonicalForm != null) { elements.UnionWith(n.CanonicalForm[0].elements); intervals.UnionWith(n.CanonicalForm[0].intervals); } else { otherCanUnn = (AppFreeCanUnn)n.Definitions.First <AST <Node> >().Node.CompilerData; intervals.UnionWith(otherCanUnn.intervals); foreach (var sp in otherCanUnn.elements) { if (processed.Contains(sp)) { continue; } if (sp.Kind == SymbolKind.ConSymb || sp.Kind == SymbolKind.MapSymb || sp.Kind == SymbolKind.UnnSymb) { processed.Add(sp); stack.Push((UserSymbol)sp); } else { elements.Add(sp); } } } } //// Step 2. Apply a set of simplification rules to canonize combinations of base sorts var realSort = table.GetSortSymbol(BaseSortKind.Real); var intSort = table.GetSortSymbol(BaseSortKind.Integer); var natSort = table.GetSortSymbol(BaseSortKind.Natural); var negSort = table.GetSortSymbol(BaseSortKind.NegInteger); var posSort = table.GetSortSymbol(BaseSortKind.PosInteger); var strSort = table.GetSortSymbol(BaseSortKind.String); //// PosInteger + {0} = Natural if (elements.Contains(posSort) && intervals.Contains(BigInteger.Zero, BigInteger.Zero)) { elements.Add(natSort); } //// Natural + NegInteger = Integer if (elements.Contains(negSort) && elements.Contains(natSort)) { elements.Add(intSort); } //// Removed subsumed sorts. if (elements.Contains(realSort)) { intervals.Clear(); elements.Remove(intSort); elements.Remove(natSort); elements.Remove(negSort); elements.Remove(posSort); } else if (elements.Contains(intSort)) { intervals.Clear(); elements.Remove(natSort); elements.Remove(negSort); elements.Remove(posSort); } if (elements.Contains(natSort)) { BigInteger min, max; if (intervals.GetExtrema(out min, out max)) { intervals.Remove(BigInteger.Zero, BigInteger.Max(BigInteger.Zero, max)); } elements.Remove(posSort); } else if (elements.Contains(posSort)) { BigInteger min, max; if (intervals.GetExtrema(out min, out max)) { intervals.Remove(BigInteger.One, BigInteger.Max(BigInteger.One, max)); } } if (elements.Contains(negSort)) { BigInteger min, max; if (intervals.GetExtrema(out min, out max)) { intervals.Remove(BigInteger.Min(BigInteger.MinusOne, min), BigInteger.MinusOne); } } if (elements.Contains(strSort)) { var dropList = new List <Symbol>(); foreach (var e in elements) { if (e.Kind == SymbolKind.BaseCnstSymb && ((BaseCnstSymb)e).CnstKind == CnstKind.String) { dropList.Add(e); } } foreach (var e in dropList) { elements.Remove(e); } } if (elements.Count == 0 && intervals.Count == 0) { var flag = new Flag( SeverityKind.Error, typeExpr.Node, Constants.BadTypeDecl.ToString(myName, "it has no members"), Constants.BadTypeDecl.Code); flags.Add(flag); return(false); } else { if (intervals.Count > 0) { ContainsConstants = true; } else { foreach (var e in elements) { if (e.Kind == SymbolKind.BaseCnstSymb || e.Kind == SymbolKind.UserCnstSymb || e.Kind == SymbolKind.BaseSortSymb) { ContainsConstants = true; break; } } } } return(true); }