internal override void BuildCallNoFlow(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name) { // TODO: splat, rhs, ... if (args.Signature.ArgumentCount == 0) { if (args.Signature.HasBlock) { metaBuilder.Result = Methods.HookupEvent.OpCall( AstUtils.Constant(this), args.TargetExpression, Ast.Convert(args.GetBlockExpression(), typeof(Proc)) ); } else { metaBuilder.Result = Methods.CreateEvent.OpCall( AstUtils.Constant(this), args.TargetExpression, AstUtils.Constant(name) ); } } else { metaBuilder.SetError(Methods.MakeWrongNumberOfArgumentsError.OpCall(Ast.Constant(args.Signature.ArgumentCount), Ast.Constant(0))); } }
internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) { if (args.Signature.HasBlock) { metaBuilder.Result = Methods.HookupEvent.OpCall( Ast.Convert(Ast.Constant(_eventInfo), typeof(EventInfo)), args.TargetExpression, Ast.Convert(args.GetBlockExpression(), typeof(Proc)) ); } else { // TODO: make error throw new NotImplementedError("no block given"); } }
internal override void BuildCallNoFlow(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name) { if (args.Signature.HasBlock) { metaBuilder.Result = Methods.HookupEvent.OpCall( Ast.Convert(Ast.Constant(_eventInfo), typeof(EventInfo)), args.TargetExpression, Ast.Convert(args.GetBlockExpression(), typeof(Proc)) ); } else { // TODO: make error throw new NotImplementedError("no block given"); } }
internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) { // TODO: splat, rhs, ... if (args.Signature.ArgumentCount == 0) { if (args.Signature.HasBlock) { metaBuilder.Result = Methods.HookupEvent.OpCall( AstUtils.Constant(this), args.TargetExpression, Ast.Convert(args.GetBlockExpression(), typeof(Proc)) ); } else { metaBuilder.Result = Methods.CreateEvent.OpCall( AstUtils.Constant(this), args.TargetExpression, AstUtils.Constant(name) ); } } else { metaBuilder.SetError(Methods.MakeWrongNumberOfArgumentsError.OpCall(Ast.Constant(args.Signature.ArgumentCount), Ast.Constant(0))); } }
internal override void BuildCallNoFlow(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name) { Assert.NotNull(metaBuilder, args, name); // 2 implicit args: self, block var argsBuilder = new ArgsBuilder(2, Parameters.Mandatory.Length, Parameters.LeadingMandatoryCount, Parameters.Optional.Length, Parameters.Unsplat != null); argsBuilder.SetImplicit(0, AstUtils.Box(args.TargetExpression)); argsBuilder.SetImplicit(1, args.Signature.HasBlock ? AstUtils.Convert(args.GetBlockExpression(), typeof(Proc)) : AstFactory.NullOfProc); argsBuilder.AddCallArguments(metaBuilder, args); if (metaBuilder.Error) { return; } // box explicit arguments: var boxedArguments = argsBuilder.GetArguments(); for (int i = 2; i < boxedArguments.Length; i++) { boxedArguments[i] = AstUtils.Box(boxedArguments[i]); } var method = GetDelegate(); if (method.GetType() == ParamsArrayDelegateType) { // Func<object, Proc, object[], object> metaBuilder.Result = AstFactory.CallDelegate(method, new[] { boxedArguments[0], boxedArguments[1], Ast.NewArrayInit(typeof(object), ArrayUtils.ShiftLeft(boxedArguments, 2)) }); } else { metaBuilder.Result = AstFactory.CallDelegate(method, boxedArguments); } }
public static Expression[]/*!*/ MakeActualArgs(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, bool includeSelf, bool selfIsInstance, bool calleeHasBlockParam, bool injectMissingBlockParam) { var actualArgs = new List<Expression>(args.ExplicitArgumentCount); // self (instance): if (includeSelf && selfIsInstance) { // test already added by method resolver Debug.Assert(args.TargetExpression != null); AddArgument(actualArgs, args.Target, args.TargetExpression); } Proc block = null; Expression blockExpression = null; // block test - we need to test for a block regardless of whether it is actually passed to the method or not // since the information that the block is not null is used for overload resolution. if (args.Signature.HasBlock) { block = args.GetBlock(); blockExpression = args.GetBlockExpression(); if (block == null) { metaBuilder.AddRestriction(Ast.Equal(blockExpression, Ast.Constant(null))); } else { // don't need to test the exact type of the Proc since the code is subclass agnostic: metaBuilder.AddRestriction(Ast.NotEqual(blockExpression, Ast.Constant(null))); } } // block: if (calleeHasBlockParam) { if (args.Signature.HasBlock) { if (block == null) { // the user explicitly passed nil as a block arg: actualArgs.Add(Ast.Constant(null)); } else { // pass BlockParam: Debug.Assert(metaBuilder.BfcVariable != null); actualArgs.Add(metaBuilder.BfcVariable); } } else { // no block passed into a method with a BlockParam: actualArgs.Add(Ast.Constant(null)); } } else if (injectMissingBlockParam) { // no block passed into a method w/o a BlockParam (we still need to fill the missing block argument): actualArgs.Add(Ast.Constant(null)); } // self (non-instance): if (includeSelf && !selfIsInstance) { // test already added by method resolver AddArgument(actualArgs, args.Target, args.TargetExpression); } // simple arguments: for (int i = 0; i < args.SimpleArgumentCount; i++) { var value = args.GetSimpleArgument(i); var expr = args.GetSimpleArgumentExpression(i); metaBuilder.AddObjectTypeRestriction(value, expr); AddArgument(actualArgs, value, expr); } // splat argument: int listLength; ParameterExpression listVariable; if (args.Signature.HasSplattedArgument) { object splattedArg = args.GetSplattedArgument(); Expression splattedArgExpression = args.GetSplattedArgumentExpression(); if (metaBuilder.AddSplattedArgumentTest(splattedArg, splattedArgExpression, out listLength, out listVariable)) { // AddTestForListArg only returns 'true' if the argument is a List<object> var list = (List<object>)splattedArg; // get arguments, add tests for (int j = 0; j < listLength; j++) { var value = list[j]; var expr = Ast.Call(listVariable, typeof(List<object>).GetMethod("get_Item"), Ast.Constant(j)); metaBuilder.AddObjectTypeCondition(value, expr); AddArgument(actualArgs, value, expr); } } else { // argument is not an array => add the argument itself: AddArgument(actualArgs, splattedArg, splattedArgExpression); } } // rhs argument: if (args.Signature.HasRhsArgument) { var value = args.GetRhsArgument(); var expr = args.GetRhsArgumentExpression(); metaBuilder.AddObjectTypeRestriction(value, expr); AddArgument(actualArgs, value, expr); } return actualArgs.ToArray(); }
/// <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> internal static void ApplyBlockFlowHandlingInternal(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args) { if (metaBuilder.Error) { return; } Expression expression = metaBuilder.Result; Expression bfcVariable = metaBuilder.BfcVariable; // 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. Type resultType = (bfcVariable != null) ? typeof(object) : expression.Type; Expression resultVariable; if (resultType != typeof(void)) { resultVariable = metaBuilder.GetTemporary(resultType, "#result"); } else { resultVariable = Expression.Empty(); } if (expression.Type != typeof(void)) { expression = Ast.Assign(resultVariable, AstUtils.Convert(expression, resultType)); } // a non-null proc is being passed to the callee: if (bfcVariable != null) { ParameterExpression methodUnwinder = metaBuilder.GetTemporary(typeof(MethodUnwinder), "#unwinder"); expression = AstFactory.Block( Ast.Assign(bfcVariable, Methods.CreateBfcForLibraryMethod.OpCall(AstUtils.Convert(args.GetBlockExpression(), typeof(Proc)))), AstUtils.Try( expression ).Filter(methodUnwinder, Methods.IsProcConverterTarget.OpCall(bfcVariable, methodUnwinder), Ast.Assign(resultVariable, Ast.Field(methodUnwinder, MethodUnwinder.ReturnValueField)) ).Finally( Methods.LeaveProcConverter.OpCall(bfcVariable) ), resultVariable ); } metaBuilder.Result = expression; }
public static Expression[] /*!*/ MakeActualArgs(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, bool includeSelf, bool selfIsInstance, bool calleeHasBlockParam, bool injectMissingBlockParam) { var actualArgs = new List <Expression>(args.ExplicitArgumentCount); // self (instance): if (includeSelf && selfIsInstance) { // test already added by method resolver Debug.Assert(args.TargetExpression != null); AddArgument(actualArgs, args.Target, args.TargetExpression); } Proc block = null; Expression blockExpression = null; // block test - we need to test for a block regardless of whether it is actually passed to the method or not // since the information that the block is not null is used for overload resolution. if (args.Signature.HasBlock) { block = args.GetBlock(); blockExpression = args.GetBlockExpression(); if (block == null) { metaBuilder.AddRestriction(Ast.Equal(blockExpression, Ast.Constant(null))); } else { // don't need to test the exact type of the Proc since the code is subclass agnostic: metaBuilder.AddRestriction(Ast.NotEqual(blockExpression, Ast.Constant(null))); } } // block: if (calleeHasBlockParam) { if (args.Signature.HasBlock) { if (block == null) { // the user explicitly passed nil as a block arg: actualArgs.Add(Ast.Constant(null)); } else { // pass BlockParam: Debug.Assert(metaBuilder.BfcVariable != null); actualArgs.Add(metaBuilder.BfcVariable); } } else { // no block passed into a method with a BlockParam: actualArgs.Add(Ast.Constant(null)); } } else if (injectMissingBlockParam) { // no block passed into a method w/o a BlockParam (we still need to fill the missing block argument): actualArgs.Add(Ast.Constant(null)); } // self (non-instance): if (includeSelf && !selfIsInstance) { // test already added by method resolver AddArgument(actualArgs, args.Target, args.TargetExpression); } // simple arguments: for (int i = 0; i < args.SimpleArgumentCount; i++) { var value = args.GetSimpleArgument(i); var expr = args.GetSimpleArgumentExpression(i); metaBuilder.AddObjectTypeRestriction(value, expr); AddArgument(actualArgs, value, expr); } // splat argument: int listLength; ParameterExpression listVariable; if (args.Signature.HasSplattedArgument) { object splattedArg = args.GetSplattedArgument(); Expression splattedArgExpression = args.GetSplattedArgumentExpression(); if (metaBuilder.AddSplattedArgumentTest(splattedArg, splattedArgExpression, out listLength, out listVariable)) { // AddTestForListArg only returns 'true' if the argument is a List<object> var list = (List <object>)splattedArg; // get arguments, add tests for (int j = 0; j < listLength; j++) { var value = list[j]; var expr = Ast.Call(listVariable, typeof(List <object>).GetMethod("get_Item"), Ast.Constant(j)); metaBuilder.AddObjectTypeCondition(value, expr); AddArgument(actualArgs, value, expr); } } else { // argument is not an array => add the argument itself: AddArgument(actualArgs, splattedArg, splattedArgExpression); } } // rhs argument: if (args.Signature.HasRhsArgument) { var value = args.GetRhsArgument(); var expr = args.GetRhsArgumentExpression(); metaBuilder.AddObjectTypeRestriction(value, expr); AddArgument(actualArgs, value, expr); } return(actualArgs.ToArray()); }
/// <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> internal static void ApplyBlockFlowHandlingInternal(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args) { if (metaBuilder.Error) { return; } Expression expression = metaBuilder.Result; Expression bfcVariable = metaBuilder.BfcVariable; // 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. Type resultType = (bfcVariable != null) ? typeof(object) : expression.Type; Expression resultVariable; if (resultType != typeof(void)) { resultVariable = metaBuilder.GetTemporary(resultType, "#result"); } else { resultVariable = Expression.Empty(); } if (expression.Type != typeof(void)) { expression = Ast.Assign(resultVariable, AstUtils.Convert(expression, resultType)); } // a non-null proc is being passed to the callee: if (bfcVariable != null) { ParameterExpression methodUnwinder = metaBuilder.GetTemporary(typeof(MethodUnwinder), "#unwinder"); expression = AstFactory.Block( Ast.Assign(bfcVariable, Methods.CreateBfcForLibraryMethod.OpCall(AstUtils.Convert(args.GetBlockExpression(), typeof(Proc)))), AstUtils.Try( expression ).Filter(methodUnwinder, Methods.IsProcConverterTarget.OpCall(bfcVariable, methodUnwinder), Ast.Assign(resultVariable, Ast.Field(methodUnwinder, MethodUnwinder.ReturnValueField)) ).Finally( Methods.LeaveProcConverter.OpCall(bfcVariable) ), resultVariable ); } metaBuilder.Result = expression; }
/// <summary> /// Takes current result and wraps it into try-filter(MethodUnwinder)-finally block that ensures correct "break" behavior for /// Ruby method calls with a block given in arguments. /// /// Sets up a RFC frame similarly to MethodDeclaration. /// </summary> public static void RuleControlFlowBuilder(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args) { Debug.Assert(args.Signature.HasBlock); if (metaBuilder.Error) { return; } // TODO (improvement): // We don't special case null block here, although we could (we would need a test for that then). // We could also statically know (via call-site flag) that the current method is not a proc-converter (passed by ref), // which would make such calls faster. var rfcVariable = metaBuilder.GetTemporary(typeof(RuntimeFlowControl), "#rfc"); var resultVariable = metaBuilder.GetTemporary(typeof(object), "#result"); MSA.ParameterExpression unwinder; metaBuilder.Result = Ast.Block( // initialize frame (RFC): Ast.Assign(rfcVariable, Methods.CreateRfcForMethod.OpCall(AstUtils.Convert(args.GetBlockExpression(), typeof(Proc)))), AstUtils.Try( Ast.Assign(resultVariable, metaBuilder.Result) ).Filter(unwinder = Ast.Parameter(typeof(MethodUnwinder), "#unwinder"), Ast.Equal(Ast.Field(unwinder, MethodUnwinder.TargetFrameField), rfcVariable), // return unwinder.ReturnValue; Ast.Assign(resultVariable, Ast.Field(unwinder, MethodUnwinder.ReturnValueField)) ).Finally( // we need to mark the RFC dead snce the block might escape and break later: Methods.LeaveMethodFrame.OpCall(rfcVariable) ), resultVariable ); }
internal override void BuildCallNoFlow(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) { Assert.NotNull(metaBuilder, args, name); // 2 implicit args: self, block var argsBuilder = new ArgsBuilder(2, MandatoryParamCount, OptionalParamCount, _body.HasUnsplatParameter); argsBuilder.SetImplicit(0, AstUtils.Box(args.TargetExpression)); argsBuilder.SetImplicit(1, args.Signature.HasBlock ? AstUtils.Convert(args.GetBlockExpression(), typeof(Proc)) : AstFactory.NullOfProc); argsBuilder.AddCallArguments(metaBuilder, args); if (metaBuilder.Error) { return; } // box explicit arguments: var boxedArguments = argsBuilder.GetArguments(); for (int i = 2; i < boxedArguments.Length; i++) { boxedArguments[i] = AstUtils.Box(boxedArguments[i]); } var method = GetDelegate(); if (method.GetType() == ParamsArrayDelegateType) { // Func<object, Proc, object[], object> metaBuilder.Result = AstFactory.CallDelegate(method, new[] { boxedArguments[0], boxedArguments[1], Ast.NewArrayInit(typeof(object), ArrayUtils.ShiftLeft(boxedArguments, 2)) }); } else { metaBuilder.Result = AstFactory.CallDelegate(method, boxedArguments); } }
/// <summary> /// "yields" to the proc. /// </summary> internal void BuildInvoke(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args) { Assert.NotNull(metaBuilder, args); Debug.Assert(!args.Signature.HasBlock); var convertedTarget = AstUtils.Convert(args.TargetExpression, typeof(BlockParam)); // test for target type: metaBuilder.AddTypeRestriction(args.Target.GetType(), args.TargetExpression); metaBuilder.Result = AstFactory.YieldExpression( args.RubyContext, args.GetSimpleArgumentExpressions(), args.GetSplattedArgumentExpression(), args.GetRhsArgumentExpression(), args.GetBlockExpression(), convertedTarget, // block param Ast.Property(convertedTarget, SelfProperty) // self ); }
/// <summary> /// Takes current result and wraps it into try-filter(MethodUnwinder)-finally block that ensures correct "break" behavior for /// Ruby method calls with a block given in arguments. /// /// Sets up a RFC frame similarly to MethodDeclaration. /// </summary> public static void RuleControlFlowBuilder(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args) { Debug.Assert(args.Signature.HasBlock); if (metaBuilder.Error) { return; } // TODO (improvement): // We don't special case null block here, although we could (we would need a test for that then). // We could also statically know (via call-site flag) that the current method is not a proc-converter (passed by ref), // which would make such calls faster. var rfcVariable = metaBuilder.GetTemporary(typeof(RuntimeFlowControl), "#rfc"); var resultVariable = metaBuilder.GetTemporary(typeof(object), "#result"); MSA.ParameterExpression unwinder; metaBuilder.Result = Ast.Block( // initialize frame (RFC): Ast.Assign(rfcVariable, Methods.CreateRfcForMethod.OpCall(AstUtils.Convert(args.GetBlockExpression(), typeof(Proc)))), AstUtils.Try( Ast.Assign(resultVariable, metaBuilder.Result) ).Filter(unwinder = Ast.Parameter(typeof(MethodUnwinder), "#unwinder"), Ast.Equal(Ast.Field(unwinder, MethodUnwinder.TargetFrameField), rfcVariable), // return unwinder.ReturnValue; Ast.Assign(resultVariable, Ast.Field(unwinder, MethodUnwinder.ReturnValueField)) ).Finally( // we need to mark the RFC dead snce the block might escape and break later: Methods.LeaveMethodFrame.OpCall(rfcVariable) ), resultVariable ); }
/// <summary> /// From control flow perspective it "calls" the proc. /// </summary> internal static void BuildCall( MetaObjectBuilder/*!*/ metaBuilder, Expression/*!*/ procExpression, // proc object Expression/*!*/ selfExpression, // self passed to the proc CallArguments/*!*/ args // user arguments passed to the proc ) { var bfcVariable = metaBuilder.GetTemporary(typeof(BlockParam), "#bfc"); metaBuilder.Result = Ast.Block( Ast.Assign(bfcVariable, Methods.CreateBfcForProcCall.OpCall(AstUtils.Convert(procExpression, typeof(Proc)))), Methods.MethodProcCall.OpCall(bfcVariable, AstFactory.YieldExpression( args.RubyContext, args.GetSimpleArgumentExpressions(), args.GetSplattedArgumentExpression(), args.GetRhsArgumentExpression(), args.GetBlockExpression(), bfcVariable, selfExpression ) ) ); }
/// <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 ); }
private void BuildDelegateConstructorCall(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, Type/*!*/ type) { if (args.Signature.HasBlock) { RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 0, 0); if (!metaBuilder.Error) { metaBuilder.Result = Methods.CreateDelegateFromProc.OpCall( AstUtils.Constant(type), AstUtils.Convert(args.GetBlockExpression(), typeof(Proc)) ); } } else { var actualArgs = RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 1, 1); if (!metaBuilder.Error) { var convertBinder = args.RubyContext.CreateConvertBinder(type, true); var converted = convertBinder.Bind(actualArgs[0], DynamicMetaObject.EmptyMetaObjects); metaBuilder.SetMetaResult(converted, args); } } }
/// <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 ); }