/** * Create a new SmartBinder with from the given types and argument name. * * @param retType the type of the return value to start with * @param name the name of the sole argument * @param type the sole argument's type * @return a new SmartBinder */ public static SmartBinder from(Class<?> retType, String name, Class<?> type) { return from(Signature.returning(retType).appendArg(name, type)); }
/** * Pass all arguments to the given function and drop any result. * * @param function a function which will receive all arguments and have its * return value inserted into the call chain * @return a new SmartBinder with the fold applied */ public SmartBinder foldVoid(SmartHandle function) { if (Arrays.equals(signature().argNames(), function.signature().argNames())) { return foldVoid(function.handle()); } else { return foldVoid(signature().asFold(void.class).permuteWith(function).handle()); } }
/** * Create a new SmartHandle that converts arguments from the given signature to * the current signature's type with the new argument names. This conversion * is equivalent to MethodHandle#asType. * * @param incoming the target MethodType from which arguments will be converted * @return a new SmartHandle that accepts the given argument types */ public SmartHandle convert(Signature incoming) { return new SmartHandle(incoming, handle.asType(incoming.type())); }
/** * Insert an argument (name + type) into the signature before the argument * with the given name. * * @param beforeName the name of the argument before which to insert * @param name the name of the new argument * @param type the type of the new argument * @return a new signature with the added arguments */ public Signature insertArg(String beforeName, String name, Class<?> type) { return insertArgs(argOffset(beforeName), new String[]{name}, new Class<?>[]{type}); }
/** * Set the argument name at the given index. * * @param index the index at which to set the argument name * @param name the name to set * @return a new signature with the given name at the given index */ public Signature argName(int index, String name) { String[] argNames = Arrays.copyOf(argNames(), argNames().length); argNames[index] = name; return new Signature(type(), argNames); }
startSig = startSig.appendArg("args", IRubyObject[].class); } else { for (int i = 0; i < arity; i++) { startSig = startSig.appendArg("arg" + i, IRubyObject.class); startSig = startSig.appendArg("block", Block.class); fullSignature = signature = startSig; } else { startSig = startSig.appendArg("args", IRubyObject[].class); } else { for (int i = 0; i < arity; i++) { startSig = startSig.appendArg("arg" + i, IRubyObject.class); fullSignature = startSig.appendArg("block", Block.class);
public static MethodHandle getFrameOnlyPre(Signature signature, CallConfiguration callConfig, RubyModule implClass, String name) { Signature inbound = signature.asFold(void.class); SmartBinder binder = SmartBinder .from(inbound); switch (callConfig) { case FrameFullScopeNone: // before logic return binder .permute("context", "self", "block") .insert(1, arrayOf("selfClass", "name"), arrayOf(RubyModule.class, String.class), implClass, name) .invokeVirtualQuiet(lookup(), "preMethodFrameOnly") .handle(); default: throw new RuntimeException("invalid input: " + callConfig); } }
Pattern pattern = Pattern.compile(oldPattern); MethodType newType = type(); if (pattern.matcher(argName(i)).matches()) { gatherCount++; newType = newType.dropParameterTypes(newCount, newCount + 1); Class<?> argType = argType(i); if (start == -1) start = i; if (type == null) { return new Signature(newType, newNames);
/** * Pass all arguments to the given function and insert the resulting value * as newName into the argument list. * * @param newName the name of the new first argument where the fold * function's result will be passed * @param function a function which will receive all arguments and have its * return value inserted into the call chain * @return a new SmartBinder with the fold applied */ public SmartBinder fold(String newName, SmartHandle function) { if (Arrays.equals(signature().argNames(), function.signature().argNames())) { return fold(newName, function.handle()); } else { return fold(newName, signature().changeReturn(function.signature().type().returnType()).permuteWith(function).handle()); } }
public MethodData(IRBytecodeAdapter method, IRScope scope, Signature signature, int specificArity) { this.method = method; this.scope = scope; this.signature = signature; this.specificArity = specificArity; // incoming arguments for (int i = 0; i < signature.argCount(); i++) { local("$" + signature.argName(i), Type.getType(signature.argType(i))); } // TODO: this should go into the PushBinding instruction local("$dynamicScope"); }
private static MethodHandle dynamicCallTarget(Signature from, Signature to) { return SmartBinder .from(from) .fold("selfClass", from.asFold(RubyClass.class).permuteWith(PGC, "context", "self")) .permute(to) .cast(to) .invokeVirtualQuiet(lookup(), "call") .handle(); }
.from(signature.asFold(boolean.class)) .permute("self") .insert(1, "selfJavaType", self.getClass()) .from(signature.changeReturn(boolean.class)) .permute("self") .insert(0, "selfClass", RubyClass.class, testClass)
/** * Drop an argument from the handle at the end, returning a new * SmartHandle. * * @param newName name of the argument * @param type type of the argument * @return a new SmartHandle with the additional argument */ public SmartHandle dropLast(String newName, Class<?> type) { return new SmartHandle(signature.appendArg(newName, type), MethodHandles.dropArguments(handle, signature.argOffset(newName), type)); }
/** * Drop an argument from the handle at the given index, returning a new * SmartHandle. * * @param index index before which the dropped argument goes * @param newName name of the argument * @param type type of the argument * @return a new SmartHandle with the additional argument */ public SmartHandle drop(int index, String newName, Class<?> type) { return new SmartHandle(signature.insertArg(index, newName, type), MethodHandles.dropArguments(handle, index, type)); }
/** * Collect arguments matching namePattern into an trailing array argument * named outName. * * The namePattern is a standard regular expression. * * @param outName the name of the new array argument * @param namePattern a pattern with which to match arguments for collecting * @return a new SmartBinder with the collect applied */ public SmartBinder collect(String outName, String namePattern) { int index = signature().argOffsets(namePattern); assert index >= 0 : "no arguments matching " + namePattern + " found in signature " + signature(); Signature newSignature = signature().collect(outName, namePattern); return new SmartBinder(this, newSignature, binder.collect(index, signature().argCount() - (newSignature.argCount() - 1), Array.newInstance(signature().argType(index), 0).getClass())); }
/** * Use the given filter function to transform the return value at this * point in the binder. The filter will be inserted into the handle, and * return values will pass through it before continuing. * * The filter's argument must match the expected return value downstream * from this point in the binder, and the return value must match the * return value at this point in the binder. * * @param filter the function to use to transform the return value at this point * @return a new SmartBinder with the filter applied */ public SmartBinder filterReturn(SmartHandle filter) { return new SmartBinder(this, signature().changeReturn(filter.signature().type().returnType()), binder.filterReturn(filter.handle())); }
public void loadBlock() { adapter.aload(signature.argOffset(JVMVisitor.BLOCK_ARG_NAME)); }
static MethodHandle buildIndyHandle(InvokeSite site, DynamicMethod method, RubyModule implClass) { MethodHandle mh = null; Signature siteToDyncall = site.signature.insertArgs(3, arrayOf("class", "name"), arrayOf(RubyModule.class, String.class)); boolean blockGiven = site.signature.lastArgType() == Block.class;
/** * Drop an argument name and type from the handle at the given index, returning a new * SmartHandle. * * @param beforeName name before which the dropped argument goes * @param newName name of the argument * @param type type of the argument * @return a new SmartHandle with the additional argument */ public SmartHandle drop(String beforeName, String newName, Class<?> type) { return new SmartHandle(signature.insertArg(beforeName, newName, type), MethodHandles.dropArguments(handle, signature.argOffset(beforeName), type)); }