/*******************************************************************************
*
* Copyright (c) 2008 Fujitsu Services Ltd.
*
* Author: Nick Battle
*
* This file is part of VDMJ.
*
* VDMJ 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.
*
* VDMJ 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 VDMJ. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
package org.overture.interpreter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.List;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import org.overture.ast.analysis.AnalysisException;
import org.overture.ast.lex.Dialect;
import org.overture.ast.lex.LexLocation;
import org.overture.ast.messages.InternalException;
import org.overture.ast.util.modules.ModuleList;
import org.overture.config.Settings;
import org.overture.interpreter.commands.CommandReader;
import org.overture.interpreter.commands.ModuleCommandReader;
import org.overture.interpreter.messages.Console;
import org.overture.interpreter.runtime.ContextException;
import org.overture.interpreter.runtime.ModuleInterpreter;
import org.overture.interpreter.util.ExitStatus;
import org.overture.interpreter.util.ModuleListInterpreter;
import org.overture.parser.lex.LexTokenReader;
import org.overture.parser.syntax.ModuleReader;
import org.overture.pog.pub.IProofObligationList;
import org.overture.typechecker.ModuleTypeChecker;
import org.overture.typechecker.TypeChecker;
/**
* The main class of the VDM-SL parser/checker/interpreter.
*/
public class VDMSL extends VDMJ
{
private ModuleListInterpreter modules = new ModuleListInterpreter();
public VDMSL()
{
Settings.dialect = Dialect.VDM_SL;
}
/**
* @see VDMJ#parse(java.util.List)
*/
@Override
public ExitStatus parse(List<File> files)
{
modules.clear();
LexLocation.resetLocations();
int perrs = 0;
int pwarn = 0;
long duration = 0;
for (File file : files)
{
ModuleReader reader = null;
try
{
if (file.getName().endsWith(".lib"))
{
FileInputStream fis = new FileInputStream(file);
GZIPInputStream gis = new GZIPInputStream(fis);
ObjectInputStream ois = new ObjectInputStream(gis);
ModuleListInterpreter loaded = null;
long begin = System.currentTimeMillis();
try
{
loaded = new ModuleListInterpreter((ModuleList) ois.readObject());
} catch (Exception e)
{
println(file + " is not a valid VDM-SL library");
perrs++;
continue;
} finally
{
ois.close();
}
long end = System.currentTimeMillis();
loaded.setLoaded();
modules.addAll(loaded);
infoln("Loaded " + plural(loaded.size(), "module", "s")
+ " from " + file + " in " + (double) (end - begin)
/ 1000 + " secs");
} else
{
long before = System.currentTimeMillis();
LexTokenReader ltr = new LexTokenReader(file, Settings.dialect, filecharset);
reader = new ModuleReader(ltr);
modules.addAll(reader.readModules());
long after = System.currentTimeMillis();
duration += after - before;
}
} catch (InternalException e)
{
println(e.toString());
} catch (Throwable e)
{
println(e.toString());
perrs++;
}
if (reader != null && reader.getErrorCount() > 0)
{
perrs += reader.getErrorCount();
reader.printErrors(Console.out);
}
if (reader != null && reader.getWarningCount() > 0)
{
pwarn += reader.getWarningCount();
reader.printWarnings(Console.out);
}
}
perrs += modules.combineDefaults();
int n = modules.notLoaded();
if (n > 0)
{
info("Parsed " + plural(n, "module", "s") + " in "
+ (double) duration / 1000 + " secs. ");
info(perrs == 0 ? "No syntax errors" : "Found "
+ plural(perrs, "syntax error", "s"));
infoln(pwarn == 0 ? "" : " and " + (warnings ? "" : "suppressed ")
+ plural(pwarn, "warning", "s"));
}
return perrs == 0 ? ExitStatus.EXIT_OK : ExitStatus.EXIT_ERRORS;
}
/**
* @see VDMJ#typeCheck()
*/
@Override
public ExitStatus typeCheck()
{
int terrs = 0;
long before = System.currentTimeMillis();
try
{
TypeChecker typeChecker = new ModuleTypeChecker(modules);
typeChecker.typeCheck();
} catch (InternalException e)
{
println(e.toString());
} catch (Throwable e)
{
println(e.toString());
terrs++;
}
long after = System.currentTimeMillis();
terrs += TypeChecker.getErrorCount();
if (terrs > 0)
{
TypeChecker.printErrors(Console.out);
}
int twarn = TypeChecker.getWarningCount();
if (twarn > 0 && warnings)
{
TypeChecker.printWarnings(Console.out);
}
int n = modules.notLoaded();
if (n > 0)
{
info("Type checked " + plural(n, "module", "s") + " in "
+ (double) (after - before) / 1000 + " secs. ");
info(terrs == 0 ? "No type errors" : "Found "
+ plural(terrs, "type error", "s"));
infoln(twarn == 0 ? "" : " and " + (warnings ? "" : "suppressed ")
+ plural(twarn, "warning", "s"));
}
if (outfile != null && terrs == 0)
{
try
{
before = System.currentTimeMillis();
FileOutputStream fos = new FileOutputStream(outfile);
GZIPOutputStream gos = new GZIPOutputStream(fos);
ObjectOutputStream oos = new ObjectOutputStream(gos);
oos.writeObject(modules);
oos.close();
after = System.currentTimeMillis();
infoln("Saved " + plural(modules.size(), "module", "s")
+ " to " + outfile + " in " + (double) (after - before)
/ 1000 + " secs. ");
} catch (IOException e)
{
infoln("Cannot write " + outfile + ": " + e.getMessage());
terrs++;
}
}
if (pog && terrs == 0)
{
IProofObligationList list;
try
{
list = assistantFactory.createModuleListAssistant().getProofObligations(modules);
if (list.isEmpty())
{
println("No proof obligations generated");
} else
{
println("Generated "
+ plural(list.size(), "proof obligation", "s")
+ ":\n");
print(list.toString());
}
} catch (AnalysisException e)
{
println(e.toString());
}
}
return terrs == 0 ? ExitStatus.EXIT_OK : ExitStatus.EXIT_ERRORS;
}
/**
* @see org.overture.interpreter.VDMJ#interpret(List, String)
*/
@Override
protected ExitStatus interpret(List<File> filenames, String defaultName)
{
ModuleInterpreter interpreter = null;
try
{
long before = System.currentTimeMillis();
interpreter = getInterpreter();
interpreter.init(null);
if (defaultName != null)
{
interpreter.setDefaultName(defaultName);
}
long after = System.currentTimeMillis();
infoln("Initialized " + plural(modules.size(), "module", "s")
+ " in " + (double) (after - before) / 1000 + " secs. ");
} catch (ContextException e)
{
println("Initialization: " + e);
e.ctxt.printStackTrace(Console.out, true);
return ExitStatus.EXIT_ERRORS;
} catch (Exception e)
{
println("Initialization: " + e.getMessage());
return ExitStatus.EXIT_ERRORS;
}
try
{
if (script != null)
{
println(interpreter.execute(script, null).toString());
return ExitStatus.EXIT_OK;
} else
{
infoln("Interpreter started");
CommandReader reader = new ModuleCommandReader(interpreter, "> ");
return reader.run(filenames);
}
} catch (ContextException e)
{
println("Execution: " + e);
e.ctxt.printStackTrace(Console.out, true);
} catch (Exception e)
{
println("Execution: " + e);
}
return ExitStatus.EXIT_ERRORS;
}
@Override
public ModuleInterpreter getInterpreter() throws Exception
{
ModuleInterpreter interpreter = new ModuleInterpreter(modules);
return interpreter;
}
}