Writing a compiler to handles, but filter seems to executed in reverse
Charles Oliver Nutter
headius at headius.com
Tue Jan 2 21:54:11 UTC 2018
I have released invokebinder 1.11, which includes Binder.filterForward that
guarantees left-to-right evaluation of the filters (by doing them
individually).
I'd still like to understand if this is intentional behavior in OpenJDK or
if it is perhaps a bug.
- Charlie
On Tue, Jan 2, 2018 at 3:10 PM Charles Oliver Nutter <headius at headius.com>
wrote:
> Yes, I figured I would need it for that too, but this filter behavior sent
> me off on a weird tangent.
>
> It is gross in code to do the filters manually in forward order, but
> perhaps it's not actually a big deal? OpenJDK's impl applies each filter as
> its own layer anyway.
>
> - Charlie
>
> On Tue, Jan 2, 2018 at 3:04 PM Remi Forax <forax at univ-mlv.fr> wrote:
>
>> You also need the loop combinator for implementing early return (the
>> return keyword),
>> I think i have an example of how to map a small language to a loop
>> combinator somewhere,
>> i will try to find that (or rewrite it) tomorrow.
>>
>> cheers,
>> Rémi
>>
>> ------------------------------
>>
>> *De: *"Charles Oliver Nutter" <headius at headius.com>
>> *À: *"Da Vinci Machine Project" <mlvm-dev at openjdk.java.net>
>> *Envoyé: *Mardi 2 Janvier 2018 21:36:33
>> *Objet: *Re: Writing a compiler to handles, but filter seems to executed
>> in reverse
>>
>> 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 <headius at headius.com>
>> wrote:
>>
>>> 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 <
>>> headius at headius.com> 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
>> mlvm-dev at openjdk.java.net
>> http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
>>
>> _______________________________________________
>> mlvm-dev mailing list
>> mlvm-dev at openjdk.java.net
>> http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/mlvm-dev/attachments/20180102/3aee7c07/attachment.html>
More information about the mlvm-dev
mailing list