Ejemplo n.º 1
0
        private static void UnboxIfGeneric(XTypeReference type, AstExpression node, XTypeSystem typeSystem)
        {
            if (type.IsGenericParameter || type.IsGenericParameterArray())
            {
                var resultType = node.GetResultType();
                if (resultType.IsByReference && !type.IsByReference)
                {
                    var elementType = resultType.ElementType;

                    var clone = new AstExpression(node);
                    node.SetCode(AstCode.SimpleCastclass).SetArguments(clone).Operand = elementType;
                }
                else
                {
                    if (TreatAsStruct(type, resultType))
                    {
                        ConvertUnboxStruct(node, resultType, typeSystem);
                    }
                    else
                    {
                        var clone = new AstExpression(node);
                        node.SetCode(AstCode.UnboxFromGeneric).SetArguments(clone).Operand = type;
                    }
                }
            }
        }
        /// <summary>
        /// Optimize expressions
        /// </summary>
        public static void Convert(AstBlock ast)
        {
            var variableExpressions = ast.GetExpressions().Where(x => x.Operand is AstVariable).ToList();
            var allVariables = variableExpressions.Select(x => (AstVariable)x.Operand).Distinct().ToList();
            var allStructVariables = allVariables.Where(x => x.Type.IsStruct()).ToList();

            var index = 0;
            foreach (var iterator in allStructVariables)
            {
                var variable = iterator;
                if (variable.IsThis || variable.IsParameter)
                    continue;
                if (variableExpressions.Any(x => (x.Operand == variable) && (x.Code == AstCode.Stloc)))
                    continue;

                // Get struct type
                var structType = variable.Type.Resolve();
                var defaultCtorDef = StructCallConverter.GetDefaultValueCtor(structType);
                var defaultCtor = variable.Type.CreateReference(defaultCtorDef);

                // Variable is not initialized
                var newObjExpr = new AstExpression(ast.SourceLocation, AstCode.Newobj, defaultCtor).SetType(variable.Type);
                var initExpr = new AstExpression(ast.SourceLocation, AstCode.Stloc, variable, newObjExpr).SetType(variable.Type);
                ast.Body.Insert(index++, initExpr);
            }           
        }
Ejemplo n.º 3
0
 /// <summary>
 /// Optimize expressions
 /// </summary>
 public static void Convert(AstNode ast)
 {
     // Expand typeof
     foreach (var pair in ast.GetExpressionPairs())
     {
         var node = pair.Expression;
         switch (node.Code)
         {
             case AstCode.Ldfld:
             //case AstCode.Ldsfld: // NOT YET
                 {
                     var field = (XFieldReference) node.Operand;
                     var clone = new AstExpression(node);
                     node.SetCode(AstCode.UnboxFromGeneric).SetArguments(clone).Operand = field.FieldType;
                 }
                 break;
             case AstCode.Call:
             case AstCode.Calli:
             case AstCode.Callvirt:
                 {
                     var method = (XMethodReference)node.Operand;
                     if ((!method.ReturnType.IsVoid()) && (pair.Parent != null))
                     {
                         var clone = new AstExpression(node);
                         node.SetCode(AstCode.UnboxFromGeneric).SetArguments(clone).Operand = method.ReturnType;
                     }
                 }
                 break;
         }
     }
 }
Ejemplo n.º 4
0
 private void FindNestedAssignments(AstExpression expr, ExpressionToInfer parent)
 {
     foreach (var arg in expr.Arguments)
     {
         if (arg.Code == AstCode.Stloc)
         {
             var expressionToInfer = new ExpressionToInfer(arg);
             allExpressions.Add(expressionToInfer);
             FindNestedAssignments(arg, expressionToInfer);
             var v = (AstVariable)arg.Operand;
             if (v.Type == null)
             {
                 assignmentExpressions[v].Add(expressionToInfer);
                 // the instruction that consumes the stloc result is handled as if it was reading the variable
                 parent.Dependencies.Add(v);
             }
         }
         else
         {
             AstVariable v;
             if (arg.Match(AstCode.Ldloc, out v) && (v.Type == null))
             {
                 parent.Dependencies.Add(v);
             }
             FindNestedAssignments(arg, parent);
         }
     }
 }
Ejemplo n.º 5
0
        /// <summary>
        /// Convert node with code Cast.
        /// </summary>
        private static void ConvertCastclass(AssemblyCompiler compiler, AstExpression node, XTypeSystem typeSystem)
        {
            var type = (XTypeReference) node.Operand;
            if (type.IsSystemArray())
            {
                // Call cast method
                var arrayHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var castToArray = arrayHelper.Methods.First(x => x.Name == "CastToArray");
                var castToArrayExpr = new AstExpression(node.SourceLocation, AstCode.Call, castToArray, node.Arguments).SetType(type);
                node.CopyFrom(castToArrayExpr);
                return;
            }

            string castMethod = null;
            if (type.IsSystemCollectionsIEnumerable())
            {
                castMethod = "CastToEnumerable";
            }
            else if (type.IsSystemCollectionsICollection())
            {
                castMethod = "CastToCollection";
            }
            else if (type.IsSystemCollectionsIList())
            {
                castMethod = "CastToList";
            }
            else if (type.IsSystemIFormattable())
            {
                castMethod = "CastToFormattable";
            }

            if (castMethod != null)
            {
                // Call cast method
                var arrayHelper = compiler.GetDot42InternalType(InternalConstants.CompilerHelperName).Resolve();
                var castToArray = arrayHelper.Methods.First(x => x.Name == castMethod);

                // Call "(x instanceof T) ? (T)x : asMethod(x)"

                // "instanceof x"
                var instanceofExpr = new AstExpression(node.SourceLocation, AstCode.SimpleInstanceOf, type, node.Arguments[0]).SetType(typeSystem.Bool);

                // CastX(x)
                var castXExpr = new AstExpression(node.SourceLocation, AstCode.Call, castToArray, node.Arguments[0]).SetType(typeSystem.Object);

                // T(x)
                var txExpr = new AstExpression(node.SourceLocation, AstCode.SimpleCastclass, type, node.Arguments[0]).SetType(type);

                // Combine
                var conditional = new AstExpression(node.SourceLocation, AstCode.Conditional, type, instanceofExpr, txExpr, castXExpr).SetType(type);

                node.CopyFrom(conditional);
                return;
            }

            // Normal castclass
            node.Code = AstCode.SimpleCastclass;
        }
Ejemplo n.º 6
0
 static AstExpression SimplifyLdObjAndStObj(AstExpression expr, ref bool modified)
 {
     if (expr.Code == AstCode.Initobj)
     {
         expr.Code = AstCode.Stobj;
         expr.Arguments.Add(new AstExpression(expr.SourceLocation, AstCode.DefaultValue, expr.Operand));
         modified = true;
     }
     else if (expr.Code == AstCode.Cpobj)
     {
         expr.Code = AstCode.Stobj;
         expr.Arguments[1] = new AstExpression(expr.SourceLocation, AstCode.Ldobj, expr.Operand, expr.Arguments[1]);
         modified = true;
     }
     AstExpression arg, arg2;
     XTypeReference type;
     AstCode? newCode = null;
     if (expr.Match(AstCode.Stobj, out type, out arg, out arg2))
     {
         switch (arg.Code)
         {
             case AstCode.Ldelema: newCode = AstCode.Stelem_Any; break;
             case AstCode.Ldloca: newCode = AstCode.Stloc; break;
             case AstCode.Ldflda: newCode = AstCode.Stfld; break;
             case AstCode.Ldsflda: newCode = AstCode.Stsfld; break;
         }
     }
     else if (expr.Match(AstCode.Ldobj, out type, out arg))
     {
         switch (arg.Code)
         {
             case AstCode.Ldelema: newCode = AstCode.Ldelem_Any; break;
             case AstCode.Ldloca: newCode = AstCode.Ldloc; break;
             case AstCode.Ldflda: newCode = AstCode.Ldfld; break;
             case AstCode.Ldsflda: newCode = AstCode.Ldsfld; break;
         }
     }
     if (newCode != null)
     {
         arg.Code = newCode.Value;
         if (expr.Code == AstCode.Stobj)
         {
             arg.InferredType = expr.InferredType;
             arg.ExpectedType = expr.ExpectedType;
             arg.Arguments.Add(arg2);
         }
         arg.ILRanges.AddRange(expr.ILRanges);
         modified = true;
         return arg;
     }
     else
     {
         return expr;
     }
 }
        /// <summary>
        /// Convert the result of the given node to uint8/uint16 if needed.
        /// </summary>
        private static void Convert(AstExpression node, AstCode convertCode, XTypeReference expectedType)
        {
            // Copy load expression
            var clone = new AstExpression(node);

            // Convert node
            node.Code = convertCode;
            node.SetArguments(clone);
            node.Operand = null;
            node.SetType(expectedType);
        }
Ejemplo n.º 8
0
        public RLRange Exit(AstCompilerVisitor compVisit, AstExpression node, List<RLRange> args)
        {
            var reg = GetMonitorRegister(compVisit, node);
            if (reg != null)
            {
                var first = compVisit.Add(node.SourceLocation, RCode.Move_object, reg, args[0].Result);
                var second = compVisit.Add(node.SourceLocation, RCode.Monitor_exit, reg);
                return new RLRange(first, second, null);
            }

            // default handling
            return new RLRange(compVisit.Add(node.SourceLocation, RCode.Monitor_exit, args[0].Result), null);
        }
Ejemplo n.º 9
0
 static bool SimplifyLdObjAndStObj(List<AstNode> body, AstExpression expr, int pos)
 {
     bool modified = false;
     expr = SimplifyLdObjAndStObj(expr, ref modified);
     if (modified && body != null)
         body[pos] = expr;
     for (int i = 0; i < expr.Arguments.Count; i++)
     {
         expr.Arguments[i] = SimplifyLdObjAndStObj(expr.Arguments[i], ref modified);
         modified |= SimplifyLdObjAndStObj(null, expr.Arguments[i], -1);
     }
     return modified;
 }
Ejemplo n.º 10
0
        static bool TransformDecimalCtorToConstant(List<AstNode> body, AstExpression expr, int pos)
        {
            XMethodReference r;
            List<AstExpression> args;
            if (expr.Match(AstCode.Newobj, out r, out args) && r.DeclaringType.IsSystemDecimal())
            {
                //if (args.Count == 1)
                //{
                //    int val;
                //    if (args[0].Match(AstCode.Ldc_I4, out val))
                //    {
                //        expr.Code = AstCode.Ldc_Decimal;
                //        expr.Operand = new decimal(val);
                //        expr.InferredType = r.DeclaringType;
                //        expr.Arguments.Clear();
                //        return true;
                //    }
                //}
                //else 
                if (args.Count == 5)
                {
                    int lo, mid, hi, isNegative, scale;
                    if (expr.Arguments[0].Match(AstCode.Ldc_I4, out lo) &&
                        expr.Arguments[1].Match(AstCode.Ldc_I4, out mid) &&
                        expr.Arguments[2].Match(AstCode.Ldc_I4, out hi) &&
                        expr.Arguments[3].Match(AstCode.Ldc_I4, out isNegative) &&
                        expr.Arguments[4].Match(AstCode.Ldc_I4, out scale))
                    {
                        // convert to a static string conversion method.
                        var dec = new decimal(lo, mid, hi, isNegative != 0, (byte)scale);
                        var str = dec.ToString(CultureInfo.InvariantCulture);

                        expr.Code = AstCode.Call;
                        expr.Operand = r.DeclaringType.Resolve().Methods.First(p => p.Name == "FromInvariantString" && p.IsStatic && p.Parameters.Count == 1);
                        expr.Arguments.Clear();
                        expr.Arguments.Add(new AstExpression(expr.SourceLocation, AstCode.Ldstr, str));
                        expr.InferredType = r.DeclaringType;
                        return true;
                    }
                }
            }
            bool modified = false;
            foreach (AstExpression arg in expr.Arguments)
            {
                modified |= TransformDecimalCtorToConstant(null, arg, -1);
            }
            return modified;
        }
