Пример #1
0
        /// <summary>
        /// If arg : argType must be a subtype of acceptingType, then returns
        /// a possibly coerced term satisfying the property. The type of the
        /// coerced term is also returned.
        ///
        /// Returns null and generates errors of if the term cannot be
        /// coerced.
        ///
        /// If computeType is false, then the type of the coerced
        /// term is not returned.
        /// </summary>
        private Tuple <Term, Term> Coerce(AppFreeCanUnn acceptingType,
                                          Term arg,
                                          Term argType,
                                          int argIndex,
                                          Node appNode,
                                          string appFun,
                                          List <Flag> flags)
        {
            bool             wasAdded;
            Set <Namespace>  spaces;
            Namespace        maxPrefix   = null;
            LiftedBool       isCoercable = LiftedBool.True;
            Set <UserSymbol> dataSorts   = null;
            Term             resultType  = null;
            UserSymbol       us;
            UserSortSymb     uss;

            //// Step 1. Check that all constants are accepted, and all data sorts
            //// can potentially be coerced.
            //// After this loop, resultType contains all constants.
            argType.Visit(
                x => x.Symbol == theUnnSymbol ? x.Args : null,
                t =>
            {
                if (t.Symbol == theUnnSymbol)
                {
                    return;
                }
                else if (t.Symbol.Kind == SymbolKind.UserSortSymb ||
                         t.Symbol.IsDataConstructor ||
                         t.Symbol.IsDerivedConstant ||
                         (t.Symbol.Kind == SymbolKind.UserCnstSymb && ((UserCnstSymb)t.Symbol).IsTypeConstant))
                {
                    if (t.Symbol.Kind == SymbolKind.UserSortSymb)
                    {
                        uss = (UserSortSymb)t.Symbol;
                        us  = uss.DataSymbol;
                    }
                    else if (t.Symbol.IsDataConstructor)
                    {
                        us  = (UserSymbol)t.Symbol;
                        uss = us.Kind == SymbolKind.ConSymb ? ((ConSymb)us).SortSymbol : ((MapSymb)us).SortSymbol;
                    }
                    else
                    {
                        uss = null;
                        us  = (UserSymbol)t.Symbol;
                    }

                    if (maxPrefix == null)
                    {
                        maxPrefix = us.Namespace;
                    }
                    else
                    {
                        us.Namespace.TryGetPrefix(maxPrefix, out maxPrefix);
                    }

                    if (dataSorts == null)
                    {
                        dataSorts = new Set <UserSymbol>(Symbol.Compare);
                    }

                    dataSorts.Add(us);
                    if (!acceptingType.Contains(uss == null ? (Symbol)us : uss))
                    {
                        if (!acceptingType.TryGetRenamings(us.Name, out spaces))
                        {
                            var flag = new Flag(
                                SeverityKind.Error,
                                appNode,
                                Constants.UnsafeArgType.ToString(
                                    argIndex + 1,
                                    appFun,
                                    t.Symbol.PrintableName),
                                Constants.UnsafeArgType.Code);
                            flags.Add(flag);
                            isCoercable = LiftedBool.False;
                        }
                        else if (isCoercable == LiftedBool.True)
                        {
                            isCoercable = LiftedBool.Unknown;
                        }
                    }
                }
                else if (!acceptingType.AcceptsConstants(t))
                {
                    var flag = new Flag(
                        SeverityKind.Error,
                        appNode,
                        Constants.UnsafeArgType.ToString(
                            argIndex + 1,
                            appFun,
                            t.Symbol != theRngSymbol ? t.Symbol.PrintableName : (t.Args[0].Symbol.PrintableName + ".." + t.Args[1].Symbol.PrintableName)),
                        Constants.UnsafeArgType.Code);
                    flags.Add(flag);
                    isCoercable = LiftedBool.False;
                }
                else
                {
                    resultType = resultType == null
                                        ? t
                                        : Index.MkApply(theUnnSymbol, new Term[] { t, resultType }, out wasAdded);
                }
            });

            if (isCoercable == false)
            {
                return(null);
            }
            else if (isCoercable == true)
            {
                return(new Tuple <Term, Term>(arg, argType));
            }

            //// Step 2. Check that there is a unique coercion from the user sorts.
            Contract.Assert(dataSorts != null && maxPrefix != null);
            Set <Namespace> rnmgs = null, cndts;
            Namespace       prefix;

            string[] suffix;

            foreach (var s in dataSorts)
            {
                suffix = s.Namespace.Split(maxPrefix);
                Contract.Assert(suffix != null);

                acceptingType.TryGetRenamings(s.Name, out spaces);
                cndts = new Set <Namespace>(Namespace.Compare);
                foreach (var ns in spaces)
                {
                    if (ns.Split(suffix, out prefix))
                    {
                        cndts.Add(prefix);
                    }
                }

                if (rnmgs == null)
                {
                    rnmgs = cndts;
                }
                else
                {
                    rnmgs.IntersectWith(cndts);
                }

                if (rnmgs.Count == 0)
                {
                    var flag = new Flag(
                        SeverityKind.Error,
                        appNode,
                        Constants.UncoercibleArgType.ToString(
                            argIndex + 1,
                            appFun,
                            s.PrintableName),
                        Constants.UncoercibleArgType.Code);
                    flags.Add(flag);
                    return(null);
                }
            }

            if (rnmgs.Count != 1)
            {
                foreach (var ns in rnmgs)
                {
                    var flag = new Flag(
                        SeverityKind.Error,
                        appNode,
                        Constants.AmbiguousCoercibleArg.ToString(
                            argIndex + 1,
                            appFun,
                            maxPrefix.FullName,
                            ns.FullName),
                        Constants.AmbiguousCoercibleArg.Code);
                    flags.Add(flag);
                }

                return(null);
            }

            var    from = maxPrefix;
            var    to   = rnmgs.GetSomeElement();
            Symbol coerced;

            foreach (var ds in dataSorts)
            {
                if (ds.Kind == SymbolKind.UserCnstSymb)
                {
                    if (!Index.SymbolTable.IsCoercible(ds, from, to, out coerced))
                    {
                        coerced = null;
                    }
                }
                else
                {
                    uss = ds.Kind == SymbolKind.ConSymb ? ((ConSymb)ds).SortSymbol : ((MapSymb)ds).SortSymbol;
                    if (!Index.SymbolTable.IsCoercible(uss, from, to, out coerced))
                    {
                        coerced = null;
                    }
                }

                if (coerced == null)
                {
                    var flag = new Flag(
                        SeverityKind.Error,
                        appNode,
                        Constants.UncoercibleArgType.ToString(
                            argIndex + 1,
                            appFun,
                            ds.PrintableName),
                        Constants.UncoercibleArgType.Code);
                    flags.Add(flag);
                    return(null);
                }
                else
                {
                    resultType = resultType == null
                                    ? Index.MkApply(coerced, TermIndex.EmptyArgs, out wasAdded)
                                    : Index.MkApply(
                        theUnnSymbol,
                        new Term[] { Index.MkApply(coerced, TermIndex.EmptyArgs, out wasAdded), resultType },
                        out wasAdded);
                }
            }

            typeEnvironment.AddCoercion(appNode, argIndex, from.FullName, to.FullName);
            var coercedArg = Index.MkApply(
                Index.SymbolTable.GetOpSymbol(ReservedOpKind.Relabel),
                new Term[] {
                Index.MkCnst(from.FullName, out wasAdded),
                Index.MkCnst(to.FullName, out wasAdded),
                arg
            },
                out wasAdded);

            return(new Tuple <Term, Term>(coercedArg, resultType));
        }