IsPromotableTo() static private method

static private IsPromotableTo ( IReflect source_ir, IReflect target_ir ) : bool
source_ir IReflect
target_ir IReflect
return bool
Example #1
0
        internal override IReflect InferType(JSField inference_target)
        {
            MethodInfo oper;

            if (this.type1 == null || inference_target != null)
            {
                oper = this.GetOperator(this.operand1.InferType(inference_target), this.operand2.InferType(inference_target));
            }
            else
            {
                oper = this.GetOperator(this.type1, this.type2);
            }
            if (oper != null)
            {
                this.metaData = oper;
                return(oper.ReturnType);
            }
            if (this.type1 == Typeob.String || this.type2 == Typeob.String)
            {
                return(Typeob.String);
            }
            if (Convert.IsPrimitiveNumericType(this.type1))
            {
                if (Convert.IsPromotableTo(this.type2, this.type1) || ((this.operand2 is ConstantWrapper) && ((ConstantWrapper)this.operand2).IsAssignableTo(this.type1)))
                {
                    return(this.type1);
                }
                else if (Convert.IsPrimitiveNumericType(this.type1) && Convert.IsPrimitiveNumericTypeFitForDouble(this.type2))
                {
                    return(Typeob.Double);
                }
            }
            return(Typeob.Object);
        }
Example #2
0
 internal void SetInferredType(IReflect ir, AST expr)
 {
     this.isDefined = true;
     if (this.type != null)
     {
         return; //The local variable has a type annotation.
     }
     if (this.outerField != null)
     {
         this.outerField.SetInferredType(ir, expr);
         return;
     }
     if (Convert.IsPrimitiveNumericType(ir))
     {
         ir = Typeob.Double;
     }
     else if (ir == Typeob.Void)
     {
         ir = Typeob.Object;
     }
     if (this.inferred_type == null)
     {
         this.inferred_type = ir;
     }
     else
     {
         //Check to see if ir is compatible with this.inferred_type. If not, generalize this.inferred_type to Object and invalidate dependants.
         if (ir == this.inferred_type)
         {
             return;
         }
         if (!Convert.IsPrimitiveNumericType(this.inferred_type) || !Convert.IsPrimitiveNumericType(ir) ||
             !Convert.IsPromotableTo(ir, this.inferred_type))
         {
             this.inferred_type = Typeob.Object;
             if (this.dependents != null) //Some other fields have had their inferred types set to something or other, based on this field's inferred type
                                          //Since the inference for this field proved wrong, the inferences for the other fields might be wrong as well.
             {
                 for (int i = 0, n = this.dependents.Count; i < n; i++)
                 {
                     ((JSLocalField)this.dependents[i]).SetInferredType(Typeob.Object, null);
                 }
             }
         }
     }
 }
 internal void SetInferredType(IReflect ir, AST expr)
 {
     this.isDefined = true;
     if (this.type != null)
     {
         return; //The local variable has a type annotation.
     }
     if (this.outerField != null)
     {
         this.outerField.SetInferredType(ir, expr);
         return;
     }
     if (Convert.IsPrimitiveNumericTypeFitForDouble(ir))
     {
         ir = Typeob.Double;
     }
     else if (ir == Typeob.Void)
     {
         ir = Typeob.Object;
     }
     if (this.inferred_type == null)
     {
         this.inferred_type = ir;
     }
     else
     {
         //Check to see if ir is compatible with this.inferred_type. If not, generalize this.inferred_type to Object and invalidate dependants.
         if (ir == this.inferred_type)
         {
             return;
         }
         if (!Convert.IsPrimitiveNumericType(this.inferred_type) || !Convert.IsPrimitiveNumericType(ir) ||
             !Convert.IsPromotableTo(ir, this.inferred_type))
         {
             this.inferred_type = Typeob.Object;
             if (this.dependents != null)
             {
                 for (int i = 0, n = this.dependents.Count; i < n; i++)
                 {
                     ((JSLocalField)this.dependents[i]).SetInferredType(Typeob.Object, null);
                 }
             }
         }
     }
 }
Example #4
0
        internal override IReflect InferType(JSField inference_target)
        {
            Debug.Assert(Globals.TypeRefs.InReferenceContext(this.type1));
            Debug.Assert(Globals.TypeRefs.InReferenceContext(this.type2));
            MethodInfo oper;

            if (this.type1 == null || inference_target != null)
            {
                oper = this.GetOperator(this.operand1.InferType(inference_target), this.operand2.InferType(inference_target));
            }
            else
            {
                oper = this.GetOperator(this.type1, this.type2);
            }
            if (oper != null)
            {
                this.metaData = oper;
                return(oper.ReturnType);
            }
            if (this.type1 == Typeob.Char && this.operatorTok == JSToken.Minus)
            {
                TypeCode t2 = Type.GetTypeCode(this.type2);
                if (Convert.IsPrimitiveNumericTypeCode(t2) || t2 == TypeCode.Boolean)
                {
                    return(Typeob.Char);
                }
                else if (t2 == TypeCode.Char)
                {
                    return(Typeob.Int32);
                }
            }
            if (Convert.IsPrimitiveNumericType(this.type1))
            {
                if (Convert.IsPromotableTo(this.type2, this.type1) || ((this.operand2 is ConstantWrapper) && ((ConstantWrapper)this.operand2).IsAssignableTo(this.type1)))
                {
                    return(this.type1);
                }
                else if (Convert.IsPrimitiveNumericType(this.type1) && Convert.IsPrimitiveNumericTypeFitForDouble(this.type2))
                {
                    return(Typeob.Double);
                }
            }
            return(Typeob.Object);
        }
Example #5
0
        internal bool IsPromotableTo(Type other)
        {
            Type st = this.GetBakedSuperType();

            if (other.IsAssignableFrom(st))
            {
                return(true);
            }
            if (other.IsInterface && this.ImplementsInterface(other))
            {
                return(true);
            }
            EnumDeclaration ed = this.owner as EnumDeclaration;

            if (ed != null && Convert.IsPromotableTo(ed.baseType.ToType(), other))
            {
                return(true);
            }
            return(false);
        }