Ejemplo n.º 11
0
        public Register GetMonitorRegister(AstCompilerVisitor compVisit, AstExpression node)
        {
            // this code is still experimental, and possibly does not handle all cases.
            var operand = node.Arguments[0].Operand;
            Register reg = null;

            if (operand is XFieldReference)
            {
                if (!_monitorUsage.TryGetValue(operand, out reg))
                {
                    reg = compVisit.Frame.AllocateTemp(FrameworkReferences.Object);
                    _monitorUsage.Add(operand, reg);
                }
            }
            return reg;
        }
 /// <summary>
 /// Optimize expressions
 /// </summary>
 public static void Convert(AstNode ast)
 {
     foreach (var node in ast.GetExpressions())
     {
         if (node.Code == AstCode.Ldloc)
         {
             var variable = (AstVariable) node.Operand;
             var varType = variable.Type;
             var expType = node.ExpectedType;
             if ((expType != null) && (!varType.IsSame(expType)))
             {
                 if (varType.IsByte() && (expType.IsChar() || expType.IsUInt16()))
                 {
                     var ldloc = new AstExpression(node);
                     var code = expType.IsUInt16() ? AstCode.Int_to_ushort : AstCode.Conv_U2;
                     node.CopyFrom(new AstExpression(node.SourceLocation, code, null, ldloc).SetType(expType));
                 } 
             }
         }
         else if (node.Code.IsCall())
         {
             var methodRef = (XMethodReference) node.Operand;
             var returnType = methodRef.ReturnType;
             var expType = node.ExpectedType;
             if ((expType != null) && (!returnType.IsSame(expType)))
             {
                 if (returnType.IsByte() && (expType.IsChar() || expType.IsUInt16()))
                 {
                     var ldloc = new AstExpression(node);
                     var code = expType.IsUInt16() ? AstCode.Int_to_ushort : AstCode.Conv_U2;
                     node.CopyFrom(new AstExpression(node.SourceLocation, code, null, ldloc).SetType(expType));
                 }
                 else if (returnType.IsUInt16() && expType.IsChar())
                 {
                     var ldloc = new AstExpression(node);
                     node.CopyFrom(new AstExpression(node.SourceLocation, AstCode.Conv_U2, null, ldloc).SetType(expType));
                 }
                 else if (returnType.IsChar() && expType.IsUInt16())
                 {
                     var ldloc = new AstExpression(node);
                     node.CopyFrom(new AstExpression(node.SourceLocation, AstCode.Int_to_ushort, null, ldloc).SetType(expType));
                 }
             }
         }
     }
 }
 /// <summary>
 /// Convert the given argument if it does not match the target type.
 /// </summary>
 private static void ConvertIfNeeded(AstExpression arg, XTypeReference targetType)
 {
     var argType = arg.GetResultType();
     if (!targetType.IsSame(argType))
     {
         if (targetType.IsChar())
         {
             if (argType.IsUInt16() || argType.IsByte()) Convert(arg, AstCode.Conv_U2, targetType);
         }
         else if (targetType.IsUInt16())
         {
             if (argType.IsChar() || argType.IsByte()) Convert(arg, AstCode.Int_to_ushort, targetType);
         }
         else if (targetType.IsInt16())
         {
             if (argType.IsChar() || argType.IsByte()) Convert(arg, AstCode.Conv_I2, targetType);
         }
     }
 }
        /// <summary>
        /// Convert the result of the given node to uint8/uint16 if needed.
        /// </summary>
        private static void ConvertIfNeeded(AstExpression node, XTypeReference valueType, AstExpression parent)
        {
            AstCode convCode;
            if (valueType.IsByte())
            {
                // Convert from int to uint8
                convCode = AstCode.Int_to_ubyte;
            }
            else if (valueType.IsUInt16())
            {
                // Convert from int to uint16
                convCode = AstCode.Int_to_ushort;
            }
            else if (valueType.IsChar())
            {
                // Convert from int to uint16
                convCode = AstCode.Conv_U2;
            }
            else
            {
                // Do not convert
                return;
            }

            // Avoid recursion
            if ((parent != null) && (parent.Code == convCode))
                return;

            // Copy load expression
            var clone = new AstExpression(node);

            // Convert node
            node.Code = convCode;
            node.Arguments.Clear();
            node.Arguments.Add(clone);
            node.Operand = null;
            node.InferredType = valueType;
            
            // keep the expected type!
            node.ExpectedType = clone.ExpectedType;
            clone.ExpectedType = valueType;
            
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Optimize expressions
        /// </summary>
        public static void Convert(AstNode ast)
        {
            // Optimize brtrue (cxx(int, int)) expressions
            foreach (var node in ast.GetExpressions(x => (x.Code == AstCode.Brtrue) || (x.Code == AstCode.Brfalse)))
            {
                var expr = node.Arguments[0];
                if (expr.Code.IsCompare() && (expr.Arguments.Count == 2))
                {
                    var arg1 = expr.Arguments[0];
                    var arg2 = expr.Arguments[1];

                    if (arg1.IsInt32() && arg2.IsInt32())
                    {
                        // Simplify
                        var code = (node.Code == AstCode.Brtrue) ? expr.Code : expr.Code.Reverse();
                        var newExpr = new AstExpression(expr.SourceLocation, code.ToBranch(), node.Operand, arg1, arg2);
                        node.CopyFrom(newExpr, true);
                    }
                }
            }
        }
Ejemplo n.º 16
0
 /// <summary>
 /// Add initialization code to the given constructor for non-initialized struct fields.
 /// </summary>
 private static void AddFieldInitializationCode(MethodSource ctor, AstBlock ast)
 {
     List<XFieldDefinition> fieldsToInitialize;
     var declaringType = ctor.Method.DeclaringType;
     var fieldsThatMayNeedInitialization = declaringType.Fields.Where(x => x.IsReachable && x.FieldType.IsEnum());
     var index = 0;
     if (ctor.Method.IsStatic)
     {
         fieldsToInitialize = fieldsThatMayNeedInitialization.Where(x => x.IsStatic && !IsInitialized(ast, x)).ToList();
         foreach (var field in fieldsToInitialize)
         {
             var defaultExpr = new AstExpression(ast.SourceLocation, AstCode.DefaultValue, field.FieldType);
             var initExpr = new AstExpression(ast.SourceLocation, AstCode.Stsfld, field, defaultExpr);
             ast.Body.Insert(index++, initExpr);
         }
     }
     else
     {
         // If there is a this ctor being called, we do not have to initialize here.
         var thisCalls = ast.GetSelfAndChildrenRecursive<AstExpression>(x => (x.Code == AstCode.Call) && ((XMethodReference) x.Operand).DeclaringType.IsSame(declaringType));
         if (thisCalls.Any(x => ((XMethodReference) x.Operand).Name == ".ctor"))
             return;
         fieldsToInitialize = fieldsThatMayNeedInitialization.Where(x => !x.IsStatic && !IsInitialized(ast, x)).ToList();
         if (fieldsToInitialize.Any())
         {
             var baseCall = FindFirstBaseCtorCall(ast, declaringType);
             var initExpressions = new List<AstExpression>();
             foreach (var field in fieldsToInitialize)
             {
                 var thisExpr = new AstExpression(ast.SourceLocation, AstCode.Ldthis, null);
                 var defaultExpr = new AstExpression(ast.SourceLocation, AstCode.DefaultValue, field.FieldType);
                 initExpressions.Add(new AstExpression(ast.SourceLocation, AstCode.Stfld, field, thisExpr, defaultExpr));
             }
             InsertAfter(ast, baseCall, initExpressions);
         }
     }
 }
Ejemplo n.º 17
0
        bool MakeCompoundAssignment(AstExpression expr)
        {
            // stelem.any(T, ldloc(array), ldloc(pos), <OP>(ldelem.any(T, ldloc(array), ldloc(pos)), <RIGHT>))
            // or
            // stobj(T, ldloc(ptr), <OP>(ldobj(T, ldloc(ptr)), <RIGHT>))
            AstCode expectedLdelemCode;

            switch (expr.Code)
            {
            case AstCode.Stelem_Any:
                expectedLdelemCode = AstCode.Ldelem_Any;
                break;

            case AstCode.Stfld:
                expectedLdelemCode = AstCode.Ldfld;
                break;

            case AstCode.Stobj:
                expectedLdelemCode = AstCode.Ldobj;
                break;

            default:
                return(false);
            }

            // all arguments except the last (so either array+pos, or ptr):
            bool hasGeneratedVar = false;

            for (int i = 0; i < expr.Arguments.Count - 1; i++)
            {
                AstVariable inputVar;
                if (!expr.Arguments[i].Match(AstCode.Ldloc, out inputVar))
                {
                    return(false);
                }
                hasGeneratedVar |= inputVar.IsGenerated;
            }
            // At least one of the variables must be generated; otherwise we just keep the expanded form.
            // We do this because we want compound assignments to be represented in ILAst only when strictly necessary;
            // other compound assignments will be introduced by ReplaceMethodCallsWithOperator
            // (which uses a reversible transformation, see ReplaceMethodCallsWithOperator.RestoreOriginalAssignOperatorAnnotation)
            if (!hasGeneratedVar)
            {
                return(false);
            }

            AstExpression op = expr.Arguments.Last();
            // in case of compound assignments with a lifted operator the result is inside NullableOf and the operand is inside ValueOf
            bool liftedOperator = false;

            if (op.Code == AstCode.NullableOf)
            {
                op             = op.Arguments[0];
                liftedOperator = true;
            }
            if (!CanBeRepresentedAsCompoundAssignment(op))
            {
                return(false);
            }

            AstExpression ldelem = op.Arguments[0];

            if (liftedOperator)
            {
                if (ldelem.Code != AstCode.ValueOf)
                {
                    return(false);
                }
                ldelem = ldelem.Arguments[0];
            }
            if (ldelem.Code != expectedLdelemCode)
            {
                return(false);
            }
            Debug.Assert(ldelem.Arguments.Count == expr.Arguments.Count - 1);
            for (int i = 0; i < ldelem.Arguments.Count; i++)
            {
                if (!ldelem.Arguments[i].MatchLdloc((AstVariable)expr.Arguments[i].Operand))
                {
                    return(false);
                }
            }
            expr.Code    = AstCode.CompoundAssignment;
            expr.Operand = null;
            expr.Arguments.RemoveRange(0, ldelem.Arguments.Count);
            // result is "CompoundAssignment(<OP>(ldelem.any(...), <RIGHT>))"
            return(true);
        }
Ejemplo n.º 18
0
        public PartialExpression TryResolveMember(Namescope namescope, AstIdentifier id, int?typeParamCount, AstExpression qualifier)
        {
            var result = TryGetMemberCached(namescope, id.Symbol, typeParamCount);

            if (result != null)
            {
                var gt = result as GenericParameterType;
                if (gt != null)
                {
                    return(qualifier == null
                        ? new PartialType(id.Source, gt)
                        : null);
                }

                var dt = result as DataType;
                if (dt != null)
                {
                    return(dt.IsAccessibleFrom(id.Source)
                        ? new PartialType(id.Source, dt)
                        : null);
                }

                var block = result as Block;
                if (block != null)
                {
                    return(block.IsAccessibleFrom(id.Source)
                        ? new PartialBlock(id.Source, block)
                        : null);
                }

                var ns = result as Namespace;
                if (ns != null)
                {
                    return(ns.IsAccessibleFrom(id.Source)
                        ? new PartialNamespace(id.Source, ns)
                        : null);
                }
            }

            var ndt = namescope as DataType;

            if (ndt != null && qualifier == null)
            {
                ndt.AssignBaseType();
                if (ndt.Base != null)
                {
                    return(TryResolveMember(ndt.Base, id, typeParamCount, null));
                }
            }

            return(null);
        }
Ejemplo n.º 19
0
 /// <summary>
 /// 构造函数。
 /// </summary>
 /// <param name="body">成员。</param>
 /// <param name="isType">类型。</param>
 public TypeIsAst(AstExpression body, Type isType) : base(typeof(bool))
 {
     this.body   = body;
     this.isType = isType;
 }
Ejemplo n.º 20
0
 /// <summary>
 /// 构造函数。
 /// </summary>
 /// <param name="tryAst">异常捕获。</param>
 protected TryAst(TryAst tryAst) : base(tryAst)
 {
     catchAsts  = tryAst.catchAsts;
     finallyAst = tryAst.finallyAst;
 }
Ejemplo n.º 21
0
 /// <summary>
 /// 构造函数。
 /// </summary>
 /// <param name="left">左表达式。</param>
 /// <param name="expressionType">计算方式。</param>
 /// <param name="right">右表达式。</param>
 public BinaryAst(AstExpression left, BinaryExpressionType expressionType, AstExpression right) : base(AnalysisType(left, expressionType, right))
 {
     this.left           = left;
     this.expressionType = expressionType;
     this.right          = right;
 }
Ejemplo n.º 22
0
        /// <summary>
        /// Optimize expressions
        /// </summary>
        public static void Convert(AstNode ast, AssemblyCompiler compiler)
        {
            foreach (var node in ast.GetExpressions())
            {
                switch (node.Code)
                {
                    // Optimize enum2int(ldsfld(enum-const))
                    //      and enum2int(int.to.enum(xxx))
                    case AstCode.Enum_to_int:
                    case AstCode.Enum_to_long:
                        {
                            var arg = node.Arguments[0];
                            XFieldReference fieldRef;
                            if (arg.Match(AstCode.Ldsfld, out fieldRef))
                            {
                                XFieldDefinition field;
                                object value;
                                if (fieldRef.TryResolve(out field) && field.IsStatic && field.DeclaringType.IsEnum && field.TryGetEnumValue(out value))
                                {
                                    // Replace with ldc_ix
                                    var wide = (node.Code == AstCode.Enum_to_long);
                                    node.SetCode(wide ? AstCode.Ldc_I8 : AstCode.Ldc_I4);
                                    node.Operand = wide ? (object)XConvert.ToLong(value) : XConvert.ToInt(value);
                                    node.Arguments.Clear();
                                }
                            }
                            else if (arg.Code == AstCode.Int_to_enum || arg.Code == AstCode.Long_to_enum)
                            {
                                var expectedType = node.ExpectedType;
                                node.CopyFrom(arg.Arguments[0]);
                                node.ExpectedType = expectedType;
                            }
                        }
                        break;
                    // optimize ceq/cne (int/long-to-enum(int), yyy)
                    case AstCode.Ceq:
                    case AstCode.Cne:
                    {
                        if (node.Arguments.Any(a=>IsToEnum(a.Code)))
                        {
                            // xx_to_enum is a quite costly operation when compared to enum-to-int,
                            // so convert this to an interger-only compare.
                            bool isLong = node.Arguments.Any(a => a.Code == AstCode.Long_to_enum);

                            foreach (var arg in node.Arguments)
                            {
                                if (IsToEnum(arg.Code))
                                {
                                    arg.CopyFrom(arg.Arguments[0]);
                                    arg.ExpectedType = isLong ? compiler.Module.TypeSystem.Long : compiler.Module.TypeSystem.Int;
                                }
                                else
                                {
                                    Debug.Assert(arg.GetResultType().IsEnum());
                                    var orig = new AstExpression(arg);
                                    var convert = new AstExpression(arg.SourceLocation,
                                        isLong ? AstCode.Enum_to_long : AstCode.Enum_to_int, null, orig);
                                    convert.ExpectedType = isLong ? compiler.Module.TypeSystem.Long : compiler.Module.TypeSystem.Int;
                                    arg.CopyFrom(convert);
                                }
                            }
                        }
                        break;
                    }
                }
            }
 
        }
Ejemplo n.º 23
0
        void ProcessArgument(AstExpression callNode, XMethodReference methodRef, int argumentIndex, MethodSource currentMethod, XModule assembly)
        {
            var node = callNode.Arguments[argumentIndex];

            // Should we do something?
            switch (node.Code)
            {
            case AstCode.Ldloca:     // Parameter
            case AstCode.AddressOf:  // Local variable
            case AstCode.Ldflda:     // Instance field
            case AstCode.Ldsflda:    // Static field
            case AstCode.Ldelema:    // Array
                break;

            case AstCode.Ldloc:
                if (!node.MatchThis() || !currentMethod.IsDotNet)
                {
                    return;
                }
                break;

            default:
                return;
            }

            // Process argument
            var method         = methodRef.Resolve();
            var argIsThis      = !method.IsStatic && (argumentIndex == 0);
            var parameterIndex = method.IsStatic ? argumentIndex : argumentIndex - 1;
            var parameter      = argIsThis ? null : method.Parameters[parameterIndex];
            var argType        = argIsThis ? method.DeclaringType : parameter.ParameterType;
            //var argAttrs = argIsThis ? ParameterAttributes.None : parameter.Attributes;
            var argIsByRef         = argType.IsByReference;
            var argIsOut           = argIsThis ? false : argIsByRef && (parameter.Kind == XParameterKind.Output); // argIsByRef && argAttrs.HasFlag(ParameterAttributes.Out);
            var argIsGenByRefParam = argIsByRef && argType.ElementType.IsGenericParameter;

            switch (node.Code)
            {
            case AstCode.Ldloca:     // Parameter
            {
                var variable = ((AstVariable)node.Operand);
                if (variable.Type.IsPrimitive || argIsByRef)
                {
                    // Box first
                    var ldloc = new AstExpression(node.SourceLocation, AstCode.Ldloc, node.Operand)
                    {
                        InferredType = variable.Type
                    };
                    if (argIsByRef)
                    {
                        var stloc = new AstExpression(node.SourceLocation, AstCode.Stloc, node.Operand)
                        {
                            InferredType = variable.Type
                        };
                        stloc.Arguments.Add(GetValueOutOfByRefArray(node, variable.Type, argIsGenByRefParam, assembly));
                        ConvertToByRefArray(node, variable.Type, ldloc, stloc, argIsOut, argIsGenByRefParam, assembly);
                    }
                    else
                    {
                        ConvertToBox(node, variable.Type, ldloc);
                    }
                }
                else if (variable.Type.IsGenericParameter)
                {
                    // Convert to ldarg
                    var ldloc = new AstExpression(node.SourceLocation, AstCode.Ldloc, node.Operand)
                    {
                        InferredType = variable.Type
                    };
                    callNode.Arguments[argumentIndex] = ldloc;
                }
            }
            break;

            case AstCode.Ldloc:     // this
            {
                var variable = ((AstVariable)node.Operand);
                if (argIsThis && (variable.Type.IsByReference))
                {
                    node.SetType(variable.Type.ElementType);
                }
                else if (argIsByRef)
                {
                    var ldclone     = new AstExpression(node);
                    var stExpr      = new AstExpression(node.SourceLocation, AstCode.Nop, null);
                    var elementType = variable.Type;
                    if (elementType.IsByReference)
                    {
                        elementType = elementType.ElementType;
                    }
                    ConvertToByRefArray(node, elementType, ldclone, stExpr, argIsOut, argIsGenByRefParam, assembly);
                }
            }
            break;

            case AstCode.AddressOf:     // Local variable
            {
                var arg     = node.Arguments[0];
                var type    = arg.GetResultType();
                var typeDef = type.Resolve();
                if (typeDef.IsPrimitive)
                {
                    if (argIsByRef)
                    {
                        throw new CompilerException("Unsupported use of AddressOf by byref argument");
                    }
                    else
                    {
                        ConvertToBox(node, type, arg);
                    }
                }
            }
            break;

            case AstCode.Ldflda:     // Instance field
            case AstCode.Ldsflda:    // Static field
            {
                var fieldRef = (XFieldReference)node.Operand;
                var field    = fieldRef.Resolve();
                if (field.FieldType.IsPrimitive || argIsByRef)
                {
                    // Box first
                    var ldfldCode = (node.Code == AstCode.Ldflda) ? AstCode.Ldfld : AstCode.Ldsfld;
                    var ldfld     = new AstExpression(node.SourceLocation, ldfldCode, node.Operand)
                    {
                        InferredType = field.FieldType
                    };
                    ldfld.Arguments.AddRange(node.Arguments);
                    if (argIsByRef)
                    {
                        var stfldCode = (node.Code == AstCode.Ldflda) ? AstCode.Stfld : AstCode.Stsfld;
                        var stfld     = new AstExpression(node.SourceLocation, stfldCode, node.Operand)
                        {
                            InferredType = field.FieldType
                        };
                        stfld.Arguments.AddRange(node.Arguments);                                                          // instance
                        stfld.Arguments.Add(GetValueOutOfByRefArray(node, field.FieldType, argIsGenByRefParam, assembly)); // value
                        ConvertToByRefArray(node, field.FieldType, ldfld, stfld, argIsOut, argIsGenByRefParam, assembly);
                    }
                    else
                    {
                        ConvertToBox(node, field.FieldType, ldfld);
                    }
                }
            }
            break;

            case AstCode.Ldelema:     // Array element
            {
                var array     = node.Arguments[0];
                var arrayType = array.GetResultType();
                var type      = arrayType.ElementType;
                if (type.IsPrimitive || argIsByRef)
                {
                    // Box first
                    var ldElemCode = type.GetLdElemCode();
                    var ldelem     = new AstExpression(node.SourceLocation, ldElemCode, node.Operand)
                    {
                        InferredType = type
                    };
                    ldelem.Arguments.AddRange(node.Arguments);
                    if (argIsByRef)
                    {
                        var stelemCode = type.GetStElemCode();
                        var stelem     = new AstExpression(node.SourceLocation, stelemCode, node.Operand)
                        {
                            InferredType = type
                        };
                        stelem.Arguments.AddRange(node.Arguments);
                        stelem.Arguments.Add(GetValueOutOfByRefArray(node, type, argIsGenByRefParam, assembly));
                        ConvertToByRefArray(node, type, ldelem, stelem, argIsOut, argIsGenByRefParam, assembly);
                    }
                    else
                    {
                        ConvertToBox(node, type, ldelem);
                    }
                }
            }
            break;
            }
        }
Ejemplo n.º 24
0
        private static void FailsafeInterlockedUsingLocking(XFieldReference field, AstExpression expr,
                                                            AstExpression targetExpr, AstBlock block, int idx,
                                                            AssemblyCompiler compiler, MethodSource currentMethod)
        {
            if (currentMethod.IsDotNet && !currentMethod.ILMethod.DeclaringType.HasSuppressMessageAttribute("InterlockedFallback"))
            {
                bool isStatic = field != null && field.Resolve().IsStatic;

                DLog.Warning(DContext.CompilerCodeGenerator,
                             "Emulating Interlocked call using failsafe locking mechanism in {0}{1}. Consider using AtomicXXX classes instead. You can suppress this message with an [SuppressMessage(\"dot42\", \"InterlockedFallback\")] attribute on the class.",
                             currentMethod.Method.FullName, !isStatic ? "" : " because a static field is referenced");
            }

            // replace with:
            //    Monitor.Enter();
            //    try { <original expression> } finally { Monitor.Exit(); }
            //
            // note that the lock is larger than it has to be, since it also sourrounds
            // the parameter evaluation.
            // It must sourround the storing and loading of the reference parameters though.
            var typeSystem = compiler.Module.TypeSystem;

            var monitorType = compiler.GetDot42InternalType("System.Threading", "Monitor");
            var enterMethod = monitorType.Resolve().Methods.Single(p => p.Name == "Enter");
            var exitMethod  = monitorType.Resolve().Methods.Single(p => p.Name == "Exit");

            AstExpression loadLockTarget = null;

            if (field != null)
            {
                if (field.Resolve().IsStatic)
                {
                    // lock on the field's class typedef.
                    // but always the element type, not on a generic instance (until Dot42 implements proper generic static field handling)
                    loadLockTarget = new AstExpression(expr.SourceLocation, AstCode.LdClass, field.DeclaringType.GetElementType())
                                     .SetType(typeSystem.Type);
                }
                else
                {
                    // lock on the fields object
                    loadLockTarget = targetExpr.Arguments[0];
                }
            }

            if (loadLockTarget == null)
            {
                // something went wrong. use a global lock.
                DLog.Warning(DContext.CompilerCodeGenerator, "unable to infer target of Interlocked call. using global lock.");
                var interlockedType = compiler.GetDot42InternalType("System.Threading", "Interlocked");
                loadLockTarget = new AstExpression(expr.SourceLocation, AstCode.LdClass, interlockedType)
                                 .SetType(typeSystem.Type);
            }

            var lockVar = new AstGeneratedVariable("lockTarget$", "")
            {
                Type = typeSystem.Object
            };
            var storeLockVar = new AstExpression(expr.SourceLocation, AstCode.Stloc, lockVar, loadLockTarget);
            var loadLockVar  = new AstExpression(expr.SourceLocation, AstCode.Ldloc, lockVar);
            var enterCall    = new AstExpression(expr.SourceLocation, AstCode.Call, enterMethod, storeLockVar);

            var replacementBlock = new AstBlock(expr.SourceLocation);

            replacementBlock.Body.Add(enterCall);

            var tryCatch = new AstTryCatchBlock(expr.SourceLocation)
            {
                TryBlock     = new AstBlock(expr.SourceLocation, expr),
                FinallyBlock = new AstBlock(expr.SourceLocation,
                                            new AstExpression(block.SourceLocation, AstCode.Call, exitMethod, loadLockVar))
            };

            replacementBlock.Body.Add(tryCatch);

            if (block.EntryGoto == expr)
            {
                block.EntryGoto = enterCall;
            }

            block.Body[idx] = replacementBlock;
        }
Ejemplo n.º 25
0
        private static bool InterlockedUsingUpdater(AstExpression interlockedCall, string methodName, XFieldReference field,
                                                    XFieldDefinition updater, AstExpression targetExpr, AstExpression parentExpr,
                                                    AssemblyCompiler compiler)
        {
            bool isStatic = field.Resolve().IsStatic;

            string replacementMethod = null;

            if (methodName == "Increment")
            {
                replacementMethod = "IncrementAndGet";
            }
            else if (methodName == "Decrement")
            {
                replacementMethod = "DecrementAndGet";
            }
            else if (methodName == "Add")
            {
                replacementMethod = "AddAndGet";
            }
            else if (methodName == "Read")
            {
                replacementMethod = "Get";
            }
            else if (methodName.StartsWith("Exchange"))
            {
                replacementMethod = "GetAndSet";
            }
            else if (methodName.StartsWith("CompareAndSet"))
            {
                // this patches through to the original java method for performance purists.
                replacementMethod = "CompareAndSet";
            }
            else if (methodName.StartsWith("CompareExchange"))
            {
                if (TransformCompareExchangeToCompareAndSet(parentExpr, compiler, ref interlockedCall))
                {
                    replacementMethod = "CompareAndSet";
                }
                else
                {
                    // The semantics here are slighlty different. Java returns a 'true' on
                    // success, while BCL returns the old value. We have crafted a replacement
                    // method with the BCL semantics though.
                    replacementMethod = "CompareExchange";
                }
            }
            else
            {
                return(false);
            }

            var updaterType = updater.FieldType.Resolve();
            var methodRef   = updaterType.Methods.FirstOrDefault(f => f.Name == replacementMethod);

            if (methodRef == null && methodName == "CompareExchange")
            {
                methodRef = updaterType.Methods.FirstOrDefault(f => f.Name.StartsWith(replacementMethod));
            }

            if (methodRef == null)
            {
                return(false);
            }

            interlockedCall.Operand = methodRef;

            if (isStatic)
            {
                interlockedCall.Arguments[0] = new AstExpression(interlockedCall.SourceLocation, AstCode.Ldnull, null)
                                               .SetType(field.DeclaringType);
            }
            else
            {
                interlockedCall.Arguments[0] = targetExpr.Arguments[0];
            }

            // add field updater instance argument.
            var ldUpdater = new AstExpression(interlockedCall.SourceLocation, AstCode.Ldsfld, updater)
                            .SetType(updaterType);

            interlockedCall.Arguments.Insert(0, ldUpdater);

            return(true);
        }
Ejemplo n.º 26
0
        static AstExpression SimplifyLdObjAndStObj(AstExpression expr, ref bool modified)
        {
            if (expr.Code == AstCode.Initobj)
            {
                expr.Code = AstCode.Stobj;
                expr.Arguments.Add(new AstExpression(expr.SourceLocation, AstCode.DefaultValue, expr.Operand));
                modified = true;
            }
            else if (expr.Code == AstCode.Cpobj)
            {
                expr.Code         = AstCode.Stobj;
                expr.Arguments[1] = new AstExpression(expr.SourceLocation, AstCode.Ldobj, expr.Operand, expr.Arguments[1]);
                modified          = true;
            }
            AstExpression  arg, arg2;
            XTypeReference type;
            AstCode?       newCode = null;

            if (expr.Match(AstCode.Stobj, out type, out arg, out arg2))
            {
                switch (arg.Code)
                {
                case AstCode.Ldelema: newCode = AstCode.Stelem_Any; break;

                case AstCode.Ldloca: newCode = AstCode.Stloc; break;

                case AstCode.Ldflda: newCode = AstCode.Stfld; break;

                case AstCode.Ldsflda: newCode = AstCode.Stsfld; break;
                }
            }
            else if (expr.Match(AstCode.Ldobj, out type, out arg))
            {
                switch (arg.Code)
                {
                case AstCode.Ldelema: newCode = AstCode.Ldelem_Any; break;

                case AstCode.Ldloca: newCode = AstCode.Ldloc; break;

                case AstCode.Ldflda: newCode = AstCode.Ldfld; break;

                case AstCode.Ldsflda: newCode = AstCode.Ldsfld; break;
                }
            }
            if (newCode != null)
            {
                arg.Code = newCode.Value;
                if (expr.Code == AstCode.Stobj)
                {
                    arg.InferredType = expr.InferredType;
                    arg.ExpectedType = expr.ExpectedType;
                    arg.Arguments.Add(arg2);
                }
                arg.ILRanges.AddRange(expr.ILRanges);
                modified = true;
                return(arg);
            }
            else
            {
                return(expr);
            }
        }
Ejemplo n.º 27
0
        private static bool TransformCompareExchangeToCompareAndSet(AstExpression parentExpr, AssemblyCompiler compiler, ref AstExpression interlockedCall)
        {
            if (parentExpr == null)
            {
                // as the return value is not used, transformation is possible.
                SwapArgumentsAndSetResultType(interlockedCall, compiler);
                return(true);
            }

            // Java returns a 'true' on  success, while BCL always returns the old value.
            // Assuming the comparants are the same, in BLC terms 'ceq' means checking for
            // success (i.e. old value is expected value), while 'cne' means checking for
            // failure (i.e. value found if different from expected value)
            // 'brfalse' a zero comparand mean branch on success, while brtrue means the opposite.

            var comparant1 = interlockedCall.Arguments[2];

            if (parentExpr.Code == AstCode.Brfalse || parentExpr.Code == AstCode.Brtrue)
            {
                // compare to not null.
                switch (comparant1.Code)
                {
                case AstCode.Ldnull:
                    break;

                case AstCode.Ldc_I4:
                case AstCode.Ldc_I8:
                {
                    if (System.Convert.ToInt64(comparant1.Operand) != 0)
                    {
                        return(false);
                    }
                    break;
                }

                default:
                    return(false);
                }

                // transformation is possible.
                parentExpr.Code = parentExpr.Code == AstCode.Brfalse ? AstCode.Brtrue : AstCode.Brfalse;
                SwapArgumentsAndSetResultType(interlockedCall, compiler);
                return(true);
            }

            // Cne should work in theory, but I have not actually seen it so I was unable to test.
            // Leave it out for safety until actually encountered.
            if (parentExpr.Code != AstCode.Ceq
                // parentExpr.Code != AstCode.Cne
                && parentExpr.Code != AstCode.__Beq &&
                parentExpr.Code != AstCode.__Bne_Un)
            {
                return(false);
            }

            var comparand2 = parentExpr.Arguments[1];

            if (comparant1.Code != comparand2.Code || !Equals(comparant1.Operand, comparand2.Operand))
            {
                return(false);
            }

            switch (comparant1.Code)
            {
            case AstCode.Ldloc:
            case AstCode.Ldnull:
            case AstCode.Ldc_I4:
            case AstCode.Ldc_I8:
                break;

            default:
                return(false);
            }

            // transformation is possible.
            if (parentExpr.Code == AstCode.Ceq)
            {
                parentExpr.CopyFrom(interlockedCall);
                interlockedCall = parentExpr;
            }
            //else if (parentExpr.Code == AstCode.Cne) // see above.
            //{
            //    parentExpr.Code = AstCode.Not;
            //    parentExpr.Arguments.RemoveAt(1);
            //}
            else if (parentExpr.Code == AstCode.__Beq)
            {
                parentExpr.Code = AstCode.Brtrue;
                parentExpr.Arguments.RemoveAt(1);
            }
            else if (parentExpr.Code == AstCode.__Bne_Un)
            {
                parentExpr.Code = AstCode.Brfalse;
                parentExpr.Arguments.RemoveAt(1);
            }
            else
            {
                return(false);
            }

            SwapArgumentsAndSetResultType(interlockedCall, compiler);
            return(true);
        }
Ejemplo n.º 28
0
        bool InlineExpressionTreeParameterDeclarations(List <AstNode> body, AstExpression expr, int pos)
        {
            // When there is a Expression.Lambda() call, and the parameters are declared in the
            // IL statement immediately prior to the one containing the Lambda() call,
            // using this code for the3 declaration:
            //   stloc(v, call(Expression::Parameter, call(Type::GetTypeFromHandle, ldtoken(...)), ldstr(...)))
            // and the variables v are assigned only once (in that statements), and read only in a Expression::Lambda
            // call that immediately follows the assignment statements, then we will inline those assignments
            // into the Lambda call using AstCode.ExpressionTreeParameterDeclarations.

            // This is sufficient to allow inlining over the expression tree construction. The remaining translation
            // of expression trees into C# will be performed by a C# AST transformer.

            for (int i = expr.Arguments.Count - 1; i >= 0; i--)
            {
                if (InlineExpressionTreeParameterDeclarations(body, expr.Arguments[i], pos))
                {
                    return(true);
                }
            }

            XMethodReference mr;
            AstExpression    lambdaBodyExpr, parameterArray;

            if (!(expr.Match(AstCode.Call, out mr, out lambdaBodyExpr, out parameterArray) && mr.Name == "Lambda"))
            {
                return(false);
            }
            if (!(parameterArray.Code == AstCode.InitArray && mr.DeclaringType.FullName == "System.Linq.Expressions.Expression"))
            {
                return(false);
            }
            int firstParameterPos = pos - parameterArray.Arguments.Count;

            if (firstParameterPos < 0)
            {
                return(false);
            }

            AstExpression[] parameterInitExpressions = new AstExpression[parameterArray.Arguments.Count + 1];
            for (int i = 0; i < parameterArray.Arguments.Count; i++)
            {
                parameterInitExpressions[i] = body[firstParameterPos + i] as AstExpression;
                if (!MatchParameterVariableAssignment(parameterInitExpressions[i]))
                {
                    return(false);
                }
                AstVariable v = (AstVariable)parameterInitExpressions[i].Operand;
                if (!parameterArray.Arguments[i].MatchLdloc(v))
                {
                    return(false);
                }
                // TODO: validate that the variable is only used here and within 'body'
            }

            parameterInitExpressions[parameterInitExpressions.Length - 1] = lambdaBodyExpr;
            Debug.Assert(expr.Arguments[0] == lambdaBodyExpr);
            expr.Arguments[0] = new AstExpression(expr.SourceLocation, AstCode.ExpressionTreeParameterDeclarations, null, parameterInitExpressions);

            body.RemoveRange(firstParameterPos, parameterArray.Arguments.Count);

            return(true);
        }
Ejemplo n.º 29
0
        AstExpression IntroducePostIncrementForInstanceFields(AstExpression expr)
        {
            // stfld(field, ldloc(instance), add(stloc(helperVar, ldfld(field, ldloc(instance))), ldc.i4(1)))
            // -> stloc(helperVar, postincrement(1, ldflda(field, ldloc(instance))))

            // Also works for array elements and pointers:

            // stelem.any(T, ldloc(instance), ldloc(pos), add(stloc(helperVar, ldelem.any(T, ldloc(instance), ldloc(pos))), ldc.i4(1)))
            // -> stloc(helperVar, postincrement(1, ldelema(ldloc(instance), ldloc(pos))))

            // stobj(T, ldloc(ptr), add(stloc(helperVar, ldobj(T, ldloc(ptr)), ldc.i4(1))))
            // -> stloc(helperVar, postIncrement(1, ldloc(ptr)))

            // callsetter(set_P, ldloc(instance), add(stloc(helperVar, callgetter(get_P, ldloc(instance))), ldc.i4(1)))
            // -> stloc(helperVar, postIncrement(1, propertyaddress. callgetter(get_P, ldloc(instance))))

            if (!(expr.Code == AstCode.Stfld || expr.Code.IsStoreToArray() || expr.Code == AstCode.Stobj))
            {
                return(null);
            }

            // Test that all arguments except the last are ldloc (1 arg for fields and pointers, 2 args for arrays)
            for (int i = 0; i < expr.Arguments.Count - 1; i++)
            {
                if (expr.Arguments[i].Code != AstCode.Ldloc)
                {
                    return(null);
                }
            }

            AstExpression addExpr = expr.Arguments[expr.Arguments.Count - 1];
            int           incrementAmount;
            AstCode       incrementCode = GetIncrementCode(addExpr, out incrementAmount);
            AstVariable   helperVar;
            AstExpression initialValue;

            if (!(incrementAmount != 0 && addExpr.Arguments[0].Match(AstCode.Stloc, out helperVar, out initialValue)))
            {
                return(null);
            }

            if (expr.Code == AstCode.Stfld)
            {
                if (initialValue.Code != AstCode.Ldfld)
                {
                    return(null);
                }
                // There might be two different FieldReference instances, so we compare the field's signatures:
                FieldReference getField = (FieldReference)initialValue.Operand;
                FieldReference setField = (FieldReference)expr.Operand;
                if (!(TypeAnalysis.IsSameType(getField.DeclaringType, setField.DeclaringType) &&
                      getField.Name == setField.Name && TypeAnalysis.IsSameType(getField.FieldType, setField.FieldType)))
                {
                    return(null);
                }
            }
            else if (expr.Code == AstCode.Stobj)
            {
                if (!(initialValue.Code == AstCode.Ldobj && initialValue.Operand == expr.Operand))
                {
                    return(null);
                }
            }
            else
            {
                if (!initialValue.Code.IsLoadFromArray())
                {
                    return(null);
                }
            }
            Debug.Assert(expr.Arguments.Count - 1 == initialValue.Arguments.Count);
            for (int i = 0; i < initialValue.Arguments.Count; i++)
            {
                if (!initialValue.Arguments[i].MatchLdloc((AstVariable)expr.Arguments[i].Operand))
                {
                    return(null);
                }
            }

            AstExpression stloc = addExpr.Arguments[0];

            if (expr.Code == AstCode.Stobj)
            {
                stloc.Arguments[0] = new AstExpression(AstCode.PostIncrement, incrementAmount, initialValue.Arguments[0]);
            }
            else
            {
                stloc.Arguments[0] = new AstExpression(AstCode.PostIncrement, incrementAmount, initialValue);
                initialValue.Code  = (expr.Code == AstCode.Stfld ? AstCode.Ldflda : AstCode.Ldelema);
            }
            // TODO: ILRanges?

            return(stloc);
        }
Ejemplo n.º 30
0
        bool IntroducePostIncrementForVariables(List <AstNode> body, AstExpression expr, int pos)
        {
            // Works for variables and static fields/properties

            // expr = ldloc(i)
            // stloc(i, add(expr, ldc.i4(1)))
            // ->
            // expr = postincrement(1, ldloca(i))
            AstVariable   exprVar;
            AstExpression exprInit;

            if (!(expr.Match(AstCode.Stloc, out exprVar, out exprInit) && exprVar.IsGenerated))
            {
                return(false);
            }

            //The next expression
            AstExpression nextExpr = body.ElementAtOrDefault(pos + 1) as AstExpression;

            if (nextExpr == null)
            {
                return(false);
            }

            AstCode loadInstruction   = exprInit.Code;
            AstCode storeInstruction  = nextExpr.Code;
            bool    recombineVariable = false;

            // We only recognise local variables, static fields, and static getters with no arguments
            switch (loadInstruction)
            {
            case AstCode.Ldloc:
                //Must be a matching store type
                if (storeInstruction != AstCode.Stloc)
                {
                    return(false);
                }
                AstVariable loadVar  = (AstVariable)exprInit.Operand;
                AstVariable storeVar = (AstVariable)nextExpr.Operand;
                if (loadVar != storeVar)
                {
                    if (loadVar.OriginalVariable != null && loadVar.OriginalVariable == storeVar.OriginalVariable)
                    {
                        recombineVariable = true;
                    }
                    else
                    {
                        return(false);
                    }
                }
                break;

            case AstCode.Ldsfld:
                if (storeInstruction != AstCode.Stsfld)
                {
                    return(false);
                }
                if (exprInit.Operand != nextExpr.Operand)
                {
                    return(false);
                }
                break;

            default:
                return(false);
            }

            AstExpression addExpr = nextExpr.Arguments[0];

            int     incrementAmount;
            AstCode incrementCode = GetIncrementCode(addExpr, out incrementAmount);

            if (!(incrementAmount != 0 && addExpr.Arguments[0].MatchLdloc(exprVar)))
            {
                return(false);
            }

            if (recombineVariable)
            {
                // Split local variable, unsplit these two instances
                // replace nextExpr.Operand with exprInit.Operand
                ReplaceVariables(method, oldVar => oldVar == nextExpr.Operand ? (AstVariable)exprInit.Operand : oldVar);
            }

            switch (loadInstruction)
            {
            case AstCode.Ldloc:
                exprInit.Code = AstCode.Ldloca;
                break;

            case AstCode.Ldsfld:
                exprInit.Code = AstCode.Ldsflda;
                break;
            }
            expr.Arguments[0] = new AstExpression(incrementCode, incrementAmount, exprInit);
            body.RemoveAt(pos + 1);             // TODO ILRanges
            return(true);
        }
Ejemplo n.º 31
0
 internal override AstExpression Revert()
 {
     AstExpression[] e = new AstExpression[elts.Count];
     int i = 0;
     foreach (expr el in elts)
         e[i++] = expr.Revert(el);
     return new TupleExpression(false, e);
 }
Ejemplo n.º 32
0
        bool TransformArrayInitializers(List <AstNode> body, AstExpression expr, int pos)
        {
            AstVariable    v, v3;
            AstExpression  newarrExpr;
            XTypeReference elementType;
            AstExpression  lengthExpr;
            int            arrayLength;

            if (expr.Match(AstCode.Stloc, out v, out newarrExpr) &&
                newarrExpr.Match(AstCode.Newarr, out elementType, out lengthExpr) &&
                lengthExpr.Match(AstCode.Ldc_I4, out arrayLength) &&
                arrayLength > 0)
            {
                Array newArr;
                int   initArrayPos;
                if (ForwardScanInitializeArrayRuntimeHelper(body, pos + 1, v, elementType, arrayLength, out newArr, out initArrayPos))
                {
                    var arrayType = new XArrayType(elementType, new XArrayDimension(0, arrayLength));
                    body[pos] = new AstExpression(expr.SourceLocation, AstCode.Stloc, v, new AstExpression(expr.SourceLocation, AstCode.InitArray,
                                                                                                           new InitArrayData(arrayType, newArr)));
                    body.RemoveAt(initArrayPos);
                }
#if !NOTUSED
                // Put in a limit so that we don't consume too much memory if the code allocates a huge array
                // and populates it extremely sparsly. However, 255 "null" elements in a row actually occur in the Mono C# compiler!
                const int maxConsecutiveDefaultValueExpressions = 0;                // 300;
                var       operands = new List <AstExpression>();
                int       numberOfInstructionsToRemove = 0;
                for (int j = pos + 1; j < body.Count; j++)
                {
                    var nextExpr = body[j] as AstExpression;
                    int arrayPos;
                    if (nextExpr != null &&
                        nextExpr.Code.IsStoreToArray() &&
                        nextExpr.Arguments[0].Match(AstCode.Ldloc, out v3) &&
                        v == v3 &&
                        nextExpr.Arguments[1].Match(AstCode.Ldc_I4, out arrayPos) &&
                        arrayPos >= operands.Count &&
                        arrayPos <= operands.Count + maxConsecutiveDefaultValueExpressions)
                    {
                        while (operands.Count < arrayPos)
                        {
                            operands.Add(new AstExpression(expr.SourceLocation, AstCode.DefaultValue, elementType));
                        }
                        operands.Add(nextExpr.Arguments[2]);
                        numberOfInstructionsToRemove++;
                    }
                    else
                    {
                        break;
                    }
                }

                /*if (operands.Count == arrayLength) {
                 *      var arrayType = new XArrayType(elementType, new XArrayDimension(0, arrayLength));
                 *      expr.Arguments[0] = new AstExpression(expr.SourceLocation, AstCode.InitArray, arrayType, operands);
                 *      body.RemoveRange(pos + 1, numberOfInstructionsToRemove);
                 *
                 *      new AstInlining(method).InlineIfPossible(body, ref pos);
                 *      return true;
                 * }*/
#endif
            }
            return(false);
        }
Ejemplo n.º 33
0
            internal static expr Convert(AstExpression expr, expr_context ctx)
            {
                expr ast;

                if (expr is ConstantExpression)
                    ast = Convert((ConstantExpression)expr);
                else if (expr is NameExpression)
                    ast = new Name((NameExpression)expr, ctx);
                else if (expr is UnaryExpression)
                    ast = new UnaryOp((UnaryExpression)expr);
                else if (expr is BinaryExpression)
                    ast = Convert((BinaryExpression)expr);
                else if (expr is AndExpression)
                    ast = new BoolOp((AndExpression)expr);
                else if (expr is OrExpression)
                    ast = new BoolOp((OrExpression)expr);
                else if (expr is CallExpression)
                    ast = new Call((CallExpression)expr);
                else if (expr is ParenthesisExpression)
                    return Convert(((ParenthesisExpression)expr).Expression);
                else if (expr is LambdaExpression)
                    ast = new Lambda((LambdaExpression)expr);
                else if (expr is ListExpression)
                    ast = new List((ListExpression)expr, ctx);
                else if (expr is TupleExpression)
                    ast = new Tuple((TupleExpression)expr, ctx);
                else if (expr is DictionaryExpression)
                    ast = new Dict((DictionaryExpression)expr);
                else if (expr is ListComprehension)
                    ast = new ListComp((ListComprehension)expr);
                else if (expr is GeneratorExpression)
                    ast = new GeneratorExp((GeneratorExpression)expr);
                else if (expr is MemberExpression)
                    ast = new Attribute((MemberExpression)expr, ctx);
                else if (expr is YieldExpression)
                    ast = new Yield((YieldExpression)expr);
                else if (expr is ConditionalExpression)
                    ast = new IfExp((ConditionalExpression)expr);
                else if (expr is IndexExpression)
                    ast = new Subscript((IndexExpression)expr, ctx);
                else if (expr is BackQuoteExpression)
                    ast = new Repr((BackQuoteExpression)expr);
                else if (expr is SetExpression)
                    ast = new Set((SetExpression)expr);
                else if (expr is DictionaryComprehension)
                    ast = new DictComp((DictionaryComprehension)expr);
                else if (expr is SetComprehension)
                    ast = new SetComp((SetComprehension)expr);
                else
                    throw new ArgumentTypeException("Unexpected expression type: " + expr.GetType());

                ast.GetSourceLocation(expr);
                return ast;
            }
        public Symbol CreateSymbol(ParameterExpression parameter, string name, string varName, IBsonSerializer serializer, bool isCurrent = false)
        {
            var varAst = AstExpression.Var(varName, isCurrent);

            return(CreateSymbol(parameter, name, varAst, serializer, isCurrent));
        }
Ejemplo n.º 35
0
        private string GetSymbolType(AstExpression expr, Symbol s, string id)
        {
            if (s == null)
            {
                var name = (s is CallableSymbol) ? " method" : " identifier";
                var e = new SymbolNotFoundException("'" + id + "' " + name +" not found.");
                e.Expr = expr;
                e.Id = id;
                throw e;
            }

            return s.Type;
        }
        public Symbol CreateSymbol(ParameterExpression parameter, AstExpression ast, IBsonSerializer serializer, bool isCurrent = false)
        {
            var parameterName = _nameGenerator.GetParameterName(parameter);

            return(CreateSymbol(parameter, name: parameterName, ast, serializer, isCurrent));
        }
Ejemplo n.º 37
0
            IErrorHandler IErrorHandler.Append(AstExpression code)
            {
                Append(code);

                return(this);
            }
 public Symbol CreateSymbol(ParameterExpression parameter, string name, AstExpression ast, IBsonSerializer serializer, bool isCurrent = false)
 {
     return(new Symbol(parameter, name, ast, serializer, isCurrent));
 }
Ejemplo n.º 39
0
        private static Type AnalysisType(AstExpression left, BinaryExpressionType expressionType, AstExpression right)
        {
            switch (expressionType)
            {
            case BinaryExpressionType.Add:
            case BinaryExpressionType.Subtract:
            case BinaryExpressionType.Multiply:
            case BinaryExpressionType.Divide:
            case BinaryExpressionType.Modulo:
                if (left.RuntimeType == right.RuntimeType && IsArithmetic(left.RuntimeType))
                {
                    return(left.RuntimeType);
                }
                throw new AstException($"{left.RuntimeType}类型不支持“{expressionType}”运算!");

            case BinaryExpressionType.LessThan:
            case BinaryExpressionType.LessThanOrEqual:
            case BinaryExpressionType.Equal:
            case BinaryExpressionType.GreaterThanOrEqual:
            case BinaryExpressionType.GreaterThan:
            case BinaryExpressionType.NotEqual:
                if (left.RuntimeType == right.RuntimeType && IsArithmetic(left.RuntimeType))
                {
                    return(typeof(bool));
                }
                throw new AstException("左右表达式类型不相同!");

            case BinaryExpressionType.OrElse:
            case BinaryExpressionType.AndAlso:
                if (left.RuntimeType == right.RuntimeType && left.RuntimeType == typeof(bool))
                {
                    return(left.RuntimeType);
                }
                throw new AstException($"{left.RuntimeType}类型不支持“{expressionType}”运算!");

            case BinaryExpressionType.Or:
            case BinaryExpressionType.And:
            case BinaryExpressionType.ExclusiveOr:
                if (left.RuntimeType == right.RuntimeType && IsIntegerOrBool(left.RuntimeType))
                {
                    return(left.RuntimeType);
                }
                throw new AstException($"{left.RuntimeType}类型不支持“{expressionType}”运算!");

            case BinaryExpressionType.LeftShift:
            case BinaryExpressionType.RightShift:
                if (IsInteger(left.RuntimeType))
                {
                    if (right.RuntimeType == typeof(int))
                    {
                        return(left.RuntimeType);
                    }

                    throw new AstException($"“{expressionType}”运算,右侧表达式类型必须是“int”!");
                }
                throw new AstException($"{left.RuntimeType}类型不支持“{expressionType}”运算!");

            case BinaryExpressionType.Power:
                if (left.RuntimeType == right.RuntimeType && left.RuntimeType == typeof(double))
                {
                    return(left.RuntimeType);
                }

#if NETSTANDARD2_1_OR_GREATER
                if (left.RuntimeType == right.RuntimeType && left.RuntimeType == typeof(float))
                {
                    return(left.RuntimeType);
                }
#endif
                throw new AstException($"{left.RuntimeType}类型不支持“{expressionType}”运算!");

            case BinaryExpressionType.OrAssign:
            case BinaryExpressionType.AndAssign:
            case BinaryExpressionType.ExclusiveOrAssign:
                if (!left.CanWrite)
                {
                    throw new AstException("左表达式不可写!");
                }
                goto case BinaryExpressionType.Or;

            case BinaryExpressionType.LeftShiftAssign:
            case BinaryExpressionType.RightShiftAssign:
                if (!left.CanWrite)
                {
                    throw new AstException("左表达式不可写!");
                }
                goto case BinaryExpressionType.LeftShift;

            case BinaryExpressionType.PowerAssign:
                if (!left.CanWrite)
                {
                    throw new AstException("左表达式不可写!");
                }
                goto case BinaryExpressionType.Power;

            case BinaryExpressionType.AddAssign:
            case BinaryExpressionType.SubtractAssign:
            case BinaryExpressionType.MultiplyAssign:
            case BinaryExpressionType.DivideAssign:
            case BinaryExpressionType.ModuloAssign:
                if (!left.CanWrite)
                {
                    throw new AstException("左表达式不可写!");
                }
                goto case BinaryExpressionType.Add;

            default:
                throw new NotImplementedException();
            }
        }
Ejemplo n.º 40
0
 public AstAndExpression(AstExpression left, AstExpression right)
 {
     Left = left;
     Right = right;
 }
Ejemplo n.º 41
0
 private BinaryAst(BinaryAst binaryAst) : base(binaryAst.RuntimeType)
 {
     left           = binaryAst.left;
     expressionType = binaryAst.expressionType - 1;
     right          = binaryAst.right;
 }
Ejemplo n.º 42
0
 public AstExpressionList(AstExpression[] expr)
 {
     Expr = expr;
 }
Ejemplo n.º 43
0
        public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.IsOneOf(__aggregateMethods))
            {
                var sourceExpression  = arguments[0];
                var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression);
                var itemSerializer    = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);

                if (method.Is(EnumerableMethod.AggregateWithFunc))
                {
                    var funcLambda           = (LambdaExpression)arguments[1];
                    var funcParameters       = funcLambda.Parameters;
                    var accumulatorParameter = funcParameters[0];
                    var accumulatorSymbol    = context.CreateSymbolWithVarName(accumulatorParameter, varName: "value", itemSerializer); // note: MQL uses $$value for the accumulator
                    var itemParameter        = funcParameters[1];
                    var itemSymbol           = context.CreateSymbolWithVarName(itemParameter, varName: "this", itemSerializer);         // note: MQL uses $$this for the item being processed
                    var funcContext          = context.WithSymbols(accumulatorSymbol, itemSymbol);
                    var funcTranslation      = ExpressionToAggregationExpressionTranslator.Translate(funcContext, funcLambda.Body);

                    var sourceVar = AstExpression.Var("source");
                    var ast       = AstExpression.Let(
                        var: AstExpression.VarBinding(sourceVar, sourceTranslation.Ast),
                        @in: AstExpression.Cond(
                            @if: AstExpression.Lte(AstExpression.Size(sourceVar), 1),
                            @then: AstExpression.ArrayElemAt(sourceVar, 0),
                            @else: AstExpression.Reduce(
                                input: AstExpression.Slice(sourceVar, 1, int.MaxValue),
                                initialValue: AstExpression.ArrayElemAt(sourceVar, 0),
                                @in: funcTranslation.Ast)));

                    return(new AggregationExpression(expression, ast, itemSerializer));
                }
                else if (method.IsOneOf(EnumerableMethod.AggregateWithSeedAndFunc, EnumerableMethod.AggregateWithSeedFuncAndResultSelector))
                {
                    var seedExpression  = arguments[1];
                    var seedTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, seedExpression);

                    var funcLambda            = (LambdaExpression)arguments[2];
                    var funcParameters        = funcLambda.Parameters;
                    var accumulatorParameter  = funcParameters[0];
                    var accumulatorSerializer = context.KnownSerializersRegistry.GetSerializer(accumulatorParameter);
                    var accumulatorSymbol     = context.CreateSymbolWithVarName(accumulatorParameter, varName: "value", accumulatorSerializer); // note: MQL uses $$value for the accumulator
                    var itemParameter         = funcParameters[1];
                    var itemSymbol            = context.CreateSymbolWithVarName(itemParameter, varName: "this", itemSerializer);                // note: MQL uses $$this for the item being processed
                    var funcContext           = context.WithSymbols(accumulatorSymbol, itemSymbol);
                    var funcTranslation       = ExpressionToAggregationExpressionTranslator.Translate(funcContext, funcLambda.Body);

                    var ast = AstExpression.Reduce(
                        input: sourceTranslation.Ast,
                        initialValue: seedTranslation.Ast,
                        @in: funcTranslation.Ast);
                    var serializer = accumulatorSerializer;

                    if (method.Is(EnumerableMethod.AggregateWithSeedFuncAndResultSelector))
                    {
                        var resultSelectorLambda              = (LambdaExpression)arguments[3];
                        var resultSelectorParameter           = resultSelectorLambda.Parameters[0];
                        var resultSelectorParameterSerializer = context.KnownSerializersRegistry.GetSerializer(resultSelectorParameter);
                        var resultSelectorSymbol              = context.CreateSymbol(resultSelectorParameter, resultSelectorParameterSerializer);
                        var resultSelectorContext             = context.WithSymbol(resultSelectorSymbol);
                        var resultSelectorTranslation         = ExpressionToAggregationExpressionTranslator.Translate(resultSelectorContext, resultSelectorLambda.Body);

                        ast = AstExpression.Let(
                            var: AstExpression.VarBinding(resultSelectorSymbol.Var, ast),
                            @in: resultSelectorTranslation.Ast);
                        serializer = context.KnownSerializersRegistry.GetSerializer(resultSelectorLambda);
                    }

                    return(new AggregationExpression(expression, ast, serializer));
                }
            }

            throw new ExpressionNotSupportedException(expression);
        }
