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 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;
        }
Пример #3
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));
 }
Пример #4
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;
            }
        }
Пример #5
0
        public object Eval(AbstractEnvironment state)
        {
            #region +, -, *, /, mod, pow

            if (Type == ILExpressionType.Plus)
            {
                object left = LeftNode.Eval(state);
                object right = RightNode.Eval(state);
                if (left != Dynamic.Value && right != Dynamic.Value)
                    return (int)left + (int)right;
                else
                    return Dynamic.Value;
            }
            if (Type == ILExpressionType.Minus)
            {
                object left = LeftNode.Eval(state);
                object right = RightNode.Eval(state);
                if (left != Dynamic.Value && right != Dynamic.Value)
                    return (int)left - (int)right;
                else
                    return Dynamic.Value;
            }
            if (Type == ILExpressionType.Mul)
            {
                object left = LeftNode.Eval(state);
                object right = RightNode.Eval(state);
                if (left != Dynamic.Value && right != Dynamic.Value)
                    return (int)left * (int)right;
                else
                    return Dynamic.Value;
            }
            if (Type == ILExpressionType.Div)
            {
                object left = LeftNode.Eval(state);
                object right = RightNode.Eval(state);
                if (left != Dynamic.Value && right != Dynamic.Value)
                    return (int)left / (int)right;
                else
                    return Dynamic.Value;
            }
            if (Type == ILExpressionType.Mod)
            {
                object left = LeftNode.Eval(state);
                object right = RightNode.Eval(state);
                if (left != Dynamic.Value && right != Dynamic.Value)
                    return (int)left % (int)right;
                else
                    return Dynamic.Value;
            }
            if (Type == ILExpressionType.Pow)
            {
                object left = LeftNode.Eval(state);
                object right = RightNode.Eval(state);
                if (left != Dynamic.Value && right != Dynamic.Value)
                    return L1Runtime.L1Runtime.Deg((int)left, (int)right);
                else
                    return Dynamic.Value;
            }

            #endregion

            #region []

            if (Type == ILExpressionType.ArrayAccess)
            {
                object left = LeftNode.Eval(state);
                object right = RightNode.Eval(state);
                if (left != Dynamic.Value && right != Dynamic.Value)
                    return ((Array)left).GetValue((int)right);
                else
                    return Dynamic.Value;
            }

            #endregion

            #region >, >=, <, <=, =, <>

            if (Type == ILExpressionType.Gr)
            {
                object left = LeftNode.Eval(state);
                object right = RightNode.Eval(state);
                if (left != Dynamic.Value && right != Dynamic.Value)
                    return (int)left > (int)right;
                else
                    return Dynamic.Value;
            }
            if (Type == ILExpressionType.Greq)
            {
                object left = LeftNode.Eval(state);
                object right = RightNode.Eval(state);
                if (left != Dynamic.Value && right != Dynamic.Value)
                    return (int)left >= (int)right;
                else
                    return Dynamic.Value;
            }
            if (Type == ILExpressionType.Le)
            {
                object left = LeftNode.Eval(state);
                object right = RightNode.Eval(state);
                if (left != Dynamic.Value && right != Dynamic.Value)
                    return (int)left < (int)right;
                else
                    return Dynamic.Value;
            }
            if (Type == ILExpressionType.Leeq)
            {
                object left = LeftNode.Eval(state);
                object right = RightNode.Eval(state);
                if (left != Dynamic.Value && right != Dynamic.Value)
                    return (int)left <= (int)right;
                else
                    return Dynamic.Value;
            }
            if (Type == ILExpressionType.Eq)
            {
                object left = LeftNode.Eval(state);
                object right = RightNode.Eval(state);
                if (left != Dynamic.Value && right != Dynamic.Value)
                    return (int)left == (int)right;
                else
                    return Dynamic.Value;
            }
            if (Type == ILExpressionType.NotEq)
            {
                object left = LeftNode.Eval(state);
                object right = RightNode.Eval(state);
                if (left != Dynamic.Value && right != Dynamic.Value)
                    return (int)left != (int)right;
                else
                    return Dynamic.Value;
            }

            #endregion

            #region Uminus, Unot

            if (Type == ILExpressionType.Uminus)
            {
                object left = LeftNode.Eval(state);
                if (left != Dynamic.Value)
                    return - (int)left;
                else
                    return Dynamic.Value;
            }
            if (Type == ILExpressionType.Unot)
            {
                object left = LeftNode.Eval(state);
                if (left != Dynamic.Value)
                    return !(bool)left;
                else
                    return Dynamic.Value;
            }

            #endregion

            #region And, Or, Xor

            if (Type == ILExpressionType.And)
            {
                throw new InvalidOperationException("And operator is not allowed in IL!");
            }
            if (Type == ILExpressionType.Or)
            {
                throw new InvalidOperationException("Or operator is not allowed in IL!");
            }
            if (Type == ILExpressionType.Xor)
            {
                object left = LeftNode.Eval(state);
                object right = RightNode.Eval(state);
                if (left != Dynamic.Value && right != Dynamic.Value)
                    return (bool)left ^ (bool)right;
                else
                    return Dynamic.Value;
            }

            #endregion

            #region Alloc, ArrayLength, VariableAccess, Const

            if (Type == ILExpressionType.Alloc)
            {
                object left = LeftNode.Eval(state);
                if (left != Dynamic.Value) {
                    int size = (int)left;
                    object[] r = new object[size];
                    if (OriginalType.NestedType == VariableType.IntType) {
                        for (int i = 0; i < size; ++i) {
                            r[i] = 0;
                        }
                    }
                    if (OriginalType.NestedType == VariableType.BoolType) {
                        for (int i = 0; i < size; ++i) {
                            r[i] = false;
                        }
                    }
                    return r;
                }
                else
                    return Dynamic.Value;
            }
            if (Type == ILExpressionType.ArrayLength)
            {
                object left = LeftNode.Eval(state);
                if (left != Dynamic.Value)
                    return ((Array)left).GetLength(0);
                else
                    return Dynamic.Value;
            }
            if (Type == ILExpressionType.VariableAccess)
            {
                return state.GetValue((string)Const);
            }
            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;
            }

            #endregion

            #region Assign

            if (Type == ILExpressionType.Assign)
            {
                object right = RightNode.Eval(state);
                if (LeftNode.Type == ILExpressionType.VariableAccess)
                {
                    state.SetValue((string)LeftNode.Const, right);
                    return right;
                }
                else if (LeftNode.Type == ILExpressionType.ArrayAccess)
                {
                    object array = LeftNode.LeftNode.Eval(state);
                    object index = LeftNode.RightNode.Eval(state);
                    if (array == Dynamic.Value)
                    {
                        return right;
                    }
                    else
                    {
                        if (index == Dynamic.Value)
                        {
                            //Set whole array as Dynamic
                            state.SetArrayAsDynamic(array);
                        }
                        else
                        {
                            ((Array)array).SetValue(right, (int)index);
                        }
                        return right;
                    }
                }
                else
                {
                    throw new InvalidOperationException("Bad assign construction!");
                }
            }

            #endregion

            #region FunctionCall

            if (Type == ILExpressionType.FunctionCall)
            {
                string functionName = (string)Const;

                var args = new List<object>();
                bool isDynamic = false;
                foreach (ILExpression expr in VAList)
                {
                    object arg = expr.Eval(state);
                    args.Add(arg);
                    if (arg == Dynamic.Value)
                        isDynamic = true;
                }
                if (isDynamic)
                    return Dynamic.Value;
                else
                    return Function.Call(args.ToArray());;
            }

            #endregion

            throw new InvalidOperationException("Bad interpreter error! =(");
        }