// 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 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); } }