Ejemplo n.º 1
0
        public virtual Proc /*!*/ ToProc(RubyScope /*!*/ scope)
        {
            ContractUtils.RequiresNotNull(scope, "scope");

            if (_procDispatcher == null)
            {
                var site = CallSite <Func <CallSite, object, object, object> > .Create(
                    // TODO: use InvokeBinder
                    RubyCallAction.Make(
                        scope.RubyContext, "call",
                        new RubyCallSignature(1, RubyCallFlags.HasImplicitSelf | RubyCallFlags.HasSplattedArgument)
                        )
                    );

                var block = new BlockCallTargetUnsplatN((blockParam, self, args, unsplat) => {
                    // block takes no parameters but unsplat => all actual arguments are added to unsplat:
                    Debug.Assert(args.Length == 0);

                    return(site.Target(site, this, unsplat));
                });

                _procDispatcher = new BlockDispatcherUnsplatN(0,
                                                              BlockDispatcher.MakeAttributes(BlockSignatureAttributes.HasUnsplatParameter, _info.GetArity()),
                                                              null, 0
                                                              );

                _procDispatcher.SetMethod(block);
            }

            // TODO:
            // MRI: source file/line are that of the to_proc method call:
            return(new Proc(ProcKind.Block, scope.SelfObject, scope, _procDispatcher));
        }
Ejemplo n.º 2
0
 public static Proc /*!*/ Create(RubyContext /*!*/ context, int parameterCount, BlockSignatureAttributes signatureAttributes, Delegate /*!*/ clrMethod)
 {
     // scope is used to get to the execution context:
     return(new Proc(ProcKind.Block, null, context.EmptyScope,
                     BlockDispatcher.Create(parameterCount, signatureAttributes, null, 0).SetMethod(clrMethod)
                     ));
 }
Ejemplo n.º 3
0
        /// <summary>
        /// Creates a proc that invokes a method of given name.
        /// <code>
        /// Proc.new do |*args|
        ///   raise ArgumentException if args.size == 0
        ///   obj.methodName(args.delete_at(0), args)
        /// end
        /// </code>
        /// </summary>
        public static Proc /*!*/ CreateMethodInvoker(RubyScope /*!*/ scope, string /*!*/ methodName)
        {
            ContractUtils.RequiresNotNull(scope, "scope");

            // TODO:
            // This should pass a proc parameter (use BlockDispatcherUnsplatProcN).
            // MRI 1.9.2 doesn't do so though (see http://redmine.ruby-lang.org/issues/show/3792).

            var site = CallSite <Func <CallSite, object, object, object, object> > .Create(
                RubyCallAction.Make(
                    scope.RubyContext, methodName,
                    new RubyCallSignature(0, RubyCallFlags.HasScope | RubyCallFlags.HasSplattedArgument)
                    )
                );

            var block = new BlockCallTargetUnsplatN((blockParam, self, args, unsplat) => {
                Debug.Assert(args.Length == 0);
                if (unsplat.Count == 0)
                {
                    throw RubyExceptions.CreateArgumentError("no receiver given");
                }
                object target = unsplat[0];
                unsplat.RemoveAt(0);
                return(site.Target(site, scope, target, unsplat));
            });

            var procDispatcher = new BlockDispatcherUnsplatN(0,
                                                             BlockDispatcher.MakeAttributes(BlockSignatureAttributes.HasUnsplatParameter, -1),
                                                             null, 0
                                                             );

            procDispatcher.SetMethod(block);
            return(new Proc(ProcKind.Proc, scope.SelfObject, scope, procDispatcher));
        }
Ejemplo n.º 4
0
        internal BlockSignatureAttributes GetBlockSignatureAttributes()
        {
            var result = BlockSignatureAttributes.None;

            if (_unsplat != null)
            {
                result |= BlockSignatureAttributes.HasUnsplatParameter;
            }

            if (_block != null)
            {
                result |= BlockSignatureAttributes.HasProcParameter;
            }

            int arity = _mandatory.Length;

            if (_unsplat != null)
            {
                arity = -(arity + 1);
            }
            else if (arity > 0 && _mandatory[_mandatory.Length - 1] is Placeholder)
            {
                arity--;
            }

            return(BlockDispatcher.MakeAttributes(result, arity));
        }
Ejemplo n.º 5
0
 internal Proc(ProcKind kind, object self, RubyScope /*!*/ scope, BlockDispatcher /*!*/ dispatcher)
 {
     Assert.NotNull(scope, dispatcher);
     _kind       = kind;
     _self       = self;
     _scope      = scope;
     _dispatcher = dispatcher;
 }
