001package org.clafer.ast.analysis;
002
003import java.util.HashMap;
004import java.util.Map;
005import java.util.Set;
006import org.clafer.ast.AstAbstractClafer;
007import org.clafer.ast.AstClafer;
008import org.clafer.ast.AstConcreteClafer;
009import org.clafer.ast.Card;
010import org.clafer.scope.Scope;
011
012/**
013 *
014 * @author jimmy
015 */
016public class ScopeAnalyzer implements Analyzer {
017
018    /*
019     * Shrinks the scope if it's greater than the upper global cardinality.
020     * Also set abstract scopes.
021     */
022    @Override
023    public Analysis analyze(Analysis analysis) {
024        Scope scope = analysis.getScope();
025        Map<AstClafer, Integer> optimizedScope = new HashMap<>();
026        optimizedScope.put(analysis.getModel(), 1);
027
028        for (Set<AstClafer> component : analysis.getClafersInParentAndSubOrder()) {
029            for (AstClafer clafer : component) {
030                if (clafer instanceof AstConcreteClafer) {
031                    Card globalCard = analysis.getGlobalCard(clafer);
032                    optimizedScope.put(clafer, Math.min(scope.getScope(clafer), globalCard.getHigh()));
033                } else {
034                    int subScopes = 0;
035                    for (AstClafer sub : ((AstAbstractClafer) clafer).getSubs()) {
036                        subScopes += optimizedScope.containsKey(sub) ? optimizedScope.get(sub) : scope.getDefaultScope();
037                    }
038                    optimizedScope.put(clafer, subScopes);
039                }
040            }
041        }
042        return analysis.setScope(new Scope(optimizedScope, scope.getDefaultScope(), scope.getIntLow(), scope.getIntHigh()));
043    }
044}