/* * #%~ * 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.definition; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.Vector; import org.overture.ast.analysis.AnalysisException; import org.overture.ast.analysis.intf.IQuestionAnswer; import org.overture.ast.assistant.IAstAssistant; import org.overture.ast.assistant.definition.PDefinitionAssistant; import org.overture.ast.definitions.AExplicitFunctionDefinition; import org.overture.ast.definitions.AExplicitOperationDefinition; import org.overture.ast.definitions.AImplicitFunctionDefinition; import org.overture.ast.definitions.AImplicitOperationDefinition; import org.overture.ast.definitions.AInheritedDefinition; import org.overture.ast.definitions.PDefinition; import org.overture.ast.definitions.SClassDefinition; import org.overture.ast.expressions.ASubclassResponsibilityExp; import org.overture.ast.intf.lex.ILexNameToken; import org.overture.ast.lex.LexNameList; import org.overture.ast.statements.ASubclassResponsibilityStm; import org.overture.ast.typechecker.NameScope; import org.overture.ast.types.AClassType; import org.overture.ast.types.PType; import org.overture.typechecker.Environment; import org.overture.typechecker.TypeCheckInfo; import org.overture.typechecker.TypeChecker; import org.overture.typechecker.TypeCheckerErrors; import org.overture.typechecker.assistant.ITypeCheckerAssistantFactory; import org.overture.typechecker.utilities.DefinitionFinder; import org.overture.typechecker.utilities.DefinitionTypeResolver; import org.overture.typechecker.utilities.NameFinder; //TODO Add assistant Javadoc /** * Top-Level assistant. Will probably remain present for conveniency's sake but the static access will be disallowed. * * @author ldc */ public class PDefinitionAssistantTC extends PDefinitionAssistant implements IAstAssistant { protected ITypeCheckerAssistantFactory af; public PDefinitionAssistantTC(ITypeCheckerAssistantFactory af) { super(af); this.af = af; } public boolean equals(PDefinition d, Object other) // Used for sets of definitions. { try { return d.apply(af.getDefinitionEqualityChecker(), other); } catch (AnalysisException e) { return false; } } public boolean hasSupertype(SClassDefinition aClassDefDefinition, PType other) { if (af.createPTypeAssistant().equals(af.createPDefinitionAssistant().getType(aClassDefDefinition), other)) { return true; } else { for (PType type : aClassDefDefinition.getSupertypes()) { AClassType sclass = (AClassType) type; if (af.createPTypeAssistant().hasSupertype(sclass, other)) { return true; } } } return false; } public boolean isFunctionOrOperation(PDefinition possible) { return af.createPDefinitionAssistant().isFunction(possible) || af.createPDefinitionAssistant().isOperation(possible); } public PDefinition findType(List<PDefinition> definitions, ILexNameToken name, String fromModule) { for (PDefinition d : definitions) { PDefinition def = findType(d, name, fromModule); if (def != null) { return def; } } return null; } public PDefinition findType(PDefinition d, ILexNameToken sought, String fromModule) { try { return d.apply(af.getDefinitionFinder(), new DefinitionFinder.Newquestion(sought, fromModule)); } catch (AnalysisException e) { return null; } } public PDefinition findName(PDefinition d, ILexNameToken sought, NameScope scope) { try { return d.apply(af.getNameFinder(), new NameFinder.Newquestion(sought, scope)); } catch (AnalysisException e) { return null; } } public PDefinition findNameBaseCase(PDefinition d, ILexNameToken sought, NameScope scope) { if (af.getLexNameTokenAssistant().isEqual(d.getName(), sought)) { if (!d.getNameScope().matches(scope)) { TypeChecker.report(3302, "State variable '" + sought.getFullName() + "' cannot be accessed from this context", sought.getLocation()); } markUsed(d); return d; } return null; } public void markUsed(PDefinition d) { try { d.apply(af.getUsedMarker()); } catch (AnalysisException e) { } } public void unusedCheck(PDefinition d) { try { d.apply(af.getUnusedChecker()); } catch (AnalysisException e) { } } public void unusedCheckBaseCase(PDefinition d) { if (!af.createPDefinitionAssistant().isUsed(d)) { TypeCheckerErrors.warning(5000, "Definition '" + d.getName() + "' not used", d.getLocation(), d); markUsed(d); // To avoid multiple warnings } } public List<PDefinition> getDefinitions(PDefinition d) { try { return d.apply(af.getDefinitionCollector()); } catch (AnalysisException e) { return null; } } public PDefinition getSelfDefinition(PDefinition d) { try { return d.apply(af.getSelfDefinitionFinder()); } catch (AnalysisException e) { return null; } } public LexNameList getVariableNames(PDefinition d) { try { return d.apply(af.getVariableNameCollector()); } catch (AnalysisException e) { return null; } } public boolean isStatic(PDefinition fdef) { return af.createPAccessSpecifierAssistant().isStatic(fdef.getAccess()); } public PDefinition deref(PDefinition d) { try { return d.apply(af.getDereferer()); } catch (AnalysisException e) { return null; } } public boolean isCallableOperation(PDefinition d) { try { return d.apply(af.getCallableOperationChecker()); } catch (AnalysisException e) { return false; } } public boolean isUsed(PDefinition d) { try { return d.apply(af.getUsedChecker()); } catch (AnalysisException e) { return false; } } public void implicitDefinitions(PDefinition d, Environment env) { try { d.apply(af.getImplicitDefinitionFinder(), env); } catch (AnalysisException e) { } } public void typeResolve(PDefinition d, IQuestionAnswer<TypeCheckInfo, PType> rootVisitor, TypeCheckInfo question) throws AnalysisException { try { d.apply(af.getDefinitionTypeResolver(), new DefinitionTypeResolver.NewQuestion(rootVisitor, question)); } catch (AnalysisException e) { } } public PType getType(PDefinition d) { try { return d.apply(af.getDefinitionTypeFinder()); } catch (AnalysisException e) { return null; } } public boolean isUpdatable(PDefinition d) { try { return d.apply(af.getUpdatableChecker()); } catch (AnalysisException e) { return false; } } public String kind(PDefinition d) { try { return d.apply(af.getKindFinder()); } catch (AnalysisException e) { return null; } } public boolean isFunction(PDefinition d) { try { return d.apply(af.getFunctionChecker()); } catch (AnalysisException e) { return false; } } public boolean isOperation(PDefinition d) { try { return d.apply(af.getOperationChecker()); } catch (AnalysisException e) { return false; } } /** * Check a DefinitionList for incompatible duplicate pattern definitions. * * @param d * @param defs * @return */ public List<PDefinition> checkDuplicatePatterns(PDefinition d, List<PDefinition> defs) { Set<PDefinition> noDuplicates = new HashSet<PDefinition>(); for (PDefinition d1 : defs) { for (PDefinition d2 : defs) { if (d1 != d2 && d1.getName() != null && d2.getName() != null && d1.getName().equals(d2.getName())) { if (!af.getTypeComparator().compatible(d1.getType(), d2.getType())) { TypeCheckerErrors.report(3322, "Duplicate patterns bind to different types", d.getLocation(), d); TypeCheckerErrors.detail2(d1.getName().getName(), d1.getType(), d2.getName().getName(), d2.getType()); } } } noDuplicates.add(d1); } return new Vector<PDefinition>(noDuplicates); } public boolean isSubclassResponsibility(PDefinition d) { while (d instanceof AInheritedDefinition) { AInheritedDefinition aid = (AInheritedDefinition) d; d = aid.getSuperdef(); } if (d instanceof AExplicitOperationDefinition) { AExplicitOperationDefinition op = (AExplicitOperationDefinition) d; return op.getBody() instanceof ASubclassResponsibilityStm; } else if (d instanceof AImplicitOperationDefinition) { AImplicitOperationDefinition op = (AImplicitOperationDefinition) d; return op.getBody() instanceof ASubclassResponsibilityStm; } else if (d instanceof AExplicitFunctionDefinition) { AExplicitFunctionDefinition fn = (AExplicitFunctionDefinition) d; return fn.getBody() instanceof ASubclassResponsibilityExp; } else if (d instanceof AImplicitFunctionDefinition) { AImplicitFunctionDefinition fn = (AImplicitFunctionDefinition) d; return fn.getBody() instanceof ASubclassResponsibilityExp; } return false; } public boolean isInstanceVariable(PDefinition def) { try { return def.apply(af.getInstanceVariableChecker()); } catch (AnalysisException e) { return false; } } }