An experimental assertion library based on code-reflections project

Tagir Valeev amaembo at gmail.com
Sat Jul 20 10:36:22 UTC 2024


Hello, Paul!

Thank you for your response!

So far, I have had a few problems with API, though probably I'm just
missing something.
1. NewOp does not provide a direct way to resolve a constructor. For
InvokeOp, one can use op.invokeDescriptor().resolveToHandle(lookup), but
creating an instance having a NewOp in hands is more tricky. I do it like
this

          Class<?>[] argTypes =
newOp.constructorType().parameterTypes().stream()
                  .map(this::toClass).toArray(Class[]::new);
          Class<?> objType = toClass(newOp.type());
          Object result =
objType.getConstructor(argTypes).newInstance(arguments.toArray());

(where toClass is a helper method to get a class from the type). I feel
that there should be a simple method to resolve to a Constructor or a
MethodHandle.

2. The initialized array creation like `int[] data = {1,2,3,4,5}` is
somewhat tricky to decompile. It has a block operand, which contains an
imperative sequence of constant loads and array stores. Probably some kind
of extended op should be provided for this, which is closer to Java source
and can be lowered?

3. I've noticed that the code model for new int['a'] does not add a ConvOp
and directly passes the char value 'a' as the argument to NewOp. I feel
that it's unexpected: NewOp should always take int as an array dimension,
so there should be a char-to-int conversion step. Am I wrong?

4. It's probably expected but I cannot call private methods and access
private fields at the Quotable lambda callsite. For this, I need a callsite
Lookup object. It would be inconvenient to pass a lookup object every time
together with lambda. Would it be possible to have some kind of
BlessedQuotable extends Quotable, which aside from quoted(), also provides
a callsite lookup? I think if we call a method that accepts a quotable
lambda, we already trust that method quite much. It looks not very useful
if that method can detect that we refer to a private field from the lambda,
but it cannot read that private field. Sorry if I'm missing something.

With best regards,
Tagir Valeev

On Wed, Jul 17, 2024 at 1:48 AM Paul Sandoz <paul.sandoz at oracle.com> wrote:

> Hi Tagir,
>
> Just back from vacation hence the late reply.
>
> This is a valid use case IMO, and can help provide valuable feedback. I
> had hoped we might see such cases, ones I don’t quite expect :-)
>
> I am interested in your views on the code model design and the API (a
> little raw right now) and how it worked out for you. I quickly browsed your
> code and it looks well structured.
>
> It may be challenging in general lifting models back to "readable source"
> (fernflower has super powers :-) ), and may be limited by the subset of
> Java code we can produce models from. (Separately, if we preserve
> sufficient source location information I wonder if that can help.)
>
> We are striving to model as much as we can but we may hit some limits,
> such as the modeling of inner classes. We also have a similar use case when
> translating models to OpenCL C or CUDA C, although we really only need to
> source to be reasonably human readable for debugging. So there is probably
> a common set of code/patterns in both cases. Further, we also have an
> interpreter mainly for testing and PoC, which presumes a model that is in
> lowered form thereby simplifying the implementation.
>
> Paul.
>
> > On Jul 6, 2024, at 4:05 AM, Tagir Valeev <amaembo at gmail.com> wrote:
> >
> > Hello!
> >
> > Recently I've implemented my pet project idea of an assertion library
> based on code reflection and want to share the results. It's mostly a
> proof-of-concept, rather than production-ready stuff, and many things are
> missing, but still one can play with it already. Here's the source code:
> >
> > https://github.com/amaembo/code-reflection-asserts
> >
> > The idea is that when you use assertions with JUnit or other testing
> framework, and assertion fails, you'd like to get diagnostics. If you use a
> simple assertion like assertTrue(list.contains(element)), you'll only get
> the failed assertion message without any details. Alternatively, people use
> libraries like AssertJ, which provide tons of helper methods to get verbose
> assertions Assertions.assertThat(list).contains(element). However, for
> every API method you need a corresponding AssertJ method, so AssertJ API is
> really big, and one needs to learn it.
> >
> > My idea is that we can get only one assertTrue method, like previously,
> but instead of supplying a direct boolean expression, we provide a quoted
> lambda instead:
> >
> > import static one.util.asserts.RefAsserts.assertTrue;
> >  assertTrue(() -> list.contains(element));
> >
> > If the assertion fails, the assertTrue method implementation does all
> the magic. It destructures the expression to individual components,
> evaluates them separately and prints the intermediate results, like:
> >
> > java.lang.AssertionError:
> > failed
> > list -> ["Hello", "World"]
> > element -> "Bye"
> > list.contains(element) -> false
> >
> > To implement this, we need a kind of decompiler that can restore the
> Java text from the Quoted tree and a kind of interpreter that can manually
> compute the result of a given subtree. I wrote a draft implementation. Only
> single expression lambdas are supported so far, and some advanced kinds of
> expressions like switch expressions or nested lambdas are not supported.
> When an unsupported construct is encountered, it falls back to the usual
> assertion mechanism (just executes the lambda). Also, the error handling is
> not implemented completely, but sometimes it works. E.g., if you write
> >
> > assertTrue(() -> (3 + 3) / (2 - 2) > 0);
> >
> > You'll get:
> >
> > failed
> > 3 + 3 -> 6
> > 2 - 2 -> 0
> > (3 + 3) / (2 - 2) -> throws java.lang.ArithmeticException: / by zero
> > (3 + 3) / (2 - 2) > 0 -> throws java.lang.ArithmeticException: / by zero
> >
> > I think you get the idea. I'd like to hear from Babylon project
> contributors whether such a kind of a library is considered to be a valid
> use case for code reflections. Any other thoughts and comments are also
> welcome.
> >
> > With best regards,
> > Tagir Valeev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/babylon-dev/attachments/20240720/c0491515/attachment-0001.htm>


More information about the babylon-dev mailing list