/*
* #%~
* The Overture Abstract Syntax Tree
* %%
* Copyright (C) 2008 - 2014 Overture
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #~%
*/
package org.overture.ast.util;
import java.util.List;
import java.util.TreeSet;
import org.overture.ast.assistant.IAstAssistantFactory;
import org.overture.ast.assistant.pattern.PTypeList;
import org.overture.ast.factory.AstFactory;
import org.overture.ast.intf.lex.ILexLocation;
import org.overture.ast.types.AOptionalType;
import org.overture.ast.types.ASeq1SeqType;
import org.overture.ast.types.ASeqSeqType;
import org.overture.ast.types.ASet1SetType;
import org.overture.ast.types.ASetSetType;
import org.overture.ast.types.AUnknownType;
import org.overture.ast.types.PType;
import org.overture.ast.types.SNumericBasicType;
@SuppressWarnings("serial")
public class PTypeSet extends TreeSet<PType>
{
public IAstAssistantFactory assistantFactory;
public PTypeSet(IAstAssistantFactory af)
{
super(new PTypeComparator());
assistantFactory = af;
}
public PTypeSet(PType t, IAstAssistantFactory af)
{
super(new PTypeComparator());
assistantFactory = af;
add(t);
}
public PTypeSet(PType t1, PType t2, IAstAssistantFactory af)
{
super(new PTypeComparator());
assistantFactory = af;
add(t1);
add(t2);
}
public PTypeSet(List<PType> types, IAstAssistantFactory af)
{
super(new PTypeComparator());
assistantFactory = af;
addAll(types);
}
@Override
public boolean add(PType t) // TODO: Create visitor over this method???? Need a assistantFactory but the call is
// from 1770 places. gkanos
{
if (t instanceof ASeq1SeqType)
{
// If we add a Seq1Type, and there is already a SeqType in the set
// we ignore the Seq1Type.
ASeq1SeqType s1t = (ASeq1SeqType) t;
ASeqSeqType st = AstFactory.newASeqSeqType(s1t.getLocation(), s1t.getSeqof());
if (contains(st))
{
return false; // Was already there
}
} else if (t instanceof ASeqSeqType)
{
// If we add a SeqType, and there is already a Seq1Type in the set
// we replace the Seq1Type.
ASeqSeqType st = (ASeqSeqType) t;
ASeq1SeqType s1t = AstFactory.newASeq1SeqType(st.getLocation(), st.getSeqof());
if (contains(s1t))
{
remove(s1t); // Replace seq with seq1
}
}
else if (t instanceof ASet1SetType)
{
// If we add a Set1Type, and there is already a SetType in the set
// we ignore the Set1Type.
ASet1SetType s1t = (ASet1SetType)t;
ASetSetType st = AstFactory.newASetSetType(s1t.getLocation(), s1t.getSetof());
if (contains(st))
{
return false; // Was already there
}
}
else if (t instanceof ASetSetType)
{
// If we add a SetType, and there is already a Set1Type in the set
// we replace the Set1Type.
ASetSetType st = (ASetSetType)t;
ASet1SetType s1t = AstFactory.newASet1SetType(st.getLocation(), st.getSetof());
if (contains(s1t))
{
remove(s1t); // Replace set1 with set
}
}
else if (t instanceof SNumericBasicType)
{
for (PType x : this)// what the this keyword refer to.. gkanos
{
if (x instanceof SNumericBasicType)
{
// this is the only call that causes problem. gkanos
if (assistantFactory.createSNumericBasicTypeAssistant().getWeight(assistantFactory.createPTypeAssistant().getNumeric(x)) < assistantFactory.createSNumericBasicTypeAssistant().getWeight(assistantFactory.createPTypeAssistant().getNumeric(t)))
{
remove(x);
break;
} else
{
return false; // Was already there
}
}
}
}
else if (t instanceof AOptionalType)
{
AOptionalType opt = (AOptionalType)t;
if (!(opt.getType() instanceof AUnknownType) && contains(opt.getType()))
{
remove(opt.getType()); // Because T | [T] = [T]
}
}
return super.add(t);
}
public PType getType(ILexLocation location)
{
// If there are any Optional(Unknowns) these are the result of
// nil values, which set the overall type as optional. Other
// optional types stay.
boolean optional = false;
// You get less confusing results without this, it seems...
// Iterator<PType> tit = this.iterator();
//
// while (tit.hasNext())
// {
// PType t = tit.next();
//
// if (t instanceof AOptionalType)
// {
// AOptionalType ot = (AOptionalType) t;
//
// if (ot.getType() instanceof AUnknownType)
// {
// if (this.size() > 1)
// {
// tit.remove();
// optional = true;
// } else
// {
// optional = false;
// }
// }
// }
// }
assert this.size() > 0 : "Getting type of empty TypeSet";
PType result = null;
if (this.size() == 1)
{
result = this.iterator().next();
} else
{
PTypeList types = new PTypeList();
for (PType pType : this)
{
types.add(pType);// .clone()
}
result = AstFactory.newAUnionType(location, types);
}
return optional ? AstFactory.newAOptionalType(location, result)
: result;
}
@Override
public String toString()
{
return Utils.setToString(this, ", ");
}
}