Ejemplo n.º 6
0
        internal BlockSignatureAttributes GetBlockSignatureAttributes()
        {
            var result = BlockSignatureAttributes.None;

            CompoundLeftValue compound;

            if (_unsplattedValue != null)
            {
                result  |= BlockSignatureAttributes.HasUnsplatParameter;
                compound = this;
            }
            else if (_leftValues.Count == 1 && (compound = _leftValues[0] as CompoundLeftValue) != null)
            {
                result |= BlockSignatureAttributes.HasSingleCompoundParameter;
            }
            else
            {
                compound = this;
            }

            int arity;

            if (this == UnspecifiedBlockSignature)
            {
                arity = -1;
            }
            else
            {
                arity = compound._leftValues.Count;
                if (compound._unsplattedValue != null)
                {
                    arity = -arity - 1;
                }
                else if (compound._leftValues.Count > 0 && compound._leftValues[compound._leftValues.Count - 1] is Placeholder)
                {
                    arity--;
                }
            }

            return(BlockDispatcher.MakeAttributes(result, arity));
        }
Ejemplo n.º 7
0
 public static Proc /*!*/ Create(RubyContext /*!*/ context, BlockCallTarget1 /*!*/ clrMethod)
 {
     return(Create(context, 1, BlockDispatcher.MakeAttributes(BlockSignatureAttributes.None, -1), clrMethod));
 }
Ejemplo n.º 8
0
        internal MSA.Expression /*!*/ Transform(AstGenerator /*!*/ gen, bool isLambda)
        {
            ScopeBuilder scope = DefineLocals(gen.CurrentScope);

            // define hidden parameters and RHS-placeholders (#1..#n will be used as RHS of a parallel assignment):
            MSA.ParameterExpression blockParameter, selfParameter;
            var parameters = DefineParameters(out selfParameter, out blockParameter);

            MSA.ParameterExpression scopeVariable = scope.DefineHiddenVariable("#scope", typeof(RubyBlockScope));
            MSA.LabelTarget         redoLabel     = Ast.Label();

            gen.EnterBlockDefinition(
                scope,
                blockParameter,
                selfParameter,
                scopeVariable,
                redoLabel
                );

            MSA.Expression          paramInit = MakeParametersInitialization(gen, parameters);
            MSA.ParameterExpression blockUnwinder, filterVariable;

            MSA.Expression traceCall, traceReturn;
            if (gen.TraceEnabled)
            {
                int firstStatementLine = _body.Count > 0 ? _body.First.Location.Start.Line : Location.End.Line;
                int lastStatementLine  = _body.Count > 0 ? _body.Last.Location.End.Line : Location.End.Line;

                traceCall   = Methods.TraceBlockCall.OpCall(scopeVariable, blockParameter, gen.SourcePathConstant, AstUtils.Constant(firstStatementLine));
                traceReturn = Methods.TraceBlockReturn.OpCall(scopeVariable, blockParameter, gen.SourcePathConstant, AstUtils.Constant(lastStatementLine));
            }
            else
            {
                traceCall = traceReturn = Ast.Empty();
            }

            MSA.Expression body = AstUtils.Try(
                paramInit,
                traceCall,
                Ast.Label(redoLabel),
                AstUtils.Try(
                    gen.TransformStatements(_body, ResultOperation.Return)
                    ).Catch(blockUnwinder = Ast.Parameter(typeof(BlockUnwinder), "#u"),
                            // redo:
                            AstUtils.IfThen(Ast.Field(blockUnwinder, BlockUnwinder.IsRedoField), Ast.Goto(redoLabel)),

                            // next:
                            gen.Return(Ast.Field(blockUnwinder, BlockUnwinder.ReturnValueField))
                            )
                ).Filter(filterVariable = Ast.Parameter(typeof(Exception), "#e"),
                         Methods.FilterBlockException.OpCall(scopeVariable, filterVariable)
                         ).Finally(
                traceReturn,
                Ast.Empty()
                );

            body = gen.AddReturnTarget(
                scope.CreateScope(
                    scopeVariable,
                    Methods.CreateBlockScope.OpCall(new AstExpressions {
                scope.MakeLocalsStorage(),
                scope.GetVariableNamesExpression(),
                blockParameter,
                selfParameter,
                EnterInterpretedFrameExpression.Instance
            }),
                    body
                    )
                );

            gen.LeaveBlockDefinition();

            int parameterCount = ParameterCount;
            var attributes = _parameters.GetBlockSignatureAttributes();

            var dispatcher = Ast.Constant(
                BlockDispatcher.Create(parameterCount, attributes, gen.SourcePath, Location.Start.Line), typeof(BlockDispatcher)
                );

            return(Ast.Coalesce(
                       (isLambda ? Methods.InstantiateLambda : Methods.InstantiateBlock).OpCall(gen.CurrentScopeVariable, gen.CurrentSelfVariable, dispatcher),
                       (isLambda ? Methods.DefineLambda : Methods.DefineBlock).OpCall(gen.CurrentScopeVariable, gen.CurrentSelfVariable, dispatcher,
                                                                                      BlockDispatcher.CreateLambda(
                                                                                          body,
                                                                                          RubyStackTraceBuilder.EncodeMethodName(gen.CurrentMethod.MethodName, gen.SourcePath, Location, gen.DebugMode),
                                                                                          parameters,
                                                                                          parameterCount,
                                                                                          attributes
                                                                                          )
                                                                                      )
                       ));
        }
