예제 #1
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);
        }
        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);
        }
        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 virtual OperatorImplementation CreateBinaryOperatorImplementation(ExpressionType op, Type arg1Type, Type arg2Type,
                                                                                    Type commonType, BinaryOperatorMethod method, UnaryOperatorMethod resultConverter)
        {
            var key           = new OperatorDispatchKey(op, arg1Type, arg2Type);
            var arg1Converter = arg1Type == commonType ? null : GetConverter(arg1Type, commonType);
            var arg2Converter = arg2Type == commonType ? null : GetConverter(arg2Type, commonType);
            var impl          = new OperatorImplementation(key, commonType, method, arg1Converter, arg2Converter, resultConverter);

            return(impl);
        }
예제 #6
0
        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
            }
        }
 private static bool CanOverflow(OperatorImplementation impl)
 {
     if (!CanOverflow(impl.Key.Op))
     {
         return(false);
     }
     if (impl.CommonType == typeof(int) && IsSmallInt(impl.Key.Arg1Type) && IsSmallInt(impl.Key.Arg2Type))
     {
         return(false);
     }
     if (impl.CommonType == typeof(double) || impl.CommonType == typeof(float))
     {
         return(false);
     }
     if (impl.CommonType == typeof(BigInteger))
     {
         return(false);
     }
     return(true);
 }
예제 #8
0
/*
 *  public virtual FunctionBindingInfo GetFunctionBindingInfo(string name, AstNodeList  parameters) {
 *    return FunctionBindings.Find(name, parameters.Count);
 *  }
 *  //Utility methods for adding library functions
 *  public FunctionBindingInfo AddFunction(string name, int paramCount) {
 *    return null;
 *  }
 *  public FunctionBindingInfo AddFunction(string name, int paramCount, FunctionFlags flags) {
 *    FunctionBindingInfo info = new FunctionBindingInfo(name, paramCount, null, flags);
 *    FunctionBindings.Add(name, info);
 *    return info;
 *  }
 */

        #region Operator implementations
        // When an implementation for exact type pair is not found, we find implementation for base type and create
        // implementation for exact types using type converters
        public virtual OperatorImplementation AddOperatorImplementation(OperatorImplementationTable implementations, OperatorDispatchKey forKey)
        {
            Type baseType = GetBaseTypeForExpression(forKey.OpSymbol, forKey.Arg1Type, forKey.Arg2Type);

            if (baseType == null)
            {
                return(null);
            }
            TypeConverter arg1Converter = GetConverter(forKey.Arg1Type, baseType);
            TypeConverter arg2Converter = GetConverter(forKey.Arg2Type, baseType);
            //Get base method for the operator and common type
            var baseKey = OperatorDispatchKey.CreateFromTypes(forKey.OpSymbol, baseType, baseType);
            OperatorImplementation baseImpl;

            if (!_baseOperatorImplementations.TryGetValue(baseKey, out baseImpl))
            {
                throw new Exception(string.Format(Resources.ErrOpNotDefinedForTypes, forKey.OpSymbol, forKey.Arg1Type, forKey.Arg2Type));
            }
            var impl = new OperatorImplementation(forKey, baseType, baseImpl.BaseMethod, arg1Converter, arg2Converter, baseImpl.ResultConverter);

            implementations[forKey] = impl;
            return(impl);
        }
예제 #9
0
 public virtual bool HandleException(Exception ex, DynamicCallDispatcher dispatcher, OperatorImplementation failedTarget, EvaluationContext context)
 {
     return(false);
 }
        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