IsPrimitiveNumericType() static private méthode

static private IsPrimitiveNumericType ( IReflect ir ) : bool
ir IReflect
Résultat bool
Exemple #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);
        }
        internal override IReflect InferType(JSField inference_target)
        {
            MethodInfo oper;

            if (this.type == null || inference_target != null)
            {
                oper = this.GetOperator(this.operand.InferType(inference_target));
            }
            else
            {
                oper = this.GetOperator(this.type);
            }
            if (oper != null)
            {
                this.metaData = oper;
                return(oper.ReturnType);
            }
            if (Convert.IsPrimitiveNumericType(this.type))
            {
                return(this.type);
            }
            else if (this.type == Typeob.Char)
            {
                return(this.type);
            }
            else if (Typeob.JSObject.IsAssignableFrom(this.type))
            {
                return(Typeob.Double);
            }
            else
            {
                return(Typeob.Object);
            }
        }
 private IReflect ProvideWrapperForPrototypeProperties(IReflect obType)
 {
     //Provide for early binding to prototype methods in fast mode, by fudging the type
     if (obType == Typeob.String)
     {
         obType = Globals.globalObject.originalString.Construct();
         ((JSObject)obType).noExpando = this.fast;
         this.isImplicitWrapper       = true;
     }
     else if ((obType is Type && Typeob.Array.IsAssignableFrom((Type)obType)) || obType is TypedArray)
     {
         obType = Globals.globalObject.originalArray.ConstructWrapper();
         ((JSObject)obType).noExpando = this.fast;
         this.isImplicitWrapper       = true;
     }
     else if (obType == Typeob.Boolean)
     {
         obType = Globals.globalObject.originalBoolean.Construct();
         ((JSObject)obType).noExpando = this.fast;
         this.isImplicitWrapper       = true;
     }
     else if (Convert.IsPrimitiveNumericType(obType))
     {
         Type baseType = (Type)obType;
         obType = Globals.globalObject.originalNumber.Construct();
         ((JSObject)obType).noExpando    = this.fast;
         ((NumberObject)obType).baseType = baseType;
         this.isImplicitWrapper          = true;
     }
     else if (obType is Type)
     {
         obType = Convert.ToIReflect((Type)obType, this.Engine);
     }
     return(obType);
 }
 internal ErrorObject(ErrorPrototype parent, Object[] args)
     : base(parent)
 {
     this.exception   = null;
     this.description = "";
     this.number      = 0;
     if (args.Length == 1)
     {
         if (args[0] == null || Convert.IsPrimitiveNumericType(args[0].GetType()))
         {
             this.number = Convert.ToNumber(args[0]);
         }
         else
         {
             this.description = Convert.ToString(args[0]);
         }
     }
     else if (args.Length > 1)
     {
         this.number      = Convert.ToNumber(args[0]);
         this.description = Convert.ToString(args[1]);
     }
     this.message   = this.description;
     this.noExpando = false;
 }
Exemple #5
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);
                 }
             }
         }
     }
 }
Exemple #7
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);
        }
