The Labs \ Source Viewer \ SSCLI \ Microsoft.JScript \ BitwiseBinaryAssign

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace Microsoft.JScript
  16. {
  17.    
  18.     using System;
  19.     using System.Reflection;
  20.     using System.Reflection.Emit;
  21.    
  22.     internal sealed class BitwiseBinaryAssign : BinaryOp
  23.     {
  24.         private BitwiseBinary binOp;
  25.         private object metaData;
  26.        
  27.         internal BitwiseBinaryAssign(Context context, AST operand1, AST operand2, JSToken operatorTok) : base(context, operand1, operand2, operatorTok)
  28.         {
  29.             this.binOp = new BitwiseBinary(context, operand1, operand2, operatorTok);
  30.             this.metaData = null;
  31.         }
  32.        
  33.         internal override object Evaluate()
  34.         {
  35.             object v1 = this.operand1.Evaluate();
  36.             object v2 = this.operand2.Evaluate();
  37.             object result = this.binOp.EvaluateBitwiseBinary(v1, v2);
  38.             try {
  39.                 this.operand1.SetValue(result);
  40.                 return result;
  41.             }
  42.             catch (JScriptException e) {
  43.                 if (e.context == null)
  44.                     e.context = this.context;
  45.                 throw e;
  46.             }
  47.             catch (Exception e) {
  48.                 throw new JScriptException(e, this.context);
  49.             }
  50.             catch {
  51.                 throw new JScriptException(JSError.NonClsException, this.context);
  52.             }
  53.         }
  54.        
  55.         internal override IReflect InferType(JSField inference_target)
  56.         {
  57.             MethodInfo oper;
  58.             if (this.type1 == null) {
  59.                 oper = this.GetOperator(this.operand1.InferType(inference_target), this.operand2.InferType(inference_target));
  60.             }
  61.             else
  62.                 oper = this.GetOperator(this.type1, this.type2);
  63.             if (oper != null) {
  64.                 this.metaData = oper;
  65.                 return oper.ReturnType;
  66.             }
  67.             if ((this.type1.IsPrimitive || Typeob.JSObject.IsAssignableFrom(this.type1)) && (this.type2.IsPrimitive || Typeob.JSObject.IsAssignableFrom(this.type2)))
  68.                 return Typeob.Int32;
  69.             else
  70.                 return Typeob.Object;
  71.         }
  72.        
  73.         internal override AST PartiallyEvaluate()
  74.         {
  75.             this.operand1 = this.operand1.PartiallyEvaluateAsReference();
  76.             this.operand2 = this.operand2.PartiallyEvaluate();
  77.             this.binOp = new BitwiseBinary(this.context, this.operand1, this.operand2, this.operatorTok);
  78.             this.operand1.SetPartialValue(this.binOp);
  79.             return this;
  80.         }
  81.        
  82.         private void TranslateToILForNoOverloadCase(ILGenerator il, Type rtype)
  83.         {
  84.             Type lhtype = Convert.ToType(this.operand1.InferType(null));
  85.             Type operand2type = Convert.ToType(this.operand2.InferType(null));
  86.             Type bbrType = BitwiseBinary.ResultType(lhtype, operand2type, this.operatorTok);
  87.             this.operand1.TranslateToILPreSetPlusGet(il);
  88.             Convert.Emit(this, il, lhtype, bbrType, true);
  89.             this.operand2.TranslateToIL(il, operand2type);
  90.             Convert.Emit(this, il, operand2type, BitwiseBinary.Operand2Type(this.operatorTok, bbrType), true);
  91.             switch (this.operatorTok) {
  92.                 case JSToken.BitwiseAnd:
  93.                     il.Emit(OpCodes.And);
  94.                     break;
  95.                 case JSToken.BitwiseOr:
  96.                     il.Emit(OpCodes.Or);
  97.                     break;
  98.                 case JSToken.BitwiseXor:
  99.                     il.Emit(OpCodes.Xor);
  100.                     break;
  101.                 case JSToken.LeftShift:
  102.                     BitwiseBinary.TranslateToBitCountMask(il, bbrType, this.operand2);
  103.                     il.Emit(OpCodes.Shl);
  104.                     break;
  105.                 case JSToken.RightShift:
  106.                     BitwiseBinary.TranslateToBitCountMask(il, bbrType, this.operand2);
  107.                     il.Emit(OpCodes.Shr);
  108.                     break;
  109.                 case JSToken.UnsignedRightShift:
  110.                     BitwiseBinary.TranslateToBitCountMask(il, bbrType, this.operand2);
  111.                     il.Emit(OpCodes.Shr_Un);
  112.                     break;
  113.                 default:
  114.                     throw new JScriptException(JSError.InternalError, this.context);
  115.                     break;
  116.             }
  117.             if (rtype != Typeob.Void) {
  118.                 LocalBuilder result = il.DeclareLocal(bbrType);
  119.                 il.Emit(OpCodes.Dup);
  120.                 il.Emit(OpCodes.Stloc, result);
  121.                 Convert.Emit(this, il, bbrType, lhtype);
  122.                 this.operand1.TranslateToILSet(il);
  123.                 il.Emit(OpCodes.Ldloc, result);
  124.                 Convert.Emit(this, il, bbrType, rtype);
  125.             }
  126.             else {
  127.                 Convert.Emit(this, il, bbrType, lhtype);
  128.                 this.operand1.TranslateToILSet(il);
  129.             }
  130.         }
  131.        
  132.         internal override void TranslateToIL(ILGenerator il, Type rtype)
  133.         {
  134.             if (this.metaData == null) {
  135.                 TranslateToILForNoOverloadCase(il, rtype);
  136.                 return;
  137.             }
  138.             if (this.metaData is MethodInfo) {
  139.                 object result = null;
  140.                 MethodInfo oper = (MethodInfo)this.metaData;
  141.                 Type type = Convert.ToType(this.operand1.InferType(null));
  142.                 ParameterInfo[] pars = oper.GetParameters();
  143.                 this.operand1.TranslateToILPreSetPlusGet(il);
  144.                 Convert.Emit(this, il, type, pars[0].ParameterType);
  145.                 this.operand2.TranslateToIL(il, pars[1].ParameterType);
  146.                 il.Emit(OpCodes.Call, oper);
  147.                 if (rtype != Typeob.Void) {
  148.                     result = il.DeclareLocal(rtype);
  149.                     il.Emit(OpCodes.Dup);
  150.                     Convert.Emit(this, il, type, rtype);
  151.                     il.Emit(OpCodes.Stloc, (LocalBuilder)result);
  152.                 }
  153.                 Convert.Emit(this, il, oper.ReturnType, type);
  154.                 this.operand1.TranslateToILSet(il);
  155.                 if (rtype != Typeob.Void)
  156.                     il.Emit(OpCodes.Ldloc, (LocalBuilder)result);
  157.             }
  158.             else {
  159.                 //Getting here is just too bad. We do not know until the code runs whether or not to call an overloaded operator method.
  160.                 //Compile operands to objects and devolve the decision making to run time thunks
  161.                 Type type = Convert.ToType(this.operand1.InferType(null));
  162.                 LocalBuilder result = il.DeclareLocal(Typeob.Object);
  163.                 this.operand1.TranslateToILPreSetPlusGet(il);
  164.                 Convert.Emit(this, il, type, Typeob.Object);
  165.                 il.Emit(OpCodes.Stloc, result);
  166.                 il.Emit(OpCodes.Ldloc, (LocalBuilder)this.metaData);
  167.                 il.Emit(OpCodes.Ldloc, result);
  168.                 this.operand2.TranslateToIL(il, Typeob.Object);
  169.                 il.Emit(OpCodes.Call, CompilerGlobals.evaluateBitwiseBinaryMethod);
  170.                 if (rtype != Typeob.Void) {
  171.                     il.Emit(OpCodes.Dup);
  172.                     il.Emit(OpCodes.Stloc, result);
  173.                 }
  174.                 Convert.Emit(this, il, Typeob.Object, type);
  175.                 this.operand1.TranslateToILSet(il);
  176.                 if (rtype != Typeob.Void) {
  177.                     il.Emit(OpCodes.Ldloc, result);
  178.                     Convert.Emit(this, il, Typeob.Object, rtype);
  179.                 }
  180.             }
  181.         }
  182.        
  183.         internal override void TranslateToILInitializer(ILGenerator il)
  184.         {
  185.             IReflect rtype = this.InferType(null);
  186.             this.operand1.TranslateToILInitializer(il);
  187.             this.operand2.TranslateToILInitializer(il);
  188.             if (rtype != Typeob.Object)
  189.                 return;
  190.             this.metaData = il.DeclareLocal(Typeob.BitwiseBinary);
  191.             ConstantWrapper.TranslateToILInt(il, (int)this.operatorTok);
  192.             il.Emit(OpCodes.Newobj, CompilerGlobals.bitwiseBinaryConstructor);
  193.             il.Emit(OpCodes.Stloc, (LocalBuilder)this.metaData);
  194.         }
  195.     }
  196.    
  197. }

Developer Fusion