private static void SpecializeFunctionCall(ILFunction context, 
		                                           ILExpression fcall, 
		                                           string resultVar, 
		                                           StringBuilder source, 
		                                           AbstractEnvironment env, 
		                                           List<FunctionCallContainer> calls)
        {
            var f = fcall.Function;
            //Stdlib function
            if (f.EmbeddedBody != null) {
                if (f.CanBeCalculatedWithoutRun && !fcall.VAList.Any(pexpr => env.IsDynamic(pexpr.Const.ToString()))) {

                    var args = fcall.VAList.Select(ilexpr => ilexpr.Eval(env))
                        .Select(o => (o is Int32) ? o : ( (o is Boolean) ? o : L1Runtime.L1Runtime.GetArrayFromObjectArray((object[])o))).ToArray();
                    var result = f.EmbeddedBody.Invoke(null, args);

                    if (env.IsDynamic(resultVar)) {
                        source.Append("\t"); source.Append(resultVar); source.Append(" := "); RenderConst(result); source.Append(");"); source.Append(System.Environment.NewLine);
                    } else {
                        if (result is L1Runtime.L1Array<int>) {
                            var l1arr = result as L1Runtime.L1Array<int>;
                            var a = new object[l1arr.GetLength()];
                            for (int i = 0; i < a.Length; ++i) {
                                a[i] = l1arr.GetValue(i);
                            }
                            result = a;
                        }
                        env.SetValue(resultVar, result);
                    }
                } else {
                    source.Append("\t"); source.Append(resultVar); source.Append(" := "); source.Append(f.Name); source.Append("(");
                    for (int i = 0; i < fcall.VAList.Count; ++i) {
                        var p = fcall.VAList[i].Const.ToString();
                        if (env.IsDynamic(p)) {
                            source.Append(p);
                        } else {
                            source.Append(RenderConst(env.GetValue(p)));
                        }
                        if (i != fcall.VAList.Count - 1)
                            source.Append(", ");
                    }
                    source.Append(");"); source.Append(System.Environment.NewLine);
                }
            } else {
                if (f.CanBeCalculatedWithoutRun && !fcall.VAList.Any(pexpr => env.IsDynamic(pexpr.Const.ToString()))) {
                    var args = fcall.VAList.Select(ilexpr => ilexpr.Eval(env)).ToArray();
                    var res = f.Call(args);

                    if (env.IsDynamic(resultVar)) {
                        source.Append("\t").Append(resultVar).Append(" := ").Append(RenderConst(res)).Append(";").AppendLine();
                    } else {
                        env.SetValue(resultVar, res);
                    }
                }
                else {
                    var functionCallRef = new FunctionCallContainer {
                        Function = fcall.Function,
                        SourceFunction = context,
                        ResultVariable = resultVar,
                        Parameters = fcall.VAList.Select(ilexpr => env.IsDynamic(ilexpr.Const.ToString()) ? ilexpr.Const.ToString() : env.GetValue(ilexpr.Const.ToString())).ToList()
                    };
                    calls.Add(functionCallRef);
                    source.Append("\t").Append(functionCallRef.ToString()).AppendLine();
                }
            }
        }
        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;
        }
        private static bool SpecializeExpression(ILFunction f, ILExpression expr, AbstractEnvironment env, StringBuilder source, List<FunctionCallContainer> calls)
        {
            if (expr.Type == ILExpressionType.Assign) {

                var left = expr.LeftNode;
                var right = expr.RightNode;
                if (left.Type == ILExpressionType.VariableAccess) {
                    var varName = left.Const.ToString();
                    try {
                        var rightRed = right.AbstactReduce(varName, env, f.LocalTypes);
                        if (rightRed is ILExpression) {
                                var fcall = rightRed as ILExpression;

                                SpecializeFunctionCall(f, fcall, varName, source, env, calls);
                                //source.Append("<<FUNCTION_CALL>>");
                        }
                        else if (env.IsDynamic(varName)) {

                            //source.Append(varName); source.Append(" := ");

                            if (rightRed is string) {
                                source.Append("\t"); source.Append(varName); source.Append(" := ");
                                source.Append((string)rightRed);
                                source.Append(";"); source.Append(System.Environment.NewLine);
                            }
                            else {
                                source.Append("\t"); source.Append(varName); source.Append(" := ");
                                source.Append(RenderConst(rightRed));
                                source.Append(";"); source.Append(System.Environment.NewLine);
                            }
                        }
                        else {
                            object val = rightRed;

                            System.Diagnostics.Debug.Assert(val is string == false);
                            System.Diagnostics.Debug.Assert(val is ILExpression == false);

                            env.SetValue(varName, val);
                        }
                    }
                    catch (NullReferenceException) {
                        source.Append("\t__spec_raise_null_ref_exception();"); source.Append(System.Environment.NewLine);
                    }
                    catch (IndexOutOfRangeException) {
                        source.Append("\t__spec_raise_index_out_of_range_exception();"); source.Append(System.Environment.NewLine);
                    }
                }
                else {
                    System.Diagnostics.Debug.Assert(left.Type == ILExpressionType.ArrayAccess);

                    try {
                        var arrayName = left.LeftNode.Const.ToString();
                        object index = null;
                        if (env.IsDynamic(left.RightNode.Const.ToString())) {
                            index = left.RightNode.Const.ToString();
                        } else {
                            index = env.GetValue(left.RightNode.Const.ToString());
                        }

                        object rightVar = null;
                        if (env.IsDynamic(right.Const.ToString())) {
                            rightVar = right.Const.ToString();
                        } else {
                            rightVar = env.GetValue(right.Const.ToString());
                        }

                        if (env.IsDynamic(arrayName)) {
                            source.Append("\t"); source.Append(arrayName); source.Append("["); source.Append(index); source.Append("] := ");
                            source.Append(rightVar); source.Append(";"); source.Append(System.Environment.NewLine);
                        }
                        else {
                            object[] a = (object[])env.GetValue(arrayName);
                            a[Convert.ToInt32(index)] = rightVar;
                        }
                    }
                    catch (NullReferenceException) {
                        source.Append("\t__spec_raise_null_ref_exception();"); source.Append(System.Environment.NewLine);
                    }
                    catch (IndexOutOfRangeException) {
                        source.Append("\t__spec_raise_index_out_of_range_exception();"); source.Append(System.Environment.NewLine);
                    }
                }

            }
            else if (expr.Type == ILExpressionType.FunctionCall) {
                source.Append("\t"); source.Append(expr.Const.ToString()); source.Append("(");
                for (int i = 0; i < expr.VAList.Count; ++i) {
                    string p = null;
                    if (env.IsDynamic(expr.VAList[i].Const.ToString())) {
                        p = expr.VAList[i].Const.ToString();
                    } else {
                        p = RenderConst(env.GetValue(expr.VAList[i].Const.ToString()));
                    }
                    source.Append(p);
                    if (i != expr.VAList.Count - 1)
                        source.Append(", ");
                }
                source.Append(");"); source.Append(System.Environment.NewLine);
            }

            return false;
        }
 //Simple expr contains dynamic variables?
 private static bool m_simpleExprContainsDynamicVariables(ILExpression expr, AbstractEnvironment env)
 {
     if (expr.Type == ILExpressionType.FunctionCall) {
         if (expr.Function.EmbeddedBody != null && !expr.Function.CanBeCalculatedWithoutRun)
             return true;
         foreach (var arg in expr.VAList) {
             if (env.IsDynamic(arg.Const.ToString()))
                 return true;
         }
         if (expr.Function.CanBeCalculatedWithoutRun == false) {
             return true;
         }
     } else if (expr.Type == ILExpressionType.VariableAccess) {
         if (env.IsDynamic(expr.Const.ToString()))
             return true;
     } else {
         if (expr.LeftNode != null) {
             if (env.IsDynamic(expr.LeftNode.Const.ToString()))
                 return true;
         }
         if (expr.RightNode != null) {
             if (env.IsDynamic(expr.RightNode.Const.ToString()))
                 return true;
         }
     }
     return false;
 }