Example #6
0
        internal override void TranslateToConditionalBranch(ILGenerator il, bool branchIfTrue, Label label, bool shortForm)
        {
            Type t1 = this.type1;
            Type t2 = this.type2;
            Type t3 = Typeob.Object;

            if (t1.IsPrimitive && t2.IsPrimitive)
            {
                t3 = Typeob.Double;
                if (Convert.IsPromotableTo(t1, t2))
                {
                    t3 = t2;
                }
                else if (Convert.IsPromotableTo(t2, t1))
                {
                    t3 = t1;
                }
                else if (t1 == Typeob.Int64 || t1 == Typeob.UInt64 || t2 == Typeob.Int64 || t2 == Typeob.UInt64)
                {
                    t3 = Typeob.Object; //Cannot convert these to double without loss of precision in some cases, so use the helper method
                }
            }
            if (t3 == Typeob.SByte || t3 == Typeob.Int16)
            {
                t3 = Typeob.Int32;
            }
            else if (t3 == Typeob.Byte || t3 == Typeob.UInt16)
            {
                t3 = Typeob.UInt32;
            }
            if (this.metaData == null)
            {
                this.operand1.TranslateToIL(il, t3);
                this.operand2.TranslateToIL(il, t3);
                if (t3 == Typeob.Object)
                {
                    il.Emit(OpCodes.Call, CompilerGlobals.jScriptCompareMethod);
                    il.Emit(OpCodes.Ldc_I4_0);
                    il.Emit(OpCodes.Conv_R8);
                    t3 = Typeob.Double;
                }
            }
            else if (this.metaData is MethodInfo)
            {
                MethodInfo      oper = (MethodInfo)this.metaData;
                ParameterInfo[] pars = oper.GetParameters();
                this.operand1.TranslateToIL(il, pars[0].ParameterType);
                this.operand2.TranslateToIL(il, pars[1].ParameterType);
                il.Emit(OpCodes.Call, oper);
                if (branchIfTrue)
                {
                    il.Emit(shortForm ? OpCodes.Brtrue_S : OpCodes.Brtrue, label);
                }
                else
                {
                    il.Emit(shortForm ? OpCodes.Brfalse_S : OpCodes.Brfalse, label);
                }
                return;
            }
            else
            {
                //Getting here is just too bad. We do not know until the code runs whether or not to call an overloaded operator method.
                //Compile operands to objects and devolve the decision making to run time thunks
                il.Emit(OpCodes.Ldloc, (LocalBuilder)this.metaData);
                this.operand1.TranslateToIL(il, Typeob.Object);
                this.operand2.TranslateToIL(il, Typeob.Object);
                il.Emit(OpCodes.Call, CompilerGlobals.evaluateRelationalMethod);
                il.Emit(OpCodes.Ldc_I4_0);
                il.Emit(OpCodes.Conv_R8);
                t3 = Typeob.Double;
            }
            if (branchIfTrue)
            {
                if (t3 == Typeob.UInt32 || t3 == Typeob.UInt64)
                {
                    switch (this.operatorTok)
                    {
                    case JSToken.GreaterThan:
                        il.Emit(shortForm ? OpCodes.Bgt_Un_S : OpCodes.Bgt_Un, label); break;

                    case JSToken.GreaterThanEqual:
                        il.Emit(shortForm ? OpCodes.Bge_Un_S : OpCodes.Bge_Un, label); break;

                    case JSToken.LessThan:
                        il.Emit(shortForm ? OpCodes.Blt_Un_S : OpCodes.Blt_Un, label); break;

                    case JSToken.LessThanEqual:
                        il.Emit(shortForm ? OpCodes.Ble_Un_S : OpCodes.Ble_Un, label); break;

                    default:
                        throw new JScriptException(JSError.InternalError, this.context);
                    }
                }
                else
                {
                    switch (this.operatorTok)
                    {
                    case JSToken.GreaterThan:
                        il.Emit(shortForm ? OpCodes.Bgt_S : OpCodes.Bgt, label); break;

                    case JSToken.GreaterThanEqual:
                        il.Emit(shortForm ? OpCodes.Bge_S : OpCodes.Bge, label); break;

                    case JSToken.LessThan:
                        il.Emit(shortForm ? OpCodes.Blt_S : OpCodes.Blt, label); break;

                    case JSToken.LessThanEqual:
                        il.Emit(shortForm ? OpCodes.Ble_S : OpCodes.Ble, label); break;

                    default:
                        throw new JScriptException(JSError.InternalError, this.context);
                    }
                }
            }
            else
            {
                if (t3 == Typeob.Int32 || t3 == Typeob.Int64)
                {
                    switch (this.operatorTok)
                    {
                    case JSToken.GreaterThan:
                        il.Emit(shortForm ? OpCodes.Ble_S : OpCodes.Ble, label); break;

                    case JSToken.GreaterThanEqual:
                        il.Emit(shortForm ? OpCodes.Blt_S : OpCodes.Blt, label); break;

                    case JSToken.LessThan:
                        il.Emit(shortForm ? OpCodes.Bge_S : OpCodes.Bge, label); break;

                    case JSToken.LessThanEqual:
                        il.Emit(shortForm ? OpCodes.Bgt_S : OpCodes.Bgt, label); break;

                    default:
                        throw new JScriptException(JSError.InternalError, this.context);
                    }
                }
                else
                {
                    switch (this.operatorTok)
                    {
                    case JSToken.GreaterThan:
                        il.Emit(shortForm ? OpCodes.Ble_Un_S : OpCodes.Ble_Un, label); break;

                    case JSToken.GreaterThanEqual:
                        il.Emit(shortForm ? OpCodes.Blt_Un_S : OpCodes.Blt_Un, label); break;

                    case JSToken.LessThan:
                        il.Emit(shortForm ? OpCodes.Bge_Un_S : OpCodes.Bge_Un, label); break;

                    case JSToken.LessThanEqual:
                        il.Emit(shortForm ? OpCodes.Bgt_Un_S : OpCodes.Bgt_Un, label); break;

                    default:
                        throw new JScriptException(JSError.InternalError, this.context);
                    }
                }
            }
        }
Example #7
0
        internal void TranslateToConditionalBranch(ILGenerator il, Type etype, bool branchIfTrue, Label label, bool shortForm)
        {
            Debug.PreCondition(this.case_value != null);
            Type t1 = etype;
            Type t2 = Convert.ToType(this.case_value.InferType(null));

            if (t1 != t2 && t1.IsPrimitive && t2.IsPrimitive)
            {
                if (t1 == Typeob.Single && t2 == Typeob.Double)
                {
                    t2 = Typeob.Single;
                }
                else if (Convert.IsPromotableTo(t2, t1))
                {
                    t2 = t1;
                }
                else if (Convert.IsPromotableTo(t1, t2))
                {
                    t1 = t2;
                }
            }
            bool nonPrimitive = true;

            if (t1 == t2 && t1 != Typeob.Object)
            {
                Convert.Emit(this, il, etype, t1);
                if (!t1.IsPrimitive && t1.IsValueType)
                {
                    il.Emit(OpCodes.Box, t1);
                }
                this.case_value.context.EmitLineInfo(il);
                this.case_value.TranslateToIL(il, t1);
                if (t1 == Typeob.String)
                {
                    il.Emit(OpCodes.Call, CompilerGlobals.stringEqualsMethod);
                }
                else if (!t1.IsPrimitive)
                {
                    if (t1.IsValueType)
                    {
                        il.Emit(OpCodes.Box, t1);
                    }
                    il.Emit(OpCodes.Callvirt, CompilerGlobals.equalsMethod);
                }
                else
                {
                    nonPrimitive = false;
                }
            }
            else
            {
                Convert.Emit(this, il, etype, Typeob.Object);
                this.case_value.context.EmitLineInfo(il);
                this.case_value.TranslateToIL(il, Typeob.Object);
                il.Emit(OpCodes.Call, CompilerGlobals.jScriptStrictEqualsMethod);
            }
            if (branchIfTrue)
            {
                if (nonPrimitive)
                {
                    il.Emit(shortForm ? OpCodes.Brtrue_S : OpCodes.Brtrue, label);
                }
                else
                {
                    il.Emit(shortForm ? OpCodes.Beq_S : OpCodes.Beq, label);
                }
            }
            else
            {
                if (nonPrimitive)
                {
                    il.Emit(shortForm ? OpCodes.Brfalse_S : OpCodes.Brfalse, label);
                }
                else
                {
                    il.Emit(shortForm ? OpCodes.Bne_Un_S : OpCodes.Bne_Un, label);
                }
            }
        }