Ejemplo n.º 44
0
        private List<AstNode> ConvertToAst(IEnumerable<ByteCode> body)
        {
            var ast = new List<AstNode>();

            // Convert stack-based IL code to ILAst tree
            foreach (var byteCode in body)
            {
                var ilRange = new InstructionRange(byteCode.Offset, byteCode.EndOffset);

                if (byteCode.StackBefore == null)
                {
                    // Unreachable code
                    continue;
                }

                var expr = new AstExpression(byteCode.SequencePoint, byteCode.Code, byteCode.Operand);
                expr.ILRanges.Add(ilRange);
                if (byteCode.Prefixes != null && byteCode.Prefixes.Length > 0)
                {
                    var prefixes = new AstExpressionPrefix[byteCode.Prefixes.Length];
                    for (var i = 0; i < prefixes.Length; i++)
                    {
                        var operand = byteCode.Prefixes[i].Operand;
                        if (operand is FieldReference)
                        {
                            operand = XBuilder.AsFieldReference(module, (FieldReference) operand);
                        }
                        else if (operand is MethodReference)
                        {
                            operand = XBuilder.AsMethodReference(module, (MethodReference)operand);
                        }
                        else if (operand is TypeReference)
                        {
                            operand = XBuilder.AsTypeReference(module, (TypeReference) operand);
                        }
                        prefixes[i] = new AstExpressionPrefix((AstCode)byteCode.Prefixes[i].OpCode.Code, operand);
                    }
                    expr.Prefixes = prefixes;
                }

                // Label for this instruction
                if (byteCode.Label != null)
                {
                    ast.Add(byteCode.Label);
                }

                // Reference arguments using temporary variables
                var popCount = byteCode.PopCount ?? byteCode.StackBefore.Length;
                for (var i = byteCode.StackBefore.Length - popCount; i < byteCode.StackBefore.Length; i++)
                {
                    var slot = byteCode.StackBefore[i];
                    expr.Arguments.Add(new AstExpression(byteCode.SequencePoint, AstCode.Ldloc, slot.LoadFrom));
                }

                // Store the result to temporary variable(s) if needed
                if (byteCode.StoreTo == null || byteCode.StoreTo.Count == 0)
                {
                    ast.Add(expr);
                }
                else if (byteCode.StoreTo.Count == 1)
                {
                    ast.Add(new AstExpression(byteCode.SequencePoint, AstCode.Stloc, byteCode.StoreTo[0], expr));
                }
                else
                {
                    var tmpVar = new AstGeneratedVariable("expr_" + byteCode.Offset.ToString("X2"), byteCode.StoreTo.Select(x => x.OriginalName).FirstOrDefault());
                    ast.Add(new AstExpression(byteCode.SequencePoint, AstCode.Stloc, tmpVar, expr));
                    foreach (var storeTo in byteCode.StoreTo.AsEnumerable().Reverse())
                    {
                        ast.Add(new AstExpression(byteCode.SequencePoint, AstCode.Stloc, storeTo, new AstExpression(byteCode.SequencePoint, AstCode.Ldloc, tmpVar)));
                    }
                }
            }

            return ast;
        }
