Exemple #1
0
 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);
 }
Exemple #2
0
        /// <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);
            }
        }
Exemple #4
0
        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);
            }
        }
Exemple #5
0
        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;
                }
            }
        }