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; }
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); }
internal void SetRuleForCall(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args) { Assert.NotNull(metaBuilder, args); Debug.Assert(args.Target == this); // TODO: we could compare infos here: // first argument must be this method: metaBuilder.AddRestriction(Ast.Equal(args.TargetExpression, Ast.Constant(this))); // set the target (becomes self in the called method): args.SetTarget(Ast.Constant(_target), _target); _info.BuildCall(metaBuilder, args, _name); }
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)); } }