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)); } } }