/* * #%~ * 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; import java.util.List; import java.util.Vector; import org.overture.ast.analysis.AnalysisException; import org.overture.ast.analysis.QuestionAdaptor; import org.overture.ast.assistant.pattern.PTypeList; import org.overture.ast.definitions.AClassInvariantDefinition; import org.overture.ast.definitions.AEqualsDefinition; 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.AInstanceVariableDefinition; import org.overture.ast.definitions.AStateDefinition; import org.overture.ast.definitions.ASystemClassDefinition; import org.overture.ast.definitions.AThreadDefinition; import org.overture.ast.definitions.ATypeDefinition; import org.overture.ast.definitions.PDefinition; import org.overture.ast.definitions.SClassDefinition; import org.overture.ast.expressions.AIntLiteralExp; import org.overture.ast.expressions.ANewExp; import org.overture.ast.expressions.ARealLiteralExp; import org.overture.ast.expressions.AUndefinedExp; import org.overture.ast.expressions.PExp; import org.overture.ast.factory.AstFactory; import org.overture.ast.factory.AstFactoryTC; import org.overture.ast.intf.lex.ILexLocation; import org.overture.ast.node.INode; import org.overture.ast.patterns.PPattern; import org.overture.ast.typechecker.NameScope; import org.overture.ast.types.AFunctionType; import org.overture.ast.types.ANamedInvariantType; import org.overture.ast.types.AOperationType; import org.overture.ast.types.ARecordInvariantType; import org.overture.ast.types.AUnresolvedType; import org.overture.ast.types.PType; import org.overture.typechecker.Environment; import org.overture.typechecker.TypeCheckerErrors; import org.overture.typechecker.assistant.ITypeCheckerAssistantFactory; /** * This class implements a way to find ImplicitDefinitions from nodes from the AST. * * @author kel */ public class ImplicitDefinitionFinder extends QuestionAdaptor<Environment> { protected ITypeCheckerAssistantFactory af; public ImplicitDefinitionFinder(ITypeCheckerAssistantFactory af) { this.af = af; } protected AStateDefinition findStateDefinition(Environment question, INode node) { return question.findStateDefinition(); } @Override public void defaultSClassDefinition(SClassDefinition node, Environment question) throws AnalysisException { // TODO: should I expand this even more? if (node instanceof ASystemClassDefinition) { // af.createASystemClassDefinitionAssistant().implicitDefinitions((ASystemClassDefinition)node, question); af.createSClassDefinitionAssistant().implicitDefinitionsBase(node, question); for (PDefinition d : node.getDefinitions()) { if (d instanceof AInstanceVariableDefinition) { AInstanceVariableDefinition iv = (AInstanceVariableDefinition) d; PType ivType = af.createPDefinitionAssistant().getType(iv); if (ivType instanceof AUnresolvedType && iv.getExpression() instanceof AUndefinedExp) { AUnresolvedType ut = (AUnresolvedType) ivType; if (ut.getName().getFullName().equals("BUS")) { TypeCheckerErrors.warning(5014, "Uninitialized BUS ignored", d.getLocation(), d); } } else if (ivType instanceof AUnresolvedType && iv.getExpression() instanceof ANewExp) { AUnresolvedType ut = (AUnresolvedType) ivType; if (ut.getName().getFullName().equals("CPU")) { ANewExp newExp = (ANewExp) iv.getExpression(); PExp exp = newExp.getArgs().size() > 0 ? newExp.getArgs().get(1) : null; double speed = 0; if (exp instanceof AIntLiteralExp) { AIntLiteralExp frequencyExp = (AIntLiteralExp) newExp.getArgs().get(1); speed = frequencyExp.getValue().getValue(); } else if (exp instanceof ARealLiteralExp) { ARealLiteralExp frequencyExp = (ARealLiteralExp) newExp.getArgs().get(1); speed = frequencyExp.getValue().getValue(); } if (speed == 0) { TypeCheckerErrors.report(3305, "CPU frequency to slow: " + speed + " Hz", d.getLocation(), d); } else if (speed > AstFactoryTC.CPU_MAX_FREQUENCY) { TypeCheckerErrors.report(3306, "CPU frequency to fast: " + speed + " Hz", d.getLocation(), d); } } } } else if (d instanceof AExplicitOperationDefinition) { AExplicitOperationDefinition edef = (AExplicitOperationDefinition) d; if (!edef.getName().getName().equals(node.getName().getName()) || !edef.getParameterPatterns().isEmpty()) { TypeCheckerErrors.report(3285, "System class can only define a default constructor", d.getLocation(), d); } } else if (d instanceof AImplicitOperationDefinition) { AImplicitOperationDefinition idef = (AImplicitOperationDefinition) d; if (!d.getName().getName().equals(node.getName().getName())) { TypeCheckerErrors.report(3285, "System class can only define a default constructor", d.getLocation(), d); } if (idef.getBody() == null) { TypeCheckerErrors.report(3283, "System class constructor cannot be implicit", d.getLocation(), d); } } else { TypeCheckerErrors.report(3284, "System class can only define instance variables and a constructor", d.getLocation(), d); } } } { af.createSClassDefinitionAssistant().implicitDefinitionsBase(node, question); } } @Override public void caseAClassInvariantDefinition(AClassInvariantDefinition node, Environment question) throws AnalysisException { } @Override public void caseAEqualsDefinition(AEqualsDefinition node, Environment question) throws AnalysisException { } @Override public void caseAExplicitFunctionDefinition( AExplicitFunctionDefinition node, Environment question) throws AnalysisException { if (node.getPrecondition() != null) { node.setPredef(af.createAExplicitFunctionDefinitionAssistant().getPreDefinition(node)); // PDefinitionAssistantTC.markUsed(d.getPredef());//ORIGINAL CODE af.getUsedMarker().caseAExplicitFunctionDefinition(node.getPredef()); } else { node.setPredef(null); } if (node.getPostcondition() != null) { node.setPostdef(af.createAExplicitFunctionDefinitionAssistant().getPostDefinition(node)); // PDefinitionAssistantTC.markUsed(d.getPostdef());//ORIGINAL CODE af.getUsedMarker().caseAExplicitFunctionDefinition(node.getPostdef()); } else { node.setPostdef(null); } } @Override public void caseAExplicitOperationDefinition( AExplicitOperationDefinition node, Environment question) throws AnalysisException { node.setState(findStateDefinition(question, node)); if (node.getPrecondition() != null) { node.setPredef(af.createAExplicitOperationDefinitionAssistant().getPreDefinition(node, question)); af.createPDefinitionAssistant().markUsed(node.getPredef()); // ORIGINAL CODE } if (node.getPostcondition() != null) { node.setPostdef(af.createAExplicitOperationDefinitionAssistant().getPostDefinition(node, question)); af.createPDefinitionAssistant().markUsed(node.getPostdef()); } } @Override public void caseAImplicitFunctionDefinition( AImplicitFunctionDefinition node, Environment question) throws AnalysisException { if (node.getPrecondition() != null) { node.setPredef(af.createAImplicitFunctionDefinitionAssistant().getPreDefinition(node)); af.createPDefinitionAssistant().markUsed(node.getPredef()); // af.createPDefinitionAssistant().markUsed(node.getPredef()); } else { node.setPredef(null); } if (node.getPostcondition() != null) { node.setPostdef(af.createAImplicitFunctionDefinitionAssistant().getPostDefinition(node)); af.createPDefinitionAssistant().markUsed(node.getPostdef()); } else { node.setPostdef(null); } } @Override public void caseAImplicitOperationDefinition( AImplicitOperationDefinition node, Environment question) throws AnalysisException { node.setState(findStateDefinition(question, node)); if (node.getPrecondition() != null) { node.setPredef(af.createAImplicitOperationDefinitionAssistant().getPreDefinition(node, question)); af.createPDefinitionAssistant().markUsed(node.getPredef()); } if (node.getPostcondition() != null) { node.setPostdef(af.createAImplicitOperationDefinitionAssistant().getPostDefinition(node, question)); af.createPDefinitionAssistant().markUsed(node.getPostdef()); } } @Override public void caseAStateDefinition(AStateDefinition node, Environment question) throws AnalysisException { if (node.getInvPattern() != null) { node.setInvdef(getInvDefinition(node)); } if (node.getInitPattern() != null) { node.setInitdef(getInitDefinition(node)); } } @Override public void caseAThreadDefinition(AThreadDefinition node, Environment question) throws AnalysisException { // ORIGINAL CODE FROM ASSISTANT // node.setOperationDef(AThreadDefinitionAssistantTC.getThreadDefinition(node)); // Mine non static call of the code. node.setOperationDef(getThreadDefinition(node)); } @Override public void caseATypeDefinition(ATypeDefinition node, Environment question) throws AnalysisException { if (node.getInvPattern() != null) { // node.setInvdef(getInvDefinition(d)); //Original code from Assistant. node.setInvdef(getInvDefinition(node)); node.getInvType().setInvDef(node.getInvdef()); } else { node.setInvdef(null); } if (node.getInvType() instanceof ANamedInvariantType) { ANamedInvariantType ntype = (ANamedInvariantType) node.getInvType(); node.getComposeDefinitions().clear(); for (PType compose : af.createPTypeAssistant().getComposeTypes(ntype.getType())) { ARecordInvariantType rtype = (ARecordInvariantType) compose; node.getComposeDefinitions().add(AstFactory.newATypeDefinition(rtype.getName(), rtype, null, null)); } } } @Override public void defaultPDefinition(PDefinition node, Environment question) throws AnalysisException { return; } public AExplicitFunctionDefinition getInitDefinition(AStateDefinition d) { ILexLocation loc = d.getInitPattern().getLocation(); List<PPattern> params = new Vector<PPattern>(); params.add(d.getInitPattern().clone()); List<List<PPattern>> parameters = new Vector<List<PPattern>>(); parameters.add(params); PTypeList ptypes = new PTypeList(); ptypes.add(AstFactory.newAUnresolvedType(d.getName())); AFunctionType ftype = AstFactory.newAFunctionType(loc, false, ptypes, AstFactory.newABooleanBasicType(loc)); PExp body = AstFactory.newAStateInitExp(d); AExplicitFunctionDefinition def = AstFactory.newAExplicitFunctionDefinition(d.getName().getInitName(loc), NameScope.GLOBAL, null, ftype, parameters, body, null, null, false, null); return def; } public AExplicitFunctionDefinition getInvDefinition(AStateDefinition d) { ILexLocation loc = d.getInvPattern().getLocation(); List<PPattern> params = new Vector<PPattern>(); params.add(d.getInvPattern().clone()); List<List<PPattern>> parameters = new Vector<List<PPattern>>(); parameters.add(params); PTypeList ptypes = new PTypeList(); ptypes.add(AstFactory.newAUnresolvedType(d.getName())); AFunctionType ftype = AstFactory.newAFunctionType(loc, false, ptypes, AstFactory.newABooleanBasicType(loc)); return AstFactory.newAExplicitFunctionDefinition(d.getName().getInvName(loc), NameScope.GLOBAL, null, ftype, parameters, d.getInvExpression(), null, null, true, null); } public AExplicitFunctionDefinition getInvDefinition(ATypeDefinition d) { ILexLocation loc = d.getInvPattern().getLocation(); List<PPattern> params = new Vector<PPattern>(); params.add(d.getInvPattern().clone()); List<List<PPattern>> parameters = new Vector<List<PPattern>>(); parameters.add(params); PTypeList ptypes = new PTypeList(); if (d.getInvType() instanceof ARecordInvariantType) { // Records are inv_R: R +> bool ptypes.add(AstFactory.newAUnresolvedType(d.getName().clone())); } else { // Named types are inv_T: x +> bool, for T = x ANamedInvariantType nt = (ANamedInvariantType) d.getInvType(); ptypes.add(nt.getType().clone()); } AFunctionType ftype = AstFactory.newAFunctionType(loc, false, ptypes, AstFactory.newABooleanBasicType(loc)); AExplicitFunctionDefinition def = AstFactory.newAExplicitFunctionDefinition(d.getName().getInvName(loc), NameScope.GLOBAL, null, ftype, parameters, d.getInvExpression(), null, null, true, null); def.setAccess(d.getAccess().clone()); // Same as type's def.setClassDefinition(d.getClassDefinition()); return def; } public AExplicitOperationDefinition getThreadDefinition(AThreadDefinition d) { AOperationType type = AstFactory.newAOperationType(d.getLocation()); // () ==> () AExplicitOperationDefinition def = AstFactory.newAExplicitOperationDefinition(d.getOperationName(), type, new Vector<PPattern>(), null, null, d.getStatement().clone()); def.setAccess(d.getAccess().clone()); def.setClassDefinition(d.getClassDefinition()); return def; } }