Exemple #8
0
        private MethodInfo GetOperator(IReflect ir)
        {
            Type t = ir is Type ? (Type)ir : Typeob.Object;

            if (this.type == t)
            {
                return(this.operatorMeth);
            }
            this.type = t;
            if (Convert.IsPrimitiveNumericType(t) || Typeob.JSObject.IsAssignableFrom(t))
            {
                this.operatorMeth = null;
                return(null);
            }
            switch (this.operatorTok)
            {
            case JSToken.BitwiseNot:
                this.operatorMeth = t.GetMethod("op_OnesComplement", BindingFlags.Public | BindingFlags.Static, JSBinder.ob, new Type[] { t }, null); break;

            case JSToken.LogicalNot:
                this.operatorMeth = t.GetMethod("op_LogicalNot", BindingFlags.Public | BindingFlags.Static, JSBinder.ob, new Type[] { t }, null); break;

            case JSToken.Minus:
                this.operatorMeth = t.GetMethod("op_UnaryNegation", BindingFlags.Public | BindingFlags.Static, JSBinder.ob, new Type[] { t }, null); break;

            case JSToken.Plus:
                this.operatorMeth = t.GetMethod("op_UnaryPlus", BindingFlags.Public | BindingFlags.Static, JSBinder.ob, new Type[] { t }, null); break;

            default:
                throw new JScriptException(JSError.InternalError, this.context);
            }
            if (this.operatorMeth == null ||
                (operatorMeth.Attributes & MethodAttributes.SpecialName) == 0 ||
                operatorMeth.GetParameters().Length != 1)
            {
                this.operatorMeth = null;
            }
            if (this.operatorMeth != null)
            {
                this.operatorMeth = new JSMethodInfo(this.operatorMeth);
            }
            return(this.operatorMeth);
        }
        private new MethodInfo GetOperator(IReflect ir1, IReflect ir2)
        {
            Type t1 = ir1 is Type ? (Type)ir1 : Typeob.Object;
            Type t2 = ir2 is Type ? (Type)ir2 : Typeob.Object;

            if (this.type1 == t1 && this.type2 == t2)
            {
                return(this.operatorMeth);
            }
            if (t1 == Typeob.String || t2 == Typeob.String ||
                ((Convert.IsPrimitiveNumericType(t1) || Typeob.JSObject.IsAssignableFrom(t1)) &&
                 (Convert.IsPrimitiveNumericType(t2) || Typeob.JSObject.IsAssignableFrom(t2))))
            {
                this.operatorMeth = null;
                this.type1        = t1;
                this.type2        = t2;
                return(null);
            }
            return(base.GetOperator(t1, t2));
        }
