package org.overture.interpreter.assistant.definition;
import org.overture.ast.assistant.IAstAssistant;
import org.overture.ast.definitions.ACpuClassDefinition;
import org.overture.ast.factory.AstFactoryTC;
import org.overture.ast.lex.LexLocation;
import org.overture.ast.lex.LexNameToken;
import org.overture.ast.statements.ANotYetSpecifiedStm;
import org.overture.ast.types.AClassType;
import org.overture.interpreter.assistant.IInterpreterAssistantFactory;
import org.overture.interpreter.messages.rtlog.RTDeclareCPUMessage;
import org.overture.interpreter.messages.rtlog.RTLogger;
import org.overture.interpreter.runtime.Context;
import org.overture.interpreter.runtime.ContextException;
import org.overture.interpreter.runtime.ObjectContext;
import org.overture.interpreter.values.CPUValue;
import org.overture.interpreter.values.NameValuePairList;
import org.overture.interpreter.values.NameValuePairMap;
import org.overture.interpreter.values.NaturalValue;
import org.overture.interpreter.values.ObjectValue;
import org.overture.interpreter.values.RealValue;
import org.overture.interpreter.values.SeqValue;
import org.overture.interpreter.values.Value;
import org.overture.interpreter.values.ValueList;
import org.overture.interpreter.values.VoidValue;
public class ACpuClassDefinitionAssistantInterpreter implements IAstAssistant
{
protected static IInterpreterAssistantFactory af;
@SuppressWarnings("static-access")
public ACpuClassDefinitionAssistantInterpreter(
IInterpreterAssistantFactory af)
{
this.af = af;
}
public CPUValue newInstance(ACpuClassDefinition node, Object object,
ValueList argvals, Context ctxt)
{
NameValuePairList nvpl = af.createPDefinitionListAssistant().getNamedValues(node.getDefinitions(), ctxt);
NameValuePairMap map = new NameValuePairMap();
map.putAll(nvpl);
RealValue sarg = (RealValue) argvals.get(1);
if (sarg.value <= 0)
{
throw new ContextException(4149, "CPU frequency to slow: "
+ sarg.value + " Hz", ctxt.location, ctxt);
} else if (sarg.value > AstFactoryTC.CPU_MAX_FREQUENCY)
{
throw new ContextException(4150, "CPU frequency to fast: "
+ sarg.value + " Hz", ctxt.location, ctxt);
}
CPUValue cpu = new CPUValue((AClassType) node.getClasstype(), map, argvals);
// TODO: Here is one basis to pass the parameter with the Context.
RTLogger.log(new RTDeclareCPUMessage(cpu.resource.getNumber(), node.getName().getName()));
return cpu;
}
public Value deploy(ANotYetSpecifiedStm node, Context ctxt)
{
try
{
ObjectContext octxt = (ObjectContext) ctxt;
CPUValue cpu = (CPUValue) octxt.self;
ObjectValue obj = (ObjectValue) octxt.lookup(varName("obj"));
redeploy(obj, cpu);
cpu.deploy(obj);
return new VoidValue();
} catch (Exception e)
{
throw new ContextException(4136, "Cannot deploy to CPU", ctxt.location, ctxt);
}
}
public Value setPriority(ANotYetSpecifiedStm node, Context ctxt)
{
try
{
ObjectContext octxt = (ObjectContext) ctxt;
CPUValue cpu = (CPUValue) octxt.self;
SeqValue opname = (SeqValue) octxt.lookup(varName("opname"));
NaturalValue priority = (NaturalValue) octxt.check(varName("priority"));
cpu.setPriority(opname.stringValue(ctxt), priority.intValue(ctxt));
return new VoidValue();
} catch (Exception e)
{
throw new ContextException(4137, "Cannot set priority: "
+ e.getMessage(), ctxt.location, ctxt);
}
}
/**
* Recursively updates all transitive references with the new CPU, but without removing the parent - child relation,
* unlike the deploy method.
*
* @param the
* objectvalue to update
* @param the
* target CPU of the redeploy
*/
private void updateCPUandChildCPUs(ObjectValue obj, CPUValue cpu)
{
if (cpu != obj.getCPU())
{
for (ObjectValue superObj : obj.superobjects)
{
updateCPUandChildCPUs(superObj, cpu);
}
obj.setCPU(cpu);
}
// update all object we have created our self.
for (ObjectValue objVal : obj.children)
{
updateCPUandChildCPUs(objVal, cpu);
}
}
/**
* Will redeploy the object and all object transitive referenced by this to the supplied cpu. Redeploy means that
* the transitive reference to and from our creator is no longer needed, and will be removed. This only applies to
* this object, as it is on the top of the hierarchy, all children will be updated with the
* <tt>updateCPUandChildrenCPUs</tt> method which recursively updates all transitive references with the new CPU,
* but without removing the parent - child relation.
*
* @param the
* object value to deploy
* @param the
* target CPU of the redeploy
*/
private void redeploy(ObjectValue obj, CPUValue cpu)
{
updateCPUandChildCPUs(obj, cpu);
// if we are moving to a new CPU, we are no longer a part of the transitive
// references from our creator, so let us remove ourself. This will prevent
// us from being updated if our creator is migrating in the
// future.
obj.removeCreator();
}
private LexNameToken varName(String name)
{
return new LexNameToken("CPU", name, new LexLocation());
}
}