Example #8
0
        private void TranslateToILForNoOverloadCase(ILGenerator il, Type rtype)
        {
            Type type = Convert.ToType(this.operand.InferType(null));

            this.operand.TranslateToILPreSetPlusGet(il);
            if (rtype == Typeob.Void)
            {
                Type rt = Typeob.Double;
                if (Convert.IsPrimitiveNumericType(type))
                {
                    if (type == Typeob.SByte || type == Typeob.Int16)
                    {
                        rt = Typeob.Int32;
                    }
                    else if (type == Typeob.Byte || type == Typeob.UInt16 || type == Typeob.Char)
                    {
                        rt = Typeob.UInt32;
                    }
                    else
                    {
                        rt = type;
                    }
                }
                Convert.Emit(this, il, type, rt);
                il.Emit(OpCodes.Ldc_I4_1);
                Convert.Emit(this, il, Typeob.Int32, rt);
                if (rt == Typeob.Double || rt == Typeob.Single)
                {
                    if (this.operatorTok == PostOrPrefix.PostfixDecrement || this.operatorTok == PostOrPrefix.PrefixDecrement)
                    {
                        il.Emit(OpCodes.Sub);
                    }
                    else
                    {
                        il.Emit(OpCodes.Add);
                    }
                }
                else if (rt == Typeob.Int32 || rt == Typeob.Int64)
                {
                    if (this.operatorTok == PostOrPrefix.PostfixDecrement || this.operatorTok == PostOrPrefix.PrefixDecrement)
                    {
                        il.Emit(OpCodes.Sub_Ovf);
                    }
                    else
                    {
                        il.Emit(OpCodes.Add_Ovf);
                    }
                }
                else
                {
                    if (this.operatorTok == PostOrPrefix.PostfixDecrement || this.operatorTok == PostOrPrefix.PrefixDecrement)
                    {
                        il.Emit(OpCodes.Sub_Ovf_Un);
                    }
                    else
                    {
                        il.Emit(OpCodes.Add_Ovf_Un);
                    }
                }
                Convert.Emit(this, il, rt, type);
                this.operand.TranslateToILSet(il);
            }
            else
            {
                //set rt to be the smallest type that is precise enough for the result and the variable
                Type rt = Typeob.Double;
                if (Convert.IsPrimitiveNumericType(rtype) && Convert.IsPromotableTo(type, rtype))
                {
                    rt = rtype;
                }
                else if (Convert.IsPrimitiveNumericType(type) && Convert.IsPromotableTo(rtype, type))
                {
                    rt = type;
                }
                if (rt == Typeob.SByte || rt == Typeob.Int16)
                {
                    rt = Typeob.Int32;
                }
                else if (rt == Typeob.Byte || rt == Typeob.UInt16 || rt == Typeob.Char)
                {
                    rt = Typeob.UInt32;
                }
                LocalBuilder result = il.DeclareLocal(rtype);
                Convert.Emit(this, il, type, rt);
                if (this.operatorTok == PostOrPrefix.PostfixDecrement)
                {
                    il.Emit(OpCodes.Dup);
                    if (type == Typeob.Char)
                    {
                        Convert.Emit(this, il, rt, Typeob.Char);
                        Convert.Emit(this, il, Typeob.Char, rtype);
                    }
                    else
                    {
                        Convert.Emit(this, il, rt, rtype);
                    }
                    il.Emit(OpCodes.Stloc, result);
                    il.Emit(OpCodes.Ldc_I4_1);
                    Convert.Emit(this, il, Typeob.Int32, rt);
                    if (rt == Typeob.Double || rt == Typeob.Single)
                    {
                        il.Emit(OpCodes.Sub);
                    }
                    else if (rt == Typeob.Int32 || rt == Typeob.Int64)
                    {
                        il.Emit(OpCodes.Sub_Ovf);
                    }
                    else
                    {
                        il.Emit(OpCodes.Sub_Ovf_Un);
                    }
                }
                else if (this.operatorTok == PostOrPrefix.PostfixIncrement)
                {
                    il.Emit(OpCodes.Dup);
                    if (type == Typeob.Char)
                    {
                        Convert.Emit(this, il, rt, Typeob.Char);
                        Convert.Emit(this, il, Typeob.Char, rtype);
                    }
                    else
                    {
                        Convert.Emit(this, il, rt, rtype);
                    }
                    il.Emit(OpCodes.Stloc, result);
                    il.Emit(OpCodes.Ldc_I4_1);
                    Convert.Emit(this, il, Typeob.Int32, rt);
                    if (rt == Typeob.Double || rt == Typeob.Single)
                    {
                        il.Emit(OpCodes.Add);
                    }
                    else if (rt == Typeob.Int32 || rt == Typeob.Int64)
                    {
                        il.Emit(OpCodes.Add_Ovf);
                    }
                    else
                    {
                        il.Emit(OpCodes.Add_Ovf_Un);
                    }
                }
                else if (this.operatorTok == PostOrPrefix.PrefixDecrement)
                {
                    il.Emit(OpCodes.Ldc_I4_1);
                    Convert.Emit(this, il, Typeob.Int32, rt);
                    if (rt == Typeob.Double || rt == Typeob.Single)
                    {
                        il.Emit(OpCodes.Sub);
                    }
                    else if (rt == Typeob.Int32 || rt == Typeob.Int64)
                    {
                        il.Emit(OpCodes.Sub_Ovf);
                    }
                    else
                    {
                        il.Emit(OpCodes.Sub_Ovf_Un);
                    }
                    il.Emit(OpCodes.Dup);
                    if (type == Typeob.Char)
                    {
                        Convert.Emit(this, il, rt, Typeob.Char);
                        Convert.Emit(this, il, Typeob.Char, rtype);
                    }
                    else
                    {
                        Convert.Emit(this, il, rt, rtype);
                    }
                    il.Emit(OpCodes.Stloc, result);
                }
                else //if (this.operatorTok == PostOrPrefix.PrefixIncrement)
                {
                    il.Emit(OpCodes.Ldc_I4_1);
                    Convert.Emit(this, il, Typeob.Int32, rt);
                    if (rt == Typeob.Double || rt == Typeob.Single)
                    {
                        il.Emit(OpCodes.Add);
                    }
                    else if (rt == Typeob.Int32 || rt == Typeob.Int64)
                    {
                        il.Emit(OpCodes.Add_Ovf);
                    }
                    else
                    {
                        il.Emit(OpCodes.Add_Ovf_Un);
                    }
                    il.Emit(OpCodes.Dup);
                    if (type == Typeob.Char)
                    {
                        Convert.Emit(this, il, rt, Typeob.Char);
                        Convert.Emit(this, il, Typeob.Char, rtype);
                    }
                    else
                    {
                        Convert.Emit(this, il, rt, rtype);
                    }
                    il.Emit(OpCodes.Stloc, result);
                }
                Convert.Emit(this, il, rt, type);
                this.operand.TranslateToILSet(il);
                il.Emit(OpCodes.Ldloc, result);
            }
        }
Example #9
0
        internal override void TranslateToIL(ILGenerator il, Type rtype)
        {
            if (this.metaData == null)
            {
                Type rt = this.operatorTok == JSToken.LogicalNot ? Typeob.Boolean : Typeob.Double;
                if (Convert.IsPrimitiveNumericType(rtype) && Convert.IsPromotableTo(this.type, rtype))
                {
                    rt = rtype;
                }
                if (this.operatorTok == JSToken.BitwiseNot && !Convert.IsPrimitiveIntegerType(rt))
                {
                    rt = this.type;
                    if (!Convert.IsPrimitiveIntegerType(rt))
                    {
                        rt = Typeob.Int32;
                    }
                }
                this.operand.TranslateToIL(il, this.type);
                Convert.Emit(this, il, this.type, rt, true);
                switch (this.operatorTok)
                {
                case JSToken.BitwiseNot:
                    il.Emit(OpCodes.Not);
                    break;

                case JSToken.LogicalNot:
                    Convert.Emit(this, il, rt, Typeob.Boolean, true);
                    rt = Typeob.Boolean;
                    il.Emit(OpCodes.Ldc_I4_0);
                    il.Emit(OpCodes.Ceq);
                    break;

                case JSToken.Minus:
                    il.Emit(OpCodes.Neg);
                    break;

                case JSToken.Plus:
                    break;

                default:
                    throw new JScriptException(JSError.InternalError, this.context);
                }
                Convert.Emit(this, il, rt, rtype);
                return;
            }
            if (this.metaData is MethodInfo)
            {
                MethodInfo      oper = (MethodInfo)this.metaData;
                ParameterInfo[] pars = oper.GetParameters();
                this.operand.TranslateToIL(il, pars[0].ParameterType);
                il.Emit(OpCodes.Call, oper);
                Convert.Emit(this, il, oper.ReturnType, rtype);
                return;
            }
            //Getting here is just too bad. We do not know until the code runs whether or not to call an overloaded operator method.
            //Compile operands to objects and devolve the decision making to run time thunks
            il.Emit(OpCodes.Ldloc, (LocalBuilder)this.metaData);
            this.operand.TranslateToIL(il, Typeob.Object);
            il.Emit(OpCodes.Call, CompilerGlobals.evaluateUnaryMethod);
            Convert.Emit(this, il, Typeob.Object, rtype);
        }
