public object ExecuteUnaryOperator(ExpressionType op, object arg1, ref OperatorImplementation previousUsed)
        {
            // 1. Get arg type
              Type arg1Type;
              try {
            arg1Type = arg1.GetType();
              } catch (NullReferenceException) {
            CheckUnassigned(arg1);
            throw;
              }

              // 2. If we had prev impl, check if current args types match it; first copy it into local variable
              OperatorDispatchKey key;
              var currentImpl = previousUsed;
              if (currentImpl != null && arg1Type != currentImpl.Key.Arg1Type)
            currentImpl = null;

              // 3. Find implementation for arg type
              if (currentImpl == null) {
            key = new OperatorDispatchKey(op, arg1Type);
            if (!OperatorImplementations.TryGetValue(key, out currentImpl))
              ThrowError(Resources.ErrOpNotDefinedForType, op, arg1Type);
              }

              // 4. Actually call
              try {
            previousUsed = currentImpl; //set previousUsed so next time we'll try this impl first
            return currentImpl.Arg1Converter(arg1);
              } catch (OverflowException) {
            if (currentImpl.OverflowHandler == null)
              throw;
            previousUsed = currentImpl.OverflowHandler; //set previousUsed to overflowHandler, so it will be used next time
            return ExecuteUnaryOperator(op, arg1, ref previousUsed); //call self recursively
              }
        }
Example #2
0
        protected object EvaluateFast(ScriptThread thread)
        {
            thread.CurrentNode = this; //standard prolog
            var arg1 = Left.Evaluate(thread);
            var arg2 = Right.Evaluate(thread);

            //If we have _lastUsed, go straight for it; if types mismatch it will throw
            if (_lastUsed != null)
            {
                try {
                    var res = _lastUsed.EvaluateBinary(arg1, arg2);
                    thread.CurrentNode = Parent; //standard epilog
                    return(res);
                } catch {
                    _lastUsed = null;
                    _failureCount++;
                    // if failed 3 times, change to method without direct try
                    if (_failureCount > 3)
                    {
                        Evaluate = DefaultEvaluateImplementation;
                    }
                } //catch
            }     // if _lastUsed
            // go for normal evaluation
            var result = thread.Runtime.ExecuteBinaryOperator(this.Op, arg1, arg2, ref _lastUsed);

            thread.CurrentNode = Parent; //standard epilog
            return(result);
        }//method
 protected OperatorImplementation AddConverter(Type fromType, Type toType, UnaryOperatorMethod method)
 {
     var key = new OperatorDispatchKey(ExpressionType.ConvertChecked, fromType, toType);
     var impl = new OperatorImplementation(key, toType, method);
     OperatorImplementations[key] = impl;
     return impl;
 }
        public object ExecuteBinaryOperator(ExpressionType op, object arg1, object arg2, ref OperatorImplementation previousUsed)
        {
            // 1. Get arg types
            Type arg1Type, arg2Type;
            try
            {
                arg1Type = arg1.GetType();
                arg2Type = arg2.GetType();
            }
            catch (NullReferenceException)
            {
                // arg1 or arg2 is null - which means never assigned.
                CheckUnassigned(arg1);
                CheckUnassigned(arg2);
                throw;
            }

            // 2. If we had prev impl, check if current args types match it; first copy it into local variable
            // Note: BinaryExpression node might already have tried it directly, without any checks, and 
            // apparently failed. At some point this attempt in BinaryExpressionNode can become disabled.
            // But we might still try it here, with proper checks
            var currentImpl = previousUsed;
            if (currentImpl != null && (arg1Type != currentImpl.Key.Arg1Type || arg2Type != currentImpl.Key.Arg2Type))
                currentImpl = null;

            // 3. Find implementation for arg types
            OperatorDispatchKey key;
            if (currentImpl == null)
            {
                key = new OperatorDispatchKey(op, arg1Type, arg2Type);
                if (!OperatorImplementations.TryGetValue(key, out currentImpl))
                    ThrowScriptError(Resources.ErrOpNotDefinedForTypes, op, arg1Type, arg2Type);
            }

            // 4. Actually call 
            try
            {
                previousUsed = currentImpl;
                return currentImpl.EvaluateBinary(arg1, arg2);
            }
            catch (OverflowException)
            {
                if (currentImpl.OverflowHandler == null) throw;
                previousUsed = currentImpl.OverflowHandler; //set previousUsed to overflowHandler, so it will be used next time
                return ExecuteBinaryOperator(op, arg1, arg2, ref previousUsed); //call self recursively
            }
            catch (IndexOutOfRangeException)
            {
                //We can get here only if we use SmartBoxing - the result is out of range of pre-allocated boxes, 
                // so attempt to lookup a boxed value in _boxes dictionary fails with outOfRange exc
                if (currentImpl.NoBoxImplementation == null) throw;
                // If NoBoxImpl is not null, then it is implementation with auto-boxing. 
                // Auto-boxing failed - the result is outside the range of our boxes array. Let's call no-box version.
                // we also set previousUsed to no-box implementation, so we use it in the future calls
                previousUsed = currentImpl.NoBoxImplementation;
                return ExecuteBinaryOperator(op, arg1, arg2, ref previousUsed); //call self recursively
            }

        }//method
 protected OperatorImplementation AddBinary(ExpressionType op, Type commonType,
                  BinaryOperatorMethod binaryMethod, UnaryOperatorMethod resultConverter)
 {
     var key = new OperatorDispatchKey(op, commonType, commonType);
     var impl = new OperatorImplementation(key, commonType, binaryMethod, null, null, resultConverter);
     OperatorImplementations[key] = impl;
     return impl;
 }
 protected object EvaluateFast(ScriptThread thread) {
   thread.CurrentNode = this;  //standard prolog
   var arg1 = Left.Evaluate(thread);
   var arg2 = Right.Evaluate(thread);
   //If we have _lastUsed, go straight for it; if types mismatch it will throw
   if (_lastUsed != null) {
     try {
       var res = _lastUsed.EvaluateBinary(arg1, arg2);
       thread.CurrentNode = Parent; //standard epilog
       return res;
     } catch {
       _lastUsed = null;
       _failureCount++;
       // if failed 3 times, change to method without direct try
       if (_failureCount > 3)
         Evaluate = DefaultEvaluateImplementation;
     } //catch
   }// if _lastUsed
   // go for normal evaluation
   var result = thread.Runtime.ExecuteBinaryOperator(this.Op, arg1, arg2, ref _lastUsed);
   thread.CurrentNode = Parent; //standard epilog
   return result;
 }//method