Ejemplo n.º 45
0
        private static EvalValue CalcExpression(IEnvironment env, AstExpression ast)
        {
            // 先计算右值
            var right = new EvalValue();

            // 可能的运算符 == <= >= && || + - * / < > %
            // && ||
            // >= <= == > <
            // + -
            // * / %
            try
            {
                Stack <AstPun>  ops    = new Stack <AstPun>();
                Queue <AstNode> output = new Queue <AstNode>();
                // 转为后缀表达式
                foreach (var item in ast)
                {
                    if (item is AstFactor || item is AstExpression)
                    {
                        output.Enqueue(item);
                    }
                    else if (item is AstPun)
                    {
                        while (ops.Count > 0 && ops.Peek() >= (item as AstPun))
                        {
                            output.Enqueue(ops.Pop());
                        }
                        ops.Push(item as AstPun);
                    }
                    else
                    {
                        throw new RunTimeException("非法表达式项", item);
                    }
                }
                while (ops.Count > 0)
                {
                    output.Enqueue(ops.Pop());
                }
                // 后缀表达式求值
                Stack <EvalValue> result = new Stack <EvalValue>();
                while (output.Count > 0)
                {
                    var item = output.Dequeue();
                    if (item is AstFactor || item is AstExpression)
                    {
                        result.Push(item.Eval(env));
                    }
                    else if (item is AstPun)
                    {
                        var       val2 = result.Pop();
                        var       val1 = result.Pop();
                        EvalValue res;
                        string    op = (item as AstPun).token.ToString();
                        if (op == "+")
                        {
                            res = val1 + val2;
                        }
                        else if (op == "-")
                        {
                            res = val1 - val2;
                        }
                        else if (op == "*")
                        {
                            res = val1 * val2;
                        }
                        else if (op == "/")
                        {
                            res = val1 / val2;
                        }
                        else if (op == "%")
                        {
                            res = val1 % val2;
                        }
                        else if (op == "<")
                        {
                            res = val1 < val2;
                        }
                        else if (op == ">")
                        {
                            res = val1 > val2;
                        }
                        else if (op == "==")
                        {
                            res =
                                (val1.type == EvalValueType.INT && val2.type == EvalValueType.INT &&
                                 val1.intVal == val2.intVal) ||
                                (val1.type == EvalValueType.STRING && val2.type == EvalValueType.STRING &&
                                 val1.strVal == val2.strVal) ?
                                EvalValue.TRUE : EvalValue.FALSE;
                        }
                        else if (op == "<=")
                        {
                            res = val1 <= val2;
                        }
                        else if (op == ">=")
                        {
                            res = val1 >= val2;
                        }
                        else if (op == "&&")
                        {
                            res = (val1 > EvalValue.ZERO).intVal > 0 && (val2 > EvalValue.ZERO).intVal > 0 ?
                                  EvalValue.TRUE : EvalValue.FALSE;
                        }
                        else if (op == "||")
                        {
                            res = (val1 > EvalValue.ZERO).intVal > 0 || (val2 > EvalValue.ZERO).intVal > 0
                                ? EvalValue.TRUE : EvalValue.FALSE;
                        }
                        else
                        {
                            throw new RunTimeException("非法运算符" + op);
                        }
                        result.Push(res);
                    }
                    else
                    {
                        throw new RunTimeException("非法表达式项", item);
                    }
                }
                if (result.Count != 1)
                {
                    throw new RunTimeException("表达式结果不正确");
                }
                right = result.Pop();
            }
            catch (Exception e)
            {
                throw new RunTimeException("计算表达式的值时出错:" + e.Message, ast);
            }

            if (ast.isAssignExpression)
            {
                // 赋值语句
                env.Set(ast.leftFactor, right);
            }
            return(right);
        }
