public static Expression IsNull(Expression[] values) { if (values.Length != 1) { return(null); } return(Ast.Equal(values[0], Ast.Null())); }
public static Expression FxOdd(params Expression[] args) { if (Expect <int>(args, 1)) { return(Ast.Equal(Ast.Add(UnwrapAndCast <int>(args[0]), Ast.Constant(1)), Ast.Constant(1))); } return(null); }
public static Expression Eq(Expression[] obj) { if (obj.Length == 2) { return(Ast.Equal(obj[0], obj[1])); } return(null); }
public static Expression FxEquals(params Expression[] args) { if (Expect <int>(args, 2)) { return(Ast.Equal(UnwrapAndCast <int>(args[0]), UnwrapAndCast <int>(args[1]))); } return(null); }
public Expression MakeTypeTest(Type type, Expression tested) { if (type == null || type == typeof(Null)) { return(Ast.Equal(tested, Ast.Constant(null))); } return(MakeTypeTestExpression(type, tested)); }
private static Restrictions GetFallbackRestrictions(Type t, EventTracker et, MetaObject self) { if (t == typeof(EventTracker)) { // // Test Generated: // BinderOps.GetEventHandlerType(((EventTracker)args[0]).Event) == et.Event.EventHandlerType // return(Restrictions.GetExpressionRestriction( Ast.Equal( Ast.Call( typeof(BinderOps).GetMethod("GetEventHandlerType"), Ast.Property( Ast.Convert( self.Expression, typeof(EventTracker) ), typeof(EventTracker).GetProperty("Event") ) ), Ast.Constant(et.Event.EventHandlerType) ) )); } else if (t == typeof(BoundMemberTracker)) { // // Test Generated: // BinderOps.GetEventHandlerType(((EventTracker)((BoundMemberTracker)args[0]).BountTo).Event) == et.Event.EventHandlerType // return(Restrictions.GetExpressionRestriction( Ast.Equal( Ast.Call( typeof(BinderOps).GetMethod("GetEventHandlerType"), Ast.Property( Ast.Convert( Ast.Property( Ast.Convert( self.Expression, typeof(BoundMemberTracker) ), typeof(BoundMemberTracker).GetProperty("BoundTo") ), typeof(EventTracker) ), typeof(EventTracker).GetProperty("Event") ) ), Ast.Constant(et.Event.EventHandlerType) ) )); } return(Restrictions.Empty); }
public static Expression /*!*/ GetObjectTypeTestExpression(object value, Expression /*!*/ expression) { if (value == null) { return(Ast.Equal(expression, AstUtils.Constant(null))); } else { return(MakeTypeTestExpression(value.GetType(), expression)); } }
protected virtual MethodBase[] GetTargetMethods() { if (_targets != null) { return(_targets); } object target = Callable; MethodBase[] targets; Delegate d; MemberGroup mg; MethodGroup mthgrp; BoundMemberTracker bmt; if ((d = target as Delegate) != null) { targets = GetDelegateTargets(d); } else if ((mg = target as MemberGroup) != null) { List <MethodInfo> foundTargets = new List <MethodInfo>(); foreach (MemberTracker mt in mg) { if (mt.MemberType == TrackerTypes.Method) { foundTargets.Add(((MethodTracker)mt).Method); } } targets = foundTargets.ToArray(); } else if ((mthgrp = target as MethodGroup) != null) { _test = Ast.AndAlso(_test, Ast.Equal(Ast.Convert(Rule.Parameters[0], typeof(object)), Ast.Constant(target))); List <MethodBase> foundTargets = new List <MethodBase>(); foreach (MethodTracker mt in mthgrp.Methods) { foundTargets.Add(mt.Method); } targets = foundTargets.ToArray(); } else if ((bmt = target as BoundMemberTracker) != null) { targets = GetBoundMemberTargets(bmt); } else { targets = GetOperatorTargets(target); } return(targets); }
private Expression /*!*/ MarshalArgument(MetaObjectBuilder /*!*/ metaBuilder, DynamicMetaObject /*!*/ arg, ArgType parameterType) { object value = arg.Value; if (value == null) { metaBuilder.AddRestriction(Ast.Equal(arg.Expression, AstUtils.Constant(null))); } else { metaBuilder.AddTypeRestriction(value.GetType(), arg.Expression); } switch (parameterType) { case ArgType.Buffer: if (value == null) { return(AstUtils.Constant(null, typeof(byte[]))); } if (value is int && (int)value == 0) { metaBuilder.AddRestriction(Ast.Equal(AstUtils.Convert(arg.Expression, typeof(int)), AstUtils.Constant(0))); return(AstUtils.Constant(null, typeof(byte[]))); } if (value.GetType() == typeof(MutableString)) { return(Methods.GetMutableStringBytes.OpCall( AstUtils.Convert(arg.Expression, typeof(MutableString)) )); } return(Methods.GetMutableStringBytes.OpCall( AstUtils.LightDynamic(ConvertToStrAction.Make(_context), typeof(MutableString), arg.Expression) )); case ArgType.Int32: if (value is int) { return(AstUtils.Convert(arg.Expression, typeof(int))); } return(Ast.Convert( Ast.Call( AstUtils.LightDynamic(ConvertToIntAction.Make(_context), typeof(IntegerValue), arg.Expression), Methods.IntegerValue_ToUInt32Unchecked ), typeof(int) )); } throw Assert.Unreachable; }
public void AddObjectTypeRestriction(object value, Expression /*!*/ expression) { if (value == null) { AddRestriction(Ast.Equal(expression, AstUtils.Constant(null))); } else { AddTypeRestriction(value.GetType(), expression); } }
private void AddFallbackMemberTest(Type t, EventTracker et) { if (t == typeof(EventTracker)) { // // Test Generated: // ScriptingRuntimeHelpers.GetEventHandlerType(((EventTracker)args[0]).Event) == et.Event.EventHandlerType // _rule.AddTest( Ast.Equal( Ast.Call( typeof(ScriptingRuntimeHelpers).GetMethod("GetEventHandlerType"), Ast.Property( Ast.Convert( _rule.Parameters[0], typeof(EventTracker) ), typeof(EventTracker).GetProperty("Event") ) ), Ast.Constant(et.Event.EventHandlerType) ) ); } else if (t == typeof(BoundMemberTracker)) { // // Test Generated: // ScriptingRuntimeHelpers.GetEventHandlerType(((EventTracker)((BoundMemberTracker)args[0]).BountTo).Event) == et.Event.EventHandlerType // _rule.AddTest( Ast.Equal( Ast.Call( typeof(ScriptingRuntimeHelpers).GetMethod("GetEventHandlerType"), Ast.Property( Ast.Convert( Ast.Property( Ast.Convert( _rule.Parameters[0], typeof(BoundMemberTracker) ), typeof(BoundMemberTracker).GetProperty("BoundTo") ), typeof(EventTracker) ), typeof(EventTracker).GetProperty("Event") ) ), Ast.Constant(et.Event.EventHandlerType) ) ); } }
public static Expression MakeParamsTest(StandardRule <T> rule, object paramArg, Expression listArg) { return(Ast.AndAlso( Ast.TypeIs(listArg, typeof(ICollection <object>)), Ast.Equal( Ast.ReadProperty( Ast.Convert(listArg, typeof(ICollection <object>)), typeof(ICollection <object>).GetProperty("Count") ), rule.AddTemplatedConstant(typeof(int), ((IList <object>)paramArg).Count) ) )); }
internal virtual void BuildInvoke(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args) { Assert.NotNull(metaBuilder, args); Debug.Assert(args.Target == this); // first argument must be this method: metaBuilder.AddRestriction(Ast.Equal(args.TargetExpression, AstUtils.Constant(this))); // set the target (becomes self in the called method): args.SetTarget(AstUtils.Constant(_target, CompilerHelpers.GetVisibleType(_target)), _target); _info.BuildCall(metaBuilder, args, _name); }
/// <summary> /// Builds the restrictions for calling with a splatted argument array. Ensures that the /// argument is still an ICollection of object and that it has the same number of arguments. /// </summary> private static BindingRestrictions MakeParamsTest(DynamicMetaObject splattee, bool testTypes) { IList <object> list = splattee.Value as IList <object>; if (list == null) { if (splattee.Value == null) { return(BindingRestrictions.GetExpressionRestriction(Ast.Equal(splattee.Expression, AstUtils.Constant(null)))); } else { return(BindingRestrictions.GetTypeRestriction(splattee.Expression, splattee.Value.GetType())); } } BindingRestrictions res = BindingRestrictions.GetExpressionRestriction( Ast.AndAlso( Ast.TypeIs(splattee.Expression, typeof(IList <object>)), Ast.Equal( Ast.Property( Ast.Convert(splattee.Expression, typeof(IList <object>)), typeof(ICollection <object>).GetDeclaredProperty("Count") ), AstUtils.Constant(list.Count) ) ) ); if (testTypes) { for (int i = 0; i < list.Count; i++) { res = res.Merge( BindingRestrictionsHelpers.GetRuntimeTypeRestriction( Ast.Call( AstUtils.Convert( splattee.Expression, typeof(IList <object>) ), typeof(IList <object>).GetMethod("get_Item"), AstUtils.Constant(i) ), CompilerHelpers.GetType(list[i]) ) ); } } return(res); }
internal static MSA.Expression /*!*/ MakeUserMethodBody(AstGenerator gen, int lastLine, MSA.Expression /*!*/ blockParameter, MSA.Expression /*!*/ rfcVariable, MSA.ParameterExpression /*!*/ methodUnwinder, MSA.Expression /*!*/ bodyStatement, ResultOperation resultOperation, int profileTickIndex, MSA.ParameterExpression stampVariable, MSA.LabelTarget returnLabel) { Assert.NotNull(blockParameter, rfcVariable, bodyStatement, methodUnwinder); Debug.Assert(!resultOperation.IsIgnore, "return value should not be ignored"); Debug.Assert(returnLabel != null || resultOperation.Variable != null, "return label needed"); MSA.Expression resultExpression = Ast.Field(methodUnwinder, MethodUnwinder.ReturnValueField); if (resultOperation.Variable != null) { resultExpression = Ast.Assign(resultOperation.Variable, resultExpression); } else { resultExpression = Ast.Return(returnLabel, resultExpression); } // TODO: move this to the caller: MSA.Expression profileStart, profileEnd; if (stampVariable != null) { profileStart = Ast.Assign(stampVariable, Methods.Stopwatch_GetTimestamp.OpCall()); profileEnd = Methods.UpdateProfileTicks.OpCall(Ast.Constant(profileTickIndex), stampVariable); } else { profileStart = profileEnd = Ast.Empty(); } return(AstUtils.Try( // initialize frame (RFC): profileStart, Ast.Assign(rfcVariable, Methods.CreateRfcForMethod.OpCall(AstUtils.Convert(blockParameter, typeof(Proc)))), bodyStatement ).Filter(methodUnwinder, Ast.Equal(Ast.Field(methodUnwinder, MethodUnwinder.TargetFrameField), rfcVariable), // return unwinder.ReturnValue; resultExpression ).Finally( Ast.Assign(Ast.Field(rfcVariable, RuntimeFlowControl.IsActiveMethodField), Ast.Constant(false)), profileEnd, gen != null && gen.TraceEnabled ? Methods.TraceMethodReturn.OpCall( gen.CurrentScopeVariable, Ast.Convert(Ast.Constant(gen.SourceUnit.Path), typeof(string)), Ast.Constant(lastLine) ) : Ast.Empty() )); }
/// <summary> /// Creates a test which tests the specific version of the type. /// </summary> private ValidationInfo /*!*/ MakeVersionCheck() { int version = Value.Version; return(new ValidationInfo( Ast.Equal( Ast.Call( typeof(PythonOps).GetMethod("GetTypeVersion"), Ast.Convert(Expression, typeof(PythonType)) ), AstUtils.Constant(version) ) )); }
/// <summary> /// Binds to the BoundMemberTracker and uses the instance in the tracker and restricts /// based upon the object instance type. /// </summary> private TargetInfo TryGetBoundMemberTargets(DynamicMetaObject self, DynamicMetaObject[] args, BoundMemberTracker bmt) { if (bmt != null) { Debug.Assert(bmt.Instance == null); // should be null for trackers that leak to user code MethodBase[] targets; // instance is pulled from the BoundMemberTracker and restricted to the correct // type. DynamicMetaObject instance = new DynamicMetaObject( AstUtils.Convert( Ast.Property( Ast.Convert(self.Expression, typeof(BoundMemberTracker)), typeof(BoundMemberTracker).GetDeclaredProperty("ObjectInstance") ), bmt.BoundTo.DeclaringType ), self.Restrictions ).Restrict(CompilerHelpers.GetType(bmt.ObjectInstance)); // we also add a restriction to make sure we're going to the same BoundMemberTracker BindingRestrictions restrictions = BindingRestrictions.GetExpressionRestriction( Ast.Equal( Ast.Property( Ast.Convert(self.Expression, typeof(BoundMemberTracker)), typeof(BoundMemberTracker).GetDeclaredProperty("BoundTo") ), AstUtils.Constant(bmt.BoundTo) ) ); switch (bmt.BoundTo.MemberType) { case TrackerTypes.MethodGroup: targets = ((MethodGroup)bmt.BoundTo).GetMethodBases(); break; case TrackerTypes.Method: targets = new MethodBase[] { ((MethodTracker)bmt.BoundTo).Method }; break; default: throw new InvalidOperationException(); // nothing else binds yet } return(new TargetInfo(instance, args, restrictions, targets)); } return(null); }
protected override MethodBase[] GetTargetMethods() { object target = Arguments[0]; Type t = GetTargetType(target); if (t != null) { Test = Ast.AndAlso(Test, Ast.Equal(Rule.Parameters[0], Ast.Constant(target))); return(CompilerHelpers.GetConstructors(t, Binder.PrivateBinding)); } return(null); }
private void AddRuntimeTest(DynamicMetaObject /*!*/ metaContext) { Assert.NotNull(metaContext); // check for runtime (note that the module's runtime could be different from the call-site runtime): if (_siteContext == null) { // TODO: use holder AddRestriction(Ast.Equal(metaContext.Expression, AstUtils.Constant(metaContext.Value))); } else if (_siteContext != metaContext.Value) { throw new InvalidOperationException("Runtime-bound site called from a different runtime"); } }
public void MakeNewRule() { Type targetType = CompilerHelpers.GetType(Target); Rule.MakeTest(StrongBoxType ?? targetType); if (typeof(TypeTracker).IsAssignableFrom(targetType)) { targetType = ((TypeTracker)Target).Type; _isStatic = true; Rule.AddTest(Ast.Equal(Rule.Parameters[0], Ast.Constant(Arguments[0]))); } MakeSetMemberRule(targetType); Rule.Target = Body; }
private MethodBase[] GetBoundMemberTargets(BoundMemberTracker bmt) { Debug.Assert(bmt.Instance == null); // should be null for trackers that leak to user code MethodBase[] targets; _instance = Ast.Convert( Ast.Property( Ast.Convert(Rule.Parameters[0], typeof(BoundMemberTracker)), typeof(BoundMemberTracker).GetProperty("ObjectInstance") ), bmt.BoundTo.DeclaringType ); _test = Ast.AndAlso( _test, Ast.Equal( Ast.Property( Ast.Convert(Rule.Parameters[0], typeof(BoundMemberTracker)), typeof(BoundMemberTracker).GetProperty("BoundTo") ), Ast.Constant(bmt.BoundTo) ) ); _test = Ast.AndAlso( _test, Rule.MakeTypeTest( CompilerHelpers.GetType(bmt.ObjectInstance), Ast.Property( Ast.Convert(Rule.Parameters[0], typeof(BoundMemberTracker)), typeof(BoundMemberTracker).GetProperty("ObjectInstance") ) ) ); switch (bmt.BoundTo.MemberType) { case TrackerTypes.MethodGroup: targets = ((MethodGroup)bmt.BoundTo).GetMethodBases(); break; case TrackerTypes.Method: targets = new MethodBase[] { ((MethodTracker)bmt.BoundTo).Method }; break; default: throw new InvalidOperationException(); // nothing else binds yet } return(targets); }
internal static MethodResolutionResult Resolve(MetaObjectBuilder /*!*/ metaBuilder, string /*!*/ methodName, CallArguments /*!*/ args, out RubyMemberInfo methodMissing) { MethodResolutionResult method; var targetClass = args.TargetClass; var visibilityContext = GetVisibilityContext(args.Signature, args.Scope); using (targetClass.Context.ClassHierarchyLocker()) { metaBuilder.AddTargetTypeTest(args.Target, targetClass, args.TargetExpression, args.MetaContext, new[] { methodName, Symbols.MethodMissing } ); if (args.Signature.IsSuperCall) { Debug.Assert(!args.Signature.IsVirtualCall && args.Signature.HasImplicitSelf); method = targetClass.ResolveSuperMethodNoLock(methodName, targetClass).InvalidateSitesOnOverride(); } else { var options = args.Signature.IsVirtualCall ? MethodLookup.Virtual : MethodLookup.Default; method = targetClass.ResolveMethodForSiteNoLock(methodName, visibilityContext, options); } if (!method.Found) { methodMissing = targetClass.ResolveMethodMissingForSite(methodName, method.IncompatibleVisibility); } else { methodMissing = null; } } // Whenever the current self's class changes we need to invalidate the rule, if a protected method is being called. if (method.Info != null && method.Info.IsProtected && visibilityContext.Class != null) { // We don't need to compare versions, just the class objects (super-class relationship cannot be changed). // Since we don't want to hold on a class object (to make it collectible) we compare references to the version handlers. metaBuilder.AddCondition(Ast.Equal( Methods.GetSelfClassVersionHandle.OpCall(AstUtils.Convert(args.MetaScope.Expression, typeof(RubyScope))), Ast.Constant(visibilityContext.Class.Version) )); } return(method); }
private void BuildCall(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name) { var actualArgs = RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 0, Int32.MaxValue); if (metaBuilder.Error) { return; } metaBuilder.AddRestriction( Ast.Equal( Ast.Property(Ast.Convert(args.TargetExpression, typeof(Win32API)), VersionProperty), Ast.Constant(_version) ) ); if (_function == IntPtr.Zero) { metaBuilder.SetError(Ast.Throw(new Func <Exception>(UninitializedFunctionError).Method.OpCall(), typeof(object))); return; } if (_signature.Length != actualArgs.Count) { metaBuilder.SetError(Ast.Throw(new Func <int, int, Exception>(InvalidParameterCountError).Method.OpCall( Ast.Constant(_signature.Length), Ast.Constant(actualArgs.Count)), typeof(object) )); return; } var calliArgs = new AstExpressions(); calliArgs.Add(Ast.Property(Ast.Convert(args.TargetExpression, typeof(Win32API)), FunctionProperty)); for (int i = 0; i < actualArgs.Count; i++) { calliArgs.Add(MarshalArgument(metaBuilder, actualArgs[i], _signature[i])); } metaBuilder.Result = Ast.Call(EmitCalliStub(), calliArgs); // MRI returns 0 if void return type is given: if (_returnType == ArgType.None) { metaBuilder.Result = Ast.Block(metaBuilder.Result, AstUtils.Constant(0)); } }
internal static MSA.Expression /*!*/ MakeCallWithBlockRetryable(AstGenerator /*!*/ gen, MSA.Expression /*!*/ invoke, MSA.Expression blockArgVariable, MSA.Expression transformedBlock, bool isBlockDefinition) { Assert.NotNull(invoke); Debug.Assert((blockArgVariable == null) == (transformedBlock == null)); // see Ruby Language.doc/Control Flow Implementation/Method Call With a Block MSA.Expression resultVariable = gen.CurrentScope.DefineHiddenVariable("#method-result", typeof(object)); MSA.ParameterExpression evalUnwinder; MSA.LabelTarget retryLabel = Ast.Label("retry"); var result = new AstBlock { Ast.Assign(blockArgVariable, Ast.Convert(transformedBlock, blockArgVariable.Type)), Ast.Label(retryLabel), (isBlockDefinition) ? Methods.InitializeBlock.OpCall(blockArgVariable) : null, AstUtils.Try( Ast.Assign(resultVariable, invoke) ).Catch(evalUnwinder = Ast.Parameter(typeof(EvalUnwinder), "#u"), Ast.Assign( resultVariable, Ast.Field(evalUnwinder, EvalUnwinder.ReturnValueField) ) ), Ast.IfThen(Ast.TypeEqual(resultVariable, typeof(BlockReturnResult)), Ast.IfThenElse(Methods.IsRetrySingleton.OpCall(resultVariable), // retry: AstUtils.IfThenElse(Ast.Equal(gen.MakeMethodBlockParameterRead(), blockArgVariable), RetryStatement.TransformRetry(gen), Ast.Goto(retryLabel) ), // return: gen.Return(ReturnStatement.Propagate(gen, resultVariable)) ) ), resultVariable }; return(result); }
internal void AddSplattedArgumentTest(IList /*!*/ value, Expression /*!*/ expression, out int listLength, out ParameterExpression /*!*/ listVariable) { Expression assignment; listVariable = expression as ParameterExpression; if (listVariable != null && typeof(IList).IsAssignableFrom(expression.Type)) { assignment = expression; } else { listVariable = GetTemporary(typeof(IList), "#list"); assignment = Ast.Assign(listVariable, AstUtils.Convert(expression, typeof(IList))); } listLength = value.Count; AddCondition(Ast.Equal(Ast.Property(assignment, typeof(ICollection).GetDeclaredProperty("Count")), AstUtils.Constant(value.Count))); }
/// <summary> /// Produces a rule for comparing a value to null - supports comparing object references and nullable types. /// </summary> private static DynamicMetaObject TryNullComparisonRule(DynamicMetaObject[] args) { Type otherType = args[1].GetLimitType(); BindingRestrictions restrictions = BindingRestrictionsHelpers.GetRuntimeTypeRestriction(args[0].Expression, args[0].GetLimitType()).Merge(BindingRestrictions.Combine(args)); if (args[0].GetLimitType() == typeof(DynamicNull)) { if (!otherType.IsValueType()) { return(new DynamicMetaObject( Ast.Equal(args[0].Expression, AstUtils.Constant(null)), restrictions )); } if (otherType.GetGenericTypeDefinition() == typeof(Nullable <>)) { return(new DynamicMetaObject( Ast.Property(args[0].Expression, otherType.GetDeclaredProperty("HasValue")), restrictions )); } } else if (otherType == typeof(DynamicNull)) { if (!args[0].GetLimitType().IsValueType()) { return(new DynamicMetaObject( Ast.Equal(args[0].Expression, AstUtils.Constant(null)), restrictions )); } if (args[0].GetLimitType().GetGenericTypeDefinition() == typeof(Nullable <>)) { return(new DynamicMetaObject( Ast.Property(args[0].Expression, otherType.GetDeclaredProperty("HasValue")), restrictions )); } } return(null); }
/// <summary> /// Takes current result and wraps it into try-filter(MethodUnwinder)-finally block that ensures correct "break" behavior for /// library method calls with block given in bfcVariable (BlockParam). /// </summary> public static void RuleControlFlowBuilder(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args) { if (metaBuilder.Error) { return; } var metaBlock = args.GetMetaBlock(); Debug.Assert(metaBlock != null, "RuleControlFlowBuilder should only be used if the signature has a block"); // We construct CF only for non-nil blocks thus we need a test for it: if (metaBlock.Value == null) { metaBuilder.AddRestriction(Ast.Equal(metaBlock.Expression, AstUtils.Constant(null))); return; } // don't need to test the exact type of the Proc since the code is subclass agnostic: metaBuilder.AddRestriction(Ast.NotEqual(metaBlock.Expression, AstUtils.Constant(null))); Expression bfcVariable = metaBuilder.BfcVariable; Debug.Assert(bfcVariable != null); // Method call with proc can invoke control flow that returns an arbitrary value from the call, so we need to type result to Object. // Otherwise, the result could only be result of targetExpression unless its return type is void. Expression resultVariable = metaBuilder.GetTemporary(typeof(object), "#result"); ParameterExpression unwinder; metaBuilder.Result = Ast.Block( Ast.Assign(bfcVariable, Methods.CreateBfcForLibraryMethod.OpCall(AstUtils.Convert(args.GetBlockExpression(), typeof(Proc)))), AstUtils.Try( Ast.Assign(resultVariable, AstUtils.Convert(metaBuilder.Result, typeof(object))) ).Filter(unwinder = Ast.Parameter(typeof(MethodUnwinder), "#unwinder"), Methods.IsProcConverterTarget.OpCall(bfcVariable, unwinder), Ast.Assign(resultVariable, Ast.Field(unwinder, MethodUnwinder.ReturnValueField)), AstUtils.Default(typeof(object)) ).Finally( Methods.LeaveProcConverter.OpCall(bfcVariable) ), resultVariable ); }
/// <summary> /// Produces a rule for comparing a value to null - supports comparing object references and nullable types. /// </summary> private static MetaObject TryNullComparisonRule(MetaObject[] args) { Type otherType = args[0].LimitType; Restrictions restrictions = Restrictions.GetTypeRestriction(args[0].Expression, args[0].LimitType).Merge(Restrictions.Combine(args)); if (args[0].LimitType == typeof(Null)) { if (!otherType.IsValueType) { return(new MetaObject( Ast.Equal(args[0].Expression, Ast.Constant(null)), restrictions )); } else if (otherType.GetGenericTypeDefinition() == typeof(Nullable <>)) { return(new MetaObject( Ast.Property(args[0].Expression, otherType.GetProperty("HasValue")), restrictions )); } } else if (otherType == typeof(Null)) { if (!args[0].LimitType.IsValueType) { return(new MetaObject( Ast.Equal(args[0].Expression, Ast.Constant(null)), restrictions )); } else if (args[0].LimitType.GetGenericTypeDefinition() == typeof(Nullable <>)) { return(new MetaObject( Ast.Property(args[0].Expression, otherType.GetProperty("HasValue")), restrictions )); } } return(null); }
private MetaObject TryNumericComparison(OperatorInfo info, MetaObject[] args) { MethodInfo[] targets = FilterNonMethods( args[0].LimitType, GetMember(OldDoOperationAction.Make(this, info.Operator), args[0].LimitType, "Compare") ); if (targets.Length > 0) { MethodBinder mb = MethodBinder.MakeBinder(this, targets[0].Name, targets); BindingTarget target = mb.MakeBindingTarget(CallTypes.None, args); if (target.Success) { Expression call = AstUtils.Convert(target.MakeExpression(), typeof(int)); switch (info.Operator) { case Operators.GreaterThan: call = Ast.GreaterThan(call, Ast.Constant(0)); break; case Operators.LessThan: call = Ast.LessThan(call, Ast.Constant(0)); break; case Operators.GreaterThanOrEqual: call = Ast.GreaterThanOrEqual(call, Ast.Constant(0)); break; case Operators.LessThanOrEqual: call = Ast.LessThanOrEqual(call, Ast.Constant(0)); break; case Operators.Equals: call = Ast.Equal(call, Ast.Constant(0)); break; case Operators.NotEquals: call = Ast.NotEqual(call, Ast.Constant(0)); break; case Operators.Compare: break; } return(new MetaObject( call, Restrictions.Combine(target.RestrictedArguments) )); } } return(null); }
private DynamicMetaObject TryNumericComparison(OperatorInfo info, OverloadResolverFactory resolverFactory, DynamicMetaObject[] args) { MethodInfo[] targets = FilterNonMethods( args[0].GetLimitType(), GetMember( MemberRequestKind.Operation, args[0].GetLimitType(), "Compare" ) ); if (targets.Length > 0) { var resolver = resolverFactory.CreateOverloadResolver(args, new CallSignature(args.Length), CallTypes.None); BindingTarget target = resolver.ResolveOverload(targets[0].Name, targets, NarrowingLevel.None, NarrowingLevel.All); if (target.Success) { Expression call = AstUtils.Convert(target.MakeExpression(), typeof(int)); switch (info.Operator) { case ExpressionType.GreaterThan: call = Ast.GreaterThan(call, AstUtils.Constant(0)); break; case ExpressionType.LessThan: call = Ast.LessThan(call, AstUtils.Constant(0)); break; case ExpressionType.GreaterThanOrEqual: call = Ast.GreaterThanOrEqual(call, AstUtils.Constant(0)); break; case ExpressionType.LessThanOrEqual: call = Ast.LessThanOrEqual(call, AstUtils.Constant(0)); break; case ExpressionType.Equal: call = Ast.Equal(call, AstUtils.Constant(0)); break; case ExpressionType.NotEqual: call = Ast.NotEqual(call, AstUtils.Constant(0)); break; } return(new DynamicMetaObject( call, target.RestrictedArguments.GetAllRestrictions() )); } } return(null); }