Example #10
0
        internal override AST PartiallyEvaluate()
        {
            this.ctor = this.ctor.PartiallyEvaluateAsCallable();

            //first weed out assignment expressions and use them as property initializers
            ASTList positionalArgs = new ASTList(this.args.context);
            ASTList namedArgs      = new ASTList(this.args.context);

            for (int i = 0, m = this.args.count; i < m; i++)
            {
                AST    arg    = this.args[i];
                Assign assign = arg as Assign;
                if (assign != null)
                {
                    assign.rhside = assign.rhside.PartiallyEvaluate();
                    namedArgs.Append(assign);
                }
                else
                {
                    positionalArgs.Append(arg.PartiallyEvaluate());
                }
            }

            int n = positionalArgs.count;

            IReflect[] argIRs = new IReflect[n];
            for (int i = 0; i < n; i++)
            {
                AST arg = positionalArgs[i];
                // only accept ConstantWrappers
                if (arg is ConstantWrapper)
                {
                    Object argument = arg.Evaluate();
                    if ((argIRs[i] = CustomAttribute.TypeOfArgument(argument)) != null)
                    {
                        this.positionalArgValues.Add(argument);
                        continue;
                    }
                }
                else if (arg is ArrayLiteral && ((ArrayLiteral)arg).IsOkToUseInCustomAttribute())
                {
                    argIRs[i] = Typeob.ArrayObject;
                    this.positionalArgValues.Add(arg.Evaluate());
                    continue;
                }
                arg.context.HandleError(JSError.InvalidCustomAttributeArgument);
                return(null); // the custom attribute is not good and it will be ignored
            }

            //Get the custom attribute and the appropriate constructor (under the covers)
            this.type = this.ctor.ResolveCustomAttribute(positionalArgs, argIRs, this.target);
            if (this.type == null)
            {
                return(null);
            }
            if (Convert.IsPromotableTo((IReflect)this.type, typeof(CodeAccessSecurityAttribute)))
            {
                this.context.HandleError(JSError.CannotUseStaticSecurityAttribute);
                return(null);
            }


            //Coerce the positional arguments to the right type and supply default values for optional parameters
            ConstructorInfo c = (ConstructorInfo)((Binding)this.ctor).member;

            ParameterInfo[] parameters = c.GetParameters();
            int             j          = 0;
            int             len        = this.positionalArgValues.Count;

            foreach (ParameterInfo p in parameters)
            {
                IReflect ir = p is ParameterDeclaration ? ((ParameterDeclaration)p).ParameterIReflect : p.ParameterType;
                if (j < len)
                {
                    Object value = this.positionalArgValues[j];
                    this.positionalArgValues[j] = Convert.Coerce(value, ir, value is ArrayObject);
                    j++;
                }
                else
                {
                    Object value;
                    if (p.DefaultValue == System.Convert.DBNull)
                    {
                        value = Convert.Coerce(null, ir);
                    }
                    else
                    {
                        value = p.DefaultValue;
                    }
                    this.positionalArgValues.Add(value);
                }
            }

            //Check validity of property/field initializers
            for (int i = 0, m = namedArgs.count; i < m; i++)
            {
                Assign assign = (Assign)namedArgs[i];
                if (assign.lhside is Lookup &&
                    (assign.rhside is ConstantWrapper ||
                     (assign.rhside is ArrayLiteral && ((ArrayLiteral)assign.rhside).IsOkToUseInCustomAttribute())))
                {
                    Object   value   = assign.rhside.Evaluate();
                    IReflect argType = null;
                    if (value is ArrayObject || ((argType = CustomAttribute.TypeOfArgument(value)) != null && argType != Typeob.Object))
                    {
                        String        name    = ((Lookup)assign.lhside).Name;
                        MemberInfo [] members = ((IReflect)this.type).GetMember(name, BindingFlags.Public | BindingFlags.Instance);
                        if (members == null || members.Length == 0)
                        {
                            assign.context.HandleError(JSError.NoSuchMember);
                            return(null);
                        }
                        if (members.Length == 1)
                        {
                            MemberInfo member = members[0];
                            if (member is FieldInfo)
                            {
                                FieldInfo fieldInfo = (FieldInfo)member;
                                if (!fieldInfo.IsLiteral && !fieldInfo.IsInitOnly)
                                {
                                    try{
                                        IReflect ir = fieldInfo is JSVariableField ? ((JSVariableField)fieldInfo).GetInferredType(null) : fieldInfo.FieldType;
                                        value = Convert.Coerce(value, ir, value is ArrayObject);
                                        this.namedArgFields.Add(member);
                                        this.namedArgFieldValues.Add(value);
                                        continue;
                                    }catch (JScriptException) {
                                        assign.rhside.context.HandleError(JSError.TypeMismatch);
                                        return(null); // the custom attribute is not good and it will be ignored
                                    }
                                }
                            }
                            else if (member is PropertyInfo)
                            {
                                PropertyInfo propertyInfo  = (PropertyInfo)member;
                                MethodInfo   setMethodInfo = JSProperty.GetSetMethod(propertyInfo, false);
                                if (setMethodInfo != null)
                                {
                                    ParameterInfo [] paramInfo = setMethodInfo.GetParameters();
                                    if (paramInfo != null && paramInfo.Length == 1)
                                    {
                                        try{
                                            IReflect ir = paramInfo[0] is ParameterDeclaration ? ((ParameterDeclaration)paramInfo[0]).ParameterIReflect : paramInfo[0].ParameterType;
                                            value = Convert.Coerce(value, ir, value is ArrayObject);
                                            this.namedArgProperties.Add(member);
                                            this.namedArgPropertyValues.Add(value);
                                        }catch (JScriptException) {
                                            assign.rhside.context.HandleError(JSError.TypeMismatch);
                                            return(null); // the custom attribute is not good and it will be ignored
                                        }
                                        continue;
                                    }
                                }
                            }
                        }
                    }
                }
                assign.context.HandleError(JSError.InvalidCustomAttributeArgument);
                return(null);
            }

            if (!this.CheckIfTargetOK(this.type))
            {
                return(null); //Ignore attribute
            }
            //Consume and discard assembly name attributes
            try{
                Type ty = this.type as Type;
                if (ty != null && this.target is AssemblyCustomAttributeList)
                {
                    if (ty.FullName == "System.Reflection.AssemblyAlgorithmIdAttribute")
                    {
                        if (this.positionalArgValues.Count > 0)
                        {
                            this.Engine.Globals.assemblyHashAlgorithm = (AssemblyHashAlgorithm)Convert.CoerceT(this.positionalArgValues[0], typeof(AssemblyHashAlgorithm));
                        }
                        return(null);
                    }
                    if (ty.FullName == "System.Reflection.AssemblyCultureAttribute")
                    {
                        if (this.positionalArgValues.Count > 0)
                        {
                            String cultureId = Convert.ToString(this.positionalArgValues[0]);
                            if (this.Engine.PEFileKind != PEFileKinds.Dll && cultureId.Length > 0)
                            {
                                this.context.HandleError(JSError.ExecutablesCannotBeLocalized);
                                return(null);
                            }
                            this.Engine.Globals.assemblyCulture = new CultureInfo(cultureId);
                        }
                        return(null);
                    }
                    if (ty.FullName == "System.Reflection.AssemblyDelaySignAttribute")
                    {
                        if (this.positionalArgValues.Count > 0)
                        {
                            this.Engine.Globals.assemblyDelaySign = Convert.ToBoolean(this.positionalArgValues[0], false);
                        }
                        return(null);
                    }
                    if (ty.FullName == "System.Reflection.AssemblyFlagsAttribute")
                    {
                        if (this.positionalArgValues.Count > 0)
                        {
                            this.Engine.Globals.assemblyFlags = (AssemblyFlags)(uint)Convert.CoerceT(this.positionalArgValues[0], typeof(uint));
                        }
                        return(null);
                    }
                    if (ty.FullName == "System.Reflection.AssemblyKeyFileAttribute")
                    {
                        if (this.positionalArgValues.Count > 0)
                        {
                            this.Engine.Globals.assemblyKeyFileName = Convert.ToString(this.positionalArgValues[0]);
                            if (this.Engine.Globals.assemblyKeyFileName != null && this.Engine.Globals.assemblyKeyFileName.Length == 0)
                            {
                                this.Engine.Globals.assemblyKeyFileName = null;
                            }
                        }
                        return(null);
                    }
                    if (ty.FullName == "System.Reflection.AssemblyKeyNameAttribute")
                    {
                        if (this.positionalArgValues.Count > 0)
                        {
                            this.Engine.Globals.assemblyKeyName = Convert.ToString(this.positionalArgValues[0]);
                            if (this.Engine.Globals.assemblyKeyName != null && this.Engine.Globals.assemblyKeyName.Length == 0)
                            {
                                this.Engine.Globals.assemblyKeyName = null;
                            }
                        }
                        return(null);
                    }
                    if (ty.FullName == "System.Reflection.AssemblyVersionAttribute")
                    {
                        if (this.positionalArgValues.Count > 0)
                        {
                            this.Engine.Globals.assemblyVersion = this.ParseVersion(Convert.ToString(this.positionalArgValues[0]));
                        }
                        return(null);
                    }
                    if (ty.FullName == "System.CLSCompliantAttribute")
                    {
                        this.Engine.isCLSCompliant = this.args == null || this.args.count == 0 || Convert.ToBoolean(this.positionalArgValues[0], false);
                        return(this);
                    }
                }
            }catch (ArgumentException) {
                this.context.HandleError(JSError.InvalidCall);
            }

            return(this);
        }