Exemple #10
0
        private MethodInfo GetOperator(IReflect ir)
        {
            Type t = ir is Type ? (Type)ir : Typeob.Object;

            if (this.type == t)
            {
                return(this.operatorMeth);
            }
            this.type = t;
            if (Convert.IsPrimitiveNumericType(t) || Typeob.JSObject.IsAssignableFrom(t))
            {
                this.operatorMeth = null;
                return(null);
            }
            switch (this.operatorTok)
            {
            case PostOrPrefix.PostfixDecrement:
            case PostOrPrefix.PrefixDecrement:
                this.operatorMeth = t.GetMethod("op_Decrement", BindingFlags.Public | BindingFlags.Static, JSBinder.ob, new Type[] { t }, null); break;

            case PostOrPrefix.PostfixIncrement:
            case PostOrPrefix.PrefixIncrement:
                this.operatorMeth = t.GetMethod("op_Increment", BindingFlags.Public | BindingFlags.Static, JSBinder.ob, new Type[] { t }, null); break;

            default:
                throw new JScriptException(JSError.InternalError, this.context);
            }
            if (this.operatorMeth != null &&
                (!this.operatorMeth.IsStatic || (operatorMeth.Attributes & MethodAttributes.SpecialName) == (MethodAttributes)0 || operatorMeth.GetParameters().Length != 1))
            {
                this.operatorMeth = null;
            }
            if (this.operatorMeth != null)
            {
                this.operatorMeth = new JSMethodInfo(this.operatorMeth);
            }
            return(this.operatorMeth);
        }
        protected override void HandleNoSuchMemberError()
        {
            IReflect obType = this.rootObject.InferType(null);
            Object   obVal  = null;

            if (this.rootObject is ConstantWrapper)
            {
                obVal = this.rootObject.Evaluate();
            }

            if ((obType == Typeob.Object && !this.isNonVirtual) ||
                (obType is JSObject && !((JSObject)obType).noExpando) ||
                (obType is GlobalScope && !((GlobalScope)obType).isKnownAtCompileTime))
            {
                return;
            }
            if (obType is Type)
            {
                Type t = (Type)obType;
                if (Typeob.ScriptFunction.IsAssignableFrom(t) || t == Typeob.MathObject)
                {
                    //dealing with an assigment to a member of a builtin constructor function.
                    Debug.Assert(this.fast);
                    this.memberNameContext.HandleError(JSError.OLENoPropOrMethod);
                    return;
                }
                if (Typeob.IExpando.IsAssignableFrom(t))
                {
                    return;
                }
                if (!this.fast)
                {
                    if (t == Typeob.Boolean || t == Typeob.String || Convert.IsPrimitiveNumericType(t))
                    {
                        return;
                    }
                }

                // Check to see if we couldn't get the member because it is non-static.
                if (obVal is ClassScope)
                {
                    MemberInfo[] members = ((ClassScope)obVal).GetMember(this.name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                    if (members.Length > 0)
                    {
                        this.memberNameContext.HandleError(JSError.NonStaticWithTypeName);
                        return;
                    }
                }
            }

            if (obVal is FunctionObject)
            {
                this.rootObject = new ConstantWrapper(((FunctionObject)obVal).name, this.rootObject.context);
                this.memberNameContext.HandleError(JSError.OLENoPropOrMethod);
                return;
            }

            // Check to see if we couldn't get the member because it is static.
            if (obType is ClassScope)
            {
                MemberInfo[] members = ((ClassScope)obType).GetMember(this.name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
                if (members.Length > 0)
                {
                    this.memberNameContext.HandleError(JSError.StaticRequiresTypeName);
                    return;
                }
            }

            if (obVal is Type)
            {
                this.memberNameContext.HandleError(JSError.NoSuchStaticMember, Convert.ToTypeName((Type)obVal));
            }
            else if (obVal is ClassScope)
            {
                this.memberNameContext.HandleError(JSError.NoSuchStaticMember, Convert.ToTypeName((ClassScope)obVal));
            }
            else if (obVal is Namespace)
            {
                this.memberNameContext.HandleError(JSError.NoSuchType, ((Namespace)obVal).Name + "." + this.name);
            }
            else
            {
                if (obType == FunctionPrototype.ob && this.rootObject is Binding &&
                    ((Binding)this.rootObject).member is JSVariableField && ((JSVariableField)((Binding)this.rootObject).member).value is FunctionObject)
                {
                    return;
                }
                this.memberNameContext.HandleError(JSError.NoSuchMember, Convert.ToTypeName(obType));
            }
        }
Exemple #12
0
        internal override void TranslateToIL(ILGenerator il, Type rtype)
        {
            if (this.metaData == null)
            {
                Type bbrType = BitwiseBinary.ResultType(this.type1, this.type2, this.operatorTok);
                if (Convert.IsPrimitiveNumericType(this.type1))
                {
                    this.operand1.TranslateToIL(il, this.type1);
                    Convert.Emit(this, il, this.type1, bbrType, true);
                }
                else
                {
                    this.operand1.TranslateToIL(il, Typeob.Double);
                    Convert.Emit(this, il, Typeob.Double, bbrType, true);
                }
                Type op2type = BitwiseBinary.Operand2Type(this.operatorTok, bbrType);
                if (Convert.IsPrimitiveNumericType(this.type2))
                {
                    this.operand2.TranslateToIL(il, this.type2);
                    Convert.Emit(this, il, this.type2, op2type, true);
                }
                else
                {
                    this.operand2.TranslateToIL(il, Typeob.Double);
                    Convert.Emit(this, il, Typeob.Double, op2type, true);
                }
                switch (this.operatorTok)
                {
                case JSToken.BitwiseAnd:
                    il.Emit(OpCodes.And);
                    break;

                case JSToken.BitwiseOr:
                    il.Emit(OpCodes.Or);
                    break;

                case JSToken.BitwiseXor:
                    il.Emit(OpCodes.Xor);
                    break;

                case JSToken.LeftShift:
                    BitwiseBinary.TranslateToBitCountMask(il, bbrType, this.operand2);
                    il.Emit(OpCodes.Shl);
                    break;

                case JSToken.RightShift:
                    BitwiseBinary.TranslateToBitCountMask(il, bbrType, this.operand2);
                    il.Emit(OpCodes.Shr);
                    break;

                case JSToken.UnsignedRightShift:
                    BitwiseBinary.TranslateToBitCountMask(il, bbrType, this.operand2);
                    il.Emit(OpCodes.Shr_Un);
                    break;

                default:
                    throw new JScriptException(JSError.InternalError, this.context);
                }
                Convert.Emit(this, il, bbrType, 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.evaluateBitwiseBinaryMethod);
            Convert.Emit(this, il, Typeob.Object, rtype);
        }
Exemple #13
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);
            }
        }
