[gwt-contrib] Re: Initial support for @GwtCreate (code-gen methods)

2013-08-22 Thread Andrés Testi


El miércoles, 21 de agosto de 2013 03:39:55 UTC-3, James Nelson escribió:
>
>
>> Thanks! I think this proposal is the most conservative way to enhance 
>> GWT.create(). A more radical approach would be to forget GWT.create() and 
>> imitate what scala macros do, as was suggested by Gotktug:
>>
>>   @Macro(SumGenerator.class)
>>   int sum(int arg0, int arg1) {
>> return 0; // we will never be here
>>   }
>>
>>   // Rebind space
>>   class SumGenerator {
>>
>> public Expr sum(GeneratorContext ctx, TreeLogger logger, 
>> Arg arg0, Arg arg1) {
>>   if(arg0.isLiteral() && arg1.isLiteral) {
>> Integer result = arg0.getValue() + arg1.getValue();
>> return ctx.compile("return " + result.toString();
>>} 
>>return ctx.compile("return %s + %s", arg0, arg1); 
>> }
>>   }
>>
>>
> I definitely like the API this offers.
>
> I do maintain a hack on UnifyAst that allows manually creating magic 
> methods;
> https://github.com/WeTheInternet/xapi/tree/master/gwt/gwt-method-inject
> It's a little ugly in the xml, since I didn't think it wise to create a 
> new gwt.xml property for something that will likely never make it into 
> master.
>
> The example generator API w/ Arg could be extrapolated from the 
> magic method injector linked to above, using the literal finder from the 
> other code review I posted.
>
> I'm not sure if it could look exactly like the snippet posted (I just 
> return JExpression to match GWT.create behavior),
> but it does allow defining arbitrary magic methods for experimentation w/ 
> extensions to the compiler.
>
> The big problem, of course, is dev mode / jvms, which do not perform magic 
> method injection.
> Those platforms would require bytecode enhancement, or (as I've been 
> doing), specifying a method body which is fully functional in a jvm 
> sans-generators.
>

You work to bring reflection to GWT seems to be enormous, I can't figure 
how it is done. It's far from my current knowledge :-) 

 

>
> The only hard part of the scala-esque macros would be ctx.compile("..."); 
> I've had to either manually create AST nodes (which then lack valid 
> SourceInfo), or generate classes so I can then get compiled jjs ast nodes 
> from UnifyAst (make sure you call StandardGeneratorContext.finish() before 
> attempting this).
> I guess it would be possible to automate all of that behind the scenes,
> or maybe it would be easy for someone with deeper knowledge than I about 
> CompilationUnitBuilder (or wherever strings would be lexed into ast nodes).
>
> For now, however, I think the scala macro idea is a bit too ambitious.
>

I agree, in the meantime we should refine ideas about enhancing 
GWT.create() . I think we would join the best of the both worlds.
 

As for passing multiple class lits to a generator, I definitely see where 
> it would be useful to have more than one class in a generator,
> although UIBinder already achieves this using generic type parameters (but 
> requires manually defining the interface, of course).
>

Agreed. UiBinder, Editors, all requiring to extends silly interfaces.
 

> This would, unfortunately, likely change the Generator interface contract 
> and thus break existing code (maybe fine for GWT 3.0, but definitely no 
> sooner).
> There is also a problem for dev mode, which I'll get into a few paragraphs 
> down.
>
>
> As for the object-instead-of-class details I posted above,
> What do you think about:
>  T GWT.construct(Class cls, Object ... params)?
>
> It would look and feel exactly like GWT.create,
> except it would support constructors with arguments (and would only be 
> usable through an annotated factory method, to provide classlits for param 
> types).
>
> This would add a new feature that cannot currently be achieved, plus 
> promote immutability (more final, less .setValue()).
>
> As such, I think I'll take a stab at it using the aforelinked 
> magic-method-inject module when I get some free time (of which I am in 
> unfortunately very short supply).
> If the experiment goes well, and I can post a working prototype, I'll be 
> sure to tag you in the pull request.
>

I'll be awaiting for it. I have an idea of how it could be done. 
 