Example #11
0
        private void TranslateToILForNoOverloadCase(ILGenerator il, Type rtype)
        {
            Type lhtype = Convert.ToType(this.operand1.InferType(null));
            Type rhtype = Convert.ToType(this.operand2.InferType(null));
            Type rt     = Typeob.Double;

            if (this.operatorTok != JSToken.Divide && (rtype == Typeob.Void || rtype == lhtype || Convert.IsPrimitiveNumericType(lhtype)) &&
                (Convert.IsPromotableTo(rhtype, lhtype) || ((this.operand2 is ConstantWrapper) && ((ConstantWrapper)this.operand2).IsAssignableTo(lhtype))))
            {
                rt = lhtype;
            }
            if (rt == Typeob.SByte || rt == Typeob.Int16)
            {
                rt = Typeob.Int32;
            }
            else if (rt == Typeob.Byte || rt == Typeob.UInt16 || rt == Typeob.Char)
            {
                rt = Typeob.UInt32;
            }

            // If we have "unsigned -= signed" or "signed -= unsigned" then generating the
            // correct code gets quite complicated.  Just go late-bound for this edge case.
            if (this.operand2 is ConstantWrapper)
            {
                if (!((ConstantWrapper)this.operand2).IsAssignableTo(rt))
                {
                    // eg: "var u : byte = 123; u -= -100;" should go late bound because
                    // of signed/unsigned mismatch but "u -= 1" should not.
                    rt = Typeob.Object;
                }
            }
            else
            {
                if ((Convert.IsPrimitiveSignedNumericType(rhtype) && Convert.IsPrimitiveUnsignedIntegerType(lhtype)) ||
                    (Convert.IsPrimitiveUnsignedIntegerType(rhtype) && Convert.IsPrimitiveSignedIntegerType(lhtype)))
                {
                    rt = Typeob.Object;
                }
            }

            this.operand1.TranslateToILPreSetPlusGet(il);
            Convert.Emit(this, il, lhtype, rt);
            this.operand2.TranslateToIL(il, rt);
            if (rt == Typeob.Object)
            {
                il.Emit(OpCodes.Ldc_I4, (int)this.operatorTok);
                il.Emit(OpCodes.Call, CompilerGlobals.numericbinaryDoOpMethod);
            }
            else if (rt == Typeob.Double || rt == Typeob.Single)
            {
                switch (this.operatorTok)
                {
                case JSToken.Divide:
                    il.Emit(OpCodes.Div); break;

                case JSToken.Minus:
                    il.Emit(OpCodes.Sub); break;

                case JSToken.Modulo:
                    il.Emit(OpCodes.Rem); break;

                case JSToken.Multiply:
                    il.Emit(OpCodes.Mul); break;

                default:
                    throw new JScriptException(JSError.InternalError, this.context);
                }
            }
            else if (rt == Typeob.Int32 || rt == Typeob.Int64 || rt == Typeob.Int16 || rt == Typeob.SByte)
            {
                switch (this.operatorTok)
                {
                case JSToken.Divide:
                    il.Emit(OpCodes.Div); break;

                case JSToken.Minus:
                    il.Emit(OpCodes.Sub_Ovf); break;

                case JSToken.Modulo:
                    il.Emit(OpCodes.Rem); break;

                case JSToken.Multiply:
                    il.Emit(OpCodes.Mul_Ovf); break;

                default:
                    throw new JScriptException(JSError.InternalError, this.context);
                }
            }
            else
            {
                switch (this.operatorTok)
                {
                case JSToken.Divide:
                    il.Emit(OpCodes.Div); break;

                case JSToken.Minus:
                    il.Emit(OpCodes.Sub_Ovf_Un); break;

                case JSToken.Modulo:
                    il.Emit(OpCodes.Rem); break;

                case JSToken.Multiply:
                    il.Emit(OpCodes.Mul_Ovf_Un); break;

                default:
                    throw new JScriptException(JSError.InternalError, this.context);
                }
            }
            if (rtype != Typeob.Void)
            {
                LocalBuilder result = il.DeclareLocal(rt);
                il.Emit(OpCodes.Dup);
                il.Emit(OpCodes.Stloc, result);
                Convert.Emit(this, il, rt, lhtype);
                this.operand1.TranslateToILSet(il);
                il.Emit(OpCodes.Ldloc, result);
                Convert.Emit(this, il, rt, rtype);
            }
            else
            {
                Convert.Emit(this, il, rt, lhtype);
                this.operand1.TranslateToILSet(il);
            }
        }
Example #12
0
 internal override AST PartiallyEvaluate()
 {
     if (this.alreadyPartiallyEvaluated)
     {
         return(this);
     }
     this.alreadyPartiallyEvaluated = true;
     if (this.inBrackets && this.AllParamsAreMissing())
     {
         if (this.isConstructor)
         {
             this.args.context.HandleError(JSError.TypeMismatch);
         }
         IReflect ir = ((TypeExpression)(new TypeExpression(this.func)).PartiallyEvaluate()).ToIReflect();
         return(new ConstantWrapper(new TypedArray(ir, this.args.count + 1), this.context));
     }
     this.func = this.func.PartiallyEvaluateAsCallable();
     this.args = (ASTList)this.args.PartiallyEvaluate();
     IReflect[] argIRs = this.ArgIRs();
     this.func.ResolveCall(this.args, argIRs, this.isConstructor, this.inBrackets);
     if (!this.isConstructor && !this.inBrackets && this.func is Binding && this.args.count == 1)
     {
         Binding b = (Binding)this.func;
         if (b.member is Type)
         {
             Type            t    = (Type)b.member;
             ConstantWrapper arg0 = this.args[0] as ConstantWrapper;
             if (arg0 != null)
             {
                 try{
                     if (arg0.value == null || arg0.value is DBNull)
                     {
                         return(this);
                     }
                     else if (arg0.isNumericLiteral && (t == Typeob.Decimal || t == Typeob.Int64 || t == Typeob.UInt64 || t == Typeob.Single))
                     {
                         return(new ConstantWrapper(Convert.CoerceT(arg0.context.GetCode(), t, true), this.context));
                     }
                     else
                     {
                         return(new ConstantWrapper(Convert.CoerceT(arg0.Evaluate(), t, true), this.context));
                     }
                 }catch {
                     arg0.context.HandleError(JSError.TypeMismatch);
                 }
             }
             else
             {
                 if (!Binding.AssignmentCompatible(t, this.args[0], argIRs[0], false))
                 {
                     this.args[0].context.HandleError(JSError.ImpossibleConversion);
                 }
             }
         }
         else if (b.member is JSVariableField)
         {
             JSVariableField field = (JSVariableField)b.member;
             if (field.IsLiteral)
             {
                 if (field.value is ClassScope)
                 {
                     ClassScope csc = (ClassScope)field.value;
                     IReflect   ut  = csc.GetUnderlyingTypeIfEnum();
                     if (ut != null)
                     {
                         if (!Convert.IsPromotableTo(argIRs[0], ut) && !Convert.IsPromotableTo(ut, argIRs[0]) && (argIRs[0] != Typeob.String || ut == csc))
                         {
                             this.args[0].context.HandleError(JSError.ImpossibleConversion);
                         }
                     }
                     else
                     {
                         if (!Convert.IsPromotableTo(argIRs[0], csc) && !Convert.IsPromotableTo(csc, argIRs[0]))
                         {
                             this.args[0].context.HandleError(JSError.ImpossibleConversion);
                         }
                     }
                 }
                 else if (field.value is TypedArray)
                 {
                     TypedArray ta = (TypedArray)field.value;
                     if (!Convert.IsPromotableTo(argIRs[0], ta) && !Convert.IsPromotableTo(ta, argIRs[0]))
                     {
                         this.args[0].context.HandleError(JSError.ImpossibleConversion);
                     }
                 }
             }
         }
     }
     return(this);
 }