Ejemplo n.º 46
0
        bool MakeAssignmentExpression(List <AstNode> body, AstExpression expr, int pos)
        {
            // exprVar = ...
            // stloc(v, exprVar)
            // ->
            // exprVar = stloc(v, ...))
            AstVariable   exprVar;
            AstExpression initializer;

            if (!(expr.Match(AstCode.Stloc, out exprVar, out initializer) && exprVar.IsGenerated))
            {
                return(false);
            }
            var           nextExpr = body.ElementAtOrDefault(pos + 1) as AstExpression;
            AstVariable   v;
            AstExpression stLocArg;

            if (nextExpr.Match(AstCode.Stloc, out v, out stLocArg) && stLocArg.MatchLdloc(exprVar))
            {
                var store2 = body.ElementAtOrDefault(pos + 2) as AstExpression;
                if (StoreCanBeConvertedToAssignment(store2, exprVar))
                {
                    // expr_44 = ...
                    // stloc(v1, expr_44)
                    // anystore(v2, expr_44)
                    // ->
                    // stloc(v1, anystore(v2, ...))
                    var inlining = new AstInlining(method);
                    if (inlining.numLdloc.GetOrDefault(exprVar) == 2 && inlining.numStloc.GetOrDefault(exprVar) == 1)
                    {
                        body.RemoveAt(pos + 2); // remove store2
                        body.RemoveAt(pos);     // remove expr = ...
                        nextExpr.Arguments[0] = store2;
                        store2.Arguments[store2.Arguments.Count - 1] = initializer;

                        inlining.InlineIfPossible(body, ref pos);

                        return(true);
                    }
                }

                body.RemoveAt(pos + 1); // remove stloc
                nextExpr.Arguments[0] = initializer;
                ((AstExpression)body[pos]).Arguments[0] = nextExpr;
                return(true);
            }

            if ((nextExpr != null) && (nextExpr.Code == AstCode.Stsfld) && nextExpr.Arguments.Count == 1)
            {
                // exprVar = ...
                // stsfld(fld, exprVar)
                // ->
                // exprVar = stsfld(fld, ...))
                if (nextExpr.Arguments[0].MatchLdloc(exprVar))
                {
                    body.RemoveAt(pos + 1); // remove stsfld
                    nextExpr.Arguments[0] = initializer;
                    ((AstExpression)body[pos]).Arguments[0] = nextExpr;
                    return(true);
                }
            }
            return(false);
        }