> The only gotcha I foresee would be dev mode (which I am not terribly 
> familiar with modifying); 
> about the only way I can think of the get the annotation with class lits 
> in the jvm would be to use reflection to look up the call stack and grab 
> the enclosing method (ick,
> I really don't like seeing comments like // Do not modify the call order 
> because this code depends on stack depth == n).
>
> Speaking of which...  getting multiple class params to work in dev mode 
> will face the same problem; how to safely (and preferably quickly) extract 
> the method annotations within the jvm.
>
>
> Anyway, they're both fun ideas to play with, and although I'm not holding 
> my breath on getting either of them into master any time soon (or ever),
> I still like a good challen

[gwt-contrib] Re: Initial support for @GwtCreate (code-gen methods)

2013-08-20 Thread James Nelson

>
>
> For posterity's sake, could you drop those links off here (or are you 
> referring to the ones Ray posted in the G+ community? The phrase "javac 8" 
> doesn't ring any bells for me).
>
>
Nevermind.  I just browsed the group and saw the thread.  My bad. 

-- 
http://groups.google.com/group/Google-Web-Toolkit-Contributors
--- 
You received this message because you are subscribed to the Google Groups "GWT 
Contributors" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to google-web-toolkit-contributors+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


[gwt-contrib] Re: Initial support for @GwtCreate (code-gen methods)

2013-08-20 Thread James Nelson

>
>
> Thanks! I think this proposal is the most conservative way to enhance 
> GWT.create(). A more radical approach would be to forget GWT.create() and 
> imitate what scala macros do, as was suggested by Gotktug:
>
>   @Macro(SumGenerator.class)
>   int sum(int arg0, int arg1) {
> return 0; // we will never be here
>   }
>
>   // Rebind space
>   class SumGenerator {
>
> public Expr sum(GeneratorContext ctx, TreeLogger logger, 
> Arg arg0, Arg arg1) {
>   if(arg0.isLiteral() && arg1.isLiteral) {
> Integer result = arg0.getValue() + arg1.getValue();
> return ctx.compile("return " + result.toString();
>} 
>return ctx.compile("return %s + %s", arg0, arg1); 
> }
>   }
>
>
I definitely like the API this offers.

I do maintain a hack on UnifyAst that allows manually creating magic 
methods;
https://github.com/WeTheInternet/xapi/tree/master/gwt/gwt-method-inject
It's a little ugly in the xml, since I didn't think it wise to create a new 
gwt.xml property for something that will likely never make it into master.

The example generator API w/ Arg could be extrapolated from the magic 
method injector linked to above, using the literal finder from the other 
code review I posted.

I'm not sure if it could look exactly like the snippet posted (I just 
return JExpression to match GWT.create behavior),
but it does allow defining arbitrary magic methods for experimentation w/ 
extensions to the compiler.

The big problem, of course, is dev mode / jvms, which do not perform magic 
method injection.
Those platforms would require bytecode enhancement, or (as I've been 
doing), specifying a method body which is fully functional in a jvm 
sans-generators.


The only hard part of the scala-esque macros would be ctx.compile("..."); 
I've had to either manually create AST nodes (which then lack valid 
SourceInfo), or generate classes so I can then get compiled jjs ast nodes 
from UnifyAst (make sure you call StandardGeneratorContext.finish() before 
attempting this).
I guess it would be possible to automate all of that behind the scenes,
or maybe it would be easy for someone with deeper knowledge than I about 
CompilationUnitBuilder (or wherever strings would be lexed into ast nodes).

For now, however, I think the scala macro idea is a bit too ambitious.




As for passing multiple class lits to a generator, I definitely see where 
it would be useful to have more than one class in a generator,
although UIBinder already achieves this using generic type parameters (but 
requires manually defining the interface, of course).

This would, unfortunately, likely change the Generator interface contract 
and thus break existing code (maybe fine for GWT 3.0, but definitely no 
sooner).
There is also a problem for dev mode, which I'll get into a few paragraphs 
down.


As for the object-instead-of-class details I posted above,
What do you think about:
 T GWT.construct(Class cls, Object ... params)?

It would look and feel exactly like GWT.create,
except it would support constructors with arguments (and would only be 
usable through an annotated factory method, to provide classlits for param 
types).