예제 #5
0
        //Reduce RIGHT part of il_expression
        public object AbstactReduce(string leftVariable, AbstractEnvironment state, Dictionary<string, VariableType> localTypeScope)
        {
            if (Type == ILExpressionType.Const) {
                if (Const is string) {
                    var s = (string)Const;
                    var a = new object[s.Length];
                    for (int i = 0; i < s.Length; ++i) {
                        a[i] = (int)s[i];
                    }
                    return a;
                }
                return Const;
            }
            //Only variable
            else if (Type == ILExpressionType.VariableAccess) {

                if (state.IsDynamic(Const.ToString()))
                    return Const.ToString();
                else
                    return state.GetValue(Const.ToString());
            }
            else if (Type == ILExpressionType.Alloc) {
                bool isDynamicLeftPart = state.IsDynamic(leftVariable);
                if (isDynamicLeftPart || state.IsDynamic(LeftNode.Const.ToString())) {
                    return "new " + localTypeScope[leftVariable].NestedType.ToCompileableString() + "[" + v(state, LeftNode.Const.ToString()) + "]";
                }
                else
                {
                    int arraySize = (int)state.GetValue(LeftNode.Const.ToString());
                    var a = new object[arraySize];
                    object defElem = null;
                    if (localTypeScope[leftVariable].NestedType.TypeEnum == VariableTypeEnum.Integer) {
                        defElem = 0;
                    }
                    if (localTypeScope[leftVariable].NestedType.TypeEnum == VariableTypeEnum.Bool) {
                        defElem = false;
                    }
                    for (int i = 0; i < arraySize; ++i) {
                        a[i] = defElem;
                    }
                    return a;
                }
            }
            else if (Type == ILExpressionType.FunctionCall) {
                return this;
            }
            //Binary expression & unary
            else {
                object r = Eval(state);
                if (r == Dynamic.Value)
                    return GetOp(LeftNode.Const.ToString(), (RightNode != null) ? RightNode.Const.ToString() : "", Type, state);
                else
                    return r;
            }
        }
예제 #6
0
 //REDNER variable or it's value
 private object v(AbstractEnvironment env, string vname)
 {
     if (env.IsDynamic(vname))
         return vname;
     else
         return rc(env.GetValue(vname));
 }