Example #13
0
        internal override void TranslateToIL(ILGenerator il, Type rtype)
        {
            if (this.metaData == null)
            {
                Type rt = Typeob.Double;
                if (Convert.IsPrimitiveNumericType(rtype) && Convert.IsPromotableTo(this.type1, rtype) && Convert.IsPromotableTo(this.type2, rtype))
                {
                    rt = rtype;
                }
                if (this.operatorTok == JSToken.Divide)
                {
                    rt = Typeob.Double;
                }
                else if (rt == Typeob.SByte || rt == Typeob.Int16)
                {
                    rt = Typeob.Int32;
                }
                else if (rt == Typeob.Byte || rt == Typeob.UInt16 || rt == Typeob.Char)
                {
                    rt = Typeob.UInt32;
                }
                this.operand1.TranslateToIL(il, rt);
                this.operand2.TranslateToIL(il, rt);
                if (rt == Typeob.Double || rt == Typeob.Single)
                {
                    switch (this.operatorTok)
                    {
                    case JSToken.Divide:
                        il.Emit(OpCodes.Div); break;

                    case JSToken.Minus:
                        il.Emit(OpCodes.Sub); break;

                    case JSToken.Modulo:
                        il.Emit(OpCodes.Rem); break;

                    case JSToken.Multiply:
                        il.Emit(OpCodes.Mul); break;

                    default:
                        throw new JScriptException(JSError.InternalError, this.context);
                    }
                }
                else if (rt == Typeob.Int32 || rt == Typeob.Int64)
                {
                    switch (this.operatorTok)
                    {
                    case JSToken.Divide:
                        il.Emit(OpCodes.Div); break;

                    case JSToken.Minus:
                        il.Emit(OpCodes.Sub_Ovf); break;

                    case JSToken.Modulo:
                        il.Emit(OpCodes.Rem); break;

                    case JSToken.Multiply:
                        il.Emit(OpCodes.Mul_Ovf); break;

                    default:
                        throw new JScriptException(JSError.InternalError, this.context);
                    }
                }
                else
                {
                    switch (this.operatorTok)
                    {
                    case JSToken.Divide:
                        il.Emit(OpCodes.Div); break;

                    case JSToken.Minus:
                        il.Emit(OpCodes.Sub_Ovf_Un); break;

                    case JSToken.Modulo:
                        il.Emit(OpCodes.Rem); break;

                    case JSToken.Multiply:
                        il.Emit(OpCodes.Mul_Ovf_Un); break;

                    default:
                        throw new JScriptException(JSError.InternalError, this.context);
                    }
                }
                if (Convert.ToType(this.InferType(null)) == Typeob.Char)
                {
                    Convert.Emit(this, il, rt, Typeob.Char);
                    Convert.Emit(this, il, Typeob.Char, rtype);
                }
                else
                {
                    Convert.Emit(this, il, rt, rtype);
                }
                return;
            }
            if (this.metaData is MethodInfo)
            {
                MethodInfo      oper = (MethodInfo)this.metaData;
                ParameterInfo[] pars = oper.GetParameters();
                this.operand1.TranslateToIL(il, pars[0].ParameterType);
                this.operand2.TranslateToIL(il, pars[1].ParameterType);
                il.Emit(OpCodes.Call, oper);
                Convert.Emit(this, il, oper.ReturnType, rtype);
                return;
            }
            //Getting here is just too bad. We do not know until the code runs whether or not to call an overloaded operator method.
            //Compile operands to objects and devolve the decision making to run time thunks
            il.Emit(OpCodes.Ldloc, (LocalBuilder)this.metaData);
            this.operand1.TranslateToIL(il, Typeob.Object);
            this.operand2.TranslateToIL(il, Typeob.Object);
            il.Emit(OpCodes.Call, CompilerGlobals.evaluateNumericBinaryMethod);
            Convert.Emit(this, il, Typeob.Object, rtype);
        }
Example #14
0
        internal override void TranslateToConditionalBranch(ILGenerator il, bool branchIfTrue, Label label, bool shortForm)
        {
            Type t1 = Convert.ToType(this.operand1.InferType(null));
            Type t2 = Convert.ToType(this.operand2.InferType(null));

            if (this.operand1 is ConstantWrapper)
            {
                if (this.operand1.Evaluate() == null)
                {
                    t1 = Typeob.Empty;
                }
            }
            if (this.operand2 is ConstantWrapper)
            {
                if (this.operand2.Evaluate() == null)
                {
                    t2 = Typeob.Empty;
                }
            }
            if (t1 != t2 && t1.IsPrimitive && t2.IsPrimitive)
            {
                if (t1 == Typeob.Single)
                {
                    t2 = t1;
                }
                else if (t2 == Typeob.Single)
                {
                    t1 = t2;
                }
                else if (Convert.IsPromotableTo(t2, t1))
                {
                    t2 = t1;
                }
                else if (Convert.IsPromotableTo(t1, t2))
                {
                    t1 = t2;
                }
            }
            bool nonPrimitive = true;

            if (t1 == t2 && t1 != Typeob.Object)
            {
                this.operand1.TranslateToIL(il, t1);
                if (!t1.IsPrimitive && t1.IsValueType)
                {
                    Convert.EmitLdloca(il, t1);
                }
                this.operand2.TranslateToIL(il, t1);
                if (t1 == Typeob.String)
                {
                    il.Emit(OpCodes.Call, CompilerGlobals.stringEqualsMethod);
                }
                else if (!t1.IsPrimitive)
                {
                    il.Emit(OpCodes.Callvirt, CompilerGlobals.equalsMethod);
                }
                else
                {
                    nonPrimitive = false;
                }
            }
            else if (t1 == Typeob.Empty)
            {
                this.operand2.TranslateToIL(il, Typeob.Object);
                branchIfTrue = !branchIfTrue;
            }
            else if (t2 == Typeob.Empty)
            {
                this.operand1.TranslateToIL(il, Typeob.Object);
                branchIfTrue = !branchIfTrue;
            }
            else
            {
                this.operand1.TranslateToIL(il, Typeob.Object);
                this.operand2.TranslateToIL(il, Typeob.Object);
                il.Emit(OpCodes.Call, CompilerGlobals.jScriptStrictEqualsMethod);
            }
            if (branchIfTrue)
            {
                if (this.operatorTok == JSToken.StrictEqual)
                {
                    if (nonPrimitive)
                    {
                        il.Emit(shortForm ? OpCodes.Brtrue_S : OpCodes.Brtrue, label);
                    }
                    else
                    {
                        il.Emit(shortForm ? OpCodes.Beq_S : OpCodes.Beq, label);
                    }
                }
                else
                if (nonPrimitive)
                {
                    il.Emit(shortForm ? OpCodes.Brfalse_S : OpCodes.Brfalse, label);
                }
                else
                {
                    il.Emit(shortForm ? OpCodes.Bne_Un_S : OpCodes.Bne_Un, label);
                }
            }
            else
            {
                if (this.operatorTok == JSToken.StrictEqual)
                {
                    if (nonPrimitive)
                    {
                        il.Emit(shortForm ? OpCodes.Brfalse_S : OpCodes.Brfalse, label);
                    }
                    else
                    {
                        il.Emit(shortForm ? OpCodes.Bne_Un_S : OpCodes.Bne_Un, label);
                    }
                }
                else
                if (nonPrimitive)
                {
                    il.Emit(shortForm ? OpCodes.Brtrue_S : OpCodes.Brtrue, label);
                }
                else
                {
                    il.Emit(shortForm ? OpCodes.Beq_S : OpCodes.Beq, label);
                }
            }
            return;
        }
