/** 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; }
@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()); }
@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)); }