Exemple #14
0
        protected MethodInfo GetOperator(IReflect ir1, IReflect ir2)
        {
            if (ir1 is ClassScope)
            {
                ir1 = ((ClassScope)ir1).GetUnderlyingTypeIfEnum();
            }
            if (ir2 is ClassScope)
            {
                ir2 = ((ClassScope)ir2).GetUnderlyingTypeIfEnum();
            }
            Type t1 = ir1 is Type ? (Type)ir1 : Typeob.Object;
            Type t2 = ir2 is Type ? (Type)ir2 : Typeob.Object;

            if (this.type1 == t1 && this.type2 == t2)
            {
                return(this.operatorMeth);
            }
            this.type1        = t1;
            this.type2        = t2;
            this.operatorMeth = null;
            if (t1 == Typeob.String || Convert.IsPrimitiveNumericType(ir1) || Typeob.JSObject.IsAssignableFrom(t1))
            {
                t1 = null;
            }
            if (t2 == Typeob.String || Convert.IsPrimitiveNumericType(ir2) || Typeob.JSObject.IsAssignableFrom(t2))
            {
                t2 = null;
            }
            if (t1 == null && t2 == null)
            {
                return(null);
            }
            //One of the operands is an object of a type that might have a user defined operator.
            String name = "op_NoSuchOp";

            switch (this.operatorTok)
            {
            case JSToken.BitwiseAnd: name = "op_BitwiseAnd"; break;

            case JSToken.BitwiseOr: name = "op_BitwiseOr"; break;

            case JSToken.BitwiseXor: name = "op_ExclusiveOr"; break;

            case JSToken.Divide: name = "op_Division"; break;

            case JSToken.Equal: name = "op_Equality"; break;

            case JSToken.GreaterThan: name = "op_GreaterThan"; break;

            case JSToken.GreaterThanEqual: name = "op_GreaterThanOrEqual"; break;

            case JSToken.LeftShift: name = "op_LeftShift"; break;

            case JSToken.LessThan: name = "op_LessThan"; break;

            case JSToken.LessThanEqual: name = "op_LessThanOrEqual"; break;

            case JSToken.Minus: name = "op_Subtraction"; break;

            case JSToken.Modulo: name = "op_Modulus"; break;

            case JSToken.Multiply: name = "op_Multiply"; break;

            case JSToken.NotEqual: name = "op_Inequality"; break;

            case JSToken.Plus: name = "op_Addition"; break;

            case JSToken.RightShift: name = "op_RightShift"; break;
            }
            Type[] types = new Type[] { this.type1, this.type2 };
            if (t1 == t2)
            {
                MethodInfo op = t1.GetMethod(name, BindingFlags.Public | BindingFlags.Static, JSBinder.ob, types, null);
                if (op != null && (op.Attributes & MethodAttributes.SpecialName) != 0 && op.GetParameters().Length == 2)
                {
                    this.operatorMeth = op;
                }
            }
            else
            {
                //Search both operand types, but only if there is a possibility that they might have operators defined on them
                MethodInfo op1 = t1 == null ? null : t1.GetMethod(name, BindingFlags.Public | BindingFlags.Static, JSBinder.ob, types, null);
                MethodInfo op2 = t2 == null ? null : t2.GetMethod(name, BindingFlags.Public | BindingFlags.Static, JSBinder.ob, types, null);
                this.operatorMeth = JSBinder.SelectOperator(op1, op2, this.type1, this.type2); //Choose the better of the two
            }
            if (this.operatorMeth != null)
            {
                this.operatorMeth = new JSMethodInfo(this.operatorMeth);
            }
            return(this.operatorMeth);
        }
Exemple #15
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);
        }
        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);
        }
Exemple #17
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);
            }
        }
Exemple #18
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);
            }
        }
Exemple #19
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);
        }