@JRubyMethod public IRubyObject parameters(ThreadContext context) { BlockBody body = this.getBlock().getBody(); return Helpers.argumentDescriptorsToParameters( context.runtime, body.getArgumentDescriptors(), isLambda()); }
public IRubyObject yieldArray(ThreadContext context, IRubyObject value, IRubyObject self) { // SSS FIXME: Later on, we can move this code into IR insructions or // introduce a specialized entry-point when we know that this block has // explicit call protocol IR instructions. IRubyObject[] args; args = IRRuntimeHelpers.singleBlockArgToArray(value); return body.yield(context, this, args, self); }
/** * For Type.LAMBDA, ensures that the args have the correct arity. * * <p>For others, transforms the given arguments appropriately for the given arity (i.e. trimming * to one arg for fixed arity of one, etc.) */ public static IRubyObject[] prepareArgs( ThreadContext context, Block.Type type, BlockBody blockBody, IRubyObject[] args) { Signature signature = blockBody.getSignature(); if (args == null) return IRubyObject.NULL_ARRAY; if (type == Block.Type.LAMBDA) { signature.checkArity(context.runtime, args); return args; } boolean isFixed = signature.isFixed(); int required = signature.required(); int actual = args.length; boolean restKwargs = blockBody instanceof IRBlockBody && ((IRBlockBody) blockBody).getSignature().hasKwargs(); // FIXME: This is a hot mess. restkwargs factors into destructing a single element array as // well. I just weaved it into this logic. // for procs and blocks, single array passed to multi-arg must be spread if ((signature != Signature.ONE_ARGUMENT && required != 0 && (isFixed || signature != Signature.OPTIONAL) || restKwargs) && actual == 1 && args[0].respondsTo("to_ary")) { IRubyObject newAry = Helpers.aryToAry(args[0]); // This is very common to yield in *IRBlockBody. When we tackle call protocol for blocks this // will combine. if (newAry.isNil()) { args = new IRubyObject[] {args[0]}; } else if (newAry instanceof RubyArray) { args = ((RubyArray) newAry).toJavaArrayMaybeUnsafe(); } else { throw context.runtime.newTypeError( args[0].getType().getName() + "#to_ary should return Array"); } actual = args.length; } // fixed arity > 0 with mismatch needs a new args array if (isFixed && required > 0 && required != actual) { IRubyObject[] newArgs = ArraySupport.newCopy(args, required); if (required > actual) { // Not enough required args pad. Helpers.fillNil(newArgs, actual, required, context.runtime); } args = newArgs; } return args; }
// ENEBO: Some of this logic should be put back into the Nodes themselves, but the more // esoteric features of 1.9 make this difficult to know how to do this yet. public BlockBody newCompiledBlockBody19(ThreadContext context, IterNode iterNode) { final ArgsNode argsNode = (ArgsNode) iterNode.getVarNode(); boolean hasMultipleArgsHead = false; if (iterNode.getVarNode() instanceof MultipleAsgnNode) { hasMultipleArgsHead = ((MultipleAsgnNode) iterNode.getVarNode()).getHeadNode() != null; } NodeType argsNodeId = BlockBody.getArgumentTypeWackyHack(iterNode); return new CompiledBlock19( ((ArgsNode) iterNode.getVarNode()).getArity(), iterNode.getScope(), compileBlock19( context, new StandardASMCompiler("blahfooblah" + System.currentTimeMillis(), "blahfooblah"), iterNode), hasMultipleArgsHead, BlockBody.asArgumentType(argsNodeId), Helpers.encodeParameterList(argsNode).split(";")); }
public BlockBody newCompiledBlockBody( ThreadContext context, IterNode iterNode, Arity arity, int argumentType) { NodeType argsNodeId = getArgumentTypeWackyHack(iterNode); boolean hasMultipleArgsHead = false; if (iterNode.getVarNode() instanceof MultipleAsgnNode) { hasMultipleArgsHead = ((MultipleAsgnNode) iterNode.getVarNode()).getHeadNode() != null; } return new CompiledBlock( Arity.procArityOf(iterNode.getVarNode()), iterNode.getScope(), compileBlock( context, new StandardASMCompiler("blahfooblah" + System.currentTimeMillis(), "blahfooblah"), iterNode), hasMultipleArgsHead, BlockBody.asArgumentType(argsNodeId)); }
public DynamicScope allocScope(DynamicScope parentScope) { // SSS: Important! Use getStaticScope() to use a copy of the static-scope stored in the // block-body. // Do not use 'closure.getStaticScope()' -- that returns the original copy of the static scope. // This matters because blocks created for Thread bodies modify the static-scope field of the // block-body // that records additional state about the block body. // // FIXME: Rather than modify static-scope, it seems we ought to set a field in block-body which // is then // used to tell dynamic-scope that it is a dynamic scope for a thread body. Anyway, to be // revisited later! EvalType evalType = ((IRBlockBody) body).getEvalType(); DynamicScope newScope = DynamicScope.newDynamicScope(body.getStaticScope(), parentScope, evalType); if (type == Block.Type.LAMBDA) newScope.setLambda(true); return newScope; }
public Block newCompiledClosure(ThreadContext context, IterNode iterNode, IRubyObject self) { Binding binding = context.currentBinding(self); NodeType argsNodeId = getArgumentTypeWackyHack(iterNode); boolean hasMultipleArgsHead = false; if (iterNode.getVarNode() instanceof MultipleAsgnNode) { hasMultipleArgsHead = ((MultipleAsgnNode) iterNode.getVarNode()).getHeadNode() != null; } BlockBody body = new CompiledBlock( Arity.procArityOf(iterNode.getVarNode()), iterNode.getScope(), compileBlock( context, new StandardASMCompiler("blahfooblah" + System.currentTimeMillis(), "blahfooblah"), iterNode), hasMultipleArgsHead, BlockBody.asArgumentType(argsNodeId)); return new Block(body, binding); }
public CompiledBlockCallback19 compileBlock19( ThreadContext context, StandardASMCompiler asmCompiler, final IterNode iterNode) { final ASTCompiler19 astCompiler = new ASTCompiler19(); final StaticScope scope = iterNode.getScope(); asmCompiler.startScript(scope); final ArgsNode argsNode = (ArgsNode) iterNode.getVarNode(); // create the closure class and instantiate it final CompilerCallback closureBody = new CompilerCallback() { public void call(BodyCompiler context) { if (iterNode.getBodyNode() != null) { astCompiler.compile(iterNode.getBodyNode(), context, true); } else { context.loadNil(); } } }; // create the closure class and instantiate it final CompilerCallback closureArgs = new CompilerCallback() { public void call(BodyCompiler context) { // FIXME: This is temporary since the variable compilers assume we want // args already on stack for assignment. We just pop and continue with // 1.9 args logic. context.consumeCurrentValue(); // args value context.consumeCurrentValue(); // passed block if (iterNode.getVarNode() != null) { if (iterNode instanceof LambdaNode) { final int required = argsNode.getRequiredArgsCount(); final int opt = argsNode.getOptionalArgsCount(); final int rest = argsNode.getRestArg(); context.getVariableCompiler().checkMethodArity(required, opt, rest); astCompiler.compileMethodArgs(argsNode, context, true); } else { astCompiler.compileMethodArgs(argsNode, context, true); } } } }; ASTInspector inspector = new ASTInspector(); inspector.inspect(iterNode.getBodyNode()); inspector.inspect(iterNode.getVarNode()); NodeType argsNodeId = BlockBody.getArgumentTypeWackyHack(iterNode); int scopeIndex = asmCompiler.getCacheCompiler().reserveStaticScope(); ChildScopedBodyCompiler closureCompiler = new ChildScopedBodyCompiler19( asmCompiler, "__file__", asmCompiler.getClassname(), inspector, scope, scopeIndex); closureCompiler.beginMethod(argsNodeId == null ? null : closureArgs, scope); closureBody.call(closureCompiler); closureCompiler.endBody(); // __file__ method to call static version SkinnyMethodAdapter method = new SkinnyMethodAdapter( asmCompiler.getClassVisitor(), ACC_PUBLIC, "__file__", getMethodSignature(4), null, null); method.start(); // invoke static __file__ method.aload(THIS); method.aload(THREADCONTEXT_INDEX); method.aload(SELF_INDEX); method.aload(ARGS_INDEX); method.aload(ARGS_INDEX + 1); // block method.invokestatic( asmCompiler.getClassname(), "__file__", asmCompiler.getStaticMethodSignature(asmCompiler.getClassname(), 4)); method.areturn(); method.end(); asmCompiler.endScript(false, false); byte[] bytes = asmCompiler.getClassByteArray(); Class blockClass = new JRubyClassLoader(context.runtime.getJRubyClassLoader()) .defineClass(asmCompiler.getClassname(), bytes); try { final AbstractScript script = (AbstractScript) blockClass.newInstance(); script.setRootScope(scope); return new CompiledBlockCallback19() { @Override public IRubyObject call( ThreadContext context, IRubyObject self, IRubyObject[] args, Block block) { return script.__file__(context, self, args, block); } @Override public String getFile() { return iterNode.getPosition().getFile(); } @Override public int getLine() { return iterNode.getPosition().getLine(); } }; } catch (Exception e) { throw new RuntimeException(e); } }
public Signature getSignature() { return body.getSignature(); }
public IRubyObject call(ThreadContext context, Block blockArg) { return body.call(context, this, blockArg); }
public IRubyObject call(ThreadContext context, IRubyObject[] args) { return body.call(context, this, args); }
public IRubyObject yieldNonArray(ThreadContext context, IRubyObject value, IRubyObject self) { return body.yield(context, this, new IRubyObject[] {value}, self); }
public IRubyObject yield(ThreadContext context, IRubyObject value) { return body.yield(context, this, value); }
public IRubyObject yieldSpecific( ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2) { return body.yieldSpecific(context, this, arg0, arg1, arg2); }
public IRubyObject call( ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block blockArg) { return body.call(context, this, arg0, arg1, arg2, blockArg); }
public IRubyObject call( ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2) { return body.call(context, this, arg0, arg1, arg2); }
public IRubyObject yieldSpecific(ThreadContext context) { return body.yieldSpecific(context, this); }
/** * What is the arity of this block? * * @return the arity */ @Deprecated public Arity arity() { return body.getSignature().arity(); }
public void setEvalType(EvalType evalType) { body.setEvalType(evalType); }
public IRubyObject call(ThreadContext context) { return body.call(context, this); }