An alternative workaround: I do the filters myself, manually, in the order
that I want them to executed. Also gross.

On Tue, Jan 2, 2018 at 2:35 PM Charles Oliver Nutter <>

> Ahh I believe I see it now.
> filterArguments starts with the first filter, and wraps the incoming
> target handle with each in turn. However, because it's starting at the
> target, you get the filters stacked up in reverse order:
> filter(target, 0, a, b, c, d)
> ends up as
> d_filter(c_filter(b_filter(a_filter(target))))
> And so naturally when invoked, they execute in reverse order.
> This seems I am surprised we have not run into this as a problem, but I
> believe most of my uses of filter in JRuby have been pure functions where
> order was not important (except for error conditions).
> Now in looking for a fix, I've run into the nasty workaround required to
> get filters to execute in the correct order: you have to reverse the
> filters, and then reverse the results again. This is far from desirable,
> since it requires at least one permute to put the results back in proper
> order.
> Is there a good justification for doing it this way, rather than having
> filterArguments start with the *last* filter nearest the target?
> - Charlie
> On Tue, Jan 2, 2018 at 2:17 PM Charles Oliver Nutter <>
> wrote:
>> Hello all, long time no write!
>> I'm finally playing with writing a "compiler" for JRuby that uses only
>> method handles to represent code structure. For most simple expressions,
>> this obviously works well. However I'm having trouble with blocks of code
>> that contain multiple expressions.
>> Starting with the standard call signature through the handle tree, we
>> have a basic (Object[])Object type. The Object[] contains local variable
>> state for the script, and will be as wide as there are local variables. AST
>> nodes are basically compiled into little functions that take in the
>> variable state and produce a value. In this way, every expression in the
>> tree can be compiled, including local variable sets and gets, loops, and so
>> on.
>> Now the tricky bit...
>> The root node for a given script contains one or more expressions that
>> should be executed in sequence, with the final result being returned. The
>> way I'm handling this in method handles is as follows (invokebinder code
>> but hopefully easy to read):
>> MethodHandle[] handles =
>>         Arrays
>>                 .stream(rootNode.children())
>>                 .map(node -> compile(node))
>>                 .toArray(n -> new MethodHandle[n]);
>> return Binder.from(Object.class, Object[].class)
>>         .permute(new int[handles.length])
>>         .filter(0, handles)
>>         .drop(0, handles.length - 1)
>>         .identity();
>> In pseudo-code, this basically duplicates the Object[] as many times as
>> there are lines of code to execute, and then uses filterArguments to
>> evaluate each in turn. Then everything but the last result is culled and
>> the final result is returned.
>> Unfortunately, this doesn't work right: filterArguments appears to
>> execute in reverse order. When I try to run a simple script like "a = 1; a"
>> the "a" value comes back null, because it is executed first.
>> Is this expected? Do filters, when executed, actually process from the
>> last argument back, rather than the first argument forward?
>> Note: I know this would be possible to do with guaranteed ordering using
>> the new loop combinators in 9. I'm working up to that for examples for a
>> talk.
>> - Charlie
mlvm-dev mailing list

Reply via email to