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 <head...@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 <head...@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@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev