//===--- Term.h - A term in the generics rewrite system ---------*- 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 // //===----------------------------------------------------------------------===// #include "Symbol.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include #ifndef SWIFT_RQM_TERM_H #define SWIFT_RQM_TERM_H namespace llvm { class raw_ostream; } namespace swift { namespace rewriting { /// A term is a sequence of one or more symbols. /// /// The Term type is a uniqued, permanently-allocated representation, /// used to represent terms in the rewrite rules themselves. See also /// MutableTerm for the other representation. /// /// The first symbol in the term must be a protocol, generic parameter, or /// associated type symbol. /// /// A layout, superclass or concrete type symbol must only appear at the /// end of a term. /// /// Out-of-line methods are documented in Term.cpp. class Term final { friend class RewriteContext; struct Storage; const Storage *Ptr; Term(const Storage *ptr) : Ptr(ptr) {} public: size_t size() const; const Symbol *begin() const; const Symbol *end() const; std::reverse_iterator rbegin() const; std::reverse_iterator rend() const; Symbol back() const; Symbol operator[](size_t index) const; /// Returns an opaque pointer that uniquely identifies this term. const void *getOpaquePointer() const { return Ptr; } static Term fromOpaquePointer(void *ptr) { return Term((Storage *) ptr); } static Term get(const MutableTerm &term, RewriteContext &ctx); const ProtocolDecl *getRootProtocol() const { return begin()->getRootProtocol(); } bool isPackTerm() { if (size() == 0) return false; auto kind = back().getKind(); return kind == Symbol::Kind::Shape; } bool containsNameSymbols() const; void dump(llvm::raw_ostream &out) const; std::optional compare(Term other, RewriteContext &ctx) const; friend bool operator==(Term lhs, Term rhs) { return lhs.Ptr == rhs.Ptr; } friend bool operator!=(Term lhs, Term rhs) { return !(lhs == rhs); } friend llvm::raw_ostream &operator<<(llvm::raw_ostream &out, Term term) { term.dump(out); return out; } }; /// A term is a sequence of one or more symbols. /// /// The MutableTerm type is a dynamically-allocated representation, /// used to represent temporary values in simplification and completion. /// See also Term for the other representation. /// /// The first symbol in the term must be a protocol, generic parameter, or /// associated type symbol. /// /// A layout constraint symbol must only appear at the end of a term. /// /// Out-of-line methods are documented in RewriteSystem.cpp. class MutableTerm final { llvm::SmallVector Symbols; public: /// Creates an empty term. At least one symbol must be added for the term /// to become valid. MutableTerm() {} explicit MutableTerm(const Symbol *begin, const Symbol *end) : Symbols(begin, end) {} explicit MutableTerm(llvm::SmallVector &&symbols) : Symbols(std::move(symbols)) {} explicit MutableTerm(llvm::ArrayRef symbols) : Symbols(symbols.begin(), symbols.end()) {} explicit MutableTerm(Term term) : Symbols(term.begin(), term.end()) {} void add(Symbol symbol) { Symbols.push_back(symbol); } void prepend(Symbol symbol) { Symbols.insert(Symbols.begin(), symbol); } void append(Term other) { Symbols.append(other.begin(), other.end()); } void append(const MutableTerm &other) { Symbols.append(other.begin(), other.end()); } void append(const Symbol *from, const Symbol *to) { Symbols.append(from, to); } std::optional compare(const MutableTerm &other, RewriteContext &ctx) const; bool empty() const { return Symbols.empty(); } size_t size() const { return Symbols.size(); } const ProtocolDecl *getRootProtocol() const { return begin()->getRootProtocol(); } bool isPackTerm() { if (size() == 0) return false; auto kind = back().getKind(); return kind == Symbol::Kind::Shape; } const Symbol *begin() const { return Symbols.begin(); } const Symbol *end() const { return Symbols.end(); } Symbol *begin() { return Symbols.begin(); } Symbol *end() { return Symbols.end(); } Symbol removeEnd() { return Symbols.pop_back_val();} std::reverse_iterator rbegin() const { return Symbols.rbegin(); } std::reverse_iterator rend() const { return Symbols.rend(); } std::reverse_iterator rbegin() { return Symbols.rbegin(); } std::reverse_iterator rend() { return Symbols.rend(); } Symbol front() const { return Symbols.front(); } Symbol back() const { return Symbols.back(); } Symbol &back() { return Symbols.back(); } Symbol operator[](size_t index) const { return Symbols[index]; } Symbol &operator[](size_t index) { return Symbols[index]; } void rewriteSubTerm(Symbol *from, Symbol *to, Term rhs); void dump(llvm::raw_ostream &out) const; friend bool operator==(const MutableTerm &lhs, const MutableTerm &rhs) { if (lhs.size() != rhs.size()) return false; return std::equal(lhs.begin(), lhs.end(), rhs.begin()); } friend bool operator!=(const MutableTerm &lhs, const MutableTerm &rhs) { return !(lhs == rhs); } friend llvm::raw_ostream &operator<<(llvm::raw_ostream &out, const MutableTerm &term) { term.dump(out); return out; } }; } // end namespace rewriting } // end namespace swift namespace llvm { template<> struct DenseMapInfo { static swift::rewriting::Term getEmptyKey() { return swift::rewriting::Term::fromOpaquePointer( llvm::DenseMapInfo::getEmptyKey()); } static swift::rewriting::Term getTombstoneKey() { return swift::rewriting::Term::fromOpaquePointer( llvm::DenseMapInfo::getTombstoneKey()); } static unsigned getHashValue(swift::rewriting::Term Val) { return DenseMapInfo::getHashValue(Val.getOpaquePointer()); } static bool isEqual(swift::rewriting::Term LHS, swift::rewriting::Term RHS) { return LHS == RHS; } }; template<> struct PointerLikeTypeTraits { public: static inline void *getAsVoidPointer(swift::rewriting::Term Val) { return const_cast(Val.getOpaquePointer()); } static inline swift::rewriting::Term getFromVoidPointer(void *Ptr) { return swift::rewriting::Term::fromOpaquePointer(Ptr); } enum { NumLowBitsAvailable = 1 }; }; } // end namespace llvm #endif