mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Previously RewriteSystem::simplify() would attempt to apply every rewrite rule at every position in the original term, which was obviously a source of overhead. The trie itself is somewhat unoptimized; for example, with a bit of effort it could merge a node with its only child, if nodes stored a range of elements to compare rather than a single element.
192 lines
5.5 KiB
C++
192 lines
5.5 KiB
C++
//===--- RewriteSystem.h - Generics with term rewriting ---------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2021 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_REWRITESYSTEM_H
|
|
#define SWIFT_REWRITESYSTEM_H
|
|
|
|
#include <algorithm>
|
|
|
|
#include "ProtocolGraph.h"
|
|
#include "Symbol.h"
|
|
#include "Term.h"
|
|
#include "Trie.h"
|
|
|
|
namespace llvm {
|
|
class raw_ostream;
|
|
}
|
|
|
|
namespace swift {
|
|
|
|
namespace rewriting {
|
|
|
|
class PropertyMap;
|
|
class RewriteContext;
|
|
|
|
/// A rewrite rule that replaces occurrences of LHS with RHS.
|
|
///
|
|
/// LHS must be greater than RHS in the linear order over terms.
|
|
///
|
|
/// Out-of-line methods are documented in RewriteSystem.cpp.
|
|
class Rule final {
|
|
Term LHS;
|
|
Term RHS;
|
|
bool deleted;
|
|
|
|
public:
|
|
Rule(Term lhs, Term rhs)
|
|
: LHS(lhs), RHS(rhs), deleted(false) {}
|
|
|
|
const Term &getLHS() const { return LHS; }
|
|
const Term &getRHS() const { return RHS; }
|
|
|
|
OverlapKind checkForOverlap(const Rule &other,
|
|
MutableTerm &t,
|
|
MutableTerm &v) const {
|
|
return LHS.checkForOverlap(other.LHS, t, v);
|
|
}
|
|
|
|
bool canReduceLeftHandSide(const Rule &other) const {
|
|
return LHS.containsSubTerm(other.LHS);
|
|
}
|
|
|
|
/// Returns if the rule was deleted.
|
|
bool isDeleted() const {
|
|
return deleted;
|
|
}
|
|
|
|
/// Deletes the rule, which removes it from consideration in term
|
|
/// simplification and completion. Deleted rules are simply marked as
|
|
/// such instead of being physically removed from the rules vector
|
|
/// in the rewrite system, to ensure that indices remain valid across
|
|
/// deletion.
|
|
void markDeleted() {
|
|
assert(!deleted);
|
|
deleted = true;
|
|
}
|
|
|
|
/// Returns the length of the left hand side.
|
|
unsigned getDepth() const {
|
|
return LHS.size();
|
|
}
|
|
|
|
void dump(llvm::raw_ostream &out) const;
|
|
|
|
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &out,
|
|
const Rule &rule) {
|
|
rule.dump(out);
|
|
return out;
|
|
}
|
|
};
|
|
|
|
/// A term rewrite system for working with types in a generic signature.
|
|
///
|
|
/// Out-of-line methods are documented in RewriteSystem.cpp.
|
|
class RewriteSystem final {
|
|
/// Rewrite context for memory allocation.
|
|
RewriteContext &Context;
|
|
|
|
/// The rules added so far, including rules from our client, as well
|
|
/// as rules introduced by the completion procedure.
|
|
std::vector<Rule> Rules;
|
|
|
|
/// A prefix trie of rule left hand sides to optimize lookup.
|
|
Trie RuleTrie;
|
|
|
|
/// The graph of all protocols transitively referenced via our set of
|
|
/// rewrite rules, used for the linear order on symbols.
|
|
ProtocolGraph Protos;
|
|
|
|
/// A list of pending terms for the associated type merging completion
|
|
/// heuristic.
|
|
///
|
|
/// The pair (lhs, rhs) satisfies the following conditions:
|
|
/// - lhs > rhs
|
|
/// - all symbols but the last are pair-wise equal in lhs and rhs
|
|
/// - the last symbol in both lhs and rhs is an associated type symbol
|
|
/// - the last symbol in both lhs and rhs has the same name
|
|
///
|
|
/// See RewriteSystem::processMergedAssociatedTypes() for details.
|
|
std::vector<std::pair<MutableTerm, MutableTerm>> MergedAssociatedTypes;
|
|
|
|
/// A list of pending pairs for checking overlap in the completion
|
|
/// procedure.
|
|
std::deque<std::pair<unsigned, unsigned>> Worklist;
|
|
|
|
/// Set these to true to enable debugging output.
|
|
unsigned DebugSimplify : 1;
|
|
unsigned DebugAdd : 1;
|
|
unsigned DebugMerge : 1;
|
|
unsigned DebugCompletion : 1;
|
|
|
|
public:
|
|
explicit RewriteSystem(RewriteContext &ctx);
|
|
~RewriteSystem();
|
|
|
|
RewriteSystem(const RewriteSystem &) = delete;
|
|
RewriteSystem(RewriteSystem &&) = delete;
|
|
RewriteSystem &operator=(const RewriteSystem &) = delete;
|
|
RewriteSystem &operator=(RewriteSystem &&) = delete;
|
|
|
|
/// Return the rewrite context used for allocating memory.
|
|
RewriteContext &getRewriteContext() const { return Context; }
|
|
|
|
/// Return the object recording information about known protocols.
|
|
const ProtocolGraph &getProtocols() const { return Protos; }
|
|
|
|
void initialize(std::vector<std::pair<MutableTerm, MutableTerm>> &&rules,
|
|
ProtocolGraph &&protos);
|
|
|
|
Symbol simplifySubstitutionsInSuperclassOrConcreteSymbol(Symbol symbol) const;
|
|
|
|
bool addRule(MutableTerm lhs, MutableTerm rhs);
|
|
|
|
bool simplify(MutableTerm &term) const;
|
|
|
|
enum class CompletionResult {
|
|
/// Confluent completion was computed successfully.
|
|
Success,
|
|
|
|
/// Maximum number of iterations reached.
|
|
MaxIterations,
|
|
|
|
/// Completion produced a rewrite rule whose left hand side has a length
|
|
/// exceeding the limit.
|
|
MaxDepth
|
|
};
|
|
|
|
std::pair<CompletionResult, unsigned>
|
|
computeConfluentCompletion(unsigned maxIterations,
|
|
unsigned maxDepth);
|
|
|
|
void simplifyRightHandSides();
|
|
|
|
std::pair<CompletionResult, unsigned>
|
|
buildPropertyMap(PropertyMap &map,
|
|
unsigned maxIterations,
|
|
unsigned maxDepth);
|
|
|
|
void dump(llvm::raw_ostream &out) const;
|
|
|
|
private:
|
|
Optional<std::pair<MutableTerm, MutableTerm>>
|
|
computeCriticalPair(const Rule &lhs, const Rule &rhs) const;
|
|
|
|
Symbol mergeAssociatedTypes(Symbol lhs, Symbol rhs) const;
|
|
void processMergedAssociatedTypes();
|
|
};
|
|
|
|
} // end namespace rewriting
|
|
|
|
} // end namespace swift
|
|
|
|
#endif
|