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); }
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); }
/* * 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); }
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