/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2010.
*/
package x10.compiler.ws.util;
import java.util.ArrayList;
import java.util.List;
import polyglot.types.Type;
import polyglot.util.Pair;
import x10.compiler.ws.codegen.AbstractWSClassGen;
/**
* @author Haichuan
*
* A reference container is used to store a reference from deeper frame to a upper frame
*
* For example frame
* _fib
* _fibF0 ( up = _fib)
* _fibF0B0 (up = _fibF0)
* _fibF0B0A0 (k = _fibF0B0, up = _fibF0)
*
* In _fibF0B0A0, if it wants to access a variable in _fib,
* it needs a reference up.up, or k.up.up.up
*
* This Reference container will store both of the two references,
* And choose the best reference from all candidates
*
*/
public class ReferenceContainer {
ReferenceStructure curRef;
AbstractWSClassGen startFrame;
List<ReferenceStructure> foundRefs;
public ReferenceContainer(AbstractWSClassGen startFrame){
foundRefs = new ArrayList<ReferenceStructure>();
curRef = new ReferenceStructure();
this.startFrame = startFrame;
}
public List<Pair<String, Type>> getBestRefStructure(){
//the best is the one with less frame distance and less size;
if(foundRefs.size() == 0){
return null;
}
ReferenceStructure bestRef = foundRefs.get(0);
for(int i = 0; i < foundRefs.size(); i++){
ReferenceStructure curRef = foundRefs.get(i);
if(curRef.distance < bestRef.distance){
bestRef = curRef;
}
else if(curRef.distance == bestRef.distance){
if(curRef.getRefsSize() < bestRef.getRefsSize()){
bestRef = curRef;
}
}
}
return bestRef.refList;
}
public void setFound(){
foundRefs.add(curRef.clone());
}
public void push(String str, AbstractWSClassGen frame){
curRef.push(str, frame.getClassDef().asType());
curRef.setDistance(startFrame.getFrameDepth() - frame.getFrameDepth());
}
public Pair<String, Type> pop(){
return curRef.pop(); //after pop, the depth is not correct
}
class ReferenceStructure{
List<Pair<String, Type>> refList;
int distance; //distance between the two frames;
public ReferenceStructure(){
refList = new ArrayList<Pair<String, Type>>();
}
public void push(String str, Type type){
refList.add(new Pair<String, Type>(str, type));
}
public Pair<String, Type> pop(){
return refList.remove(refList.size() - 1);
}
protected int getRefsSize(){
return refList.size();
}
protected int getDistance() {
return distance;
}
protected void setDistance(int distance) {
this.distance = distance;
}
@Override
protected ReferenceStructure clone(){
ReferenceStructure result = new ReferenceStructure();
result.distance = this.distance;
for(Pair<String, Type> p: refList){
result.refList.add(p);
}
return result;
}
}
}