Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Typed Macros #135

Open
masonwheeler opened this issue Mar 21, 2016 · 5 comments
Open

Proposal: Typed Macros #135

masonwheeler opened this issue Mar 21, 2016 · 5 comments

Comments

@masonwheeler
Copy link
Contributor

As powerful as Boo's macro system is, it has one very notable limitation: it runs before type binding takes place, which makes it extremely cumbersome to try to write macro code that needs to be aware of types for whatever reason.

It would be nice to add a mechanism for type-aware macros. This is simply a proposal at the moment, for discussion purposes, but here's an initial outline:

  • Add a new TypemacroMacro which descends from MacroMacro and does exactly the same thing as MacroMacro, except that the generated macro class is tagged with an attribute, virtual method, or other way of marking it as a typed macro.
  • When the MacroExpander encounters a macro, it first checks to see if it's a typed macro, and if so, it leaves it alone.
  • Processing continues. Nodes get bound to types.
  • Add a second MacroExpander pass after type inference. This one unconditionally expands all macros, and runs CodeReifier over the result. At this point, type information is available, which makes writing certain types of macros much, much easier.

Implementing and testing this would be a non-trivial undertaking, so any thoughts on the subject would be welcomed.

@masonwheeler
Copy link
Contributor Author

One obvious optimization: On MacroExpander's first pass, set a static property to true if it finds a typed macro. On the second pass, check this property, and if it's false, the entire pass can be skipped. This means we don't get the additional overhead of a new compiler pass unless it's actually being used.

@BitPuffin
Copy link
Contributor

One area where this might cause bad problems with is in code such as the one you suggested to me with a problem:

macro dependentMacro:
   var myModule = FindMyModule(CompileUnit)
   var checker = MacroSearcher()
   myModule.Accept(checker)
   return dependentMacro if checker.ContainsMacros
   //perform your logic here

class MacroSearcher(DepthFirstVisitor):
   property ContainsMacros as bool

   override def OnMacroStatement(node as MacroStatement):
      ContainsMacros = true

Basically, the addition of typed macros could cause an infinite loop for macros that try to run in a certain order.. Maybe we should also come up with a better solution to somehow control the order of macro expansion.

@BitPuffin
Copy link
Contributor

After thinking about it. I think perhaps that a better solution is to create some kind of "FutureTypeReference" in the cases where the type is inferred for type references. This would obviously change the structure a bit of the compiler, since any code with 'FutureTypeReference's would have to be error checked after type inference stage, but that would basically solve whatever a typed macro would solve without having to make a distinguishing of the macros. I also think it would be pretty easy to work with probably?

@masonwheeler
Copy link
Contributor Author

A hypothetical FutureTypeReference would solve the case where you need to create a declaration for a type that hasn't been inferred yet, but there are plenty of other interesting use cases that it would not help with. For example, having your macro treat code differently depending on the inferred type of an expression inside the macro body. For that, the macro actually needs access to the types.

@BitPuffin
Copy link
Contributor

True, you're right. I guess both would be good improvements!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants