private static String getAxioms(Definition definition) { StringBuilder sb = new StringBuilder(); for (Rule rule : definition.functionRules().values()) { if (rule.containsAttribute(Attribute.SMT_LEMMA_KEY)) { try { KILtoSMTLib transformer = new KILtoSMTLib(false); String leftExpression = ((SMTLibTerm) rule.leftHandSide().accept(transformer)).expression(); String rightExpression = ((SMTLibTerm) rule.rightHandSide().accept(transformer)).expression(); sb.append("(assert (forall ("); sb.append(getQuantifiedVariables(transformer.variables())); sb.append(") (! (= "); sb.append(leftExpression); sb.append(" "); sb.append(rightExpression); sb.append(") :pattern("); sb.append(leftExpression); sb.append("))))\n"); } catch (UnsupportedOperationException e) { } } } return sb.toString(); }
/** Partially evaluate the right-hand side and the conditions for each rule. */ private static Definition evaluateDefinition(TermContext termContext) { Definition definition = termContext.global().getDefinition(); /* replace the unevaluated rules defining functions with their partially evaluated counterparts */ ArrayList<Rule> partiallyEvaluatedRules = new ArrayList<>(); /* iterate until a fixpoint is reached, because the evaluation with functions uses Term#substituteAndEvalaute */ while (true) { boolean change = false; partiallyEvaluatedRules.clear(); for (Rule rule : Iterables.concat( definition.functionRules().values(), definition.anywhereRules().values())) { Rule freshRule = rule.getFreshRule(termContext); Rule evaluatedRule = evaluateRule(freshRule, termContext); partiallyEvaluatedRules.add(evaluatedRule); if (!evaluatedRule.equals(freshRule)) { change = true; } } if (!change) { break; } definition.functionRules().clear(); definition.anywhereRules().clear(); definition.addRuleCollection(partiallyEvaluatedRules); } /* replace the unevaluated rules and macros with their partially evaluated counterparts */ partiallyEvaluatedRules.clear(); Iterable<Rule> rules = Iterables.concat( definition.rules(), definition.macros(), definition.patternRules().values(), definition.patternFoldingRules()); for (Rule rule : rules) { partiallyEvaluatedRules.add(evaluateRule(rule, termContext)); } definition.rules().clear(); definition.macros().clear(); definition.patternRules().clear(); definition.patternFoldingRules().clear(); definition.addRuleCollection(partiallyEvaluatedRules); return definition; }
// apply rule by matching private void rewriteByRule(Term term, Rule rule) { stopwatch.reset(); stopwatch.start(); termResults = new ArrayList<Term>(); TermContext context = TermContext.of(definition); ConstrainedTerm constrainedTerm = new ConstrainedTerm(term, context); SymbolicConstraint leftHandSideConstraint = new SymbolicConstraint(context); leftHandSideConstraint.addAll(rule.requires()); for (Variable variable : rule.freshVariables()) { leftHandSideConstraint.add(variable, IntToken.fresh()); } ConstrainedTerm leftHandSide = new ConstrainedTerm( rule.leftHandSide(), rule.lookups().getSymbolicConstraint(context), leftHandSideConstraint, context); for (SymbolicConstraint constraint : constrainedTerm.unify(leftHandSide)) { if (!constraint.isMatching(leftHandSide)) { continue; } constraint.orientSubstitution(leftHandSide.variableSet()); Term result = rule.rightHandSide(); /* apply the constraints substitution on the rule RHS */ result = result.substituteAndEvaluate(constraint.substitution(), context); /* compute all results */ termResults.add(result); } stopwatch.stop(); }
@Override public void visit(Rule rule) { rule.leftHandSide().accept(this); rule.rightHandSide().accept(this); rule.lookups().accept(this); for (Term term : rule.requires()) { term.accept(this); } for (Term term : rule.ensures()) { term.accept(this); } for (Variable variable : rule.freshVariables()) { variable.accept(this); } }
private void narrowByRule(ConstrainedTerm constrainedTerm, Rule rule) { stopwatch.reset(); stopwatch.start(); constrainedTermResults = new ArrayList<ConstrainedTerm>(); SymbolicConstraint leftHandSideConstraint = new SymbolicConstraint(constrainedTerm.termContext()); leftHandSideConstraint.addAll(rule.requires()); for (Variable variable : rule.freshVariables()) { leftHandSideConstraint.add(variable, IntToken.fresh()); } ConstrainedTerm leftHandSide = new ConstrainedTerm( rule.leftHandSide(), rule.lookups().getSymbolicConstraint(constrainedTerm.termContext()), leftHandSideConstraint, constrainedTerm.termContext()); for (SymbolicConstraint constraint : constrainedTerm.unify(leftHandSide)) { constraint.addAll(rule.ensures()); /* rename rule variables in the constraints */ Map<Variable, Variable> freshSubstitution = constraint.rename(rule.variableSet()); Term result = rule.rightHandSide(); /* rename rule variables in the rule RHS */ result = result.substituteWithBinders(freshSubstitution, constrainedTerm.termContext()); /* apply the constraints substitution on the rule RHS */ result = result.substituteWithBinders(constraint.substitution(), constrainedTerm.termContext()); /* evaluate pending functions in the rule RHS */ result = result.evaluate(constrainedTerm.termContext()); /* eliminate anonymous variables */ constraint.eliminateAnonymousVariables(); /* compute all results */ constrainedTermResults.add( new ConstrainedTerm(result, constraint, constrainedTerm.termContext())); } stopwatch.stop(); }
@Override public KRunProofResult<Set<org.kframework.kil.Term>> prove(Module module) throws KRunExecutionException { TermContext termContext = TermContext.of(globalContext); List<Rule> rules = new ArrayList<Rule>(); for (org.kframework.kil.ModuleItem moduleItem : module.getItems()) { if (!(moduleItem instanceof org.kframework.kil.Rule)) { continue; } Rule rule = transformer.transformAndEval((org.kframework.kil.Rule) moduleItem); Rule freshRule = rule.getFreshRule(termContext); rules.add(freshRule); } CounterGetter counterGetter = new CounterGetter(context); counterGetter.visitNode(module); BigInteger counter = counterGetter.counter.add(BigInteger.ONE); SymbolicRewriter symbolicRewriter = executor.getSymbolicRewriter(); List<ConstrainedTerm> proofResults = new ArrayList<>(); for (org.kframework.kil.ModuleItem moduleItem : module.getItems()) { if (!(moduleItem instanceof org.kframework.kil.Rule) || moduleItem.containsAttribute(Attribute.TRUSTED_KEY)) { continue; } termContext.setCounter(counter); Rule rule = transformer.transformAndEval((org.kframework.kil.Rule) moduleItem); ConstrainedTerm initialTerm = new ConstrainedTerm( rule.leftHandSide(), ConjunctiveFormula.of(termContext).addAll(rule.requires())); ConstrainedTerm targetTerm = new ConstrainedTerm( rule.rightHandSide(), ConjunctiveFormula.of(termContext).addAll(rule.ensures())); proofResults.addAll(symbolicRewriter.proveRule(initialTerm, targetTerm, rules)); } return new KRunProofResult<>( proofResults.isEmpty(), Collections.<org.kframework.kil.Term>emptySet()); }
/** Partially evaluate the right-hand side and the conditions of a specified rule. */ private static Rule evaluateRule(Rule rule, TermContext termContext) { try { // TODO(AndreiS): some evaluation is required in the LHS as well // TODO(YilongL): cannot simply uncomment the following code because it // may evaluate the LHS using the rule itself // Term leftHandSide = rule.leftHandSide().evaluate(termContext); Rule origRule = rule; Term rightHandSide = rule.rightHandSide().evaluate(termContext); List<Term> requires = new ArrayList<>(); for (Term term : rule.requires()) { requires.add(term.evaluate(termContext)); } List<Term> ensures = new ArrayList<>(); for (Term term : rule.ensures()) { ensures.add(term.evaluate(termContext)); } ConjunctiveFormula lookups = ConjunctiveFormula.of(termContext); for (Equality equality : rule.lookups().equalities()) { lookups = lookups.add( equality.leftHandSide().evaluate(termContext), equality.rightHandSide().evaluate(termContext)); } Map<CellLabel, Term> rhsOfWriteCell = null; if (rule.isCompiledForFastRewriting()) { rhsOfWriteCell = new HashMap<>(); for (Map.Entry<CellLabel, Term> entry : rule.rhsOfWriteCell().entrySet()) { rhsOfWriteCell.put(entry.getKey(), entry.getValue().evaluate(termContext)); } } Rule newRule = new Rule( rule.label(), rule.leftHandSide(), rightHandSide, requires, ensures, rule.freshConstants(), rule.freshVariables(), lookups, rule.isCompiledForFastRewriting(), rule.lhsOfReadCell(), rhsOfWriteCell, rule.cellsToCopy(), rule.matchingInstructions(), rule, termContext); return newRule.equals(rule) ? origRule : newRule; } catch (KEMException e) { e.exception.addTraceFrame( "while compiling rule at location " + rule.getSource() + rule.getLocation()); throw e; } }
@Override public ASTNode visit(org.kframework.kil.Rule node, Void _void) { try { assert node.getBody() instanceof org.kframework.kil.Rewrite; JavaBackendRuleData ruleData = node.getAttribute(JavaBackendRuleData.class); if (ruleData == null) { ruleData = new JavaBackendRuleData(); } concreteCollectionSize = ruleData.getConcreteDataStructureSize(); org.kframework.kil.Rewrite rewrite = (org.kframework.kil.Rewrite) node.getBody(); Term leftHandSide = (Term) this.visitNode(rewrite.getLeft()); Term rightHandSide = (Term) this.visitNode(rewrite.getRight()); List<Term> requires = new ArrayList<>(); if (node.getRequires() != null) { transformConjunction(requires, (Term) this.visitNode(node.getRequires())); } List<Term> ensures = new ArrayList<>(); if (node.getEnsures() != null) { transformConjunction(ensures, (Term) this.visitNode(node.getEnsures())); } ConjunctiveFormula lookups = ConjunctiveFormula.of(termContext); for (org.kframework.kil.BuiltinLookup lookup : ruleData.getLookups()) { Variable base = (Variable) this.visitNode(lookup.base()); Term key = (Term) this.visitNode(lookup.key()); if (lookup instanceof org.kframework.kil.SetLookup) { if (lookup.choice()) { lookups = lookups.add(DataStructures.choice(base, termContext), key); } else { lookups = lookups.add(DataStructures.lookup(base, key, termContext), BoolToken.TRUE); } } else { Term value = (Term) this.visitNode(lookup.value()); if (lookup instanceof org.kframework.kil.MapLookup) { if (lookup.choice()) { lookups = lookups.add(DataStructures.choice(base, termContext), key); } lookups = lookups.add(DataStructures.lookup(base, key, termContext), value); } else { // ListLookup lookups = lookups.add(DataStructures.lookup(base, key, termContext), value); } } } // TODO(AndreiS): check !Variable only appears in the RHS Set<Variable> freshConstants = node.getBody() .variables() .stream() .filter(v -> v.isFreshConstant()) .map(v -> (Variable) this.visitNode(v)) .collect(Collectors.toSet()); Set<Variable> freshVariables = node.getBody() .variables() .stream() .filter(v -> v.isFreshVariable()) .map(v -> (Variable) this.visitNode(v)) .collect(Collectors.toSet()); assert leftHandSide.kind() == rightHandSide.kind() || leftHandSide.kind().isComputational() && rightHandSide.kind().isComputational(); concreteCollectionSize = Collections.emptyMap(); java.util.Map<CellLabel, Term> lhsOfReadCell = null; java.util.Map<CellLabel, Term> rhsOfWriteCell = null; if (ruleData.isCompiledForFastRewriting()) { lhsOfReadCell = Maps.newHashMap(); for (java.util.Map.Entry<String, org.kframework.kil.Term> entry : ruleData.getLhsOfReadCell().entrySet()) { lhsOfReadCell.put(CellLabel.of(entry.getKey()), (Term) this.visitNode(entry.getValue())); } rhsOfWriteCell = Maps.newHashMap(); for (java.util.Map.Entry<String, org.kframework.kil.Term> entry : ruleData.getRhsOfWriteCell().entrySet()) { rhsOfWriteCell.put(CellLabel.of(entry.getKey()), (Term) this.visitNode(entry.getValue())); } } java.util.Set<CellLabel> cellsToCopy = null; if (ruleData.getCellsToCopy() != null) { cellsToCopy = Sets.newHashSet(); for (String cellLabelName : ruleData.getCellsToCopy()) { cellsToCopy.add(CellLabel.of(cellLabelName)); } } Rule rule = new Rule( node.getLabel(), leftHandSide, rightHandSide, requires, ensures, freshConstants, freshVariables, lookups, ruleData.isCompiledForFastRewriting(), lhsOfReadCell, rhsOfWriteCell, cellsToCopy, ruleData.getMatchingInstructions(), node, termContext); if (freshRules) { return rule.getFreshRule(termContext); } return rule; } catch (KEMException e) { e.exception.addTraceFrame( "while compiling rule at " + node.getSource() + node.getLocation() + " to backend"); throw e; } }
@Override public ASTNode transform(org.kframework.kil.Rule node) throws TransformerException { assert node.getBody() instanceof org.kframework.kil.Rewrite; org.kframework.kil.Rewrite rewrite = (org.kframework.kil.Rewrite) node.getBody(); Term leftHandSide = (Term) rewrite.getLeft().accept(this); Term rightHandSide = (Term) rewrite.getRight().accept(this); Collection<Term> requires = new ArrayList<Term>(); Collection<Variable> freshVariables = new ArrayList<Variable>(); // TODO: Deal with Ensures if (node.getRequires() != null) { Term term = (Term) node.getRequires().accept(this); if (term instanceof KItem && ((KItem) term).kLabel().toString().equals("'_andBool_")) { for (Term item : ((KItem) term).kList().getItems()) { if (item instanceof KItem && ((KItem) item).kLabel().toString().equals("'fresh(_)")) { freshVariables.add((Variable) ((KItem) item).kList().get(0)); } else { requires.add(item); } } } else { if (term instanceof KItem && ((KItem) term).kLabel().toString().equals("'fresh(_)")) { freshVariables.add((Variable) ((KItem) term).kList().get(0)); } else { requires.add(term); } } } SymbolicConstraint lookups = new SymbolicConstraint(new TermContext(definition)); for (org.kframework.kil.BuiltinLookup lookup : node.getLookups()) { Variable base = (Variable) lookup.base().accept(this); Term key = (Term) lookup.key().accept(this); if (lookup instanceof org.kframework.kil.SetLookup) { lookups.add(new SetLookup(base, key), BoolToken.TRUE); } else { Term value = (Term) lookup.value().accept(this); if (lookup instanceof org.kframework.kil.MapLookup) { lookups.add(new MapLookup(base, key), value); } else { // ListLookup lookups.add(new ListLookup(base, key), value); } } } assert leftHandSide.kind() == rightHandSide.kind() || ((leftHandSide.kind() == Kind.KITEM || leftHandSide.kind() == Kind.K || leftHandSide.kind() == Kind.KLIST) && (rightHandSide.kind() == Kind.KITEM || rightHandSide.kind() == Kind.K || rightHandSide.kind() == Kind.KLIST)); Rule rule = new Rule( leftHandSide, rightHandSide, requires, freshVariables, lookups, node.getAttributes()); return rule.getFreshRule(new TermContext(definition)); }
@Override public void buildIndex() { /* populate the table of rules rewriting the top configuration */ List<Index> indices = new ArrayList<Index>(); indices.add(TopIndex.TOP); indices.add(BottomIndex.BOTTOM); for (KLabelConstant kLabel : definition.kLabels()) { indices.add(new KLabelIndex(kLabel)); indices.add(new FreezerIndex(kLabel, -1)); if (!kLabel.productions().isEmpty()) { int maxArity = getMaxArityForProductions(kLabel.productions()); for (int i = 0; i < maxArity; ++i) { indices.add(new FreezerIndex(kLabel, i)); } } } // for (KLabelConstant frozenKLabel : definition.frozenKLabels()) { // for (int i = 0; i < frozenKLabel.productions().get(0).getArity(); ++i) { // indices.add(new FreezerIndex(frozenKLabel, i)); // } // } for (String sort : definition.builtinSorts()) { indices.add(new TokenIndex(sort)); } /* Map each index to a list of rules unifiable with that index */ /* Heating rules and regular rules have their first index checked */ /* Cooling rules have their second index checked */ ImmutableMap.Builder<Index, List<Rule>> mapBuilder = ImmutableMap.builder(); ImmutableMap.Builder<Index, List<Rule>> heatingMapBuilder = ImmutableMap.builder(); ImmutableMap.Builder<Index, List<Rule>> coolingMapBuilder = ImmutableMap.builder(); ImmutableMap.Builder<Index, List<Rule>> simulationMapBuilder = ImmutableMap.builder(); for (Index index : indices) { ImmutableList.Builder<Rule> listBuilder = ImmutableList.builder(); ImmutableList.Builder<Rule> heatingListBuilder = ImmutableList.builder(); ImmutableList.Builder<Rule> coolingListBuilder = ImmutableList.builder(); ImmutableList.Builder<Rule> simulationListBuilder = ImmutableList.builder(); for (Rule rule : definition.rules()) { if (rule.containsAttribute("heat")) { if (index.isUnifiable(rule.indexingPair().first)) { heatingListBuilder.add(rule); } } else if (rule.containsAttribute("cool")) { if (index.isUnifiable(rule.indexingPair().second)) { coolingListBuilder.add(rule); } } else if (rule.containsAttribute("alphaRule")) { if (index.isUnifiable(rule.indexingPair().first)) { simulationListBuilder.add(rule); } } else { if (index.isUnifiable(rule.indexingPair().first)) { listBuilder.add(rule); } } } ImmutableList<Rule> rules = listBuilder.build(); if (!rules.isEmpty()) { mapBuilder.put(index, rules); } rules = heatingListBuilder.build(); if (!rules.isEmpty()) { heatingMapBuilder.put(index, rules); } rules = coolingListBuilder.build(); if (!rules.isEmpty()) { coolingMapBuilder.put(index, rules); } rules = simulationListBuilder.build(); if (!rules.isEmpty()) { simulationMapBuilder.put(index, rules); } } heatingRuleTable = heatingMapBuilder.build(); coolingRuleTable = coolingMapBuilder.build(); ruleTable = mapBuilder.build(); simulationRuleTable = simulationMapBuilder.build(); ImmutableList.Builder<Rule> listBuilder = ImmutableList.builder(); for (Rule rule : definition.rules()) { if (!rule.containsKCell()) { listBuilder.add(rule); } } unindexedRules = listBuilder.build(); }