/* * #%~ * 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.assistant.type; import java.util.LinkedList; import org.overture.ast.analysis.AnalysisException; import org.overture.ast.analysis.intf.IQuestionAnswer; import org.overture.ast.assistant.IAstAssistant; import org.overture.ast.assistant.pattern.PTypeList; import org.overture.ast.assistant.type.PTypeAssistant; import org.overture.ast.definitions.ATypeDefinition; import org.overture.ast.definitions.PDefinition; import org.overture.ast.intf.lex.ILexLocation; import org.overture.ast.intf.lex.ILexNameToken; import org.overture.ast.types.AAccessSpecifierAccessSpecifier; import org.overture.ast.types.ABracketType; import org.overture.ast.types.AClassType; import org.overture.ast.types.AFunctionType; import org.overture.ast.types.AOperationType; import org.overture.ast.types.AProductType; import org.overture.ast.types.ARecordInvariantType; import org.overture.ast.types.SSetType; import org.overture.ast.types.AUnionType; import org.overture.ast.types.AUnknownType; import org.overture.ast.types.AVoidType; import org.overture.ast.types.PType; import org.overture.ast.types.SMapType; import org.overture.ast.types.SSeqType; import org.overture.typechecker.Environment; import org.overture.typechecker.TypeCheckInfo; import org.overture.typechecker.TypeChecker; import org.overture.typechecker.assistant.ITypeCheckerAssistantFactory; import org.overture.typechecker.utilities.type.ConcreateTypeImplementor; import org.overture.typechecker.utilities.type.PTypeResolver; public class PTypeAssistantTC extends PTypeAssistant implements IAstAssistant { protected ITypeCheckerAssistantFactory af; public PTypeAssistantTC(ITypeCheckerAssistantFactory af) { super(af); this.af = af; } public boolean hasSupertype(AClassType cto, PType other) { return af.createPDefinitionAssistant().hasSupertype(cto.getClassdef(), other); } public boolean isType(PType type, Class<? extends PType> typeclass) { try { return type.apply(af.getPTypeExtendedChecker(), typeclass); } catch (AnalysisException e) { return false; } } public PType polymorph(PType type, ILexNameToken pname, PType actualType) { try { return type.apply(af.getConcreateTypeImplementor(), new ConcreateTypeImplementor.Newquestion(pname, actualType)); } catch (AnalysisException e) { return null; } } public boolean isUnknown(PType type) { if (type instanceof AUnionType) { return isUnknown((AUnionType) type); } else if (type instanceof AUnknownType) { return true; } return false; } public boolean isUnion(PType type) { try { return type.apply(af.getUnionBasisChecker()); } catch (AnalysisException e) { return false; } } public AUnionType getUnion(PType type) { try { return type.apply(af.getUnionTypeFinder()); } catch (AnalysisException e) { return null; } } public boolean isFunction(PType type) { try { return type.apply(af.getPTypeFunctionChecker()); } catch (AnalysisException e) { return false; } } public AFunctionType getFunction(PType type) { try { return type.apply(af.getFunctionTypeFinder()); } catch (AnalysisException e) { return null; } } public PType typeResolve(PType type, ATypeDefinition root, IQuestionAnswer<TypeCheckInfo, PType> rootVisitor, TypeCheckInfo question) { try { return type.apply(af.getPTypeResolver(), new PTypeResolver.Newquestion(root, rootVisitor, question)); } catch (AnalysisException e) { return null; } } public void unResolve(PType type) { try { type.apply(af.getTypeUnresolver()); } catch (AnalysisException e) { } } public boolean isOperation(PType type) { try { return type.apply(af.getOperationBasisChecker()); } catch (AnalysisException e) { return false; } } public AOperationType getOperation(PType type) { try { return type.apply(af.getOperationTypeFinder()); } catch (AnalysisException e) { return null; } } public boolean isSeq(PType type) { try { return type.apply(af.getSeqBasisChecker()); } catch (AnalysisException e) { return false; } } public SSeqType getSeq(PType type) { try { return type.apply(af.getSeqTypeFinder()); } catch (AnalysisException e) { return null; } } public boolean isMap(PType type) { try { return type.apply(af.getMapBasisChecker()); } catch (AnalysisException e) { return false; } } public SMapType getMap(PType type) { try { return type.apply(af.getMapTypeFinder()); } catch (AnalysisException e) { return null; } } public boolean isSet(PType type) { try { return type.apply(af.getSetBasisChecker()); } catch (AnalysisException e) { return false; } } public SSetType getSet(PType type) { try { return type.apply(af.getSetTypeFinder()); } catch (AnalysisException e) { return null; } } public boolean isRecord(PType type) { try { return type.apply(af.getRecordBasisChecker()); } catch (AnalysisException e) { return false; } } public boolean isTag(PType type) { try { return type.apply(af.getTagBasisChecker()); } catch (AnalysisException e) { return false; } } public ARecordInvariantType getRecord(PType type) { try { return type.apply(af.getRecordTypeFinder()); } catch (AnalysisException e) { return null; } } public boolean isClass(PType type, Environment env) { try { return type.apply(af.getClassBasisChecker(env)); } catch (AnalysisException e) { return false; } } public AClassType getClassType(PType type, Environment env) { try { return type.apply(af.getClassTypeFinder(env)); } catch (AnalysisException e) { return null; } } public AProductType getProduct(PType type) { try { return type.apply(af.getProductTypeFinder()); } catch (AnalysisException e) { return null; } } public boolean isProduct(PType type) { try { return type.apply(af.getProductBasisChecker()); } catch (AnalysisException e) { return false; } } public boolean narrowerThan(PType type, AAccessSpecifierAccessSpecifier accessSpecifier) { try { return type.apply(af.getNarrowerThanComparator(), accessSpecifier); } catch (AnalysisException e) { return false; } } public boolean narrowerThanBaseCase(PType type, AAccessSpecifierAccessSpecifier accessSpecifier) { if (type.getDefinitions() != null) { boolean result = false; for (PDefinition d : type.getDefinitions()) { result = result || af.createPAccessSpecifierAssistant().narrowerThan(d.getAccess(), accessSpecifier); } return result; } else { return false; } } public boolean equals(PType type, Object other) { try { return type.apply(af.getTypeEqualityChecker(), other); } catch (AnalysisException e) { return false; } } public PType deBracket(PType other) { while (other instanceof ABracketType) { other = ((ABracketType) other).getType(); } return other; } // public static Object deBracket(Object other) // used at pog-string-base, problematic conversion. // { // while (other instanceof ABracketType) // { // other = ((ABracketType) other).getType(); // } // // return other; // } public PType isType(PType type, String typename) { try { return type.apply(af.getPTypeFinder(), typename); } catch (AnalysisException e) { return null; } } public String toDisplay(PType type) { try { return type.apply(af.getTypeDisplayer()); } catch (AnalysisException e) { return null; } } public boolean isProduct(PType type, int size) { try { return type.apply(af.getProductExtendedChecker(), size); } catch (AnalysisException e) { return false; } } public AProductType getProduct(PType type, int size) { try { return type.apply(af.getProductExtendedTypeFinder(), size); } catch (AnalysisException e) { return null; } } public boolean equals(LinkedList<PType> parameters, LinkedList<PType> other) { if (parameters.size() != other.size()) { return false; } for (int i = 0; i < parameters.size(); i++) { if (!af.createPTypeAssistant().equals(parameters.get(i), other.get(i))) { return false; } } return true; } public boolean isVoid(PType type) { try { return type.apply(af.getVoidBasisChecker()); } catch (AnalysisException e) { return false; } } public boolean hasVoid(PType type) { try { return type.apply(af.getVoidExistanceChecker()); } catch (AnalysisException e) { return false; } } public Object deBracket(Object other) { while (other instanceof ABracketType) { other = ((ABracketType) other).getType(); } return other; } public PTypeList getComposeTypes(PType type) { try { return type.apply(af.getComposeTypeCollector()); } catch (AnalysisException e) { return new PTypeList(); } } public PType checkConstraint(PType constraint, PType actual, ILexLocation location) { if (constraint != null) { if (!af.getTypeComparator().isSubType(actual, constraint, true)) { TypeChecker.report(3327, "Value is not of the right type", location); TypeChecker.detail2("Actual", actual, "Expected", constraint); } } return actual; } public PType possibleConstraint(PType constraint, PType actual, ILexLocation location) { if (constraint != null) { if (!af.getTypeComparator().compatible(constraint, actual)) { TypeChecker.report(3327, "Value is not of the right type", location); TypeChecker.detail2("Actual", actual, "Expected", constraint); } } return actual; } public PType checkReturnType(PType constraint, PType actual, ILexLocation location) { PTypeAssistantTC assistant = af.createPTypeAssistant(); if (constraint != null && !(actual instanceof AVoidType) && !assistant.isUnknown(actual)) { if (assistant.hasVoid(actual) && !(constraint instanceof AVoidType)) { TypeChecker.report(3328, "Statement may return void value", location); TypeChecker.detail2("Actual", actual, "Expected", constraint); } else if (!af.getTypeComparator().compatible(constraint, actual)) { TypeChecker.report(3327, "Value is not of the right type", location); TypeChecker.detail2("Actual", actual, "Expected", constraint); } } return actual; } public boolean isUnknown(AUnionType type) { for (PType t : type.getTypes()) { if (af.createPTypeAssistant().isUnknown(t)) { return true; } } return false; } }