001package org.clafer.ast.analysis;
002
003import java.util.ArrayList;
004import java.util.Collections;
005import java.util.Comparator;
006import java.util.HashMap;
007import java.util.List;
008import java.util.Map;
009import org.clafer.ast.AstAbstractClafer;
010import org.clafer.ast.AstClafer;
011import org.clafer.ast.Card;
012
013/**
014 *
015 * @author jimmy
016 */
017public class AbstractOffsetAnalyzer implements Analyzer {
018
019    @Override
020    public Analysis analyze(final Analysis analysis) {
021        Map<AstAbstractClafer, Offsets> offsetsMap = new HashMap<>();
022        for (AstAbstractClafer abstractClafer : analysis.getAbstractClafers()) {
023            Map<AstClafer, Integer> offsets = new HashMap<>();
024            List<AstClafer> reverseOffsets = new ArrayList<>();
025            int offset = 0;
026            List<AstClafer> subs = new ArrayList<>(abstractClafer.getSubs());
027            /*
028             * What is this optimization?
029             *
030             * This optimization is to put more "stable" Clafers near the
031             * beginning, to reduce the number of backtracking for LowGroups.
032             */
033            Collections.sort(subs, new Comparator<AstClafer>() {
034                @Override
035                public int compare(AstClafer o1, AstClafer o2) {
036                    Card card1 = analysis.getGlobalCard(o1);
037                    Card card2 = analysis.getGlobalCard(o2);
038                    double ratio1 = ((double) card1.getLow() + 1) / ((double) card1.getHigh() + 1);
039                    double ratio2 = ((double) card2.getLow() + 1) / ((double) card2.getHigh() + 1);
040                    return -Double.compare(ratio1, ratio2);
041                }
042            });
043            for (AstClafer sub : subs) {
044                offsets.put(sub, offset);
045                int skip = analysis.getScope(sub);
046                for (int i = 0; i < skip; i++) {
047                    reverseOffsets.add(sub);
048                }
049                offset += skip;
050            }
051            offsetsMap.put(abstractClafer, new Offsets(abstractClafer, offsets, reverseOffsets.toArray(new AstClafer[reverseOffsets.size()])));
052        }
053        return analysis.setOffsetMap(offsetsMap);
054    }
055}