package org.overture.interpreter.util; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.Vector; import org.overture.ast.analysis.AnalysisException; import org.overture.ast.definitions.ABusClassDefinition; import org.overture.ast.definitions.ACpuClassDefinition; import org.overture.ast.definitions.ASystemClassDefinition; import org.overture.ast.definitions.PDefinition; import org.overture.ast.definitions.SClassDefinition; import org.overture.ast.factory.AstFactoryTC; import org.overture.ast.intf.lex.ILexNameToken; import org.overture.ast.lex.LexLocation; import org.overture.ast.lex.LexNameToken; import org.overture.ast.typechecker.NameScope; import org.overture.ast.types.AClassType; import org.overture.ast.types.PType; import org.overture.ast.util.definitions.ClassList; import org.overture.interpreter.assistant.IInterpreterAssistantFactory; import org.overture.interpreter.debug.DBGPReader; import org.overture.interpreter.messages.Console; import org.overture.interpreter.messages.rtlog.RTOperationMessage; import org.overture.interpreter.runtime.ClassInterpreter; import org.overture.interpreter.runtime.ContextException; import org.overture.interpreter.runtime.RootContext; import org.overture.interpreter.runtime.RuntimeValidator; import org.overture.interpreter.runtime.StateContext; import org.overture.interpreter.runtime.state.ASystemClassDefinitionRuntime; import org.overture.interpreter.scheduler.ResourceScheduler; import org.overture.interpreter.values.BUSValue; import org.overture.interpreter.values.CPUValue; import org.overture.interpreter.values.ObjectValue; import org.overture.interpreter.values.QuoteValue; import org.overture.interpreter.values.RealValue; import org.overture.interpreter.values.TransactionValue; import org.overture.interpreter.values.UpdatableValue; import org.overture.interpreter.values.ValueList; import org.overture.interpreter.values.ValueSet; import org.overture.parser.lex.LexException; import org.overture.parser.syntax.ParserException; import org.overture.pog.obligation.ProofObligationList; import org.overture.pog.pub.ProofObligationGenerator; public class ClassListInterpreter extends ClassList { /** * */ private static final long serialVersionUID = -6070028869925906992L; public ClassListInterpreter(ClassList classList) { super(); addAll(classList); } public ClassListInterpreter() { super(); } public void systemInit(ResourceScheduler scheduler, DBGPReader dbgp, RootContext initialContext) { ASystemClassDefinition systemClass = null; for (SClassDefinition cdef : this) { if (cdef instanceof ASystemClassDefinition) { systemClass = (ASystemClassDefinition) cdef; systemInit(systemClass, scheduler, dbgp, initialContext); TransactionValue.commitAll(); } } } public RootContext initialize(IInterpreterAssistantFactory af, DBGPReader dbgp) { StateContext globalContext = null; if (isEmpty()) { globalContext = new StateContext(af, new LexLocation(), "global environment"); } else { globalContext = new StateContext(af, this.get(0).getLocation(), "public static environment"); } globalContext.setThreadState(dbgp, CPUValue.vCPU); // Initialize all the functions/operations first because the values // "statics" can call them. for (SClassDefinition cdef : this) { af.createSClassDefinitionAssistant().staticInit(cdef, globalContext); } // Values can forward reference each other, which means that we don't // know what order to initialize the classes in. So we have a crude // retry mechanism, looking for "forward reference" like exceptions. ContextException failed = null; int retries = 3; // Potentially not enough. Set<ContextException> trouble = new HashSet<ContextException>(); do { failed = null; trouble.clear(); for (SClassDefinition cdef : this) { try { af.createSClassDefinitionAssistant().staticValuesInit(cdef, globalContext); } catch (ContextException e) { trouble.add(e); // These two exceptions mean that a member could not be // found, which may be a forward reference, so we retry... if (e.number == 4034 || e.number == 6) { failed = e; } else { throw e; } } } } while (--retries > 0 && failed != null); if (!trouble.isEmpty()) { ContextException toThrow = trouble.iterator().next(); for (ContextException e : trouble) { Console.err.println(e); if (e.number != 4034) // Not in scope err { toThrow = e; } } throw toThrow; } return globalContext; } public ProofObligationList getProofObligations( IInterpreterAssistantFactory assistantFactory) throws AnalysisException { // TODO: Check this method, where it is used. ProofObligationList obligations = new ProofObligationList(); for (SClassDefinition c : this) { obligations.addAll(ProofObligationGenerator.generateProofObligations(c)); } obligations.trivialCheck(); return obligations; } public void setLoaded() { for (SClassDefinition d : this) { d.setTypeChecked(true); } } public int notLoaded() { int count = 0; for (SClassDefinition d : this) { if (!d.getTypeChecked()) { count++; } } return count; } public PDefinition findName(LexNameToken name, NameScope scope) { SClassDefinition d = map.get(name.module); if (d != null) { PDefinition def = ClassInterpreter.getInstance().getAssistantFactory().createPDefinitionAssistant().findName(d, name, scope); if (def != null) { return def; } } return null; } public void systemInit(ASystemClassDefinition systemClass, ResourceScheduler scheduler, DBGPReader dbgp, RootContext initialContext) { // systemContext = new StateContext(location, "RT system environment"); initialContext.setThreadState(dbgp, CPUValue.vCPU); try { // First go through the definitions, looking for CPUs to decl // before we can deploy to them in the constructor. We have to // predict the CPU numbers at this point. List<PDefinition> cpudefs = new Vector<PDefinition>(); ACpuClassDefinition instance = null; for (PDefinition d : systemClass.getDefinitions()) { PType t = d.getType(); if (t instanceof AClassType) { AClassType ct = (AClassType) t; if (ct.getClassdef() instanceof ACpuClassDefinition) { cpudefs.add(d); instance = (ACpuClassDefinition) ct.getClassdef(); } } } // Run the constructor to do any deploys etc. ASystemClassDefinitionRuntime.system = initialContext.assistantFactory.createSClassDefinitionAssistant().makeNewInstance(systemClass, null, new ValueList(), initialContext, new HashMap<ILexNameToken, ObjectValue>(), false); // Bind system instances to runtime validator RuntimeValidator.bindSystemVariables(systemClass, initialContext.assistantFactory); // Do CPUs first so that default BUSses can connect all CPUs. ValueSet cpus = new ValueSet(); for (PDefinition d : cpudefs) { UpdatableValue v = (UpdatableValue) ASystemClassDefinitionRuntime.system.members.get(d.getName()); CPUValue cpu = null; if (v.isUndefined()) { ValueList args = new ValueList(); args.add(new QuoteValue("FCFS")); // Default policy args.add(new RealValue(0)); // Default speed cpu = (CPUValue) initialContext.assistantFactory.createACpuClassDefinitionAssistant().newInstance(instance, null, args, initialContext); v.set(systemClass.getLocation(), cpu, initialContext); } else { cpu = (CPUValue) v.deref(); } // RTLogger.log(new RTDeclareCPUMessage(cpu.resource.getNumber(), !v.isUndefined(), // systemClass.getName().getName(), d.getName().getName())); // Set the name and scheduler for the CPU resource, and // associate the resource with the scheduler. cpu.setup(scheduler, d.getName().getName()); cpus.add(cpu); } // We can create vBUS now that all the CPUs have been created // This must be first, to ensure it's bus number 0. BUSValue.vBUS = makeVirtualBUS(cpus,initialContext); BUSValue.vBUS.setup(scheduler, "vBUS"); for (PDefinition d : systemClass.getDefinitions()) { PType t = d.getType(); if (t instanceof AClassType) { AClassType ct = (AClassType) t; if (ct.getClassdef() instanceof ABusClassDefinition) { UpdatableValue v = (UpdatableValue) ASystemClassDefinitionRuntime.system.members.get(d.getName()); BUSValue bus = null; if (!v.isUndefined()) { bus = (BUSValue) v.deref(); // Set the name and scheduler for the BUS resource, and // associate the resource with the scheduler. bus.setup(scheduler, d.getName().getName()); } } } } // For efficiency, we create a 2D array of CPU-to-CPU bus links BUSValue.createMap(initialContext, cpus); // Disable the system construction - all objects have not been created and deployed. RTOperationMessage.inSystemConstruction = false; } catch (ContextException e) { throw e; // FIXME:this exception should be thrown // } catch (ValueException e) // { // throw new ContextException(e, systemClass.getLocation()); } catch (Exception e) { throw new ContextException(4135, "Cannot instantiate a system class", systemClass.getLocation(), initialContext); } } public BUSValue makeVirtualBUS(ValueSet cpus,RootContext initialContext) { try { return new BUSValue((AClassType) AstFactoryTC.newABusClassDefinition(initialContext.assistantFactory).getType(), cpus); } catch (ParserException e) { } catch (LexException e) { } return null; } }