Ejemplo n.º 47
0
 public AstDivExpression(AstUnaryExpr left, AstExpression right)
 {
     Left = left;
     Right = right;
 }
Ejemplo n.º 48
0
 public AstCast(AstExpression targetType, AstExpression arg)
     : base(arg.Source)
 {
     TargetType = targetType;
     Argument   = arg;
 }
Ejemplo n.º 49
0
 /// <summary>
 /// Generate an Add opcode.
 /// </summary>
 private static RCode OpcodeForType(AstExpression expr, RCode[] opcodes)
 {
     return OpcodeForType(expr.GetResultType(), opcodes);
 }
Ejemplo n.º 50
0
        public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method     = expression.Method;
            var parameters = method.GetParameters();
            var arguments  = expression.Arguments.ToArray();

            if (method.IsOneOf(__windowMethods))
            {
                var partitionExpression  = arguments[0];
                var partitionTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, partitionExpression);
                var partitionSerializer  = (ISetWindowFieldsPartitionSerializer)partitionTranslation.Serializer;
                var inputSerializer      = partitionSerializer.InputSerializer;

                AstWindow window = null;
                if (HasArgument <Expression>(parameters, "window", arguments, out var windowExpression))
                {
                    window = TranslateWindow(context, expression, windowExpression, inputSerializer);
                }

                if (method.IsOneOf(__nullaryMethods))
                {
                    var @operator  = GetNullaryWindowOperator(method);
                    var ast        = AstExpression.NullaryWindowExpression(@operator, window);
                    var serializer = BsonSerializer.LookupSerializer(method.ReturnType); // TODO: use correct serializer
                    return(new AggregationExpression(expression, ast, serializer));
                }

                AggregationExpression selectorTranslation = null;
                if (HasArgument <LambdaExpression>(parameters, "selector", arguments, out var selectorLambda))
                {
                    selectorTranslation = TranslateSelector(context, selectorLambda, inputSerializer);
                }

                if (method.IsOneOf(__unaryMethods))
                {
                    var @operator  = GetUnaryWindowOperator(method);
                    var ast        = AstExpression.UnaryWindowExpression(@operator, selectorTranslation.Ast, window);
                    var serializer = BsonSerializer.LookupSerializer(method.ReturnType); // TODO: use correct serializer
                    return(new AggregationExpression(expression, ast, serializer));
                }

                if (method.IsOneOf(__binaryMethods))
                {
                    var selector1Lambda      = GetArgument <LambdaExpression>(parameters, "selector1", arguments);
                    var selector2Lambda      = GetArgument <LambdaExpression>(parameters, "selector2", arguments);
                    var selector1Translation = TranslateSelector(context, selector1Lambda, inputSerializer);
                    var selector2Translation = TranslateSelector(context, selector2Lambda, inputSerializer);

                    var @operator  = GetBinaryWindowOperator(method);
                    var ast        = AstExpression.BinaryWindowExpression(@operator, selector1Translation.Ast, selector2Translation.Ast, window);
                    var serializer = BsonSerializer.LookupSerializer(method.ReturnType); // TODO: use correct serializer
                    return(new AggregationExpression(expression, ast, serializer));
                }

                if (method.IsOneOf(__derivativeOrIntegralMethods))
                {
                    WindowTimeUnit?unit = default;
                    if (HasArgument <Expression>(parameters, "unit", arguments, out var unitExpression))
                    {
                        unit = unitExpression.GetConstantValue <WindowTimeUnit>(expression);
                    }

                    var @operator  = GetDerivativeOrIntegralWindowOperator(method);
                    var ast        = AstExpression.DerivativeOrIntegralWindowExpression(@operator, selectorTranslation.Ast, unit, window);
                    var serializer = BsonSerializer.LookupSerializer(method.ReturnType); // TODO: use correct serializer
                    return(new AggregationExpression(expression, ast, serializer));
                }

                if (method.IsOneOf(__exponentialMovingAverageMethods))
                {
                    var weightingExpression = arguments[2];
                    var weighting           = weightingExpression.GetConstantValue <ExponentialMovingAverageWeighting>(expression);

                    var ast        = AstExpression.ExponentialMovingAverageWindowExpression(selectorTranslation.Ast, weighting, window);
                    var serializer = BsonSerializer.LookupSerializer(method.ReturnType); // TODO: use correct serializer
                    return(new AggregationExpression(expression, ast, serializer));
                }

                if (method.IsOneOf(__shiftMethods))
                {
                    var byExpression = arguments[2];
                    var by           = byExpression.GetConstantValue <int>(expression);

                    AstExpression defaultValue = null;
                    if (method.Is(WindowMethod.ShiftWithDefaultValue))
                    {
                        var defaultValueExpression  = arguments[3];
                        var defaultValueTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, defaultValueExpression);
                        defaultValue = defaultValueTranslation.Ast;
                    }

                    var ast        = AstExpression.ShiftWindowExpression(selectorTranslation.Ast, by, defaultValue);
                    var serializer = BsonSerializer.LookupSerializer(method.ReturnType); // TODO: use correct serializer
                    return(new AggregationExpression(expression, ast, serializer));
                }
            }

            throw new ExpressionNotSupportedException(expression);
        }
