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 CompiledBlockCallback compileBlock( ThreadContext context, StandardASMCompiler asmCompiler, final IterNode iterNode) { final ASTCompiler astCompiler = new ASTCompiler(); final StaticScope scope = iterNode.getScope(); asmCompiler.startScript(scope); // 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) { if (iterNode.getVarNode() != null) { astCompiler.compileAssignment(iterNode.getVarNode(), context); } else { context.consumeCurrentValue(); } if (iterNode.getBlockVarNode() != null) { astCompiler.compileAssignment(iterNode.getBlockVarNode(), context); } else { context.consumeCurrentValue(); } } }; ASTInspector inspector = new ASTInspector(); inspector.inspect(iterNode.getBodyNode()); inspector.inspect(iterNode.getVarNode()); int scopeIndex = asmCompiler.getCacheCompiler().reserveStaticScope(); ChildScopedBodyCompiler closureCompiler = new ChildScopedBodyCompiler( asmCompiler, "__file__", asmCompiler.getClassname(), inspector, scope, scopeIndex); closureCompiler.beginMethod(closureArgs, scope); closureBody.call(closureCompiler); closureCompiler.endBody(); // __file__ method with [] args; no-op SkinnyMethodAdapter method = new SkinnyMethodAdapter( asmCompiler.getClassVisitor(), ACC_PUBLIC, "__file__", getMethodSignature(4), null, null); method.start(); method.aload(SELF_INDEX); method.areturn(); method.end(); // __file__ method to call static version method = new SkinnyMethodAdapter( asmCompiler.getClassVisitor(), ACC_PUBLIC, "__file__", getMethodSignature(1), 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__", getStaticMethodSignature(asmCompiler.getClassname(), 1)); 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 CompiledBlockCallback() { @Override public IRubyObject call( ThreadContext context, IRubyObject self, IRubyObject args, Block block) { return script.__file__(context, self, args, block); } @Override public String getFile() { return "blah"; } @Override public int getLine() { return -1; } }; } catch (Exception e) { throw new RuntimeException(e); } }