001package org.clafer.compiler;
002
003import java.util.ArrayList;
004import java.util.List;
005import org.clafer.ast.AstAbstractClafer;
006import org.clafer.ast.AstClafer;
007import org.clafer.ast.AstConcreteClafer;
008import org.clafer.ast.compiler.AstSolutionMap;
009import org.clafer.collection.Pair;
010import org.clafer.common.Check;
011import org.clafer.instance.InstanceClafer;
012import org.clafer.instance.InstanceModel;
013import org.clafer.instance.InstanceRef;
014import org.clafer.ir.IrIntVar;
015import org.clafer.ir.IrSetVar;
016import org.clafer.ir.compiler.IrSolutionMap;
017
018/**
019 *
020 * @author jimmy
021 */
022public class ClaferSolutionMap {
023
024    private final AstSolutionMap astSolution;
025    private final IrSolutionMap irSolution;
026
027    ClaferSolutionMap(AstSolutionMap astSolution, IrSolutionMap irSolution) {
028        this.astSolution = Check.notNull(astSolution);
029        this.irSolution = Check.notNull(irSolution);
030    }
031
032    public InstanceModel getInstance() {
033        List<InstanceClafer> topInstances = new ArrayList<>();
034        for (AstConcreteClafer child : astSolution.getModel().getChildren()) {
035            // [0] because top clafers only have exactly one children set
036            IrSetVar topSetIrVar = astSolution.getSiblingVars(child)[0];
037            int[] topIds = irSolution.getSetValue(topSetIrVar);
038            for (int topId : topIds) {
039                topInstances.add(getInstanceClafer(child, topId));
040            }
041        }
042        return new InstanceModel(topInstances.toArray(new InstanceClafer[topInstances.size()]));
043    }
044
045    private InstanceClafer getInstanceClafer(AstConcreteClafer clafer, int id) {
046        List<InstanceClafer> children = new ArrayList<>();
047        InstanceRef ref = getInstanceClafer(clafer, id, children);
048        return new InstanceClafer(clafer, id, ref, children.toArray(new InstanceClafer[children.size()]));
049    }
050
051    private InstanceRef getInstanceClafer(AstClafer clafer, int id, List<InstanceClafer> children) {
052        for (AstConcreteClafer child : clafer.getChildren()) {
053            IrSetVar childSetIrVar = astSolution.getSiblingVars(child)[id];
054            int[] childIds = irSolution.getSetValue(childSetIrVar);
055            for (int childId : childIds) {
056                children.add(getInstanceClafer(child, childId));
057            }
058        }
059        InstanceRef ref = null;
060        if (clafer.hasSuperClafer()) {
061            ref = getInstanceClafer(clafer.getSuperClafer(),
062                    id + astSolution.getAnalysis().getOffsets(clafer.getSuperClafer()).getOffset(clafer),
063                    children);
064        }
065        if (clafer.hasRef()) {
066            IrIntVar refIrVar = astSolution.getRefVars(clafer.getRef())[id];
067            AstClafer targetType = clafer.getRef().getTargetType();
068            int value = irSolution.getIntValue(refIrVar);
069            if (targetType instanceof AstAbstractClafer) {
070                Pair<AstConcreteClafer, Integer> concreteRef = astSolution.getAnalysis().getConcreteId(
071                        targetType, value);
072                targetType = concreteRef.getFst();
073                value = concreteRef.getSnd().intValue();
074            }
075            ref = new InstanceRef(targetType, value);
076        }
077        return ref;
078    }
079
080    public AstSolutionMap getAstSolution() {
081        return astSolution;
082    }
083
084    public IrSolutionMap getIrSolution() {
085        return irSolution;
086    }
087}