Ejemplo n.º 51
0
 internal static AstExpression[] RevertExprs(PythonList exprs)
 {
     // it is assumed that list elements are expr
     AstExpression[] ret = new AstExpression[exprs.Count];
     for (int i = 0; i < exprs.Count; i++)
         ret[i] = ((expr)exprs[i]).Revert();
     return ret;
 }
Ejemplo n.º 52
0
        private void AddToExpressionStack(Stack <AstExpression> stack, AstExpression expression)
        {
            stack.Push(expression);

            // Add any sub-expressions
            switch (expression.Kind)
            {
            case AstNodeKind.ConversionExpression:
            {
                var conversion = (AstConversionExpression)expression;
                AddToExpressionStack(stack, conversion.Expression);
                break;
            }

            case AstNodeKind.AddExpression:
            case AstNodeKind.SubtractExpression:
            case AstNodeKind.MultiplyExpression:
            case AstNodeKind.DivideExpression:
            case AstNodeKind.ModuloExpression:
            case AstNodeKind.EqualToExpression:
            case AstNodeKind.NotEqualToExpression:
            case AstNodeKind.LessThanExpression:
            case AstNodeKind.LessThanOrEqualToExpression:
            case AstNodeKind.GreaterThanExpression:
            case AstNodeKind.GreaterThanOrEqualToExpression:
            {
                var binary = (AstBinaryExpression)expression;
                stack.Push(binary.Right);
                stack.Push(binary.Left);
                break;
            }

            case AstNodeKind.CallExpression:
            {
                var call = (AstCallExpression)expression;
                var args = call.Arguments;

                // Push arguments in reverse order
                for (int i = args.Count - 1; i >= 0; i--)
                {
                    AddToExpressionStack(stack, args[i]);
                }

                AddToExpressionStack(stack, call.Address);
                break;
            }

            case AstNodeKind.ReadMemoryExpression:
            {
                var readMemory = (AstReadMemoryExpression)expression;
                AddToExpressionStack(stack, readMemory.Address);
                break;
            }

            case AstNodeKind.DispatchExpression:
            {
                var dispatch = (AstDispatchExpression)expression;
                var args     = dispatch.Arguments;

                // Push arguments in reverse order
                for (int i = args.Count - 1; i >= 0; i--)
                {
                    AddToExpressionStack(stack, args[i]);
                }

                break;
            }
            }
        }
