/* * #%~ * The VDM Type Checker * %% * 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.typechecker.utilities.type; import org.overture.ast.analysis.AnalysisException; import org.overture.ast.analysis.QuestionAnswerAdaptor; import org.overture.ast.node.INode; import org.overture.ast.types.ABracketType; import org.overture.ast.types.AClassType; import org.overture.ast.types.AFunctionType; import org.overture.ast.types.ANamedInvariantType; import org.overture.ast.types.AOperationType; import org.overture.ast.types.AOptionalType; import org.overture.ast.types.AProductType; import org.overture.ast.types.AQuoteType; import org.overture.ast.types.ARecordInvariantType; 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.AUndefinedType; import org.overture.ast.types.AUnionType; import org.overture.ast.types.AUnknownType; import org.overture.ast.types.AUnresolvedType; import org.overture.ast.types.AVoidReturnType; import org.overture.ast.types.AVoidType; import org.overture.ast.types.PType; import org.overture.ast.types.SInvariantType; import org.overture.ast.types.SMapType; import org.overture.ast.util.PTypeSet; import org.overture.typechecker.assistant.ITypeCheckerAssistantFactory; /** * This class checks if 2 objects of a Type are equal. * * @author kel */ public class TypeEqualityChecker extends QuestionAnswerAdaptor<Object, Boolean> { protected ITypeCheckerAssistantFactory af; public TypeEqualityChecker(ITypeCheckerAssistantFactory af) { this.af = af; } @Override public Boolean caseABracketType(ABracketType type, Object other) throws AnalysisException { return type.getType().apply(this, other); } @Override public Boolean caseAClassType(AClassType type, Object other) throws AnalysisException { other = deBracket((PType) other); if (other instanceof AClassType) { AClassType oc = (AClassType) other; return type.getName().equals(oc.getName()); // NB. name only } return false; } @Override public Boolean caseAFunctionType(AFunctionType type, Object other) throws AnalysisException { other = deBracket((PType) other); if (!(other instanceof AFunctionType)) { return false; } AFunctionType fo = (AFunctionType) other; return type.getPartial() == fo.getPartial() && type.getResult().apply(this, fo.getResult()) && af.createPTypeAssistant().equals(type.getParameters(), fo.getParameters()); } @Override public Boolean defaultSInvariantType(SInvariantType type, Object other) throws AnalysisException { if (type instanceof ANamedInvariantType) { other = deBracket((PType) other); if (other instanceof ANamedInvariantType) { ANamedInvariantType nother = (ANamedInvariantType) other; return ((ANamedInvariantType) type).getName().equals(nother.getName()); } return false; } else if (type instanceof ARecordInvariantType) { other = af.createPTypeAssistant().deBracket(other); if (other instanceof ARecordInvariantType) { ARecordInvariantType rother = (ARecordInvariantType) other; return ((ARecordInvariantType) type).getName().equals(rother.getName()); // NB. identical } return false; } else { other = deBracket((PType) other); return type.getClass() == other.getClass(); } } @Override public Boolean defaultSMapType(SMapType type, Object other) throws AnalysisException { // return SMapTypeAssistantTC.equals(type, other); other = af.createPTypeAssistant().deBracket(other); if (other.getClass() == type.getClass()) // inmaps too { SMapType mt = (SMapType) other; // return PTypeAssistantTC.equals(type.getFrom(),mt.getFrom()) && PTypeAssistantTC.equals(type.getTo(), // mt.getTo()); return type.getFrom().apply(this, mt.getFrom()) && type.getTo().apply(this, mt.getTo()); } return false; } @Override public Boolean caseAOperationType(AOperationType type, Object other) throws AnalysisException { other = af.createPTypeAssistant().deBracket(other); if (!(other instanceof AOperationType)) { return false; } AOperationType oother = (AOperationType) other; return type.getResult().apply(this, oother.getResult()) && af.createPTypeAssistant().equals(type.getParameters(), oother.getParameters()); } @Override public Boolean caseAOptionalType(AOptionalType type, Object other) throws AnalysisException { if (other instanceof AOptionalType) { AOptionalType oo = (AOptionalType) other; return type.getType().apply(this, oo.getType()); } return false; } @Override public Boolean caseAProductType(AProductType type, Object other) throws AnalysisException { other = deBracket((PType) other); if (other instanceof AProductType) { AProductType pother = (AProductType) other; return af.createPTypeAssistant().equals(type.getTypes(), pother.getTypes()); // FIXME: apply method is not applicable here. } return false; } @Override public Boolean caseAQuoteType(AQuoteType type, Object other) throws AnalysisException { other = deBracket((PType) other); if (other instanceof AQuoteType) { AQuoteType qother = (AQuoteType) other; return type.getValue().getValue().equals(qother.getValue().getValue()); } return false; } @Override public Boolean caseASet1SetType(ASet1SetType type, Object other) throws AnalysisException { other = deBracket((PType) other); if (other instanceof ASet1SetType) { ASet1SetType os = (ASet1SetType) other; // NB empty set same type as any set return type.getEmpty() || os.getEmpty() || type.getSetof().apply(this, os.getSetof()); } return false; } @Override public Boolean caseASetSetType(ASetSetType type, Object other) throws AnalysisException { other = deBracket((PType) other); if (other instanceof ASetSetType) { ASetSetType os = (ASetSetType) other; // NB empty set same type as any set return type.getEmpty() || os.getEmpty() || type.getSetof().apply(this, os.getSetof()); } return false; } @Override public Boolean caseASeqSeqType(ASeqSeqType type, Object other) throws AnalysisException { other = deBracket((PType) other); if (other instanceof ASeqSeqType) { ASeqSeqType os = (ASeqSeqType) other; // NB. Empty sequence is the same type as any sequence return type.getEmpty() || os.getEmpty() || af.createPTypeAssistant().equals(type.getSeqof(), os.getSeqof()); } return false; } @Override public Boolean caseASeq1SeqType(ASeq1SeqType type, Object other) throws AnalysisException { other = deBracket((PType) other); if (other instanceof ASeq1SeqType) { ASeq1SeqType os = (ASeq1SeqType) other; // NB. Empty sequence is the same type as any sequence return type.getEmpty() || os.getEmpty() || af.createPTypeAssistant().equals(type.getSeqof(), os.getSeqof()); } return false; } @Override public Boolean caseAUndefinedType(AUndefinedType type, Object other) throws AnalysisException { other = deBracket((PType) other); return other instanceof AUndefinedType; } @Override public Boolean caseAUnionType(AUnionType type, Object other) throws AnalysisException { other = deBracket((PType) other); PTypeSet types = new PTypeSet(type.getTypes(), af); if (other instanceof AUnionType) { AUnionType uother = (AUnionType) other; for (PType t : uother.getTypes()) { if (!types.contains(t)) { return false; } } return true; } return types.contains(other); } @Override public Boolean caseAUnknownType(AUnknownType type, Object other) throws AnalysisException { return true; } @Override public Boolean caseAUnresolvedType(AUnresolvedType type, Object other) throws AnalysisException { other = deBracket((PType) other); if (other instanceof AUnresolvedType) { AUnresolvedType nother = (AUnresolvedType) other; return type.getName().equals(nother.getName()); } if (other instanceof ANamedInvariantType) { ANamedInvariantType nother = (ANamedInvariantType) other; return type.getName().equals(nother.getName()); } return false; } @Override public Boolean caseAVoidType(AVoidType type, Object other) throws AnalysisException { // return AVoidTypeAssistantTC.equals(type, other); other = deBracket((PType) other); return other instanceof AVoidType; } @Override public Boolean caseAVoidReturnType(AVoidReturnType type, Object other) throws AnalysisException { other = deBracket((PType) other); return other instanceof AVoidReturnType; } @Override public Boolean defaultPType(PType type, Object other) throws AnalysisException { other = deBracket((PType) other); return type.getClass() == other.getClass(); } public static PType deBracket(PType other) { while (other instanceof ABracketType) { other = ((ABracketType) other).getType(); } return other; } @Override public Boolean createNewReturnValue(INode node, Object question) throws AnalysisException { // TODO Auto-generated method stub return null; } @Override public Boolean createNewReturnValue(Object node, Object question) throws AnalysisException { // TODO Auto-generated method stub return null; } }