Commit Graph

145 Commits

Author SHA1 Message Date
Slava Pestov
371366eb4b RequirementMachine: Assert that non-redundant rules are fully resolved 2021-10-08 14:28:27 -04:00
Slava Pestov
b8177995df RequirementMachine: Sort requirements and canonicalize same-type requirements 2021-10-08 14:28:27 -04:00
Slava Pestov
566971dbc2 RequirementMachine: Add some comments and assertions around state transitions 2021-10-08 14:28:27 -04:00
Slava Pestov
03dfa60edd RequirementMachine: Initial implementation of requirement minimization 2021-10-06 00:11:21 -04:00
Slava Pestov
acb12fa750 RequirementMachine: More complete implementation of findProtocolConformanceRules() 2021-10-06 00:11:21 -04:00
Slava Pestov
62c9347d3b RequirementMachine: Overhaul generating conformances algorithm 2021-10-01 00:57:44 -04:00
Slava Pestov
2db676d41a RequirementMachine: Homotopy reduction deletes rules with unresolved name symbols first 2021-10-01 00:57:44 -04:00
Slava Pestov
34592cb2fa RequirementMachine: Fix generating conformances algorithm for rules of the form [P].[P] => [P] 2021-10-01 00:56:50 -04:00
Slava Pestov
64d1931e15 RequirementMachine: Sketch out "generating conformances" algorithm 2021-09-27 19:04:16 -04:00
Slava Pestov
5f3d781ed3 RequirementMachine: Homotopy reduction tweaks
- Skip permanent rules (there's no point, we'll add them back next time)
- Skip conformance rules (these will be handled separately)
- Delete 3-cells that are entirely "in-context" (but don't quote me on
  this one, I'm not quite yet convinced it's correct, but it feels right)
2021-09-27 19:03:34 -04:00
Slava Pestov
2923a334f5 RequirementMachine: Remove unused method 2021-09-27 19:03:30 -04:00
Slava Pestov
7ad0c3cc79 RequirementMachine: Add a mode allowing unresolved name symbols in rewrite rules 2021-09-27 19:03:26 -04:00
Slava Pestov
2b068b3c48 RequirementMachine: Encapsulate 3-cells in a new HomotopyGenerator data type 2021-09-24 08:59:51 -04:00
Slava Pestov
99dab70840 RequirementMachine: Mark associated type introduction rules permanent 2021-09-24 08:59:51 -04:00
Slava Pestov
8fbe93c469 RequirementMachine: Rename Rule::isDeleted() => isSimplified(), and add isPermanent(), isRedundant() bits 2021-09-24 08:59:51 -04:00
Slava Pestov
1fa36c70c6 RequirementMachine: Factor out Rule::isPropertyRule() from the property map 2021-09-24 08:59:51 -04:00
Slava Pestov
67fad897ab RequirementMachine: Compute left canonical forms of paths 2021-09-24 08:59:51 -04:00
Slava Pestov
5f03c737d2 RequirementMachine: Preliminary implementation of homotopy reduction 2021-09-24 08:59:50 -04:00
Slava Pestov
c6403e65e1 RequirementMachine: RewriteStep stores both whiskers 2021-09-24 08:59:50 -04:00
Slava Pestov
5cbfbae536 RequirementMachine: Represent concrete type adjustment in a rewrite path 2021-09-24 08:59:50 -04:00
Slava Pestov
b317a5c5ee RequirementMachine: Verify homotopy generators 2021-09-24 08:59:50 -04:00
Slava Pestov
a75327e6b1 RequirementMachine: Record homotopy generators when adding new rules during completion 2021-09-24 08:59:50 -04:00
Slava Pestov
b2a21b3117 RequirementMachine: Preliminary plumbing for computing homotopy generators 2021-09-24 08:59:50 -04:00
Slava Pestov
9fac25d65b RequirementMachine: Clean up merged associated type algorithm some more
The left and right hand side of a merged associated type candidate rule
have a common prefix except for the associated type symbol at the end.

Instead of passing two MutableTerms, we can pass a single uniqued
Term and a Symbol.

Also, we can compute the merged symbol before pushing the candidate
onto the vector. This avoids unnecessary work if the merged symbol
is equal to the right hand side's symbol.
2021-09-02 23:02:52 -04:00
Slava Pestov
62f56d7c13 RequirementMachine: Skip trivial overlaps
If resolving an overlap produces a pair where both sides are equal,
we don't have to reduce both sides before throwing it out.
2021-09-02 22:57:10 -04:00
Slava Pestov
399a600e32 RequirementMachine: Add -debug-requirement-machine= flag to control debug output 2021-08-20 01:29:22 -04:00
Slava Pestov
0935952038 RequirementMachine: Cache result of mergeAssociatedTypes() 2021-08-19 22:14:58 -04:00
Slava Pestov
af05377afa RequirementMachine: Use trie to find overlapping rules 2021-08-13 16:34:27 -04:00
Slava Pestov
2fc6ec551b RequirementMachine: Use trie for left hand side simplification
In a confluent rewrite system, if the left hand side of a rule
X => Y can be reduced by some other rule X' => Y', then it is
permissible to delete the original rule X => Y altogether.

