示例#1
0
 public Combinator(MatchedVariables variables, IList <Predicate> predicates,
                   IList <Expression> expressions, HashSet <Fact> allFacts)
 {
     this.variables      = variables;
     this.expressions    = expressions;
     this.allFacts       = allFacts;
     this.currentIt      = null;
     this.pred           = predicates.FirstOrDefault();
     this.fit            = allFacts.Where(fact => fact.MatchPredicate(this.pred)).GetEnumerator();
     this.nextPredicates = predicates.Skip(1).ToList();
 }
示例#2
0
        // do not produce new facts, only find one matching set of facts
        public bool Test(HashSet <Fact> facts)
        {
            HashSet <ulong> variables_set = new HashSet <ulong>();

            foreach (Predicate pred in this.Body)
            {
                variables_set.AddAll(pred.Ids.Where((id) => id is ID.Variable).Select(id => ((ID.Variable)id).Value));
            }
            MatchedVariables variables = new MatchedVariables(variables_set);

            if (!this.Body.Any())
            {
                return(variables.CheckExpressions(this.Expressions).IsDefined);
            }

            Combinator c = new Combinator(variables, this.Body, this.Expressions, facts);

            return(c.Next().IsDefined);
        }
示例#3
0
        public Option <MatchedVariables> Next()
        {
            bool hasNext = true;

            while (hasNext)
            {
                if (this.currentIt == null)
                {
                    // we iterate over the facts that match the current predicate
                    if (this.fit.MoveNext())
                    {
                        Fact currentFact = this.fit.Current;

                        // create a new MatchedVariables in which we fix variables we could unify from our first predicate and the current fact
                        MatchedVariables vars      = this.variables.Clone();
                        bool             match_ids = true;

                        // we know the fact matches the predicate's format so they have the same number of terms
                        // fill the MatchedVariables before creating the next combinator
                        for (int i = 0; i < pred.Ids.Count && match_ids; ++i)
                        {
                            ID id = pred.Ids[i];
                            if (id is ID.Variable idVariable)
                            {
                                ulong key   = idVariable.Value;
                                ID    value = currentFact.Predicate.Ids[i];

                                if (!vars.Insert(key, value))
                                {
                                    match_ids = false;
                                }
                            }
                        }

                        if (match_ids)
                        {
                            // there are no more predicates to check
                            if (!nextPredicates.Any())
                            {
                                Option <Dictionary <ulong, ID> > v_opt = vars.CheckExpressions(this.expressions);
                                if (v_opt.IsDefined)
                                {
                                    return(Option <MatchedVariables> .Some(vars));
                                }
                            }
                            else
                            {
                                // we found a matching fact, we create a new combinator over the rest of the predicates
                                // no need to copy all of the expressions at all levels
                                this.currentIt = new Combinator(vars, nextPredicates, new List <Expression>(), this.allFacts);
                            }
                        }
                    }
                    else
                    {
                        hasNext = false;
                    }
                }
                else
                {
                    Option <MatchedVariables> nextVarsOpt = this.currentIt.Next();
                    // the iterator is empty, try with the next fact
                    if (nextVarsOpt.IsDefined)
                    {
                        MatchedVariables nextVars = nextVarsOpt.Get();

                        Option <Dictionary <ulong, ID> > v_opt = nextVars.CheckExpressions(this.expressions);
                        if (v_opt.IsDefined)
                        {
                            return(Option <MatchedVariables> .Some(nextVars));
                        }
                    }
                    else
                    {
                        this.currentIt = null;
                    }
                }
            }

            return(Option <MatchedVariables> .None());
        }
示例#4
0
        public void Apply(HashSet <Fact> facts, HashSet <Fact> newFacts, HashSet <ulong> restrictedSymbols)
        {
            HashSet <ulong> variablesSet = new HashSet <ulong>();

            foreach (Predicate pred in this.Body)
            {
                variablesSet.AddAll(pred.Ids.Where(id => id is ID.Variable).Select(id => ((ID.Variable)id).Value));
            }
            MatchedVariables variables = new MatchedVariables(variablesSet);

            if (!this.Body.Any())
            {
                Option <Dictionary <ulong, ID> > h_opt = variables.CheckExpressions(this.Expressions);
                if (h_opt.IsDefined)
                {
                    Dictionary <ulong, ID> h = h_opt.Get();
                    Predicate predicate      = this.Head.Clone();

                    for (int i = 0; i < predicate.Ids.Count; i++)
                    {
                        ID id = predicate.Ids[i];
                        if (id is ID.Variable)
                        {
                            ID value = h[((ID.Variable)id).Value];
                            predicate.Ids[i] = value;
                        }
                    }

                    newFacts.Add(new Fact(predicate));
                }
            }

            var combined = new Combinator(variables, this.Body, this.Expressions, facts).Combine();

            foreach (Dictionary <ulong, ID> h in combined)
            {
                Predicate predicate        = this.Head.Clone();
                bool      unbound_variable = false;

                for (int i = 0; i < predicate.Ids.Count; i++)
                {
                    ID id = predicate.Ids[i];
                    if (id is ID.Variable)
                    {
                        bool isInDictionnary = h.TryGetValue(((ID.Variable)id).Value, out ID value);

                        predicate.Ids[i] = value;
                        // variables that appear in the head should appear in the body and constraints as well
                        if (value == null)
                        {
                            unbound_variable = true;
                        }
                    }
                }
                // if the generated fact has #authority or #ambient as first element and we're n ot in a privileged rule
                // do not generate it
                bool isRestrictedSymbol = false;
                ID   first = predicate.Ids.FirstOrDefault();
                if (first != null && first is ID.Symbol)
                {
                    if (restrictedSymbols.Contains(((ID.Symbol)first).Value))
                    {
                        isRestrictedSymbol = true;
                    }
                }
                if (!unbound_variable && !isRestrictedSymbol)
                {
                    newFacts.Add(new Fact(predicate));
                }
            }
        }