/*
* #%~
* 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.visitor;
import java.util.List;
import java.util.Vector;
import org.overture.ast.analysis.intf.IQuestionAnswer;
import org.overture.ast.definitions.AExplicitFunctionDefinition;
import org.overture.ast.definitions.AImplicitFunctionDefinition;
import org.overture.ast.definitions.PDefinition;
import org.overture.ast.factory.AstFactory;
import org.overture.ast.intf.lex.ILexNameToken;
import org.overture.ast.modules.AAllImport;
import org.overture.ast.modules.AFunctionValueImport;
import org.overture.ast.modules.AModuleModules;
import org.overture.ast.modules.AOperationValueImport;
import org.overture.ast.modules.ATypeImport;
import org.overture.ast.modules.SValueImport;
import org.overture.ast.typechecker.NameScope;
import org.overture.ast.types.PType;
import org.overture.ast.types.SInvariantType;
import org.overture.typechecker.FlatCheckedEnvironment;
import org.overture.typechecker.TypeCheckInfo;
import org.overture.typechecker.TypeCheckerErrors;
public class TypeCheckerImportsVisitor extends AbstractTypeCheckVisitor
{
public TypeCheckerImportsVisitor(
IQuestionAnswer<TypeCheckInfo, PType> typeCheckVisitor)
{
super(typeCheckVisitor);
}
@Override
public PType caseAAllImport(AAllImport node, TypeCheckInfo question)
{
return null; // Implicitly OK.
}
@Override
public PType caseATypeImport(ATypeImport node, TypeCheckInfo question)
{
if (node.getDef() != null && node.getFrom() != null)
{
PDefinition def = node.getDef();
ILexNameToken name = node.getName();
AModuleModules from = node.getFrom();
def.setType((SInvariantType) question.assistantFactory.createPTypeAssistant().typeResolve(question.assistantFactory.createPDefinitionAssistant().getType(def), null, THIS, question));
PDefinition expdef = question.assistantFactory.createPDefinitionListAssistant().findType(from.getExportdefs(), name, null);
if (expdef != null)
{
PType exptype = question.assistantFactory.createPTypeAssistant().typeResolve(expdef.getType(), null, THIS, question);
if (!question.assistantFactory.getTypeComparator().compatible(def.getType(), exptype))
{
TypeCheckerErrors.report(3192, "Type import of " + name
+ " does not match export from " + from.getName(), node.getLocation(), node);
TypeCheckerErrors.detail2("Import", def.getType().toString() // TODO: .toDetailedString()
, "Export", exptype.toString()); // TODO:
// .toDetailedString());
}
}
}
return null;
}
@Override
public PType defaultSValueImport(SValueImport node, TypeCheckInfo question)
{
PType type = node.getImportType();
AModuleModules from = node.getFrom();
ILexNameToken name = node.getName();
if (type != null && from != null)
{
type = question.assistantFactory.createPTypeAssistant().typeResolve(type, null, THIS, question);
PDefinition expdef = question.assistantFactory.createPDefinitionListAssistant().findName(from.getExportdefs(), name, NameScope.NAMES);
if (expdef != null)
{
PType exptype = question.assistantFactory.createPTypeAssistant().typeResolve(expdef.getType(), null, THIS, question);
if (!question.assistantFactory.getTypeComparator().compatible(type, exptype))
{
TypeCheckerErrors.report(3194, "Type of value import "
+ name + " does not match export from "
+ from.getName(), node.getLocation(), node);
TypeCheckerErrors.detail2("Import", type.toString(), // TODO:
// .toDetailedString(),
"Export", exptype.toString()); // TODO:
// .toDetailedString());
}
}
}
return null;
}
@Override
public PType caseAFunctionValueImport(AFunctionValueImport node,
TypeCheckInfo question)
{
if (node.getTypeParams().size() == 0)
{
return defaultSValueImport(node, question);
}
else
{
List<PDefinition> defs = new Vector<PDefinition>();
for (ILexNameToken pname : node.getTypeParams())
{
ILexNameToken pnameClone = pname.clone();
PDefinition p = AstFactory.newALocalDefinition(pname.getLocation(), pnameClone, NameScope.NAMES, AstFactory.newAParameterType(pnameClone));
question.assistantFactory.createPDefinitionAssistant().markUsed(p);
defs.add(p);
}
FlatCheckedEnvironment params = new FlatCheckedEnvironment(question.assistantFactory, defs, question.env, NameScope.NAMES);
PType rtype = question.assistantFactory.createPTypeAssistant().typeResolve(node.getImportType(), null, THIS, question.newInfo(params));
node.setImportType(rtype);
PDefinition def = question.assistantFactory.createPDefinitionListAssistant().findName(node.getFrom().getExportdefs(), node.getName(), NameScope.NAMES);
if (def instanceof AExplicitFunctionDefinition)
{
AExplicitFunctionDefinition efd = (AExplicitFunctionDefinition)def;
if (efd.getTypeParams() == null || efd.getTypeParams().isEmpty())
{
TypeCheckerErrors.report(3352, "Imported " + node.getName() + " function has no type paramaters", node.getLocation(), node);
}
else if (!efd.getTypeParams().toString().equals(node.getTypeParams().toString()))
{
TypeCheckerErrors.report(3353, "Imported " + node.getName() + " function type parameters incorrect", node.getLocation(), node);
TypeCheckerErrors.detail2("Imported", node.getTypeParams(), "Actual", efd.getTypeParams());
}
if (efd.getType() != null && !efd.getType().toString().equals(node.getImportType().toString()))
{
TypeCheckerErrors.report(3184, "Imported " + node.getName() + " function type incorrect", node.getLocation(), node);
TypeCheckerErrors.detail2("Imported", node.getImportType(), "Actual", efd.getType());
}
node.setImportType(efd.getType().clone());
}
else if (def instanceof AImplicitFunctionDefinition)
{
AImplicitFunctionDefinition ifd = (AImplicitFunctionDefinition)def;
if (ifd.getTypeParams() == null || ifd.getTypeParams().isEmpty())
{
TypeCheckerErrors.report(3352, "Imported " + node.getName() + " function has no type paramaters", node.getLocation(), node);
}
else if (!ifd.getTypeParams().toString().equals(node.getTypeParams().toString()))
{
TypeCheckerErrors.report(3353, "Imported " + node.getName() + " function type parameters incorrect", node.getLocation(), node);
TypeCheckerErrors.detail2("Imported", node.getTypeParams(), "Actual", ifd.getTypeParams());
}
if (ifd.getType() != null && !ifd.getType().toString().equals(node.getImportType().toString()))
{
TypeCheckerErrors.report(3184, "Imported " + node.getName() + " function type incorrect", node.getLocation(), node);
TypeCheckerErrors.detail2("Imported", node.getImportType(), "Actual", ifd.getType());
}
node.setImportType(ifd.getType().clone());
}
}
return null;
}
@Override
public PType caseAOperationValueImport(AOperationValueImport node,
TypeCheckInfo question)
{
return defaultSValueImport(node, question);
}
}