private static IEnumerable <string> ComputeReachableStates(string machineName, MachineInfo machineInfo, IEnumerable <string> initialSet) { var dfsStack = new Stack <string>(); var visitedStates = new HashSet <string>(); foreach (string stateName in initialSet) { dfsStack.Push(stateName); visitedStates.Add(stateName); } while (dfsStack.Count > 0) { string curState = dfsStack.Pop(); StateInfo curStateInfo = machineInfo.stateNameToStateInfo[curState]; foreach (string e in curStateInfo.transitions.Keys) { string nextState = curStateInfo.transitions[e].target; if (visitedStates.Contains(nextState)) { continue; } visitedStates.Add(nextState); dfsStack.Push(nextState); } foreach (string nextState in ComputeGotoTargets(machineName, machineInfo, curStateInfo)) { if (visitedStates.Contains(nextState)) { continue; } visitedStates.Add(nextState); dfsStack.Push(nextState); } } return(visitedStates); }
private void GenerateProgramData(AST <Model> model) { funToFileName = new Dictionary <AST <Node>, string>(); allEvents = new Dictionary <string, EventInfo>(); exportedEvents = new HashSet <string>(); allEnums = new Dictionary <string, Dictionary <string, int> >(); allEvents[HaltEvent] = new EventInfo(1, false, PTypeNull.Node); allEvents[NullEvent] = new EventInfo(1, false, PTypeNull.Node); allMachines = new Dictionary <string, MachineInfo>(); allGlobalFuns = new Dictionary <string, FunInfo>(); linkMap = new Dictionary <string, string>(); LinkedList <AST <FuncTerm> > terms; terms = GetBin(factBins, "FileInfo"); foreach (var term in terms) { using (var it = term.Node.Args.GetEnumerator()) { it.MoveNext(); var fun = it.Current; it.MoveNext(); var fileInfo = it.Current as Cnst; string fileName = null; if (fileInfo != null) { fileName = fileInfo.GetStringValue(); if (compiler.Options.shortFileNames) { fileName = Path.GetFileName(fileName); } } funToFileName[Factory.Instance.ToAST(fun)] = fileName; } } terms = GetBin(factBins, "EventDecl"); foreach (var term in terms) { using (var it = term.Node.Args.GetEnumerator()) { it.MoveNext(); var name = ((Cnst)it.Current).GetStringValue(); it.MoveNext(); var bound = it.Current; it.MoveNext(); var payloadType = (FuncTerm)(it.Current.NodeKind == NodeKind.Id ? PTypeNull.Node : it.Current); if (bound.NodeKind == NodeKind.Id) { allEvents[name] = new EventInfo(payloadType); } else { var ft = (FuncTerm)bound; var maxInstances = (int)((Cnst)GetArgByIndex(ft, 0)).GetNumericValue().Numerator; var maxInstancesAssumed = ((Id)ft.Function).Name == "AssumeMaxInstances"; allEvents[name] = new EventInfo(maxInstances, maxInstancesAssumed, payloadType); } } } terms = GetBin(factBins, "EnumTypeDef"); foreach (var term in terms) { using (var it = term.Node.Args.GetEnumerator()) { it.MoveNext(); var name = ((Cnst)it.Current).GetStringValue(); it.MoveNext(); FuncTerm strIter = it.Current as FuncTerm; it.MoveNext(); FuncTerm valIter = it.Current as FuncTerm; var constants = new Dictionary <string, int>(); if (valIter == null) { var val = 0; while (strIter != null) { var constant = (GetArgByIndex(strIter, 0) as Cnst).GetStringValue(); constants[constant] = val; strIter = GetArgByIndex(strIter, 1) as FuncTerm; val++; } } else { while (strIter != null) { var constant = (GetArgByIndex(strIter, 0) as Cnst).GetStringValue(); var val = (GetArgByIndex(valIter, 0) as Cnst).GetNumericValue(); constants[constant] = (int)val.Numerator; strIter = GetArgByIndex(strIter, 1) as FuncTerm; valIter = GetArgByIndex(valIter, 1) as FuncTerm; } } allEnums[name] = constants; } } terms = GetBin(factBins, "MachineDecl"); foreach (var term in terms) { using (var it = term.Node.Args.GetEnumerator()) { it.MoveNext(); var machineName = ((Cnst)it.Current).GetStringValue(); allMachines[machineName] = new MachineInfo(); it.MoveNext(); allMachines[machineName].type = ((Id)it.Current).Name; it.MoveNext(); var bound = it.Current; if (bound.NodeKind != NodeKind.Id) { var ft = (FuncTerm)bound; allMachines[machineName].maxQueueSize = (int)((Cnst)GetArgByIndex(ft, 0)).GetNumericValue().Numerator; allMachines[machineName].maxQueueSizeAssumed = ((Id)ft.Function).Name == "AssumeMaxInstances"; } it.MoveNext(); allMachines[machineName].initStateName = GetNameFromQualifiedName(machineName, (FuncTerm)it.Current); } } terms = GetBin(factBins, "ObservesDecl"); foreach (var term in terms) { using (var it = term.Node.Args.GetEnumerator()) { it.MoveNext(); var machineDecl = (FuncTerm)it.Current; var machineName = GetName(machineDecl, 0); it.MoveNext(); allMachines[machineName].observesEvents.Add(((Cnst)it.Current).GetStringValue()); } } terms = GetBin(factBins, "MachineReceives"); foreach (var term in terms) { using (var it = term.Node.Args.GetEnumerator()) { it.MoveNext(); var machineDecl = (FuncTerm)it.Current; var machineName = GetName(machineDecl, 0); it.MoveNext(); string eventName; if (it.Current.NodeKind == NodeKind.Id) { var name = ((Id)it.Current).Name; if (name != "NIL") { eventName = HaltEvent; allMachines[machineName].receiveSet.Add(eventName); } } else { eventName = ((Cnst)it.Current).GetStringValue(); allMachines[machineName].receiveSet.Add(eventName); } } } terms = GetBin(factBins, "MachineSends"); foreach (var term in terms) { using (var it = term.Node.Args.GetEnumerator()) { it.MoveNext(); var machineDecl = (FuncTerm)it.Current; var machineName = GetName(machineDecl, 0); it.MoveNext(); string eventName; if (it.Current.NodeKind == NodeKind.Id) { var name = ((Id)it.Current).Name; if (name != "NIL") { eventName = HaltEvent; allMachines[machineName].sendsSet.Add(eventName); } } else { eventName = ((Cnst)it.Current).GetStringValue(); allMachines[machineName].sendsSet.Add(eventName); } } } terms = GetBin(factBins, "VarDecl"); foreach (var term in terms) { using (var it = term.Node.Args.GetEnumerator()) { it.MoveNext(); var varName = ((Cnst)it.Current).GetStringValue(); it.MoveNext(); var machineDecl = (FuncTerm)it.Current; var machineName = GetName(machineDecl, 0); var varTable = allMachines[machineName].localVariableToVarInfo; it.MoveNext(); var type = (FuncTerm)it.Current; varTable[varName] = new VariableInfo(type); } } Dictionary <AST <Node>, Node> translatedBody = new Dictionary <AST <Node>, Node>(); terms = GetBin(factBins, "TranslatedBody"); foreach (var term in terms) { using (var it = term.Node.Args.GetEnumerator()) { it.MoveNext(); var cntxt = Factory.Instance.ToAST(it.Current); it.MoveNext(); var newStmt = it.Current; translatedBody[cntxt] = newStmt; } } terms = GetBin(factBins, "FunDecl"); foreach (var term in terms) { var termAlias = Factory.Instance.ToAST(termToAlias[term]); using (var it = term.Node.Args.GetEnumerator()) { it.MoveNext(); string funName = ((Cnst)it.Current).GetStringValue(); it.MoveNext(); var owner = it.Current; it.MoveNext(); var isModel = ((Id)it.Current).Name == "MODEL"; it.MoveNext(); var parameters = it.Current as FuncTerm; it.MoveNext(); var returnTypeName = it.Current is Id ? PTypeNull : (AST <FuncTerm>)Factory.Instance.ToAST(it.Current); it.MoveNext(); var locals = it.Current as FuncTerm; it.MoveNext(); var body = translatedBody[termAlias]; var funInfo = new FunInfo(false, parameters, returnTypeName, locals, body); if (owner is FuncTerm) { var machineDecl = (FuncTerm)owner; var machineName = GetName(machineDecl, 0); var machineInfo = allMachines[machineName]; machineInfo.funNameToFunInfo[funName] = funInfo; } else { allGlobalFuns[funName] = funInfo; } } } terms = GetBin(factBins, "FunProtoDecl"); foreach (var term in terms) { using (var it = term.Node.Args.GetEnumerator()) { it.MoveNext(); string funName = ((Cnst)it.Current).GetStringValue(); it.MoveNext(); var parameters = it.Current as FuncTerm; it.MoveNext(); var returnTypeName = it.Current is Id ? PTypeNull : (AST <FuncTerm>)Factory.Instance.ToAST(it.Current); if (!allGlobalFuns.ContainsKey(funName)) { allGlobalFuns.Add(funName, new FunInfo(parameters, returnTypeName)); } } } this.anonFunToName = new Dictionary <AST <Node>, string>(); var anonFunCounter = new Dictionary <string, int>(); int anonFunCounterStatic = 0; foreach (var x in allMachines.Keys) { anonFunCounter[x] = 0; } terms = GetBin(factBins, "AnonFunDecl"); foreach (var term in terms) { var termAlias = Factory.Instance.ToAST(termToAlias[term]); using (var it = term.Node.Args.GetEnumerator()) { it.MoveNext(); var machineDecl = it.Current as FuncTerm; it.MoveNext(); var ownerFunName = it.Current as Cnst; it.MoveNext(); var locals = it.Current as FuncTerm; it.MoveNext(); var body = translatedBody[termAlias]; it.MoveNext(); var envVars = it.Current as FuncTerm; if (machineDecl == null) { var funName = "AnonFunStatic" + anonFunCounterStatic; allGlobalFuns[funName] = new FunInfo(true, envVars, PToZing.PTypeNull, locals, body); anonFunToName[termAlias] = funName; anonFunCounterStatic++; } else { var machineName = GetName(machineDecl, 0); var machineInfo = allMachines[machineName]; var funName = "AnonFun" + anonFunCounter[machineName]; machineInfo.funNameToFunInfo[funName] = new FunInfo(true, envVars, PToZing.PTypeNull, locals, body); anonFunToName[termAlias] = funName; anonFunCounter[machineName]++; } } } terms = GetBin(factBins, "StateDecl"); foreach (var term in terms) { using (var it = term.Node.Args.GetEnumerator()) { it.MoveNext(); var qualifiedStateName = (FuncTerm)it.Current; it.MoveNext(); var machineDecl = (FuncTerm)it.Current; var ownerName = GetName(machineDecl, 0); var stateName = GetNameFromQualifiedName(ownerName, qualifiedStateName); it.MoveNext(); var entryActionName = it.Current.NodeKind == NodeKind.Cnst ? ((Cnst)it.Current).GetStringValue() : anonFunToName[Factory.Instance.ToAST(it.Current)]; it.MoveNext(); var exitFunName = it.Current.NodeKind == NodeKind.Cnst ? ((Cnst)it.Current).GetStringValue() : anonFunToName[Factory.Instance.ToAST(it.Current)]; it.MoveNext(); var temperature = StateTemperature.WARM; var t = ((Id)it.Current).Name; if (t == "HOT") { temperature = StateTemperature.HOT; } else if (t == "COLD") { temperature = StateTemperature.COLD; } var stateTable = allMachines[ownerName].stateNameToStateInfo; stateTable[stateName] = new StateInfo(ownerName, entryActionName, exitFunName, temperature, GetPrintedNameFromQualifiedName(qualifiedStateName)); } } terms = GetBin(factBins, "TransDecl"); foreach (var term in terms) { using (var it = term.Node.Args.GetEnumerator()) { it.MoveNext(); var stateDecl = (FuncTerm)it.Current; var qualifiedStateName = (FuncTerm)GetArgByIndex(stateDecl, 0); var stateOwnerMachineName = GetMachineName(stateDecl, 1); var stateName = GetNameFromQualifiedName(stateOwnerMachineName, qualifiedStateName); var stateTable = allMachines[stateOwnerMachineName].stateNameToStateInfo[stateName]; it.MoveNext(); string eventName; if (it.Current.NodeKind == NodeKind.Id) { var name = ((Id)it.Current).Name; if (name == "NULL") { eventName = NullEvent; stateTable.hasNullTransition = true; } else { // name == "HALT" eventName = HaltEvent; } } else { eventName = ((Cnst)it.Current).GetStringValue(); } it.MoveNext(); var targetStateName = GetNameFromQualifiedName(stateOwnerMachineName, (FuncTerm)it.Current); it.MoveNext(); if (it.Current.NodeKind == NodeKind.Cnst) { var exitFunName = ((Cnst)it.Current).GetStringValue(); stateTable.transitions[eventName] = new TransitionInfo(targetStateName, exitFunName); } else if (it.Current.NodeKind == NodeKind.Id && (it.Current as Id).Name == "PUSH") { stateTable.transitions[eventName] = new TransitionInfo(targetStateName); } else { var exitFunName = anonFunToName[Factory.Instance.ToAST(it.Current)]; stateTable.transitions[eventName] = new TransitionInfo(targetStateName, exitFunName); } } } terms = GetBin(factBins, "DoDecl"); foreach (var term in terms) { using (var it = term.Node.Args.GetEnumerator()) { it.MoveNext(); var stateDecl = (FuncTerm)it.Current; var qualifiedStateName = (FuncTerm)GetArgByIndex(stateDecl, 0); var stateOwnerMachineName = GetMachineName(stateDecl, 1); var stateName = GetNameFromQualifiedName(stateOwnerMachineName, qualifiedStateName); var stateTable = allMachines[stateOwnerMachineName].stateNameToStateInfo[stateName]; it.MoveNext(); string eventName; if (it.Current.NodeKind == NodeKind.Id) { var name = ((Id)it.Current).Name; if (name == "NULL") { eventName = NullEvent; } else { // name == "HALT" eventName = HaltEvent; } } else { eventName = ((Cnst)it.Current).GetStringValue(); } it.MoveNext(); var action = it.Current; if (action.NodeKind == NodeKind.Cnst) { stateTable.dos[eventName] = ((Cnst)action).GetStringValue(); } else if (action.NodeKind == NodeKind.Id && (action as Id).Name == "DEFER") { stateTable.deferredEvents.Add(eventName); } else if (action.NodeKind == NodeKind.Id && (action as Id).Name == "IGNORE") { stateTable.dos[eventName] = "ignore"; } else { stateTable.dos[eventName] = anonFunToName[Factory.Instance.ToAST(action)]; } } } terms = GetBin(factBins, "Annotation"); foreach (var term in terms) { using (var it = term.Node.Args.GetEnumerator()) { it.MoveNext(); FuncTerm annotationContext = it.Current.NodeKind == NodeKind.Id ? aliasToTerm[Factory.Instance.ToAST(it.Current)] : (FuncTerm)it.Current; string annotationContextKind = ((Id)annotationContext.Function).Name; if (annotationContextKind != "FunDecl") { continue; } string ownerName = GetOwnerName(annotationContext, 1, 0); string funName = GetName(annotationContext, 0); it.MoveNext(); string annotation = ((Cnst)it.Current).GetStringValue(); it.MoveNext(); if (annotation == "invokescheduler") { if (ownerName == null) { allGlobalFuns[funName].invokeSchedulerFuns.Add(it.Current); } else { allMachines[ownerName].funNameToFunInfo[funName].invokeSchedulerFuns.Add(it.Current); } } else if (annotation == "printvalue") { Cnst indexCnst = it.Current as Cnst; if (indexCnst != null) { string arg = indexCnst.GetStringValue(); if (ownerName == null) { allGlobalFuns[funName].printArgs.Add(arg); } else { allMachines[ownerName].funNameToFunInfo[funName].printArgs.Add(arg); } } } else if (annotation == "invokeplugin") { if (ownerName == null) { allGlobalFuns[funName].invokePluginFuns.Add(it.Current); } else { allMachines[ownerName].funNameToFunInfo[funName].invokePluginFuns.Add(it.Current); } } } } terms = GetBin(factBins, "LinkMap"); foreach (var term in terms) { using (var it = term.Node.Args.GetEnumerator()) { it.MoveNext(); var createdIorM = ((Cnst)it.Current).GetStringValue(); it.MoveNext(); var createdM = ((Cnst)it.Current).GetStringValue(); linkMap.Add(createdIorM, createdM); } } terms = GetBin(factBins, "ExportedEvent"); foreach (var term in terms) { using (var it = term.Node.Args.GetEnumerator()) { it.MoveNext(); var eventName = ((Cnst)it.Current).GetStringValue(); exportedEvents.Add(eventName); } } terms = GetBin(factBins, "MaxNumLocals"); foreach (var term in terms) { using (var it = term.Node.Args.GetEnumerator()) { it.MoveNext(); var typingContextAlias = Factory.Instance.ToAST(it.Current); FuncTerm typingContext = aliasToTerm[typingContextAlias]; string typingContextKind = ((Id)typingContext.Function).Name; it.MoveNext(); var maxNumLocals = (int)((Cnst)it.Current).GetNumericValue().Numerator; if (typingContextKind == "FunDecl") { string ownerName = GetOwnerName(typingContext, 1, 0); string funName = GetName(typingContext, 0); if (ownerName == null) { allGlobalFuns[funName].maxNumLocals = maxNumLocals; } else { allMachines[ownerName].funNameToFunInfo[funName].maxNumLocals = maxNumLocals; } } else { // typingContextKind == "AnonFunDecl" string ownerName = GetOwnerName(typingContext, 0, 0); string funName = anonFunToName[typingContextAlias]; if (ownerName == null) { allGlobalFuns[funName].maxNumLocals = maxNumLocals; } else { allMachines[ownerName].funNameToFunInfo[funName].maxNumLocals = maxNumLocals; } } } } if (compiler.Options.liveness != LivenessOption.None) { foreach (var machineName in allMachines.Keys) { if (!allMachines[machineName].IsSpec) { continue; } var machineInfo = allMachines[machineName]; List <string> initialSet = new List <string>(); foreach (var stateName in ComputeReachableStates(machineName, machineInfo, new string[] { machineInfo.initStateName })) { if (machineInfo.stateNameToStateInfo[stateName].IsWarm) { continue; } if (machineInfo.stateNameToStateInfo[stateName].IsHot) { machineInfo.specType = SpecType.FINALLY; continue; } initialSet.Add(stateName); } foreach (var stateName in ComputeReachableStates(machineName, machineInfo, initialSet)) { if (machineInfo.stateNameToStateInfo[stateName].IsHot) { machineInfo.specType = SpecType.REPEATEDLY; break; } } } if (allMachines.Values.All(x => !x.IsSpec || x.specType == SpecType.SAFETY)) { compiler.Options.liveness = LivenessOption.None; } } }
private HashSet <string> ComputeGotoTargets(string machineName, MachineInfo machineInfo, StateInfo stateInfo) { HashSet <string> targets = new HashSet <string>(); targets.UnionWith(ComputeGotoTargets(machineName, machineInfo.funNameToFunInfo[stateInfo.entryActionName].body)); foreach (var actionName in stateInfo.dos.Values) { targets.UnionWith(ComputeGotoTargets(machineName, machineInfo.funNameToFunInfo[actionName].body)); } return(targets); }