Example #15
0
        internal override void TranslateToIL(ILGenerator il, Type rtype)
        {
            Type type = Convert.ToType(this.InferType(null));

            if (this.metaData == null)
            {
                Type rt = Typeob.Object;
                if (rtype == Typeob.Double)
                {
                    rt = rtype;
                }
                else if (this.type1 == Typeob.Char && this.type2 == Typeob.Char)
                {
                    rt = Typeob.String;
                }
                else if (Convert.IsPrimitiveNumericType(rtype) && Convert.IsPromotableTo(this.type1, rtype) && Convert.IsPromotableTo(this.type2, rtype))
                {
                    rt = rtype;
                }
                else if (this.type1 != Typeob.String && this.type2 != Typeob.String) //Both will be converted to numbers
                {
                    rt = Typeob.Double;                                              //Won't get here unless InferType returned Typeob.Double.
                }
                else
                {
                    rt = Typeob.String;
                }
                if (rt == Typeob.SByte || rt == Typeob.Int16)
                {
                    rt = Typeob.Int32;
                }
                else if (rt == Typeob.Byte || rt == Typeob.UInt16 || rt == Typeob.Char)
                {
                    rt = Typeob.UInt32;
                }
                if (rt == Typeob.String)
                {
                    if (this.operand1 is Plus && this.type1 == rt)
                    {
                        Plus op1 = (Plus)this.operand1;
                        if (op1.operand1 is Plus && op1.type1 == rt)
                        {
                            Plus op11 = (Plus)op1.operand1;
                            if (op11.operand1 is Plus && op11.type1 == rt)
                            {
                                int len = op1.TranslateToILArrayOfStrings(il, 1);
                                il.Emit(OpCodes.Dup);
                                ConstantWrapper.TranslateToILInt(il, len - 1);
                                this.operand2.TranslateToIL(il, rt);
                                il.Emit(OpCodes.Stelem_Ref);
                                il.Emit(OpCodes.Call, CompilerGlobals.stringConcatArrMethod);
                                Convert.Emit(this, il, rt, rtype);
                                return;
                            }
                            Plus.TranslateToStringWithSpecialCaseForNull(il, op11.operand1);
                            Plus.TranslateToStringWithSpecialCaseForNull(il, op11.operand2);
                            Plus.TranslateToStringWithSpecialCaseForNull(il, op1.operand2);
                            Plus.TranslateToStringWithSpecialCaseForNull(il, this.operand2);
                            il.Emit(OpCodes.Call, CompilerGlobals.stringConcat4Method);
                            Convert.Emit(this, il, rt, rtype);
                            return;
                        }
                        Plus.TranslateToStringWithSpecialCaseForNull(il, op1.operand1);
                        Plus.TranslateToStringWithSpecialCaseForNull(il, op1.operand2);
                        Plus.TranslateToStringWithSpecialCaseForNull(il, this.operand2);
                        il.Emit(OpCodes.Call, CompilerGlobals.stringConcat3Method);
                        Convert.Emit(this, il, rt, rtype);
                        return;
                    }
                    Plus.TranslateToStringWithSpecialCaseForNull(il, this.operand1);
                    Plus.TranslateToStringWithSpecialCaseForNull(il, this.operand2);
                    il.Emit(OpCodes.Call, CompilerGlobals.stringConcat2Method);
                    Convert.Emit(this, il, rt, rtype);
                    return;
                }
                this.operand1.TranslateToIL(il, rt);
                this.operand2.TranslateToIL(il, rt);
                if (rt == Typeob.Object)
                {
                    il.Emit(OpCodes.Call, CompilerGlobals.plusDoOpMethod);
                }
                else if (rt == Typeob.Double || rt == Typeob.Single)
                {
                    il.Emit(OpCodes.Add);
                }
                else if (rt == Typeob.Int32 || rt == Typeob.Int64)
                {
                    il.Emit(OpCodes.Add_Ovf);
                }
                else
                {
                    il.Emit(OpCodes.Add_Ovf_Un);
                }

                if (type == Typeob.Char)
                {
                    Convert.Emit(this, il, rt, Typeob.Char);
                    Convert.Emit(this, il, Typeob.Char, rtype);
                }
                else
                {
                    Convert.Emit(this, il, rt, rtype);
                }
                return;
            }
            if (this.metaData is MethodInfo)
            {
                MethodInfo      oper = (MethodInfo)this.metaData;
                ParameterInfo[] pars = oper.GetParameters();
                this.operand1.TranslateToIL(il, pars[0].ParameterType);
                this.operand2.TranslateToIL(il, pars[1].ParameterType);
                il.Emit(OpCodes.Call, oper);
                Convert.Emit(this, il, oper.ReturnType, rtype);
                return;
            }
            //Getting here is just too bad. We do not know until the code runs whether or not to call an overloaded operator method.
            //Compile operands to objects and devolve the decision making to run time thunks
            //Also get here when dealing with Int64 and UInt64. These cannot always be converted to doubles. The late-bound code checks for this.
            il.Emit(OpCodes.Ldloc, (LocalBuilder)this.metaData);
            this.operand1.TranslateToIL(il, Typeob.Object);
            this.operand2.TranslateToIL(il, Typeob.Object);
            il.Emit(OpCodes.Callvirt, CompilerGlobals.evaluatePlusMethod);
            Convert.Emit(this, il, Typeob.Object, rtype);
        }
Example #16
0
        internal override void TranslateToConditionalBranch(ILGenerator il, bool branchIfTrue, Label label, bool shortForm)
        {
            Type t1 = Convert.ToType(this.operand1.InferType(null));
            Type t2 = Convert.ToType(this.operand2.InferType(null));

            if (this.operand1 is ConstantWrapper)
            {
                if (this.operand1.Evaluate() == null)
                {
                    t1 = Typeob.Empty;
                }
            }
            if (this.operand2 is ConstantWrapper)
            {
                if (this.operand2.Evaluate() == null)
                {
                    t2 = Typeob.Empty;
                }
            }
            if (t1 != t2 && t1.IsPrimitive && t2.IsPrimitive)
            {
                if (t1 == Typeob.Single)
                {
                    t2 = t1;
                }
                else if (t2 == Typeob.Single)
                {
                    t1 = t2;
                }
                else if (Convert.IsPromotableTo(t2, t1))
                {
                    t2 = t1;
                }
                else if (Convert.IsPromotableTo(t1, t2))
                {
                    t1 = t2;
                }
            }
            bool nonPrimitive = true;

            if (t1 == t2 && t1 != Typeob.Object)
            {
                // Operand types are equal and not Object - need to compare values only. Primitive
                // values get compared with IL instructions; other values including value types
                // get compared with Object.Equals. String is special cased for perf.
                Type t = t1;
                if (!t1.IsPrimitive)
                {
                    t = Typeob.Object;
                }
                this.operand1.TranslateToIL(il, t);
                this.operand2.TranslateToIL(il, t);
                if (t1 == Typeob.String)
                {
                    il.Emit(OpCodes.Call, CompilerGlobals.stringEqualsMethod);
                }
                else if (!t1.IsPrimitive)
                {
                    il.Emit(OpCodes.Callvirt, CompilerGlobals.equalsMethod);
                }
                else
                {
                    nonPrimitive = false;
                }
            }
            else if (t1 == Typeob.Empty)
            {
                this.operand2.TranslateToIL(il, Typeob.Object);
                branchIfTrue = !branchIfTrue;
            }
            else if (t2 == Typeob.Empty)
            {
                this.operand1.TranslateToIL(il, Typeob.Object);
                branchIfTrue = !branchIfTrue;
            }
            else
            {
                this.operand1.TranslateToIL(il, Typeob.Object);
                this.operand2.TranslateToIL(il, Typeob.Object);
                il.Emit(OpCodes.Call, CompilerGlobals.jScriptStrictEqualsMethod);
            }
            if (branchIfTrue)
            {
                if (this.operatorTok == JSToken.StrictEqual)
                {
                    if (nonPrimitive)
                    {
                        il.Emit(shortForm ? OpCodes.Brtrue_S : OpCodes.Brtrue, label);
                    }
                    else
                    {
                        il.Emit(shortForm ? OpCodes.Beq_S : OpCodes.Beq, label);
                    }
                }
                else
                if (nonPrimitive)
                {
                    il.Emit(shortForm ? OpCodes.Brfalse_S : OpCodes.Brfalse, label);
                }
                else
                {
                    il.Emit(shortForm ? OpCodes.Bne_Un_S : OpCodes.Bne_Un, label);
                }
            }
            else
            {
                if (this.operatorTok == JSToken.StrictEqual)
                {
                    if (nonPrimitive)
                    {
                        il.Emit(shortForm ? OpCodes.Brfalse_S : OpCodes.Brfalse, label);
                    }
                    else
                    {
                        il.Emit(shortForm ? OpCodes.Bne_Un_S : OpCodes.Bne_Un, label);
                    }
                }
                else
                if (nonPrimitive)
                {
                    il.Emit(shortForm ? OpCodes.Brtrue_S : OpCodes.Brtrue, label);
                }
                else
                {
                    il.Emit(shortForm ? OpCodes.Beq_S : OpCodes.Beq, label);
                }
            }
            return;
        }