This would add a new feature that cannot currently be achieved, plus 
promote immutability (more final, less .setValue()).

As such, I think I'll take a stab at it using the aforelinked 
magic-method-inject module when I get some free time (of which I am in 
unfortunately very short supply).
If the experiment goes well, and I can post a working prototype, I'll be 
sure to tag you in the pull request.

The only gotcha I foresee would be dev mode (which I am not terribly 
familiar with modifying); 
about the only way I can think of the get the annotation with class lits in 
the jvm would be to use reflection to look up the call stack and grab the 
enclosing method (ick,
I really don't like seeing comments like // Do not modify the call order 
because this code depends on stack depth == n).

Speaking of which...  getting multiple class params to work in dev mode 
will face the same problem; how to safely (and preferably quickly) extract 
the method annotations within the jvm.


Anyway, they're both fun ideas to play with, and although I'm not holding 
my breath on getting either of them into master any time soon (or ever),
I still like a good challenge, and I think something like GWT.construct() 
could be a lot of fun to work on.

If you have any ideas or suggestions, do let me know!
 

> This last proposal requires a hard work to be done, and a totally new 
> generator API. Before to start with something like this, I prefer to 
> explore the code-gen compiler plugin for javac 8 mentioned by Ray in the 
> other thread. We should stay standard and portable as possible.
>
>
For posterity's sake, could you drop those links off here (or are you 
referring to the ones Ray posted in the G+ community? The phrase "javac 8" 
doesn't ring any bells for me).

Thanks,
James

-- 
http://groups.google.com

[gwt-contrib] Re: Initial support for @GwtCreate (code-gen methods)

2013-08-20 Thread Andrés Testi
Hi James, thanks for your feedback!
 

> Note that the @GwtCreate class parameters aren't replaced by 
>> GwtCreateFactory as was originally suggested by Ray Cromwell. This provides 
>> access to actual parameters.
>>
>>
> It would be possible to do a full replacement if the factory also gave 
> access to the class field, and any code in the method block accessing the 
> class could be re-routed through the factory.
> Though, I see no good reason why to do the extra work this way, I figured 
> I'd mention it in case someone else has a use case for it.
>


I think that having the class field isolated from GwtCreateFactory,  the 
code pruner would have better opportunities to remove the extra parameter. 
 

>
> * Upcoming improvements:
>>
>>   1) Support for explicit generators
>>
>> @GwtCreate(generator = FooGenerator.class)
>>
>>
> Did you see my pull request with some (very) basic support for this?
> https://gwt-review.googlesource.com/#/c/4000/
>


Sure! I studied your patch before implementing this one.

 

