el-next@uel.java.net

Re: Should FunctionMapper be deprecated?

From: Mike Brock <cbrock_at_redhat.com>
Date: Thu, 1 Apr 2010 15:31:53 -0400

MVEL is really a hybrid LR(k) parser. It does support FQCN+method() calls, yes. It also support direct-aliasing (analogous to FunctionMapper), and imported classes. MVEL imports java.lang.* just like Java, so things like "System.currentTimeMillis()" are written just as so.

From a parsing perspective, MVEL uses brute-force for these cases. It sees something like "com.foo", it first searches the symbols and variable tables to see if it knows what "com" is. If not, it captures the entire token, and then begins back-stepping, trying to see it's a FQCN, FQCN+method, or FQCN+field.

Mike.


On 2010-03-26, at 2:21 PM, Kin-man Chung wrote:

> I weren't worry about parsing efficiency, but more about feasibility.
> I should take a closer look at MVEL, but I gather that it uses the
> syntax #{com.acme.Functions.myFunc()} for static methods, and that
> it is not too hard to implement.
>
> Talking about hande-written parser vs. javacc. It has brought to
> my attention that javacc generates non-performant codes, especially
> in areas of buffer allocations and the need to turn String to stream
> and back to String again. Is this your experience?
>
> Ah I digress. So we seem to agree that we should use the syntax
>
> #{com.acme.Functions,myFunc()}
>
> for static method calls. What about the import functionality
> in API? It is useful as a shorthand?
>
> Kin-man
>
> On 03/26/10 08:54, Mike Brock wrote:
>> I don't really think parsing efficiency here should be the consideration. I think the language should be designed to come as naturally to developers as possible. And this is coming from a guy who prided myself on implementing the fastest EL parser. :)
>>
>> There's more than one parsing strategy to dealing with the problem in any case. And when I decided to take this approach in MVEL I really had to rack my brain to come up with a way that didn't kill parsing performance -- but then again, I was handwriting my parser, which is probably not appropriate here.
>>
>> Moreover, proper caching facilities should negate the need for the parse to happen more than once in most cases.
>>
>> On 2010-03-24, at 1:47 PM, Kin-man Chung wrote:
>>
>>>
>>>
>>> On 03/23/10 04:38, Martin Marinschek wrote:
>>>> Hi guys,
>>>>
>>>> I would love to have the ability to call static functions directly -
>>>> so my +1. However, I do see the parsing problems you point out,
>>>> Kin-Man.
>>>>
>>>> How about the following: we would device a new namespace, a
>>>> classpath-namespace for the Unified EL:
>>>>
>>>> new namespace: http://unified.el/classpath, prefix e.g. cp
>>>>
>>>> and then could do the following:
>>>>
>>>> #{cp:com.acme.functions.MyFunction()}
>>>>
>>>> Does that sound reasonable?
>>>>
>>> Reasonable, but it still needs token look-ahead during parsing.
>>>
>>> If we apply look-ahead to our original "natural" syntax,
>>>
>>> #{com.acme.Functions.myFunction()}.
>>>
>>> The parser can determine that "com.acme.Functions" is actually the
>>> name of a "package + class", and decide that this is potentially a
>>> static method invocation.
>>>
>>> I'll need to look a the Glassfish EL implementation to see if the
>>> grammar can be easily changed to do this. For those who have
>>> implemented EL before, can you also take a look, from easy of
>>> implementation angle? Thanks.
>>>
>>> In addition, I think it'll be useful to add in the API, some kind of
>>> import function. For instance,, we can have
>>>
>>> elProcessor.import("com.acme.Functions");
>>>
>>> then the static methods of this class can be used in the expression
>>>
>>> #{Functions.myFunctio()}
>>>
>>> BTW, we have exactly the same problem with Enum literals, such as
>>> com.acme.Days.MONDAY, so anything we use here can also be used there!
>>>
>>> -Kin-man
>>>
>>>> Alternatively, I would say that this is an issue where annotations
>>>> would definitely help to reduce the configuration clutter!
>>>>
>>>> And by the way, as to your remarks JSF 2: facelets also has a
>>>> possibility to register EL-functions, and we use that extensively in
>>>> our projects, so contrary to what you say, I think this is widely used
>>>> in the JSF space.
>>>>
>>> I stand corrected then. In that case, FunctionMapper will not be
>>> deprecated, but will coexist with new way of calling static methods.
>>>
>>> -Kin-man
>>>
>>>> best regards,
>>>>
>>>> Martin
>>>>
>>>> On 3/22/10, Mike Brock<cbrock_at_redhat.com> wrote:
>>>>> +1
>>>>>
>>>>> This was originally one of those major limitations that really precipitated
>>>>> my decision to start developing MVEL. MVEL, of course, adopts plain
>>>>> Java-syntax for static calls, which I think makes the most amount of sense
>>>>> and is obviously very useful.
>>>>>
>>>>> That said, I think it makes sense to be able to alias static methods as
>>>>> functions. The approach we've taken, which is probably a little too
>>>>> heavy-weight for the EL spec, is through the introduction of full
>>>>> function-pointer support at the language and runtime level. So, you're
>>>>> fundamentally able to do something like this:
>>>>>
>>>>> time = System.currentTimeMillis; // reference the method
>>>>> time(); // call it.
>>>>>
>>>>> However, this has the useful side-effect of allowing you to inject functions
>>>>> as regular variables from the API:
>>>>>
>>>>> Map<String, Object> vars = new HashMap<String, Object>();
>>>>> vars.put("time", System.class.getMethod("currentTimeMillis"));
>>>>>
>>>>> long time = MVEL.eval("time()", vars, Long.class);
>>>>>
>>>>> Just food for thought.
>>>>>
>>>>> Mike.
>>>>>
>>>>> On 2010-03-17, at 6:39 PM, Kin-man Chung wrote:
>>>>>
>>>>>> Current EL allows static functions to be invoked by the use of a
>>>>>> FunctionMapper. See java.el package in
>>>>>> http://java.sun.com/javaee/5/docs/api/
>>>>>>
>>>>>> For instance, if the prefix "pre" and "foo" maps to the method
>>>>>> com.acme.bar.method, then the expression
>>>>>>
>>>>>> "#{pre:foo()}"
>>>>>>
>>>>>> cuases this method to be invoked.
>>>>>>
>>>>>> The need for both the prefix and a name, which can be unrelated
>>>>>> to the actual method name, is clunky and unintuitive, and has its
>>>>>> roots in JSP.
>>>>>>
>>>>>> Since we already allow methods in EL expressions in EL 2.2, we should
>>>>>> extend this to include static methods. The most obvious syntax to use
>>>>>> is to include the package name, such as
>>>>>>
>>>>>> "#{com.acme.bar.method())"
>>>>>>
>>>>>> The downside is that we are overloading the meaning of the . operator
>>>>>> here, and might cause problems in parsing. There may be other ways.
>>>>>>
>>>>>> I'd assume we'd deprecate FunctionMapper and not include it in
>>>>>> ELProcessor.
>>>>>>
>>>>>> -Kin-man
>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: el-next-unsubscribe_at_uel.dev.java.net
>>>>>> For additional commands, e-mail: el-next-help_at_uel.dev.java.net
>>>>>>
>>>>>
>>>>> On 2010-03-17, at 6:39 PM, Kin-man Chung wrote:
>>>>>
>>>>>> Current EL allows static functions to be invoked by the use of a
>>>>>> FunctionMapper. See java.el package in
>>>>>> http://java.sun.com/javaee/5/docs/api/
>>>>>>
>>>>>> For instance, if the prefix "pre" and "foo" maps to the method
>>>>>> com.acme.bar.method, then the expression
>>>>>>
>>>>>> "#{pre:foo()}"
>>>>>>
>>>>>> cuases this method to be invoked.
>>>>>>
>>>>>> The need for both the prefix and a name, which can be unrelated
>>>>>> to the actual method name, is clunky and unintuitive, and has its
>>>>>> roots in JSP.
>>>>>>
>>>>>> Since we already allow methods in EL expressions in EL 2.2, we should
>>>>>> extend this to include static methods. The most obvious syntax to use
>>>>>> is to include the package name, such as
>>>>>>
>>>>>> "#{com.acme.bar.method())"
>>>>>>
>>>>>> The downside is that we are overloading the meaning of the . operator
>>>>>> here, and might cause problems in parsing. There may be other ways.
>>>>>>
>>>>>> I'd assume we'd deprecate FunctionMapper and not include it in
>>>>>> ELProcessor.
>>>>>>
>>>>>> -Kin-man
>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: el-next-unsubscribe_at_uel.dev.java.net
>>>>>> For additional commands, e-mail: el-next-help_at_uel.dev.java.net
>>>>>>
>>>>>
>>>>>
>>>>
>>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: el-next-unsubscribe_at_uel.dev.java.net
>>> For additional commands, e-mail: el-next-help_at_uel.dev.java.net
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: el-next-unsubscribe_at_uel.dev.java.net
>> For additional commands, e-mail: el-next-help_at_uel.dev.java.net
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: el-next-unsubscribe_at_uel.dev.java.net
> For additional commands, e-mail: el-next-help_at_uel.dev.java.net
>