mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
245 lines
6.0 KiB
C++
245 lines
6.0 KiB
C++
//===--- Rule.h - An oriented rewrite rule in a rewrite system --*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2022 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_RULE_H
|
|
#define SWIFT_RULE_H
|
|
|
|
#include "swift/Basic/Assertions.h"
|
|
#include <optional>
|
|
|
|
#include "Symbol.h"
|
|
#include "Term.h"
|
|
|
|
namespace llvm {
|
|
class raw_ostream;
|
|
}
|
|
|
|
namespace swift {
|
|
|
|
namespace rewriting {
|
|
|
|
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 Rule.cpp.
|
|
class Rule final {
|
|
Term LHS;
|
|
Term RHS;
|
|
|
|
/// A 'permanent' rule cannot be deleted by homotopy reduction. These
|
|
/// do not correspond to generic requirements and are re-added when the
|
|
/// rewrite system is built.
|
|
unsigned Permanent : 1;
|
|
|
|
/// An 'explicit' rule is a generic requirement written by the user.
|
|
unsigned Explicit : 1;
|
|
|
|
/// An 'LHS simplified' rule's left hand side was reduced via another rule.
|
|
/// Set by simplifyLeftHandSides().
|
|
unsigned LHSSimplified : 1;
|
|
|
|
/// An 'RHS simplified' rule's right hand side can be reduced via another rule.
|
|
/// Set by simplifyRightHandSides().
|
|
unsigned RHSSimplified : 1;
|
|
|
|
/// A 'substitution simplified' rule's left hand side contains substitutions
|
|
/// which can be reduced via another rule.
|
|
/// Set by simplifyLeftHandSideSubstitutions().
|
|
unsigned SubstitutionSimplified : 1;
|
|
|
|
/// A 'redundant' rule was eliminated by homotopy reduction. Redundant rules
|
|
/// still participate in term rewriting, but they are not part of the minimal
|
|
/// set of requirements in a generic signature.
|
|
unsigned Redundant : 1;
|
|
|
|
/// A 'conflicting' rule is a property rule which cannot be satisfied by any
|
|
/// concrete type because it is mutually exclusive with some other rule.
|
|
/// An example would be a pair of concrete type rules:
|
|
///
|
|
/// T.[concrete: Int] => T
|
|
/// T.[concrete: String] => T
|
|
///
|
|
/// Conflicting rules are detected in property map construction, and are
|
|
/// dropped from the minimal set of requirements.
|
|
unsigned Conflicting : 1;
|
|
|
|
/// A 'recursive' rule is a concrete type or superclass rule where the right
|
|
/// hand side occurs as a proper prefix of one of its substitutions.
|
|
///
|
|
/// Recursive rules are detected in RewriteSystem::computeRecursiveRules(),
|
|
/// and are dropped from the minimal set of requirements.
|
|
unsigned Recursive : 1;
|
|
|
|
/// Whether this rule is now finalized and immutable.
|
|
unsigned Frozen : 1;
|
|
|
|
public:
|
|
Rule(Term lhs, Term rhs)
|
|
: LHS(lhs), RHS(rhs) {
|
|
Permanent = false;
|
|
Explicit = false;
|
|
LHSSimplified = false;
|
|
RHSSimplified = false;
|
|
SubstitutionSimplified = false;
|
|
Redundant = false;
|
|
Conflicting = false;
|
|
Recursive = false;
|
|
Frozen = false;
|
|
}
|
|
|
|
const Term &getLHS() const { return LHS; }
|
|
const Term &getRHS() const { return RHS; }
|
|
|
|
std::optional<Symbol> isPropertyRule() const;
|
|
|
|
const ProtocolDecl *isProtocolConformanceRule() const;
|
|
|
|
const ProtocolDecl *isAnyConformanceRule() const;
|
|
|
|
bool isIdentityConformanceRule() const;
|
|
|
|
bool isProtocolRefinementRule(RewriteContext &ctx) const;
|
|
|
|
bool isCircularConformanceRule() const;
|
|
|
|
bool isSameElementRule() const;
|
|
|
|
/// See above for an explanation of these predicates.
|
|
bool isPermanent() const {
|
|
return Permanent;
|
|
}
|
|
|
|
bool isExplicit() const {
|
|
return Explicit;
|
|
}
|
|
|
|
bool isLHSSimplified() const {
|
|
return LHSSimplified;
|
|
}
|
|
|
|
bool isRHSSimplified() const {
|
|
return RHSSimplified;
|
|
}
|
|
|
|
bool isSubstitutionSimplified() const {
|
|
return SubstitutionSimplified;
|
|
}
|
|
|
|
bool isRedundant() const {
|
|
return Redundant;
|
|
}
|
|
|
|
bool isConflicting() const {
|
|
return Conflicting;
|
|
}
|
|
|
|
bool isRecursive() const {
|
|
return Recursive;
|
|
}
|
|
|
|
bool isFrozen() const {
|
|
return Frozen;
|
|
}
|
|
|
|
bool containsNameSymbols() const {
|
|
return (LHS.containsNameSymbols() ||
|
|
RHS.containsNameSymbols());
|
|
}
|
|
|
|
std::optional<Identifier> isProtocolTypeAliasRule() const;
|
|
|
|
bool isDerivedFromConcreteProtocolTypeAliasRule() const;
|
|
|
|
void markLHSSimplified() {
|
|
ASSERT(!Frozen);
|
|
ASSERT(!LHSSimplified);
|
|
LHSSimplified = true;
|
|
}
|
|
|
|
void markRHSSimplified() {
|
|
ASSERT(!Frozen);
|
|
ASSERT(!RHSSimplified);
|
|
RHSSimplified = true;
|
|
}
|
|
|
|
void markSubstitutionSimplified() {
|
|
ASSERT(!Frozen);
|
|
ASSERT(!SubstitutionSimplified);
|
|
SubstitutionSimplified = true;
|
|
}
|
|
|
|
void markPermanent() {
|
|
ASSERT(!Frozen);
|
|
ASSERT(!Explicit && !Permanent &&
|
|
"Permanent and explicit are mutually exclusive");
|
|
Permanent = true;
|
|
}
|
|
|
|
void markExplicit() {
|
|
ASSERT(!Frozen);
|
|
ASSERT(!Explicit && !Permanent &&
|
|
"Permanent and explicit are mutually exclusive");
|
|
Explicit = true;
|
|
}
|
|
|
|
void markRedundant() {
|
|
ASSERT(!Frozen);
|
|
ASSERT(!Redundant);
|
|
Redundant = true;
|
|
}
|
|
|
|
void markConflicting() {
|
|
// It's okay to mark a rule as conflicting multiple times.
|
|
if (Conflicting)
|
|
return;
|
|
|
|
ASSERT(!Frozen);
|
|
ASSERT(!Permanent && "Permanent rule should not conflict with anything");
|
|
Conflicting = true;
|
|
}
|
|
|
|
void markRecursive() {
|
|
ASSERT(!Frozen);
|
|
ASSERT(!Permanent && "Permanent rule should not be recursive");
|
|
ASSERT(!Recursive);
|
|
Recursive = true;
|
|
}
|
|
|
|
void freeze() {
|
|
Redundant = false;
|
|
Frozen = true;
|
|
}
|
|
|
|
unsigned getDepth() const;
|
|
|
|
unsigned getNesting() const;
|
|
|
|
std::optional<int> compare(const Rule &other, RewriteContext &ctx) const;
|
|
|
|
void dump(llvm::raw_ostream &out) const;
|
|
|
|
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &out,
|
|
const Rule &rule) {
|
|
rule.dump(out);
|
|
return out;
|
|
}
|
|
};
|
|
|
|
} // end namespace rewriting
|
|
|
|
} // end namespace swift
|
|
|
|
#endif
|