Confluence means that rewrite rules can be applied in any
order, so it is always valid to apply X' => Y' first, thus
X => Y is obsolete.

This was previously done in the completion procedure via a
quadratic algorithm that attempted to reduce each existing
rule via the newly-added rule obtained by resolving a critical
pair. Instead, we can do this in the post-processing pass
where we reduce right hand sides using a trie to speed up
the lookup.

This increases the amount of work performed by the
completion procedure, but eliminates the quadratic algorithm,
saving time overall.
2021-08-07 01:51:31 -04:00
Slava Pestov
776a0889b7 RequirementMachine: Parametrize Trie by value type and add support for longest-suffix match
The PropertyMap wants to use a try to map to PropertyBags, and it
needs longest-suffix rather than shortest-prefix matching.

Implement both by making Trie into a template class with two
parameters; the ValueType, and the MatchKind.

Note that while the MatchKind encodes the longest vs shortest
match part, matching on the prefix vs suffix of a term is up
to the caller, since the find() and insert() methods of Trie
take a pair of iterators, so simply passing in begin()/end() vs
rbegin()/rend() selects the direction.
2021-08-06 14:17:20 -04:00
Slava Pestov
156fa2cc04 RequirementMachine: Speed up term simplification with a prefix trie
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.
2021-08-05 21:42:50 -04:00
Slava Pestov
92ac06a25b RequirementMachine: Rules store uniqued Terms 2021-08-05 21:42:50 -04:00
Slava Pestov
ed966e7337 RequirementMachine: Add histograms for symbol kinds and term length 2021-08-05 21:42:50 -04:00
Slava Pestov
7adfd86e37 RequirementMachine: Split off Symbol.cpp and Term.cpp from RewriteSystem.cpp 2021-08-05 21:42:49 -04:00
Slava Pestov
d3db1b6753 RequirementMachine: EquivalenceClassMap => PropertyMap
EquivalenceClass is now PropertyBag.
2021-07-23 17:21:57 -04:00
Slava Pestov
cfb1595ec5 RequirementMachine: Rename Atom => Symbol 2021-07-23 15:58:50 -04:00
Slava Pestov
4184ebd0a8 RequirementMachine: Split off RewriteContext.{h,cpp} from RewriteSystem.{h,cpp} 2021-07-14 00:16:06 -04:00
Slava Pestov
c32ec95c13 RequirementMachine: Enforce that rewrite rules preserve the term's 'domain'
Intuitively, the first token of a rewrite rule determines if the rule
applies to a protocol requirement signature 'Self', or a generic
parameter in the top-level generic signature. A rewrite rule can never
take a type starting with the protocol 'Self' to a type starting with a
generic parameter, or vice versa.

Enforce this by defining the notion of a 'domain', which is the set of
protocols to which the first atom in a term applies to. This set can be
empty (if we have a generic parameter atom), or it may contain more than
one element (if we have an associated type atom for a merged associated
type).
2021-07-14 00:14:29 -04:00
Slava Pestov
00eca7ee97 RequirementMachine: Add reverse iterators over Term and MutableTerm
I thought I needed these for something but turns out that I don't,
but there's no harm in adding them since surely they will come up
eventually.
2021-07-14 00:06:17 -04:00
Slava Pestov
35daf17dc4 RequirementMachine: Implement RewriteContext::getTypeForTerm()
Protocol atoms map to the 'Self' parameter; GenericParam and Name
atoms map in the obvious way.

An associated type atom `[P1&P1&...&Pn:A]` has one or more protocols
P0...Pn and an identifier 'A'.

We map it back to a AssociatedTypeDecl as follows:

- For each protocol Pn, look for associated types A in Pn itself,
  and all protocols that Pn refines.

- For each candidate associated type An in protocol Qn where
  Pn refines Qn, get the associated type anchor An' defined in
  protocol Qn', where Qn refines Qn'.

- Out of all the candidiate pairs (Qn', An'), pick the one where
  the protocol Qn' is the lowest element according to the linear
  order defined by TypeDecl::compare().

The associated type An' is then the canonical associated type
representative of the associated type atom `[P0&...&Pn:A]`.
2021-07-09 00:03:39 -04:00
Slava Pestov
56700983de RequirementMachine: Completion step and depth limits also apply to equivalence class map 2021-07-08 23:31:53 -04:00
Slava Pestov
f28d9b3dbf RequirementMachine: Stub out the equivalence class map 2021-06-30 01:34:20 -04:00
Slava Pestov
8107cea766 RequirementMachine: Define operator<< overloads 2021-06-29 13:09:11 -04:00
Slava Pestov
d03ff29a46 RequirementMachine: Protocol atoms order before associated type atoms
If you have a same-type requirement like 'Self.Foo == Self' inside a
protocol P, we add a rewrite rule:

[P].Foo => [P]

Simplification turns this into

[P:Foo] => [P]

Previously, the order was backwards so we would end up with

[P] => [P:Foo]

Which would mess up the conformance information in the equivalence class map.
2021-06-29 13:09:11 -04:00
Slava Pestov
6c164f682e RequirementMachine: Move files to a new subdirectory under lib/AST/
Also move a all headers other than RequirementMachine.h there, since
I don't expect they will be used outside of the rewrite system
implementation itself.
2021-06-25 00:04:09 -04:00