janino-compiler / janino

Janino is a super-small, super-fast Java™ compiler.
http://janino-compiler.github.io/janino
Other
1.21k stars 205 forks source link

ExpressionEvaluator - migrating from 3.0.15 to 3.1.12 causes "Must only be called before "cook()" #217

Closed rpzdev011 closed 4 months ago

rpzdev011 commented 4 months ago

Hi, I've been reusing same ExpressionEvaluator object instance to evaluate multiple expressions.

However, when I migrated from Janino 3.0.15 to 3.1.12, it was no longer possible. For example following simple evaluation fails:

ExpressionEvaluator se = new ExpressionEvaluator();
se.cook("(2 * 5)");
System.out.println("=> "+se.evaluate(null));

se.cook("5<9");
System.out.println("=> "+se.evaluate(null));

I'm wondering why it is not possible in 3.1.x?

aunkrig commented 4 months ago

Hey Andy,all *Evaluator classes are NOT designed to be cooked more than once, seehttp://janino-compiler.github.io/janino/apidocs/org/codehaus/commons/compiler/IExpressionEvaluator.htmlActually I believed that they would actively inhibit recooking, but obviously they aren’t…The reason being is that the EE initially creates one ClassLoader and defines the classes (typically only one) generated by the compilation in that ClassLoader. After that has happened, it is impossible to „redefine“ the same class in the same ClassLoader.In old versions, this contract was technically enforced by completely configuring the EE, including the expression, through the constructor. Because it is not possible to invoke the constructor more than once for one object, it was impossible to reconfigure a different expression later.However when the configuration possibilities got more and more complex, the number of constructor parameters grew to ridiculous figure, and I changed the design to a no-arg constructor, a bunch of setters, and a „cook()“ method. Much more flexible, but the contract is no longer implicitly enforced. (The old constructors with many parameters remained for compatibility.)In retrospect, I maybe should have chosen the FACTORY pattern instead, but all alternatives have their pros and cons. The con of the current version is that it doesn’t prevent you from recooking.Summarized: Just don’t do it. Don’t recook. Use a fresh EE for each expression.CU ArnoAm 07.03.2024 um 12:40 schrieb Andy Kelly @.**>: Hi, I've been reusing same ExpressionEvaluator object instance to evaluate multiple expressions. However, when I migrated from Janino 3.0.15 to 3.1.12, it was no longer possible. For example following simple evaluation fails: ExpressionEvaluator se = new ExpressionEvaluator(); se.cook("(2 5)"); System.out.println("=> "+se.evaluate(null));

se.cook("5<9"); System.out.println("=> "+se.evaluate(null));

I'm wondering why it is not possible in 3.1.x?

—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you are subscribed to this thread.Message ID: @.***>

rpzdev011 commented 4 months ago

thanks a lot for the detail explanation!