예제 #1
0
        STb <FuncDecl, Expr, Sort> GenerateSTb()
        {
            var name = DeclarationType.ContainingNamespace.Name + "." +
                       (DeclarationType.ContainingType == null ? "" : DeclarationType.ContainingType.Name + ".") + DeclarationType.Name;

            Console.WriteLine("Exploring " + name);

            Expr    inputVar    = _info.AutomataCtx.MkVar(0, Mapper.GetSortMapping(_transducerType.TypeArguments[0]).Sort);
            Expr    registerVar = _info.AutomataCtx.MkVar(1, Mapper.GetSortMapping(DeclarationType).Sort);
            Mutator register    = Mapper.GetSortMapping(DeclarationType).MutatorForValue(registerVar);

            var methods = DeclarationType.DeclaringSyntaxReferences.Select(r => r.GetSyntax())
                          .SelectMany(s => s.DescendantNodes(n => !(n is MethodDeclarationSyntax)))
                          .OfType <MethodDeclarationSyntax>().Select(Syntax => new { Syntax, Symbol = Model.GetDeclaredSymbol(Syntax) as IMethodSymbol })
                          .Where(x => x.Symbol != null);

            // Find the Update function
            var updateMethods = methods.Where(x => x.Symbol.MetadataName == "Update" && x.Symbol.IsOverride &&
                                              x.Symbol.Parameters.Length == 1 && x.Symbol.Parameters[0].Type == InputTypeSymbol).ToArray();

            if (updateMethods.Length == 0)
            {
                throw new SyntaxErrorException("No IEnumerable<" + OutputTypeSymbol + "> Update(" + InputTypeSymbol + ") method declared");
            }
            else if (updateMethods.Length > 1)
            {
                throw new SyntaxErrorException("Multiple Update methods declared");
            }
            var updateMethod = updateMethods[0];
            // Explore the Update function
            var updateCfg = new ControlFlowGraph(updateMethod.Syntax.Body, Model);
            Dictionary <ISymbol, Mutator> parameters = updateMethod.Symbol.Parameters
                                                       .ToDictionary(p => (ISymbol)p, p => Mapper.GetSortMapping(_transducerType.TypeArguments[0]).MutatorForValue(inputVar));
            var updateEntryState = new MainExplorationState(_info, updateCfg.EntryPoint, register, parameters, new[] { inputVar, registerVar });
            var updateRule       = updateEntryState.Explore();

            // Find the Finish function
            var finishMethods = methods.Where(x => x.Symbol.MetadataName == "Finish" && x.Symbol.IsOverride &&
                                              x.Symbol.Parameters.Length == 0).ToArray();
            STbRule <Expr> finishRule;

            if (finishMethods.Length == 0)
            {
                finishRule = new BaseRule <Expr>(Sequence <Expr> .Empty, register.CreateUpdate(), 0);
            }
            else
            {
                if (finishMethods.Length > 1)
                {
                    throw new SyntaxErrorException("Multiple Finish methods declared");
                }
                var finishMethod = finishMethods[0];
                // Explore the Finish function
                var finishCfg        = new ControlFlowGraph(finishMethod.Syntax.Body, Model);
                var finishEntryState = new MainExplorationState(_info, finishCfg.EntryPoint, register, new Dictionary <ISymbol, Mutator>(), new[] { registerVar });
                finishRule = finishEntryState.Explore();
            }

            var outputSort = Mapper.GetSortMapping(_transducerType.TypeArguments[1]).Sort;
            var stb        = new STb <FuncDecl, Expr, Sort>(_info.AutomataCtx, DeclarationType.Name, inputVar.Sort, outputSort, registerVar.Sort,
                                                            Mapper.GetSortMapping(DeclarationType).MutatorForDefaultValue().CreateUpdate().SafeSimplify(Ctx), 0);

            stb.AssignRule(0, updateRule);
            stb.AssignFinalRule(0, finishRule);

            if (ShowGraphStages.Contains(ShowGraph.Stage.UnSimplified))
            {
                stb.ShowGraph();
            }
            stb = stb.Flatten();
            if (ShowGraphStages.Contains(ShowGraph.Stage.Simplified))
            {
                stb.ToST().ShowGraph();
            }
            return(stb);
        }