/*******************************************************************************
*
* Copyright (c) 2009 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.debug;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import java.util.Vector;
import java.util.concurrent.ArrayBlockingQueue;
import org.overture.ast.definitions.SClassDefinition;
import org.overture.ast.modules.AModuleModules;
import org.overture.interpreter.debug.RemoteInterpreter.Call.CallType;
import org.overture.interpreter.runtime.ClassInterpreter;
import org.overture.interpreter.runtime.Interpreter;
import org.overture.interpreter.runtime.ModuleInterpreter;
import org.overture.interpreter.runtime.SourceFile;
import org.overture.interpreter.scheduler.BasicSchedulableThread;
import org.overture.interpreter.values.Value;
import org.overture.interpreter.values.ValueFactory;
public class RemoteInterpreter
{
private final Interpreter interpreter;
private final DBGPReader dbgp;
private boolean running = false;
private Thread vdmExecuteThread;
public RemoteInterpreter(Interpreter interpreter, DBGPReader dbgp)
{
this.interpreter = interpreter;
this.dbgp = dbgp;
}
public Interpreter getInterpreter()
{
return interpreter;
}
public ValueFactory getValueFactory()
{
return new ValueFactory();
}
public DBGPReader getDebugReader()
{
return dbgp;
}
public String execute(String line) throws Exception
{
if (isFinished)
{
throw new Exception("RemoteInterpreter has finished.");
}
executionQueueRequest.add(new Call(CallType.Execute, line));
Object result = executionQueueResult.take();
if (result instanceof Exception)
{
throw (Exception) result;
} else
{
return ((Value) result).toString();
}
}
public Value valueExecute(String line) throws Exception
{
if (isFinished)
{
throw new Exception("RemoteInterpreter has finished.");
}
executionQueueRequest.add(new Call(CallType.Execute, line));
Object result = executionQueueResult.take();
if (result instanceof Exception)
{
throw (Exception) result;
} else
{
return (Value) result;
}
}
public void init()
{
interpreter.init(dbgp);
}
public void create(String var, String exp) throws Exception
{
if (isFinished)
{
throw new Exception("RemoteInterpreter has finished.");
}
if (interpreter instanceof ClassInterpreter)
{
executionQueueRequest.add(new Call(CallType.Create, var, exp));
Object result = executionQueueResult.take();
if (result instanceof Exception)
{
throw (Exception) result;
}
} else
{
throw new Exception("Only available for VDM++ and VDM-RT");
}
}
public String getEnvironment()
{
return interpreter.getInitialContext();
}
public Set<File> getSourceFiles()
{
return interpreter.getSourceFiles();
}
public SourceFile getSourceFile(File file) throws IOException
{
return interpreter.getSourceFile(file);
}
public List<String> getModules() throws Exception
{
List<String> names = new Vector<String>();
if (interpreter instanceof ClassInterpreter)
{
throw new Exception("Only available for VDM-SL");
} else
{
for (AModuleModules m : ((ModuleInterpreter) interpreter).getModules())
{
names.add(m.getName().getName());
}
}
return names;
}
public List<String> getClasses() throws Exception
{
List<String> names = new Vector<String>();
if (interpreter instanceof ClassInterpreter)
{
for (SClassDefinition def : ((ClassInterpreter) interpreter).getClasses())
{
names.add(def.getName().getName());
}
} else
{
throw new Exception("Only available for VDM++ and VDM-RT");
}
return names;
}
public void finish()
{
isFinished = true;
if (vdmExecuteThread != null)
{
vdmExecuteThread.interrupt();
}
}
ArrayBlockingQueue<Call> executionQueueRequest = new ArrayBlockingQueue<Call>(1);
ArrayBlockingQueue<Object> executionQueueResult = new ArrayBlockingQueue<Object>(1);
private boolean isFinished;
public static class Call
{
public enum CallType
{
Execute, Create
};
public final CallType type;
public final String exp;
public final String var;
public Call(CallType type, String var, String exp)
{
this.type = type;
this.var = var;
this.exp = exp;
}
public Call(CallType type, String exp)
{
this.type = type;
this.var = null;
this.exp = exp;
}
@Override
public String toString()
{
return this.type + " " + this.var + " " + this.exp;
}
}
public void processRemoteCalls() throws Exception
{
if (running)
{
return;
}
if (BasicSchedulableThread.getThread(Thread.currentThread()) == null)
{
throw new Exception("Process Remote Calls can only be called from a valid VDM thread");
}
running = true;
vdmExecuteThread = Thread.currentThread();
while (!isFinished)
{
try
{
Call call = executionQueueRequest.take();
try
{
switch (call.type)
{
case Create:
if (interpreter instanceof ClassInterpreter)
{
ClassInterpreter ci = (ClassInterpreter) interpreter;
ci.create(call.var, call.exp);
executionQueueResult.add(new Object());
}
break;
case Execute:
executionQueueResult.add(interpreter.execute(call.exp, dbgp));
break;
}
} catch (Exception e)
{
executionQueueResult.add(e);
}
} catch (InterruptedException e)
{
return;
}
}
}
}