/*******************************************************************************
* Copyright (c) 2009-2013 CWI
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI
* * Mark Hills - Mark.Hills@cwi.nl (CWI)
* * Arnold Lankamp - Arnold.Lankamp@cwi.nl
*******************************************************************************/
package org.rascalmpl.checker;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import org.rascalmpl.debug.IRascalMonitor;
import org.rascalmpl.interpreter.Configuration;
import org.rascalmpl.interpreter.Evaluator;
import org.rascalmpl.interpreter.asserts.ImplementationError;
import org.rascalmpl.interpreter.env.GlobalEnvironment;
import org.rascalmpl.interpreter.env.ModuleEnvironment;
import org.rascalmpl.interpreter.load.StandardLibraryContributor;
import org.rascalmpl.parser.gtd.exception.ParseError;
import org.rascalmpl.uri.URIUtil;
import org.rascalmpl.value.ISourceLocation;
import org.rascalmpl.value.IValue;
import org.rascalmpl.value.IValueFactory;
import org.rascalmpl.value.type.Type;
import org.rascalmpl.value.type.TypeStore;
import org.rascalmpl.values.ValueFactoryFactory;
import org.rascalmpl.values.uptr.ITree;
public class StaticChecker {
private final Evaluator eval;
public static final String TYPECHECKER = "typecheckTree";
private boolean checkerEnabled;
private boolean initialized;
private boolean loaded;
private Type pathConfigConstructor = null;
public StaticChecker(PrintWriter stderr, PrintWriter stdout) {
GlobalEnvironment heap = new GlobalEnvironment();
ModuleEnvironment root = heap.addModule(new ModuleEnvironment("$staticchecker$", heap));
eval = new Evaluator(ValueFactoryFactory.getValueFactory(), stderr, stdout, root, heap);
eval.addRascalSearchPathContributor(StandardLibraryContributor.getInstance());
checkerEnabled = false;
initialized = false;
loaded = false;
}
private IValue eval(IRascalMonitor monitor, String cmd) {
try {
return eval.eval(monitor, cmd, URIUtil.rootLocation("checker")).getValue();
} catch (ParseError pe) {
throw new ImplementationError("syntax error in static checker modules", pe);
}
}
public synchronized void load(IRascalMonitor monitor) {
eval(monitor, "import lang::rascal::types::CheckTypes;");
eval(monitor, "import util::Reflective;");
TypeStore ts = eval.getHeap().getModule("util::Reflective").getStore();
pathConfigConstructor = ts.lookupConstructor(ts.lookupAbstractDataType("PathConfig"), "pathConfig").iterator().next();
loaded = true;
}
public void init() {
initialized = true;
}
public Configuration getConfiguration() {
return eval.getConfiguration();
}
public boolean isInitialized() {
return initialized;
}
public synchronized ITree checkModule(IRascalMonitor monitor, ISourceLocation module) {
if (checkerEnabled) {
return (ITree) eval.call(monitor, "check", module, getPathConfig());
}
return null;
}
private IValue getPathConfig() {
assert pathConfigConstructor != null;
IValueFactory vf = ValueFactoryFactory.getValueFactory();
Map<String, IValue> kwArgs = new HashMap<>();
kwArgs.put("srcPath", vf.list(eval.getRascalResolver().collect().toArray(new IValue[0])));
// default args for the rest
return vf.constructor(pathConfigConstructor, new IValue[0], kwArgs);
}
public synchronized void disableChecker() {
checkerEnabled = false;
}
public synchronized void enableChecker(IRascalMonitor monitor) {
if (!loaded) {
load(monitor);
}
checkerEnabled = true;
}
public boolean isCheckerEnabled() {
return checkerEnabled;
}
public void addRascalSearchPath(ISourceLocation uri) {
eval.addRascalSearchPath(uri);
}
public void addClassLoader(ClassLoader classLoader) {
eval.addClassLoader(classLoader);
}
public Evaluator getEvaluator() {
return eval;
}
}