Example #7
0
 protected void AddImplementation(string op, Type baseType, BinaryOperatorMethod baseMethod, TypeConverter resultConverter) {
   var key = OperatorDispatchKey.CreateFromTypes(op, baseType, baseType);
   var imp = new OperatorImplementation(key, baseType, baseMethod,  null, null, resultConverter);
   _baseOperatorImplementations.Add(key, imp);
 }
 protected OperatorImplementation AddUnary(ExpressionType op, Type commonType, UnaryOperatorMethod unaryMethod) {
   var key = new OperatorDispatchKey(op, commonType);
   var impl = new OperatorImplementation(key, commonType, null, unaryMethod, null, null);
   OperatorImplementations[key] = impl;
   return impl;
 }
 private static bool CanOverflow(OperatorImplementation impl) {
   if (!CanOverflow(impl.Key.Op))
     return false;
   if (impl.CommonType == typeof(Int32) && IsSmallInt(impl.Key.Arg1Type) && IsSmallInt(impl.Key.Arg2Type))
     return false;
   if (impl.CommonType == typeof(double) || impl.CommonType == typeof(Single))
     return false;
   if (impl.CommonType == typeof(BigInteger))
     return false;
   return true;
 }
 protected virtual OperatorImplementation CreateBinaryOperatorImplementation(ExpressionType op, Type arg1Type, Type arg2Type, 
                Type commonType, BinaryOperatorMethod method, UnaryOperatorMethod resultConverter) {
   OperatorDispatchKey key = new OperatorDispatchKey(op, arg1Type, arg2Type);
   UnaryOperatorMethod arg1Converter = arg1Type == commonType ? null : GetConverter(arg1Type, commonType);
   UnaryOperatorMethod arg2Converter = arg2Type == commonType ? null : GetConverter(arg2Type, commonType);
   var impl = new OperatorImplementation(
     key, commonType, method, arg1Converter, arg2Converter, resultConverter);
   return impl; 
 }