Ejemplo n.º 53
0
 internal static expr Convert(AstExpression expr)
 {
     return Convert(expr, Load.Instance);
 }
Ejemplo n.º 54
0
 public AstExprFilter(AstExpression expression)
 {
     _expression = Ensure.IsNotNull(expression, nameof(expression));
 }
Ejemplo n.º 55
0
 internal static slice TrySliceConvert(AstExpression expr)
 {
     if (expr is SliceExpression)
         return new Slice((SliceExpression)expr);
     if (expr is ConstantExpression && ((ConstantExpression)expr).Value == PythonOps.Ellipsis)
         return Ellipsis.Instance;
     if (expr is TupleExpression && ((TupleExpression)expr).IsExpandable)
         return new ExtSlice(((Tuple)Convert(expr)).elts);
     return null;
 }
Ejemplo n.º 56
0
 public AstProperty(string comment, IReadOnlyList <AstAttribute> attrs, Modifiers modifiers, string cond, AstExpression dataType, AstExpression optionalInterfaceType, AstIdentifier name, AstAccessor get, AstAccessor set)
     : base(comment, attrs, modifiers, cond, dataType, name)
 {
     OptionalInterfaceType = optionalInterfaceType;
     Get = get;
     Set = set;
 }
Ejemplo n.º 57
0
 internal AndExpression(AstExpression left_child, AstExpression right_child) {
     this.left_child = left_child;
     this.right_child = right_child;
 }
Ejemplo n.º 58
0
 public static AstExpression WithILRanges(this AstExpression expr, IEnumerable <InstructionRange> ilranges)
 {
     expr.ILRanges.AddRange(ilranges);
     return(expr);
 }
Ejemplo n.º 59
0
        public string Resolve(AstExpression expr)
        {
            if (expr is AstMathExpression || expr is AstIntegerValueExpression)
            {
                return BuiltInTypes.INT;
            }
            else if (expr is AstBoolValueExpression || expr is AstBoolExpression)
            {
                return BuiltInTypes.BOOL;
            }
            else if (expr is AstIdArrayExpression)
            {
                return BuiltInTypes.INT;
            }
            else if (expr is AstIntegerListExpression)
            {
                return BuiltInTypes.INT;
            }
            else if (expr is AstIdExpression)
            {
                var s = table.Lookup((expr as AstIdExpression).Id);

                if (s != null && Symbol.IsArray(s))
                {
                    return BuiltInTypes.INT_ARRAY;
                }

                return GetSymbolType(expr, s, (expr as AstIdExpression).Id);
            }
            else if (expr is AstThisMethodCallExpression)
            {
                var key = (expr as AstThisMethodCallExpression).Name.Id;
                var s = table.LookupFunction(key);
                return GetSymbolType(expr, s, (expr as AstThisMethodCallExpression).Name.Id);
            }
            else if (expr is AstExternalMethodCallExpression)
            {
                var key = (expr as AstExternalMethodCallExpression).Target.Id + (expr as AstExternalMethodCallExpression).Name.Id;
                var s = table.LookupFunction(key);
                return GetSymbolType(expr, s, (expr as AstExternalMethodCallExpression).Target.Id + "." + (expr as AstExternalMethodCallExpression).Name.Id);
            }
            else if (expr is AstNegateUnaryExpr)
            {
                return BuiltInTypes.INT;
            }
            else if (expr is AstSimpleUnaryExpr)
            {
                return this.Resolve((expr as AstSimpleUnaryExpr).SimpleTerm);
            }
            else if (expr is AstSimpleTermExpr)
            {
                return this.Resolve((expr as AstSimpleTermExpr).Expr);
            }
            else if (expr is AstArrayIndex)
            {
                return this.Resolve((expr as AstArrayIndex).Expr);
            }
            else if (expr is AstExpressionList)
            {
                bool result = (expr as AstExpressionList).Expr.All(s => string.Equals(Resolve(s), "int"));
                if (!result)
                    return "error";
                else
                    return BuiltInTypes.INT;
            }
            else if (expr is AstStringLiteralExpression)
            {
                return BuiltInTypes.STRING;
            }
            else if (expr is AstComparison)
            {
                return BuiltInTypes.BOOL;
            }
            else
            {
                throw new Exception("Unknown expression type.");
            }
        }
Ejemplo n.º 60
0
        /// <summary>
        /// Convert the given node to a array creation operation with given element type and argument.
        /// </summary>
        private static void ConvertToByRefArray(AstExpression node, XTypeReference elementType, AstExpression argument, AstExpression storeArgument, bool isOut, bool argIsGenParam, XModule assembly)
        {
            var arrayElementType = argIsGenParam ? assembly.TypeSystem.Object : elementType;

            if (argIsGenParam && ((!isOut) || (elementType == null) || !elementType.IsSame(argument.GetResultType())))
            {
                argument = new AstExpression(node.SourceLocation, AstCode.Box, elementType, argument);
            }

            node.Code         = isOut ? AstCode.ByRefOutArray : AstCode.ByRefArray;
            node.Operand      = arrayElementType;
            node.InferredType = new XByReferenceType(arrayElementType);
            node.ExpectedType = new XByReferenceType(arrayElementType);
            node.Arguments.Clear();
            node.Arguments.Add(argument);
            node.StoreByRefExpression = storeArgument;
        }