>   2) Multiple parameters for GWT.create() by means of @GwtCreate.Param
>>
>>UiBinder createBinder(
>> @GwtCreate(generator = UiBinGen.class) final Class uiType, 
>> @GwtCreate.Param final Class ownerType) {
>>
>
> Is the intention here to just send more classes to the generator,
> or to actually send parameters to the constructor of the rebound object 
> being instantiated?
>

The intention here is to send more than one arguments to the generator by 
means a special annotation as was suggested by Ray.

 

>   Foo createFoo(
> @GwtCreate final Class fooType,
> @GwtCreate.Param final Class arg1,
> @GwtCreate.Param final Class arg2) {  
> return GWT.create(fooType, arg1, arg2);
>   }
>
> Sending classes is no good, because the constructor needs the values.
>
> Personally, I think the best solution is to add the parameters to 
> @GwtCreate;
>
>   Foo createFoo(
> @GwtCreate({String.class, int.class})
> final Class fooType,
> String arg1, int arg2) {  
> return GWT.create(fooType, arg1, arg2);
>   }
>
> Class values in annotations must be class literals, so that makes that 
> easy.
>

My intention was to provide extra parameters as arguments for code-gen 
methods, i.e:

   createUiBinder(Widget.class, Owner.class, "template.ui.xml"); 
 

> It also means we don't care about the order of extra parameters sent to 
> the method,
> nor are we forced to get these values from the method parameters (or even 
> declare GWT.create params as params in method);
> the invocation of GWT.create(cls, params) would simply supply the 
> JExpressions to pass along to constructors.
> (Have to pull out the initializers from the JNewArray made by the 
> generics, but that's simple).
>
> I assume we would be changing GWT.create to be create(Class c, Object 
> ... params);
> the compiler could bail if params.length > 0 anywhere that's not in a 
> method (method w/ parameter) annotated with @GwtCreate.
>
> Then, add a JType[] and JExpression[] to JGwtCreate to be able to find the 
> right constructor and have values to send it 
> (not sure if unboxing would work without a tweak, but that's no biggie).
>
>
> The only hard-ish part would be updating ResolveRebinds to pass along the 
> list of JExpressions correctly.
>
>
> Do you have any work started in this area, cos I'd be glad to give it a 
> shot / send over a pull request.
>

No, I don't have did nothing in this are, you are welcome to join efforts 
and ideas :-)
 

>
> To allow mixed multiple code-gen parameters, we would bind main 
> parameters by name
>
>>
>>   
>>   void mixedMultiple(
>>   @GwtCreate final Class fooType, 
>>   @GwtCreate.Param("fooType") final Class fooArg,
>>   @GwtCreate final Class barType, 
>>   @GwtCreate.Param("barType") final Class barArg)
>>
>
> I really don't like this much typing to wire stuff up.
> Putting the params in the @GwtCreate would make this much cleaner:
>
>  B create(
> @GwtCreate({String.class}) final Class fooType,
> @GwtCreate({Foo.class}) final Class barType) {
> F foo = GWT.create(fooType, "some string");
> return GWT.create(barType, foo); // params can come from anywhere
>   }
>

As I mentioned before, I want to pass "some string" as argument to 
create(fooType, barType, String)
 

>   3) Support for GWT.create(this.getClass()) ? not exactly, but...
>>
>> Explicits generators can eliminate the issue of the unique generator 
>> per class hierarchy. An aditional boolean parameter for @GwtCreate would 
>> mitigate the code size issue
>>
>>   abstract class UiBinderComposite extends UiBinderComposite {
>>
>> public UiBinderComposite() {
>>   UiBinder binder = 
>> createBinder(getClass());
>> }
>>
>> private static UiBinder
>> createBinder(@GwtCreate(
>> /

[gwt-contrib] Re: Initial support for @GwtCreate (code-gen methods)

2013-08-17 Thread James Nelson
I like it!

I've got a few comments / ideas, but overall, I'm glad to see more work 
being done to empower core GWT functionality.

 

> Note that the @GwtCreate class parameters aren't replaced by 
> GwtCreateFactory as was originally suggested by Ray Cromwell. This provides 
> access to actual parameters.
>
>
It would be possible to do a full replacement if the factory also gave 
access to the class field, and any code in the method block accessing the 
class could be re-routed through the factory.
Though, I see no good reason why to do the extra work this way, I figured 
I'd mention it in case someone else has a use case for it.
 

* Upcoming improvements:
>
>   1) Support for explicit generators
>
> @GwtCreate(generator = FooGenerator.class)
>
>
Did you see my pull request with some (very) basic support for this?
https://gwt-review.googlesource.com/#/c/4000/

 

> We should forbid assignation between parameters that differs in 
> @GwtCreate signature
>
>   Foo createFoo(@GwtCreate(generator = FooGen.class) final Class extends Foo>) {...}
>
>
Agreed.  Final isn't necessary to trace values, but it does ensure users 
don't get weird behavior.


  2) Multiple parameters for GWT.create() by means of @GwtCreate.Param
>
>UiBinder createBinder(
> @GwtCreate(generator = UiBinGen.class) final Class uiType, 
> @GwtCreate.Param final Class ownerType) {
>

Is the intention here to just send more classes to the generator,
or to actually send parameters to the constructor of the rebound object 
being instantiated?

  Foo createFoo(
@GwtCreate final Class fooType,
@GwtCreate.Param final Class arg1,
@GwtCreate.Param final Class arg2) {  
return GWT.create(fooType, arg1, arg2);
  }

Sending classes is no good, because the constructor needs the values.

Personally, I think the best solution is to add the parameters to 
@GwtCreate;

  Foo createFoo(
@GwtCreate({String.class, int.class})
final Class fooType,
String arg1, int arg2) {  
return GWT.create(fooType, arg1, arg2);
  }

Class values in annotations must be class literals, so that makes that easy.

It also means we don't care about the order of extra parameters sent to the 
method,
nor are we forced to get these values from the method parameters (or even 
declare GWT.create params as params in method);
the invocation of GWT.create(cls, params) would simply supply the 
JExpressions to pass along to constructors.
(Have to pull out the initializers from the JNewArray made by the generics, 
but that's simple).

I assume we would be changing GWT.create to be create(Class c, Object 
... params);
the compiler could bail if params.length > 0 anywhere that's not in a 
method (method w/ parameter) annotated with @GwtCreate.

Then, add a JType[] and JExpression[] to JGwtCreate to be able to find the 
right constructor and have values to send it 
(not sure if unboxing would work without a tweak, but that's no biggie).


The only hard-ish part would be updating ResolveRebinds to pass along the 
list of JExpressions correctly.


Do you have any work started in this area, cos I'd be glad to give it a 
shot / send over a pull request.
 

To allow mixed multiple code-gen parameters, we would bind main 
parameters by name

>
>   
>   void mixedMultiple(
>   @GwtCreate final Class fooType, 
>   @GwtCreate.Param("fooType") final Class fooArg,
>   @GwtCreate final Class barType, 
>   @GwtCreate.Param("barType") final Class barArg)
>

I really don't like this much typing to wire stuff up.
Putting the params in the @GwtCreate would make this much cleaner:

 B create(
@GwtCreate({String.class}) final Class fooType,
@GwtCreate({Foo.class}) final Class barType) {
F foo = GWT.create(fooType, "some string");
return GWT.create(barType, foo); // params can come from anywhere
  }
 

>   3) Support for GWT.create(this.getClass()) ? not exactly, but...
>
> Explicits generators can eliminate the issue of the unique generator 
> per class hierarchy. An aditional boolean parameter for @GwtCreate would 
> mitigate the code size issue
>
>   abstract class UiBinderComposite extends UiBinderComposite {
>
> public UiBinderComposite() {
>   UiBinder binder = 
> createBinder(getClass());
> }
>
> private static UiBinder
> createBinder(@GwtCreate(
> // The explicit generator knows when to stop the code 
> generation
> generator = UiBinderCompositeGenerator.class,
>
> // this.getClass() is disallowed by default.
> allowsThisClass = true) 
> final Class type) {
>
>   return GWT.create(type);
> }
>   }
>

I am unsure how a param in @GwtCreate on the method affects enhancing this 
classes.
Would it enhance the this of the type sent to th

[gwt-contrib] Re: Initial support for @GwtCreate (code-gen methods)

2013-08-16 Thread Andrés Testi
JEnumTypeTest doesn't fails anymore, I think the issue was solved yesterday 
:-) 

-- 
http://groups.google.com/group/Google-Web-Toolkit-Contributors
--- 
You received this message because you are subscribed to the Google Groups "GWT 
Contributors" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to google-web-toolkit-contributors+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


[gwt-contrib] Re: Initial support for @GwtCreate (code-gen methods)

2013-08-16 Thread Andrés Testi
I forgot to upload the @GwtCreate annotation. You can find It here 
https://gwt-review.googlesource.com/#/c/4111/
Regards

- Andrés

El viernes, 16 de agosto de 2013 06:30:15 UTC-3, Andrés Testi escribió:
>
> I've been working on a prototype inspired by Ray Cromwell's proposal for 
> @GwtCreate parameters, borrowing some ideas from Scala implicit macros. I 
> apologize for not to post this in the "Possible GWT.create() Improvements" 
> thread, but this message is too long to be only a comment. 
> You can check my patch at https://gwt-review.googlesource.com/4110. This 
> prototype has passed many JUnit tests cases and works fine (only fails 
> JEnumTypeTest after my last pull, I don't know why). Devmode also works.
> This proposal differs from Ray's original idea in that @GwtCreate is a 
> parameter annotation instead of a method annotation. Later I will justify 
> this decision.
> This new proposal consists on rewriting methods adding a trailing implicit 
> parameter of type o for each parameter annotated with @GwtCreate. 
> GwtCreateFactory is a hidden interface used by the compiler:
>
>   interface GwtCreateFactory {
>  T create();
>   }
>
> When the compiler finds a code-gen method like
>
>   Foo createFoo(@GwtCreate final Class fooType) {
> return GWT.create(fooType);
>   }
>
> it is rewritten as
>
>   Foo createFoo(final Class type, GwtCreateFactory 
> fooType$factory) {
> return fooType$factory.create();
>   }
>
> IMPORTANT: 
>  The @GwtCreate parameter requires to be final.
>  This proposal doesn't require constant evaluation expression. The 
> final modifier is required to disable non reproductible side effects.
>
> At method call site, an invocation like
>
>   Foo foo = createFoo(SubFoo.class);
>
> is rewritten as
>
>   class SubFoo$GwtCreateFactory implements GwtCreateFactory {
> @Override public  T create() {
>   return GWT.create(SubFoo.class);
> }
>   }
>
>   Foo foo = createFoo(SubFoo.class, new SubFoo$GwtCreateFactory());
>
> Just like Scala implicit parameters, @GwtCreate can fight against type 
> erasure and subtyping
>
>   interface FooCreator {
>
>  T create(@GwtCreate Class fooType);  
>   }
>
>   class FooCreatorImpl extends FooCreator {
>
>  T create(@GwtCreate final Class fooType) {
>   return GWT.create(fooType);
> }
>   }
>
> code-gen constructors are supported too
>
>   class CreateByConstructor {
>   
> final T instance;
>  
> public  CreateByConstructor(@GwtCreate final Class fooType) {
>   instance = GWT.create(fooType);
> }
>   }
>
> Again, as in Scala implicit parameters, nesting is allowed
>
>   class Foo {}
>   class SubFoo extends Foo {}
>
>F createFoo(@GwtCreate final Class fooType) {
> return GWT.create(fooType);
>   }
>
>S createSubFoo(@GwtCreate final Class subFooType) {
> return createFoo(subFooType);
>   }
>
> The decision to locate @GwtCreate on parameters was taken to support mixed 
> code-gen methods
>
>   
>   void fooBarCreator(@GwtCreate final Class fooType, @GwtCreate final 
> Class barType) {
> foo = GWT.create(fooType);
> bar = GWT.create(barType);
>   }
>
> Note that the @GwtCreate class parameters aren't replaced by 
> GwtCreateFactory as was originally suggested by Ray Cromwell. This provides 
> access to actual parameters.
>
>   Class storedType;
>   T instance;
>
>   void createFoo(@GwtCreate final Class type) {
> storedType = type;
> instance = GWT.create(type);  
>   }
>
> * Upcoming improvements:
>
>   1) Support for explicit generators
>
> @GwtCreate(generator = FooGenerator.class)
>
> We should forbid assignation between parameters that differs in 
> @GwtCreate signature
>
>   Foo createFoo(@GwtCreate(generator = FooGen.class) final Class extends Foo>) {...}
>
>   // This will fail
>   Foo forbiddenNesting(@GwtCreate(generator = BarGen.class) final 
> Class fooType) {
> return createFoo(fooType);
>   }
>
>   2) Multiple parameters for GWT.create() by means of @GwtCreate.Param
>
>UiBinder createBinder(
> @GwtCreate(generator = UiBinGen.class) final Class uiType, 
> @GwtCreate.Param final Class ownerType) {
>
>  return GWT.create(uiType, ownerType);
>   }
>
> @GwtCreate.Params must respect the same kind of signature rules than 
> @GwtCreate, and a strict order of invocation
>
>   // Good ordering
>   Foo createFoo(
> @GwtCreate final Class fooType,
> @GwtCreate.Param final Class arg1,
> @GwtCreate.Param final Class arg2) {  
> return GWT.create(fooType, arg1, arg2);
>   }
>
>   // Bad ordering, this will fail
>   Foo createFoo(
>   @GwtCreate final Class fooType,
>   @GwtCreate.Param final Class arg1,
>   @GwtCreate.Param final Class arg2) { 
>
> return GWT.create(fooType, arg2, arg1);
>   }
>  
> To allow mixed multiple code-gen parameters, we would bind main 
> paramet