/* * #%~ * 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.ArrayList; import java.util.HashSet; import java.util.LinkedList; 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.definitions.AInheritedDefinition; import org.overture.ast.definitions.AInstanceVariableDefinition; import org.overture.ast.definitions.AStateDefinition; import org.overture.ast.definitions.PDefinition; import org.overture.ast.definitions.SClassDefinition; import org.overture.ast.intf.lex.ILexNameToken; import org.overture.ast.lex.LexNameList; import org.overture.ast.typechecker.NameScope; import org.overture.ast.types.AAccessSpecifierAccessSpecifier; import org.overture.ast.types.PType; import org.overture.typechecker.Environment; import org.overture.typechecker.TypeCheckException; import org.overture.typechecker.TypeCheckInfo; import org.overture.typechecker.TypeCheckerErrors; import org.overture.typechecker.assistant.ITypeCheckerAssistantFactory; public class PDefinitionListAssistantTC implements IAstAssistant { protected ITypeCheckerAssistantFactory af; public PDefinitionListAssistantTC(ITypeCheckerAssistantFactory af) { this.af = af; } public void implicitDefinitions(List<PDefinition> paramDefinitions, Environment env) { for (PDefinition d : paramDefinitions) { af.createPDefinitionAssistant().implicitDefinitions(d, env); // System.out.println(); } } public PDefinition findName(List<PDefinition> definitions, ILexNameToken name, NameScope scope) { for (PDefinition d : definitions) { PDefinition def = af.createPDefinitionAssistant().findName(d, name, scope); if (def != null) { return def; } } return null; } public AStateDefinition findStateDefinition(List<PDefinition> definitions) { for (PDefinition d : definitions) { if (d instanceof AStateDefinition) { return (AStateDefinition) d; } } return null; } public void unusedCheck(List<PDefinition> definitions) { for (PDefinition d : definitions) { af.createPDefinitionAssistant().unusedCheck(d); } } public Set<PDefinition> findMatches(List<PDefinition> definitions, ILexNameToken name) { Set<PDefinition> set = new HashSet<PDefinition>(); for (PDefinition d : singleDefinitions(definitions)) { if (af.createPDefinitionAssistant().isFunctionOrOperation(d) && d.getName().matches(name)) { set.add(d); } } return set; } public List<PDefinition> singleDefinitions(List<PDefinition> definitions) { List<PDefinition> all = new ArrayList<PDefinition>(); for (PDefinition d : definitions) { all.addAll(af.createPDefinitionAssistant().getDefinitions(d)); } return all; } public void markUsed(List<PDefinition> definitions) { for (PDefinition d : definitions) { af.createPDefinitionAssistant().markUsed(d); } } public void typeCheck(List<PDefinition> defs, IQuestionAnswer<TypeCheckInfo, PType> rootVisitor, TypeCheckInfo question) throws AnalysisException { for (PDefinition d : defs) { if (d.getName() != null && d.getName().getName().equals("RESULT")) { TypeCheckerErrors.report(3336, "Illegal use of RESULT reserved identifier", d.getLocation(), d); } d.apply(rootVisitor, question); } } public LexNameList getVariableNames(List<PDefinition> list) { LexNameList variableNames = new LexNameList(); for (PDefinition d : list) { variableNames.addAll(af.createPDefinitionAssistant().getVariableNames(d)); } return variableNames; } public void setAccessibility(List<PDefinition> defs, AAccessSpecifierAccessSpecifier access) { for (PDefinition d : defs) { d.setAccess(access.clone()); } } public void typeResolve(List<PDefinition> definitions, IQuestionAnswer<TypeCheckInfo, PType> rootVisitor, TypeCheckInfo question) throws AnalysisException { TypeCheckException problem = null; for (PDefinition definition : definitions) { try { af.createPDefinitionAssistant().typeResolve(definition, rootVisitor, question); } catch (TypeCheckException te) { if (problem == null) { problem = te; } else { problem.addExtra(te); } } } if (problem != null) { throw problem; } } public PDefinition findType(List<PDefinition> actualDefs, ILexNameToken name, String fromModule) { for (PDefinition d : actualDefs) { PDefinition def = af.createPDefinitionAssistant().findType(d, name, fromModule); if (def != null) { return def; } } return null; } public void initializedCheck(LinkedList<PDefinition> definitions) { for (PDefinition d : definitions) { if (d instanceof AInstanceVariableDefinition) { AInstanceVariableDefinition ivd = (AInstanceVariableDefinition) d; initializedCheck(ivd); } } } public void setClassDefinition(List<PDefinition> defs, SClassDefinition classDefinition) { af.createPDefinitionAssistant().setClassDefinition(defs, classDefinition); } public boolean hasSubclassResponsibilities(List<PDefinition> definitions) { PDefinitionAssistantTC assistant = af.createPDefinitionAssistant(); for (PDefinition d : definitions) { if (assistant.isSubclassResponsibility(d)) { return true; } } return false; } public void removeDuplicates(List<PDefinition> definitions) { LinkedList<PDefinition> fixed = new LinkedList<PDefinition>(); for (PDefinition d : definitions) { boolean found = false; if (d instanceof AInheritedDefinition) { AInheritedDefinition indef = (AInheritedDefinition)d; List<PType> q = indef.getSuperdef().getName().getTypeQualifier(); indef.getName().setTypeQualifier(q); } for (PDefinition e : fixed) { if (e.getName() != null && af.getLexNameTokenAssistant().isEqual(e.getName(), d.getName())) { found = true; break; } } if (!found) { fixed.add(d); } } if (fixed.size() < definitions.size()) { definitions.clear(); definitions.addAll(fixed); } } public List<PDefinition> removeAbstracts(List<PDefinition> list) { List<PDefinition> keep = new Vector<PDefinition>(); PDefinitionAssistantTC assistant = af.createPDefinitionAssistant(); for (PDefinition def: list) { if (assistant.isSubclassResponsibility(def)) { boolean found = false; for (PDefinition def2: list) { if (def2 instanceof AInheritedDefinition) { AInheritedDefinition indef2 = (AInheritedDefinition)def2; List<PType> q = indef2.getSuperdef().getName().getTypeQualifier(); indef2.getName().setTypeQualifier(q); } if (!assistant.isSubclassResponsibility(def2) && af.createPDefinitionAssistant().findName(def, def2.getName(), NameScope.NAMESANDSTATE) != null) { found = true; break; } } if (!found) { keep.add(def); } } else { keep.add(def); } } return keep; } public void initializedCheck(AInstanceVariableDefinition ivd) { if (!ivd.getInitialized() && !af.createPAccessSpecifierAssistant().isStatic(ivd.getAccess())) { TypeCheckerErrors.warning(5001, "Instance variable '" + ivd.getName() + "' is not initialized", ivd.getLocation(), ivd); } } }