Ejemplo n.º 9
0
 public static Proc /*!*/ Create(RubyContext /*!*/ context, BlockCallTarget1 /*!*/ clrMethod)
 {
     return(Create(context, 1, BlockDispatcher.MakeAttributes(BlockSignatureAttributes.HasSingleCompoundParameter, -1), clrMethod));
 }
Ejemplo n.º 10
0
        internal override MSA.Expression /*!*/ Transform(AstGenerator /*!*/ gen)
        {
            MSA.Expression parentScope = gen.CurrentScopeVariable;
            ScopeBuilder   scope       = new ScopeBuilder();

            // define hidden parameters and RHS-placeholders (#1..#n will be used as RHS of a parallel assignment):
            MSA.Expression            blockParameter, selfParameter;
            MSA.ParameterExpression[] parameters = DefineParameters(out selfParameter, out blockParameter);

            MSA.Expression  scopeVariable = scope.DefineHiddenVariable("#scope", typeof(RubyBlockScope));
            MSA.LabelTarget redoLabel     = Ast.Label();

            gen.EnterBlockDefinition(
                scope,
                blockParameter,
                selfParameter,
                scopeVariable,
                redoLabel
                );

            if (_definedScope != null)
            {
                _definedScope.TransformLocals(scope);
            }

            MSA.Expression          paramInit     = MakeParametersInitialization(gen, parameters);
            MSA.ParameterExpression blockUnwinder = scope.DefineHiddenVariable("#unwinder", typeof(BlockUnwinder));

            MSA.Expression loop = AstFactory.Infinite(null, redoLabel,
                                                      AstUtils.Try(
                                                          gen.TransformStatements(_body, ResultOperation.Return)
                                                          ).Catch(blockUnwinder,
                                                                  // redo:
                                                                  AstUtils.IfThen(Ast.Field(blockUnwinder, BlockUnwinder.IsRedoField), Ast.Continue(redoLabel)),

                                                                  // next:
                                                                  gen.Return(Ast.Field(blockUnwinder, BlockUnwinder.ReturnValueField))
                                                                  )
                                                      );

            if (gen.TraceEnabled)
            {
                int firstStatementLine = _body.Count > 0 ? _body[0].Location.Start.Line : Location.End.Line;
                int lastStatementLine  = _body.Count > 0 ? _body[_body.Count - 1].Location.End.Line : Location.End.Line;

                loop = Ast.TryFinally(
                    Ast.Block(
                        Methods.TraceBlockCall.OpCall(scopeVariable, blockParameter, Ast.Convert(Ast.Constant(gen.SourceUnit.Path), typeof(string)), Ast.Constant(firstStatementLine)),
                        loop
                        ),
                    Methods.TraceBlockReturn.OpCall(scopeVariable, blockParameter, Ast.Convert(Ast.Constant(gen.SourceUnit.Path), typeof(string)), Ast.Constant(lastStatementLine))
                    );
            }

            MSA.Expression body = Ast.Block(
                Ast.Assign(scopeVariable,
                           Methods.CreateBlockScope.OpCall(scope.VisibleVariables(), parentScope, blockParameter, selfParameter)
                           ),

                paramInit,

                loop,

                Ast.Empty()
                );

            body = gen.AddReturnTarget(scope.CreateScope(body));
            gen.LeaveBlockDefinition();

            int parameterCount = _parameters.LeftValues.Count;

            var attributes = _parameters.GetBlockSignatureAttributes();

            return(Methods.DefineBlock.OpCall(
                       gen.CurrentScopeVariable,
                       gen.CurrentRfcVariable,
                       gen.CurrentSelfVariable,
                       Ast.Lambda(
                           BlockDispatcher.GetDelegateType(parameterCount, attributes),
                           body,
                           gen.EncodeMethodName(gen.CurrentMethod.MethodName, Location),
                           new ReadOnlyCollection <MSA.ParameterExpression>(parameters)
                           ),
                       Ast.Constant(parameterCount),
                       Ast.Constant(attributes)
                       ));
        }
Ejemplo n.º 11
0
 public static Proc /*!*/ Create(RubyContext /*!*/ context, Delegate /*!*/ clrMethod, object self, int parameterCount)
 {
     // scope is used to get to the execution context:
     return(new Proc(ProcKind.Block, self, context.EmptyScope, BlockDispatcher.Create(clrMethod, parameterCount, BlockSignatureAttributes.None)));
 }