macro_prototype icon indicating copy to clipboard operation
macro_prototype copied to clipboard

Statement/Expression/Element macros

Open jakemac53 opened this issue 4 years ago • 4 comments

Mostly a placeholder issue for now, we need to spec this feature out.

The general idea is to allow macros inside of constructor bodies. These macros would be able to inline any code they wish at their invocation site, effectively replacing a call to the macro with arbitrary code.

Use cases might include:

  • https://github.com/jakemac53/macro_prototype/issues/24
  • https://github.com/jakemac53/macro_prototype/issues/18
  • Configuration dependent code - for instance you should be able to write your own version of assert that actually inlines nothing in release builds.
  • Can possibly help with a macro based version of flutter_hooks

These macros would likely run in a new 4th macro phase, and would have full reflective access to the program, but would not be able to add any new declarations to the program, only inline some code at the site where they are invoked.

jakemac53 avatar Jul 29 '21 17:07 jakemac53

Thinking some more about this I was wondering if reusing the annotation syntax is going to limit macros applicability in these situations, since currently macros always have to have an element to annotate. Expressions is just one application, creating top-level definitions / declarations based off of a Code object is another one. Currently in order to create a top-level final variable based off a macro, you would need either to have a VariableDefinitionMacro which doesn't exist in this prototype or annotate a library declaration which seems like a really hacky workaround. Something similar could be said for generating classes / enums etc based off of a Resource. You would either need to annotate the library or some other thing that might not be related. Could there be a syntax like @@ or something else that would allow macros in these situations and differentiate them from annotations, or is it possible that we could just omit the @ altogether in these situations?

TimWhiting avatar Sep 17 '21 19:09 TimWhiting

The thinking so far has been to add library level macros (which would likely annotate the library directive).

You can also annotate imports I think? so that could be one option (annotate the import of the macro itself?).

If we do statement/expression/element level macros they very likely would look a bit different and not be annotation based (probably look like a function call).

jakemac53 avatar Sep 17 '21 20:09 jakemac53

+1 for function-looking macros.

I would really like the ability to do:

final value = @macro(params);

rrousselGit avatar Sep 17 '21 20:09 rrousselGit

In particular, I was thinking that function-like macros would be a good solution for #18 / flutter_hooks and #37

For #37, the idea is that we'd change:

final dependency = Provider(...);

final provider = Provider<MyClass>((ref) {
  final value = ref.watch(dependency);

  return MyClass();
},
  dependencies: { dependency },
 );

into:

final dependency = Provider(...);

final provider = Provider<MyClass>((ref) {
  final value = @watch(dependency);

  return MyClass();
});

and the macro would take care of adding the entry to "dependencies".

In this case, the macro parameter wouldn't be the Provider instance (since it's dynamic), but rather a Code/expression instance

rrousselGit avatar Sep 17 '21 20:09 rrousselGit