Class Resolver3

All Implemented Interfaces:
Rewriter

public class Resolver3 extends Rewrite
Transforms a "raw" module into an "instantiated" one. Usage: create a new object of this class for one top level raw module and call resolveAllPublics().
The resulting resolvedModule ist self-contained: All Definitions rewritten from imported modules are cloned to definitions contained directly therein; as NAME they get the original name prepended by the complete import prefix path.
The overall control flow is roughly as follows:
    resolveAllPublics()
     |      |
     |      |
     V      
    createNewInstance(..)
   ^   V
  /    Clone the definition object,
 |     Call rewriting match(..) for the 
 |      RegExp = def.value.
 |         |   |   |        
 |         V   |   |
 |         action(Subst/Insertion)
 |         =update rewriting contexts
 |             V   |
 |             rewriteFields([div. constructors])
 |             =rewrite expression objects, filling
 |              fields with rewrite of sub-expr
 |                 V
 |                 rewriteFields(Reference)
 |                 () Apply local rewrites and
 |                    visit target expression recursively
 |                 () or else apply import level rewrites 
 |                    and visit target expr. recursively
 |                 () or else restore "frozen @" replacement context
 |                    and visit again.
 |                 () otherwise: 
 |                        |
 |                        V
 |                       visitPossiblyImportedDef(..)
 |                        V  |
 |                       loadImportedModule()
 |                           V
 |                           visitDefinition(..)
 |                           () if instance for this combination (of rawDef and importContext)
 |                              does NOT exist:
 |                                 create a new Instance and start its rewriting.
 |                                 on return: if ".cyclic" is not set: set ".complete"
 |                           // now an instance exists:
 |                           () if instance is not "bound()": memorize a classifcation request
 |                           () if !.complete and insert mode then set .cyclic
 |                           () if insertMode and !cyclic: rewrite reference to 
 |                                                rewritten contents/expression
 |                           () if insertMode and cyclic: rewrite reference to 
 |                                    "@ x" combination, "x" the rewritten definition
 |                           () else store rewritten instance as reference's ".resolved"
 |                           (The results are stored in two maps : 
 |                                   "reference2rawDef" and "reference2importContext".)
 |          |       
 |          |       
 |          |       
 |          |
  \         V
   \     processWaitingReferences()
    \    V
     \ ->processWaitingReference(..)
     /\     creates a new Instance object, which
    /  \    is either its own class, or related to another 
   /    \   Instance of the same raw def as its representative
  /      \  (hypothetically or confirmed).
  |       \ |     |
  |        \V     |
  |         createNewInstance(..)
  |               V
  |               equivalent(ref's def, old instantiation of same def)
  |               V
  |               (new Equivalence()).match()
  \                   V
   \                  descend(Reference)
    \----------------                 
 
 
  
Central object is Resolver3.Instance which is built for every found combination of Definition and Resolver3.ImportContext. (Additionally Instances will be needed for combinations of local substitution, insert operation and recursive call as in "@x^(a/b)" with "x=...x...". This is done by the methods createNewInstance(eu.bandm.tools.d2d2.base.Resolver3.ImportContext,eu.bandm.tools.d2d2.model.Definition,@eu.bandm.tools.annotations.Opt eu.bandm.tools.d2d2.model.Reference) and Resolver3.Instance.newHypothesis(Instance). The former also does the CLONING of the Definition object and the rewriting of the expression. (The latter only creates a new Instance object reflecting the hypothesis of being equivalent with the method's argument.)
First all public definitions from the top-level raw module are given one Resolver3.Instance, which is an "equivalence class", i.e. its own representative. During this, each expression value is visited with the rewriting method of this class, and all rewriting directives (local and coming with module imports) are applied. As a result, all reached References are attributed by the maps reference2rawDef and reference2importContext, reflecting the result of applying all rewrite directives.
Every Resolver3.Instance is addressed globally by a "characteristic pair" of raw definition and import context. Additionally a reached reference is entered in the set waitingForEquivalence, iff there is no Resolver3.Instance yet for this combination, or only one with a failed hypothesis.
In the second phase this set is emptied one-by-one by processWaitingReference(eu.bandm.tools.d2d2.model.Reference):
If for the characteristic pair of the reference a "bound()" Resolver3.Instance exists, nothing is done.
Otherwise an Resolver3.Instance is created. Every already existing Resolver3.Instance for the same raw definition, which is an equivalence class, i.e. its own representative, is tested against the import context of the critical reference by calling equivalent(Definition,Definition).
As soon as one such call succeeds, Resolver3.Instance.hypothesisConfirmed() is called on this hypothesis, making it a permanent fact.
If this does not happen, the new Instance is made its own class by Resolver3.Instance.setIsClass().
The equivalence test implemented by the class Resolver3.Equivalence goes from the two definitions to the two expressions, and visits them pairwise.
Failure is signalled by throwing the local Exception Resolver3.DifferenceFound.
As soon as the two constructors of the compared expression sub-tree are not identical, a failure is found.
The same holds vor un-equal constant values.
When two References are reached, first processWaitingReference(eu.bandm.tools.d2d2.model.Reference) is called for both of them recursively, and then the representatives of the two resulting Instance objects are compared.
The Resolver3.Instance which is currently under test against some equivalence class has been stored in currentHypothesis. So, whenever an Resolver3.Instance (=x) is reached which is itself hypothetical, the dependency is memorized by adding "currentHypothesis" to "x.requiredBy" and setting "currentHypothesis.requires=true" (This is for optimization /object reuse only).
Whenever a hypothesis fails, the failure is propagated to all in its ".requiredBy" set, and the representing Reference (from Resolver3.Instance.reprRef is re-entered into waitingForEquivalence.







TESTS as with 20160826:

d2d2/test> make expand MODULE=basic.deliverables
(( ALTE VBERSION !?!)) d2d2/test/basic.deliverables.expanded 853 lines without equivalence.
d2d2/test/EXPANDED_basic.deliverables 998 line with equivalence.
d2d2/test> make expand MODULE=d2d-meta