Example #17
0
        private void TranslateToILForNoOverloadCase(ILGenerator il, Type rtype)
        {
            Type lhtype = Convert.ToType(this.operand1.InferType(null));
            Type rhtype = Convert.ToType(this.operand2.InferType(null));
            Type rt     = Typeob.Object;

            if (lhtype == Typeob.String || rhtype == Typeob.String)
            {
                rt = Typeob.String;
            }
            else if (rtype == Typeob.Void || rtype == lhtype || Convert.IsPrimitiveNumericType(lhtype) &&
                     (Convert.IsPromotableTo(rhtype, lhtype) || ((this.operand2 is ConstantWrapper) && ((ConstantWrapper)this.operand2).IsAssignableTo(lhtype))))
            {
                rt = lhtype;
            }
            if (rt == Typeob.SByte || rt == Typeob.Int16)
            {
                rt = Typeob.Int32;
            }
            else if (rt == Typeob.Byte || rt == Typeob.UInt16)
            {
                rt = Typeob.UInt32;
            }

            // If we have "unsigned += signed" or "signed += unsigned" then generating the
            // correct code gets quite complicated.  Just go late-bound for this edge case.
            if (this.operand2 is ConstantWrapper)
            {
                if (!((ConstantWrapper)this.operand2).IsAssignableTo(rt))
                {
                    // eg: "var u : byte = 123; u += -100;" should go late bound because
                    // of signed/unsigned mismatch but "u += 1" should not.
                    rt = Typeob.Object;
                }
            }
            else
            {
                if ((Convert.IsPrimitiveSignedNumericType(rhtype) && Convert.IsPrimitiveUnsignedIntegerType(lhtype)) ||
                    (Convert.IsPrimitiveUnsignedIntegerType(rhtype) && Convert.IsPrimitiveSignedIntegerType(lhtype)))
                {
                    rt = Typeob.Object;
                }
            }

            this.operand1.TranslateToILPreSetPlusGet(il);
            Convert.Emit(this, il, lhtype, rt);
            this.operand2.TranslateToIL(il, rt);
            if (rt == Typeob.Object || rt == Typeob.String)
            {
                il.Emit(OpCodes.Call, CompilerGlobals.plusDoOpMethod);
                rt = Typeob.Object;
            }
            else if (rt == Typeob.Double || rt == Typeob.Single)
            {
                il.Emit(OpCodes.Add);
            }
            else if (rt == Typeob.Int32 || rt == Typeob.Int64 || rt == Typeob.Int16 || rt == Typeob.SByte)
            {
                il.Emit(OpCodes.Add_Ovf);
            }
            else
            {
                il.Emit(OpCodes.Add_Ovf_Un);
            }
            if (rtype != Typeob.Void)
            {
                LocalBuilder result = il.DeclareLocal(rt);
                il.Emit(OpCodes.Dup);
                il.Emit(OpCodes.Stloc, result);
                Convert.Emit(this, il, rt, lhtype);
                this.operand1.TranslateToILSet(il);
                il.Emit(OpCodes.Ldloc, result);
                Convert.Emit(this, il, rt, rtype);
            }
            else
            {
                Convert.Emit(this, il, rt, lhtype);
                this.operand1.TranslateToILSet(il);
            }
        }
 internal override void TranslateToConditionalBranch(ILGenerator il, bool branchIfTrue, Label label, bool shortForm)
 {
     if (this.metaData == null)
     {
         Type t1 = this.type1;
         Type t2 = this.type2;
         Type t3 = Typeob.Object;
         bool emitNullAndUndefined = true;
         if (t1.IsPrimitive && t2.IsPrimitive)
         {
             t3 = Typeob.Double;
             if (t1 == Typeob.Single || t2 == Typeob.Single)
             {
                 t3 = Typeob.Single;
             }
             else if (Convert.IsPromotableTo(t1, t2))
             {
                 t3 = t2;
             }
             else if (Convert.IsPromotableTo(t2, t1))
             {
                 t3 = t1;
             }
         }
         else if (t1 == Typeob.String && (t2 == Typeob.String || t2 == Typeob.Empty || t2 == Typeob.Null))
         {
             t3 = Typeob.String;
             if (t2 != Typeob.String)
             {
                 emitNullAndUndefined = false;
                 branchIfTrue         = !branchIfTrue;
             }
         }
         else if ((t1 == Typeob.Empty || t1 == Typeob.Null) && t2 == Typeob.String)
         {
             t3 = Typeob.String;
             emitNullAndUndefined = false;
             branchIfTrue         = !branchIfTrue;
         }
         if (t3 == Typeob.SByte || t3 == Typeob.Int16)
         {
             t3 = Typeob.Int32;
         }
         else if (t3 == Typeob.Byte || t3 == Typeob.UInt16)
         {
             t3 = Typeob.UInt32;
         }
         if (emitNullAndUndefined)
         {
             this.operand1.TranslateToIL(il, t3);
             this.operand2.TranslateToIL(il, t3);
             if (t3 == Typeob.Object)
             {
                 il.Emit(OpCodes.Call, CompilerGlobals.jScriptEqualsMethod);
             }
             else if (t3 == Typeob.String)
             {
                 il.Emit(OpCodes.Call, CompilerGlobals.stringEqualsMethod);
             }
         }
         else if (t1 == Typeob.String)
         {
             this.operand1.TranslateToIL(il, t3);
         }
         else if (t2 == Typeob.String)
         {
             this.operand2.TranslateToIL(il, t3);
         }
         if (branchIfTrue)
         {
             if (this.operatorTok == JSToken.Equal)
             {
                 if (t3 == Typeob.String || t3 == Typeob.Object)
                 {
                     il.Emit(shortForm ? OpCodes.Brtrue_S : OpCodes.Brtrue, label);
                 }
                 else
                 {
                     il.Emit(shortForm ? OpCodes.Beq_S : OpCodes.Beq, label);
                 }
             }
             else
             if (t3 == Typeob.String || t3 == Typeob.Object)
             {
                 il.Emit(shortForm ? OpCodes.Brfalse_S : OpCodes.Brfalse, label);
             }
             else
             {
                 il.Emit(shortForm ? OpCodes.Bne_Un_S : OpCodes.Bne_Un, label);
             }
         }
         else
         {
             if (this.operatorTok == JSToken.Equal)
             {
                 if (t3 == Typeob.String || t3 == Typeob.Object)
                 {
                     il.Emit(shortForm ? OpCodes.Brfalse_S : OpCodes.Brfalse, label);
                 }
                 else
                 {
                     il.Emit(shortForm ? OpCodes.Bne_Un_S : OpCodes.Bne_Un, label);
                 }
             }
             else
             if (t3 == Typeob.String || t3 == Typeob.Object)
             {
                 il.Emit(shortForm ? OpCodes.Brtrue_S : OpCodes.Brtrue, label);
             }
             else
             {
                 il.Emit(shortForm ? OpCodes.Beq_S : OpCodes.Beq, label);
             }
         }
         return;
     }
     if (this.metaData is MethodInfo)
     {
         MethodInfo      oper = (MethodInfo)this.metaData;
         ParameterInfo[] pars = oper.GetParameters();
         this.operand1.TranslateToIL(il, pars[0].ParameterType);
         this.operand2.TranslateToIL(il, pars[1].ParameterType);
         il.Emit(OpCodes.Call, oper);
         if (branchIfTrue)
         {
             il.Emit(shortForm ? OpCodes.Brtrue_S : OpCodes.Brtrue, label);
         }
         else
         {
             il.Emit(shortForm ? OpCodes.Brfalse_S : OpCodes.Brfalse, label);
         }
         return;
     }
     //Getting here is just too bad. We do not know until the code runs whether or not to call an overloaded operator method.
     //Compile operands to objects and devolve the decision making to run time thunks
     il.Emit(OpCodes.Ldloc, (LocalBuilder)this.metaData);
     this.operand1.TranslateToIL(il, Typeob.Object);
     this.operand2.TranslateToIL(il, Typeob.Object);
     il.Emit(OpCodes.Call, CompilerGlobals.evaluateEqualityMethod);
     if (branchIfTrue)
     {
         if (this.operatorTok == JSToken.Equal)
         {
             il.Emit(shortForm ? OpCodes.Brtrue_S : OpCodes.Brtrue, label);
         }
         else
         {
             il.Emit(shortForm ? OpCodes.Brfalse_S : OpCodes.Brfalse, label);
         }
     }
     else
     {
         if (this.operatorTok == JSToken.Equal)
         {
             il.Emit(shortForm ? OpCodes.Brfalse_S : OpCodes.Brfalse, label);
         }
         else
         {
             il.Emit(shortForm ? OpCodes.Brtrue_S : OpCodes.Brtrue, label);
         }
     }
     return;
 }