public void AddSpecPoint(SpecPoint sp)
 {
     if (f_container.ContainsKey(sp.P) == false) {
         f_container.Add(sp.P, new List<SpecPoint>());
     }
     f_container[sp.P].Add(sp);
 }
        private static FunctionSpecializationResult SpecializeFunction(
		                                                               ILFunction function, 
		                                                               Dictionary<string, object> pars, 
		                                                               List<string> forceDynamic)
        {
            var source = new StringBuilder(1024 * 1024);
            int LabelId = 1;

            var visited = new SpecPointContainer();
            var q = new Queue<SpecPoint>();
            var initEnv = new AbstractEnvironment();
            foreach (var kvp in pars) {
                initEnv.SetValue(kvp.Key, kvp.Value);
            }
            foreach (var kvp in function.LocalTypes) {
                if (pars.ContainsKey(kvp.Key))
                    continue;

                object val = null;
                if (kvp.Value.TypeEnum == L1Runtime.SyntaxTree.VariableTypeEnum.Integer)
                    val = 0;
                if (kvp.Value.TypeEnum == L1Runtime.SyntaxTree.VariableTypeEnum.Bool)
                    val = false;
                if (kvp.Value.TypeEnum == L1Runtime.SyntaxTree.VariableTypeEnum.Char)
                    val = (char)0;
                initEnv.SetValue(kvp.Key, val);
            }
            foreach (var d in forceDynamic) {
                initEnv.SetValue(d, Dynamic.Value);
            }

            initEnv = _bindTimeAnalyze(function, initEnv);
            initEnv.Trace();

            Dictionary<VariableType, List<string>> localVarsInfo = new Dictionary<VariableType, List<string>>();
            foreach (var kvp in function.LocalTypes) {
                if (initEnv.IsDynamic(kvp.Key) && !function.Parameters.Contains(kvp.Key)) {
                    if (localVarsInfo.ContainsKey(kvp.Value) == false) {
                        localVarsInfo.Add(kvp.Value, new List<string>());
                    }
                    localVarsInfo[kvp.Value].Add(kvp.Key);
                }
            }
            foreach (var kvp in localVarsInfo) {
                source.Append("\t"); source.Append(kvp.Key.ToCompileableString()); source.Append(" ");
                for (int i = 0; i < kvp.Value.Count; ++i) {
                    source.Append(kvp.Value[i]);
                    if (i != kvp.Value.Count - 1)
                        source.Append(", ");
                }
                source.Append(";"); source.Append(System.Environment.NewLine);
            }

            foreach (var kvp in pars) {
                if (kvp.Value != Dynamic.Value && initEnv.IsDynamic(kvp.Key)) {
                    source.Append("\t");
                    source.Append(function.LocalTypes[kvp.Key].ToCompileableString());
                    source.Append(" ");
                    source.Append(kvp.Key); source.Append(" := "); source.Append(RenderConst(kvp.Value));
                    source.Append(";"); source.AppendLine();
                }
            }

            source.Append("* Begin of function specialized body"); source.Append(System.Environment.NewLine);

            var initialSp = new SpecPoint { Env = initEnv, P = 1, L = LabelId++ } ;
            q.Enqueue(initialSp);
            initialSp.Env.Freeze();
            visited.AddSpecPoint(initialSp);

            int operations = 0;
            var calls = new List<FunctionCallContainer>();
            while (q.Count != 0) {
                operations++;

                var sp = q.Dequeue();
                var env = sp.Env.Clone();

                source.Append("L_"); source.Append(sp.L); source.Append(":"); source.Append(System.Environment.NewLine);

                bool stopped = false;
                int p = sp.P;

                while (!stopped) {
                    var instr = function.Body[p - 1];

                    if (instr is ILExpression) {
                        var expr = instr as ILExpression;

                        stopped = SpecializeExpression(function, expr, env, source, calls);

                        p++;
                    }
                    else if (instr is ILBranch) {
                        var br = (instr as ILBranch);

                        var condVar = br.Condition.Const.ToString();
                        if (env.IsDynamic(condVar)) {

                            env.Freeze();
                            var succSp = visited.GetSpecPoint(br.SuccessJump, env);
                            var failSp = visited.GetSpecPoint(br.FailJump, env);

                            if (succSp == null) {
                                succSp = new SpecPoint { Env = env, P = br.SuccessJump, L = LabelId++ };
                                q.Enqueue(succSp);
                                visited.AddSpecPoint(succSp);
                            }
                            if (failSp == null) {
                                failSp = new SpecPoint { Env = env, P = br.FailJump, L = LabelId++ };
                                q.Enqueue(failSp);
                                visited.AddSpecPoint(failSp);
                            }

                            source.Append("\tif "); source.Append(condVar); source.Append(" then ");
                            source.Append("goto "); source.Append("L_"); source.Append(succSp.L);
                            source.Append(" else ");
                            source.Append("goto "); source.Append("L_"); source.Append(failSp.L);
                            source.Append(" end;"); source.Append(System.Environment.NewLine);

                            stopped = true;
                        }
                        else {
                            var cond = (bool)env.GetValue(condVar);
                            if (cond)
                                p = br.SuccessJump;
                            else
                                p = br.FailJump;
                        }
                    }
                    else if (instr is ILGoto) {
                        p = (instr as ILGoto).GoTo;
                    }
                    else if (instr is ILReturn) {
                        var ret = (instr as ILReturn);

                        if (ret.Return == null) {
                            source.Append("\treturn;"); source.Append(System.Environment.NewLine);
                        }
                        else {
                            source.Append("\treturn ");
                            var retVar = ret.Return.Const.ToString();
                            if (env.IsDynamic(retVar)) {
                                source.Append(retVar);
                            }
                            else {
                                m_renderConst(source, env.GetValue(retVar));
                            }
                            source.Append(";"); source.Append(System.Environment.NewLine);
                        }

                        stopped = true;
                    }
                }

                //TODO: Stop if too big query and try with more dynamic variables

                if (operations >= MaximimOperations) {
                    var ch = visited.GetMostChangeableVariables();
                    forceDynamic = forceDynamic.Union(ch).ToList();

                    var res1 = SpecializeFunction(function, pars, forceDynamic);
                    return res1;
                }
            }
            source.Append("0").AppendLine();

            //System.Console.WriteLine(source.ToString());

            var r = new FunctionSpecializationResult { FunctionCallsNeedToResolve = calls, Source = source, Function = function, SpecializationRules = pars };
            return r;
        }