/*
* #%~
* 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.util;
import java.io.File;
import java.util.List;
import java.util.Vector;
import org.overture.ast.analysis.AnalysisException;
import org.overture.ast.definitions.PDefinition;
import org.overture.ast.definitions.SClassDefinition;
import org.overture.ast.expressions.PExp;
import org.overture.ast.factory.AstFactoryTC;
import org.overture.ast.modules.AModuleModules;
import org.overture.ast.typechecker.NameScope;
import org.overture.ast.types.PType;
import org.overture.ast.util.modules.ModuleList;
import org.overture.parser.lex.LexException;
import org.overture.parser.messages.VDMError;
import org.overture.parser.messages.VDMWarning;
import org.overture.parser.syntax.ParserException;
import org.overture.parser.util.ParserUtil;
import org.overture.parser.util.ParserUtil.ParserResult;
import org.overture.typechecker.ClassTypeChecker;
import org.overture.typechecker.Environment;
import org.overture.typechecker.FlatEnvironment;
import org.overture.typechecker.ModuleTypeChecker;
import org.overture.typechecker.TypeCheckInfo;
import org.overture.typechecker.TypeChecker;
import org.overture.typechecker.assistant.ITypeCheckerAssistantFactory;
import org.overture.typechecker.assistant.TypeCheckerAssistantFactory;
import org.overture.typechecker.visitor.TypeCheckVisitor;
public class TypeCheckerUtil
{
public static class TypeCheckResult<T>
{
public final ParserResult<T> parserResult;
public final List<VDMWarning> warnings;
public final List<VDMError> errors;
public final T result;
public TypeCheckResult(ParserResult<T> parserResult, T result,
List<VDMWarning> warnings, List<VDMError> errors)
{
this.parserResult = parserResult;
this.result = result;
this.warnings = warnings;
this.errors = errors;
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("Parse result:\n" + parserResult);
sb.append("\n\n\n");
sb.append("TypeCheck result:\n");
sb.append("\tErrors:");
sb.append(getErrorString());
sb.append("\tWarnings:");
sb.append(getWarningString());
return sb.toString();
}
public String getErrorString()
{
StringBuilder sb = new StringBuilder();
for (VDMError err : errors)
{
sb.append("\n\t" + err);
}
return sb.toString();
}
public String getWarningString()
{
StringBuilder sb = new StringBuilder();
for (VDMWarning err : warnings)
{
sb.append("\n\t" + err);
}
return sb.toString();
}
}
public static class ExpressionTypeChecker extends TypeChecker
{
PExp expression;
Environment env;
public PType type;
public ExpressionTypeChecker(PExp expression, Environment env)
{
this.expression = expression;
this.env = env;
}
public ExpressionTypeChecker(PExp expression)
{
this(expression, new FlatEnvironment(new TypeCheckerAssistantFactory(), new Vector<PDefinition>()));// new
// ModuleEnvironment(""));
}
@Override
public void typeCheck()
{
try
{
type = expression.apply(new TypeCheckVisitor(), new TypeCheckInfo(assistantFactory, env, NameScope.NAMESANDSTATE));
} catch (AnalysisException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static TypeCheckResult<List<AModuleModules>> typeCheckSl(File file)
{
return typeCheckSl(file, null);
}
public static TypeCheckResult<List<AModuleModules>> typeCheckSl(File file,
String charset)
{
ParserResult<List<AModuleModules>> parserResult = ParserUtil.parseSl(file, charset);
ModuleList modules = new ModuleList(parserResult.result);
return typeCheck(parserResult, parserResult.result, new ModuleTypeChecker(modules));
}
public static TypeCheckResult<List<AModuleModules>> typeCheckSl(
List<File> file)
{
return typeCheckSl(file, null);
}
public static TypeCheckResult<List<AModuleModules>> typeCheckSl(
List<File> file, String charset)
{
ParserResult<List<AModuleModules>> parserResult = ParserUtil.parseSl(file, charset);
ModuleList modules = new ModuleList(parserResult.result);
modules.combineDefaults();
return typeCheck(parserResult, parserResult.result, new ModuleTypeChecker(modules));
}
public static TypeCheckResult<List<AModuleModules>> typeCheckSl(
String content)
{
return typeCheckSl(content, null);
}
public static TypeCheckResult<List<AModuleModules>> typeCheckSl(
String content, String charset)
{
ParserResult<List<AModuleModules>> parserResult = ParserUtil.parseSl(content, charset);
return typeCheck(parserResult, parserResult.result, new ModuleTypeChecker(parserResult.result));
}
public static TypeCheckResult<List<SClassDefinition>> typeCheckPp(File file)
{
return typeCheckPp(file, null);
}
public static TypeCheckResult<List<SClassDefinition>> typeCheckPp(
File file, String charset)
{
ParserResult<List<SClassDefinition>> parserResult = ParserUtil.parseOo(file, charset);
return typeCheck(parserResult, parserResult.result, new ClassTypeChecker(parserResult.result));
}
public static TypeCheckResult<List<SClassDefinition>> typeCheckPp(
List<File> file)
{
return typeCheckPp(file, null);
}
public static TypeCheckResult<List<SClassDefinition>> typeCheckPp(
List<File> file, String charset)
{
ParserResult<List<SClassDefinition>> parserResult = ParserUtil.parseOo(file, charset);
return typeCheck(parserResult, parserResult.result, new ClassTypeChecker(parserResult.result));
}
public static TypeCheckResult<List<SClassDefinition>> typeCheckPp(
String content)
{
return typeCheckPp(content, null);
}
public static TypeCheckResult<List<SClassDefinition>> typeCheckPp(
String content, String charset)
{
ParserResult<List<SClassDefinition>> parserResult = ParserUtil.parseOo(content, charset);
return typeCheck(parserResult, parserResult.result, new ClassTypeChecker(parserResult.result));
}
public static TypeCheckResult<List<SClassDefinition>> typeCheckRt(
List<File> file) throws ParserException, LexException
{
return typeCheckRt(file, null);
}
public static TypeCheckResult<List<SClassDefinition>> typeCheckRt(
List<File> file, String charset) throws ParserException,
LexException
{
return typeCheckRt(ParserUtil.parseOo(file, charset));
}
public static TypeCheckResult<List<SClassDefinition>> typeCheckRt(File file)
throws ParserException, LexException
{
return typeCheckRt(file, null);
}
public static TypeCheckResult<List<SClassDefinition>> typeCheckRt(
File file, String charset) throws ParserException, LexException
{
return typeCheckRt(ParserUtil.parseOo(file, charset));
}
public static TypeCheckResult<List<SClassDefinition>> typeCheckRt(
String content) throws ParserException, LexException
{
return typeCheckRt(content, null);
}
public static TypeCheckResult<List<SClassDefinition>> typeCheckRt(
String content, String charset) throws ParserException,
LexException
{
return typeCheckRt(ParserUtil.parseOo(content, charset));
}
protected static TypeCheckResult<List<SClassDefinition>> typeCheckRt(
ParserResult<List<SClassDefinition>> parserResult)
throws ParserException, LexException
{
final ITypeCheckerAssistantFactory af = new TypeCheckerAssistantFactory();
List<SClassDefinition> classes = new Vector<SClassDefinition>();
classes.addAll(parserResult.result);
classes.add(AstFactoryTC.newACpuClassDefinition(af));
classes.add(AstFactoryTC.newABusClassDefinition(af));
return typeCheck(parserResult, classes, new ClassTypeChecker(classes, af));
}
public static TypeCheckResult<PExp> typeCheckExpression(String content)
throws ParserException, LexException
{
ParserResult<PExp> parserResult = ParserUtil.parseExpression(content);
return typeCheck(parserResult, parserResult.result, new ExpressionTypeChecker(parserResult.result));
}
public static <P> TypeCheckResult<P> typeCheck(
ParserResult<P> parserResult, P tcList, TypeChecker tc)
{
if (parserResult.errors.isEmpty())
{
TypeChecker.clearErrors();
tc.typeCheck();
return new TypeCheckResult<P>(parserResult, parserResult.result, TypeChecker.getWarnings(), TypeChecker.getErrors());
}
return new TypeCheckResult<P>(parserResult, null, new Vector<VDMWarning>(), new Vector<VDMError>());
}
}