public PTranslation(Compiler compiler, AST <Model> model, Dictionary <string, Dictionary <int, SourceInfo> > idToSourceInfo) { this.compiler = compiler; this.idToSourceInfo = idToSourceInfo; this.factBins = new Dictionary <string, LinkedList <AST <FuncTerm> > >(); this.aliasToTerm = new Dictionary <AST <Node>, FuncTerm>(); this.termToAlias = new Dictionary <AST <FuncTerm>, Node>(); model.FindAll( new NodePred[] { NodePredFactory.Instance.Star, NodePredFactory.Instance.MkPredicate(NodeKind.ModelFact) }, (path, n) => { var mf = (ModelFact)n; Id binding = mf.Binding; FuncTerm match = (FuncTerm)mf.Match; string matchName = ((Id)match.Function).Name; var matchAst = (AST <FuncTerm>)Factory.Instance.ToAST(match); if (binding != null) { var bindingAst = Factory.Instance.ToAST(binding); aliasToTerm[bindingAst] = match; termToAlias[matchAst] = binding; } GetBin(factBins, matchName).AddLast(matchAst); }); GenerateProgramData(model); }
/// <summary> /// Attempts to resolve all the type name appearing in the type term. /// </summary> internal bool ResolveTypes(List <Flag> flags, CancellationToken cancel) { if (typeExpr == null) { return(true); } var compQuery = new NodePred[] { NodePredFactory.Instance.Star, NodePredFactory.Instance.MkPredicate(NodeKind.Enum) | NodePredFactory.Instance.MkPredicate(NodeKind.Id) }; bool result = true; typeExpr.FindAll( compQuery, (path, node) => { if (node.NodeKind == NodeKind.Id && (((LinkedList <ChildInfo>)path).Last.Previous == null || ((LinkedList <ChildInfo>)path).Last.Previous.Value.Node.NodeKind != NodeKind.Enum)) { result = AddTypeName((Id)node, flags) & result; } else if (node.NodeKind == NodeKind.Enum) { result = AddEnum((API.Nodes.Enum)node, flags) & result; } }, cancel); return(result); }
public bool Compile( string filename, string nameSpace, TextWriter writer, ProgressReporter reporter) { GenerateConfig config; if (!configMap.TryGetValue(filename, out config)) { config = new GenerateConfig(); } var env = new Env(); try { InstallResult ires; var progName = new ProgramName(filename); env.Install(filename, out ires); PrintFlags(ires.Flags, reporter); if (!ires.Succeeded) { return(false); } AST <API.Nodes.Program> program = null; foreach (var touched in ires.Touched) { if (touched.Program.Node.Name.Equals(progName)) { program = touched.Program; break; } } if (program == null) { reporter.Error(filename, 0, 0, "Could not find input file"); return(false); } string name; string modName = null; var moduleQuery = new NodePred[] { NodePredFactory.Instance.Star, NodePredFactory.Instance.Module }; program.FindAll( moduleQuery, (ch, n) => { if (n.TryGetStringAttribute(AttributeKind.Name, out name)) { if (modName == null) { modName = name; } else { reporter.Warning( filename, n.Span.StartLine, n.Span.StartCol, string.Format("Code will only be generated for module {0}; ignoring module {1}.", modName, name)); } } }); if (modName == null) { reporter.Warning(filename, 0, 0, "Could not find any modules in input file."); return(true); } var opts = new GeneratorOptions( GeneratorOptions.Language.CSharp, config.IsThreadSafe, config.IsNewOnly, modName, nameSpace); Task <GenerateResult> gres; env.Generate(progName, modName, writer, opts, out gres); gres.Wait(); PrintFlags(filename, gres.Result.Flags, reporter); return(gres.Result.Succeeded); } catch (Exception e) { reporter.Error(filename, 0, 0, e.Message); return(false); } }
public bool Generate(FormulaCodeGeneratorTask genTask) { var outputFile = InputFile + ".g.cs"; var env = new Env(); try { InstallResult ires; var progName = new ProgramName(InputFile); env.Install(InputFile, out ires); PrintFlags(genTask, ires.Flags); if (!ires.Succeeded) { return(false); } AST <Program> program = null; foreach (var touched in ires.Touched) { if (touched.Program.Node.Name.Equals(progName)) { program = touched.Program; break; } } if (program == null) { PrintError(genTask, InputFile, "Could not find input file"); return(false); } string name; string modName = null; var moduleQuery = new NodePred[] { NodePredFactory.Instance.Star, NodePredFactory.Instance.Module }; program.FindAll( moduleQuery, (ch, n) => { if (n.TryGetStringAttribute(AttributeKind.Name, out name)) { if (modName == null) { modName = name; } else { genTask.Log.LogWarning( string.Empty, string.Empty, string.Empty, InputFile, n.Span.StartLine, n.Span.StartCol, n.Span.EndLine, n.Span.EndCol, "Code will only be generated for module {0}; ignoring module {1}.", modName, name); } } }); if (modName == null) { PrintWarning(genTask, InputFile, "Could not find any modules in input file."); return(true); } try { var outInfo = new System.IO.FileInfo(outputFile); if (outInfo.Exists) { outInfo.Delete(); } using (var sw = new System.IO.StreamWriter(outputFile)) { var opts = new GeneratorOptions( GeneratorOptions.Language.CSharp, IsThreadSafe, IsNewOnly, modName, Namespace); Task <GenerateResult> gres; env.Generate(progName, modName, sw, opts, out gres); gres.Wait(); PrintFlags(genTask, InputFile, gres.Result.Flags); if (gres.Result.Succeeded) { genTask.Log.LogMessage("Transformed {0} -> {1}", InputFile, outputFile); } return(gres.Result.Succeeded); } } catch (Exception e) { PrintError(genTask, outputFile, e.Message); return(false); } } catch (Exception e) { PrintError(genTask, InputFile, e.Message); return(false); } }
private void GenerateProgramData(AST <Model> model) { var factBins = new Dictionary <string, LinkedList <AST <FuncTerm> > >(); model.FindAll( new NodePred[] { NodePredFactory.Instance.Star, NodePredFactory.Instance.MkPredicate(NodeKind.ModelFact) }, (path, n) => { var mf = (ModelFact)n; FuncTerm ft = (FuncTerm)mf.Match; GetBin(factBins, ft).AddLast((AST <FuncTerm>)Factory.Instance.ToAST(ft)); }); funToFileName = new Dictionary <AST <Node>, string>(); allEvents = new Dictionary <string, EventInfo>(); allEnums = new Dictionary <string, List <Tuple <string, int> > >(); allEvents[HaltEvent] = new EventInfo(1, false, PTypeNull.Node); allEvents[NullEvent] = new EventInfo(1, false, PTypeNull.Node); allMachines = new Dictionary <string, MachineInfo>(); allStaticFuns = 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 List <Tuple <string, int> >(); if (valIter == null) { var val = 0; while (strIter != null) { var constant = (GetArgByIndex(strIter, 0) as Cnst).GetStringValue(); constants.Add(Tuple.Create <string, int>(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.Add(Tuple.Create <string, int>(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, "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) { 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[term]; 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 { allStaticFuns[funName] = funInfo; } } } 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) { if (anonFunToName.ContainsKey(term)) { continue; } 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[term]; it.MoveNext(); var envVars = it.Current as FuncTerm; if (machineDecl == null) { var funName = "AnonFunStatic" + anonFunCounterStatic; allStaticFuns[funName] = new FunInfo(true, envVars, PToZing.PTypeNull, locals, body); anonFunToName[term] = 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[term] = 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.Id) { stateTable.transitions[eventName] = new TransitionInfo(targetStateName); } else { var exitFunName = it.Current.NodeKind == NodeKind.Cnst ? ((Cnst)it.Current).GetStringValue() : 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.actions[eventName] = ((Cnst)action).GetStringValue(); } else if (action.NodeKind == NodeKind.Id) { if (((Id)action).Name == "DEFER") { stateTable.deferredEvents.Add(eventName); } else { // ((Id)action).Name == "IGNORE" stateTable.ignoredEvents.Add(eventName); stateTable.actions[eventName] = "ignore"; } } else { stateTable.actions[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 = (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) { allStaticFuns[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) { allStaticFuns[funName].printArgs.Add(arg); } else { allMachines[ownerName].funNameToFunInfo[funName].printArgs.Add(arg); } } } else if (annotation == "invokeplugin") { if (ownerName == null) { allStaticFuns[funName].invokePluginFuns.Add(it.Current); } else { allMachines[ownerName].funNameToFunInfo[funName].invokePluginFuns.Add(it.Current); } } } } 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(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(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; } } }