@Override public void visit(KCollectionFragment kCollectionFragment) { for (Term term : kCollectionFragment) { term.accept(this); } visit((Collection) kCollectionFragment); }
@Override public ASTNode visit(org.kframework.kil.KApp node, Void _void) { if (node.getLabel() instanceof org.kframework.kil.Token) { if (node.getLabel() instanceof BoolBuiltin) { return BoolToken.of(((BoolBuiltin) node.getLabel()).booleanValue()); } else if (node.getLabel() instanceof IntBuiltin) { return IntToken.of(((IntBuiltin) node.getLabel()).bigIntegerValue()); } else if (node.getLabel() instanceof StringBuiltin) { return StringToken.of(((StringBuiltin) node.getLabel()).stringValue()); } else if (node.getLabel() instanceof FloatBuiltin) { return FloatToken.of( ((FloatBuiltin) node.getLabel()).bigFloatValue(), ((FloatBuiltin) node.getLabel()).exponent()); } else if (node.getLabel() instanceof GenericToken) { return UninterpretedToken.of( Sort.of(((GenericToken) node.getLabel()).tokenSort()), ((GenericToken) node.getLabel()).value()); } else { assert false : "unsupported Token " + node.getLabel(); } } Term kLabel = (Term) this.visitNode(node.getLabel()); Term kList = (Term) this.visitNode(node.getChild()); if (kList instanceof Variable) { kList = kList.sort().equals(Sort.KLIST) ? kList : KList.singleton(kList); } return KItem.of(kLabel, kList, termContext, node.getSource(), node.getLocation()); }
@Override public void visit(SetUpdate setUpdate) { setUpdate.base().accept(this); for (Term key : setUpdate.removeSet()) { key.accept(this); } }
/** 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 void visit(BuiltinSet builtinSet) { for (Term term : builtinSet.elements()) { term.accept(this); } // for (BuiltinSet.Operation operation : builtinSet.operations()) { // operation.element().accept(this); // } visit((Collection) builtinSet); }
@Override public void visit(MapUpdate mapUpdate) { mapUpdate.map().accept(this); for (Term key : mapUpdate.removeSet()) { key.accept(this); } for (java.util.Map.Entry<Term, Term> entry : mapUpdate.updateMap().entrySet()) { entry.getKey().accept(this); entry.getValue().accept(this); } }
@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); } }
@Override public void visit(KList node) { if (node.isGround() && node.isNormal()) { rhsSchedule.add(RHSInstruction.PUSH(node)); } else { int size = 0; if (node.hasFrame()) { node.frame().accept(this); size++; } for (int i = node.concreteSize() - 1; i >= 0; i--) { Term k = node.get(i); k.accept(this); size++; } rhsSchedule.add(RHSInstruction.CONSTRUCT(new Constructor(ConstructorType.KLIST, size))); } }
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 void visit(BuiltinSet node) { if (node.isGround() && node.isNormal()) { rhsSchedule.add(RHSInstruction.PUSH(node)); } else { int sizeBase = 0; for (Term base : node.baseTerms()) { base.accept(this); sizeBase++; } int sizeElem = 0; for (Term elem : node.elements()) { elem.accept(this); sizeElem++; } rhsSchedule.add( RHSInstruction.CONSTRUCT( new Constructor(ConstructorType.BUILTIN_SET, sizeElem, sizeBase))); } }
@Override public void visit(BuiltinMap node) { if (node.isGround() && node.isNormal()) { rhsSchedule.add(RHSInstruction.PUSH(node)); } else { int sizeBase = 0; for (Term base : node.baseTerms()) { base.accept(this); sizeBase++; } int sizeElem = 0; for (Map.Entry<Term, Term> entry : node.getEntries().entrySet()) { entry.getValue().accept(this); entry.getKey().accept(this); sizeElem++; } rhsSchedule.add( RHSInstruction.CONSTRUCT( new Constructor(ConstructorType.BUILTIN_MAP, sizeElem, sizeBase))); } }
// 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(); }
/** * Given a term, it uses queries the index table to find the rules that may apply. * * @param term The term being re-written * @return A list of rules that may apply */ @Override public List<Rule> getRules(Term term) { Set<Rule> rules = new LinkedHashSet<>(); for (IndexingPair pair : term.getIndexingPairs(definition)) { if (ruleTable.get(pair.first) != null) { rules.addAll(ruleTable.get(pair.first)); } if (heatingRuleTable.get(pair.first) != null) { rules.addAll(heatingRuleTable.get(pair.first)); } if (coolingRuleTable.get(pair.second) != null) { rules.addAll(coolingRuleTable.get(pair.second)); } } rules.addAll(unindexedRules); return new ArrayList<>(rules); }
@Override public ASTNode transform(KItem kItem) { if (!(kItem.kLabel() instanceof KLabelConstant)) { throw new UnsupportedOperationException(); } KLabelConstant kLabel = (KLabelConstant) kItem.kLabel(); if (!(kItem.kList() instanceof KList)) { throw new UnsupportedOperationException(); } KList kList = (KList) kItem.kList(); if (kList.hasFrame()) { throw new UnsupportedOperationException(); } String label = kLabel.smtlib(); if (label == null) { throw new UnsupportedOperationException("missing SMTLib translation for " + kLabel); } if (label.startsWith("(")) { // smtlib expression instead of operator String expression = label; for (int i = 0; i < kList.getContents().size(); i++) { expression = expression.replaceAll( "\\#" + (i + 1) + "(?![0-9])", ((SMTLibTerm) kList.get(i).accept(this)).expression()); } return new SMTLibTerm(expression); } List<Term> arguments; switch (label) { case "exists": Variable variable = (Variable) kList.get(0); label = "exists ((" + variable.name() + " " + variable.sort() + ")) "; arguments = ImmutableList.of(kList.get(1)); break; case "extract": int beginIndex = ((IntToken) kList.get(1)).intValue(); int endIndex = ((IntToken) kList.get(2)).intValue() - 1; label = "(_ extract " + endIndex + " " + beginIndex + ")"; arguments = ImmutableList.of(kList.get(0)); break; default: arguments = kList.getContents(); } if (!arguments.isEmpty()) { StringBuilder sb = new StringBuilder(); sb.append("("); sb.append(label); for (Term argument : arguments) { sb.append(" "); sb.append(((SMTLibTerm) argument.accept(this)).expression()); } sb.append(")"); return new SMTLibTerm(sb.toString()); } else { return new SMTLibTerm(label); } }
@Override public void visit(BuiltinList node) { if (node.hasFrame()) node.frame().accept(this); for (Term t : node.elementsLeft()) t.accept(this); for (Term t : node.elementsRight()) t.accept(this); }
@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; } }
public static Term expand( Term term, SymbolicConstraint constraint, boolean narrow, TermContext context) { return (Term) term.accept(new PatternExpander(constraint, narrow, context)); }
public static Term expandAndEvaluate(TermContext termContext, KExceptionManager kem, Term term) { term = new MacroExpander(termContext, kem).processTerm(term); term = term.evaluate(termContext); return term; }
@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)); }