public ActionSet(ComprehensionData comprData) { Contract.Requires(comprData != null); AST = Factory.Instance.ToAST(comprData.Node); Index = comprData.Owner.Index; myComprData = comprData; TypeEnvironment = comprData.Owner.TypeEnvironment.AddChild(comprData.Node); IsCompiled = LiftedBool.Unknown; }
private bool RecordValidationResult(bool result) { if (!result) { IsCompiled = LiftedBool.False; } return(result); }
public ActionSet(AST <Node> ast, TermIndex index) { Contract.Requires(index != null && ast != null); Contract.Requires(ast.Node.NodeKind == NodeKind.Rule || ast.Node.NodeKind == NodeKind.ContractItem); //// TODO: Accept contract specifications too. AST = ast; Index = index; myComprData = null; TypeEnvironment = new TypeEnvironment(ast.Node, index); IsCompiled = LiftedBool.Unknown; }
/// <summary> /// Compiles the action set into a set of rules. Should not be called if validation failed. /// </summary> public bool Compile(RuleTable rules, List <Flag> flags, CancellationToken cancel) { bool result = true; if (IsCompiled != LiftedBool.Unknown) { return((bool)IsCompiled); } else if (myComprData == null) { foreach (var a in actions) { result = a.Compile(rules, flags, cancel) && result; } return((bool)(IsCompiled = result)); } //// For a comprehension need to compile the bodies of the actions //// before compiling the actions, so a representation for the comprehension is known. FindData[] parts; var bodies = new LinkedList <Term>(); foreach (var a in actions) { result = a.Body.Compile(rules, out parts, flags, cancel) && result; if (result) { bodies.AddLast(rules.MkBodyTerm(parts)); } } if (!result) { return((bool)(IsCompiled = result)); } bool wasAdded; Term reads = Index.TrueValue; var comprSymbol = Index.SymbolTable.GetOpSymbol(ReservedOpKind.Compr); var conjSymbol = Index.SymbolTable.GetOpSymbol(ReservedOpKind.Conj); foreach (var kv in myComprData.ReadVars.Reverse) { reads = Index.MkApply(conjSymbol, new Term[] { kv.Key, reads }, out wasAdded); } var headSet = new Set <Term>(Term.Compare); foreach (var a in actions) { headSet.Add(a.HeadTerm); } Term heads = Index.TrueValue; foreach (var h in headSet.Reverse) { heads = Index.MkApply(conjSymbol, new Term[] { h, heads }, out wasAdded); } myComprData.Representation = Index.MkApply(comprSymbol, new Term[] { heads, reads, rules.MkBodiesTerm(bodies) }, out wasAdded); foreach (var a in actions) { result = a.Compile(rules, flags, cancel) && result; } return((bool)(IsCompiled = result)); }
/// <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)); }