Is CCI/AST merging two abstraction layers in one?

Feb 5, 2010 at 6:28 AM
Edited Feb 5, 2010 at 6:54 AM

Hello.

This is an issue that sprung to my mind several times since I thought of switching from a compiler based on CCI-Metadata only to a compiler based on CCI-AST.

When you have to compile, say, a instance method invocation, you may have a MethodInvocation object in your compiler's AST with target expression, method name and actual arguments.

Using CCI-Metadata you would look-up for the type of the object instance, find all methods with that name, pick the one that is appropriate and then you will generate the CIL code.

Using CCI-AST you would just map your MethodInvocation the corresponding CCI-AST and all the details that require a knowledge of the actual type is carried out by CCI-AST itself. Maybe a little of help is required to perform the binding but nothing more.

Now what happens if you are generating something that is close to a MethodInvocation but it's not quite the same?

Let's call it CoolMethodInvocation. The CIL code emitted for CoolMethodInvocation is the same of a normal method invocation but there is "some more" (maybe before or after).

Now the point is: what if that "something more" depends on the actual type's metadata, for example the actual method called?

What would you do working with CCI-AST?

Of course 99% of the times it's easy to map that "something more" to some other CCI-AST objects. Let's make it 100%. That's not the problem.

But in order be able to choose what to do that you have to perform the binding yourself, map your objects to CCI-AST object, including the usual CCI-AST method invocation object.

At the end you performed the binding of a method two times with two different part of the compiler.

This is only an example but the problem is a more general. If this happens only once - for example your compiler only implements that CoolMethodInvocation - this is not a big problem. In other cases - for example if the language you are implementing includes some metaprogramming features - the same problem emerges more and more often.

Am I missing something? Is this something that the current version of CCI-AST was not designed for? What's the best way to approach this kind of problems? For example in this case what would be the way to ask CCI-AST to perform the method binding the way it would do it when compiling the normal method call. Is it exposed? (I'll try and follow the code but I wouldn't mind a hint!)

I'm sure I still don't understand all the architecture some I have overlooked something.

Thanks!

Coordinator
Feb 5, 2010 at 7:29 AM

The general architecture is that your parser would contruct a CoolMethodInvocation node and this node will have find a way to project itself onto the CodeModel. Hopefully, there is a base class, such as MethodCall that has most of the functionality that you want and that provides virtual methods that you can override to customize its behavior to be what CoolMethodInvocation needs, and hopefully the base class of LanguageSpecificCompilationHelper does the same, allowing you to customize the behavior of MethodCall without overridding.

However, if these are not what you want, you'll just have to write your own projection code. Note that you only have to project onto the CodeModel. The standard component for projecting from the CodeModel to the Metadata model is still going to be there for you.

It sounds a bit like you are contemplating projecting your CoolMethodInvocation not the the CodeModel but to the base class of the AST model. That is not quite what the architecture has in mind and does suffer from the problems you allude to.

Feb 5, 2010 at 7:46 AM

"Hopefully, there is a base class, such as MethodCall that has most of the functionality that you want and that provides virtual methods that you can override to customize its behavior to be what CoolMethodInvocation needs"

I guess it's what CreateObjectInstanceForResolvedConstructor does with CreateObjectInstance. It's also related to the specific example I described.

Thanks.

 

Feb 5, 2010 at 2:17 PM
hermanv wrote:
However, if these are not what you want, you'll just have to write your own projection code. Note that you only have to project onto the CodeModel. The standard component for projecting from the CodeModel to the Metadata model is still going to be there for you.

Am I correct if I say that if I start to implement CodeModel for something I have to implement it for everything? If MethodCall is not good for me and I can't subclass it in any usefulway and I implement IMethodCall I'll have to drop the whole AstsProjectedAsCodeModel layer and replace it with my own version.

I guess that now I understand why the codeplex project is called "Code and AST" components even if the solution is called "AST". In a sense, CodeModel is even more important the AST part.

Am I saying something stupid?

I reread your previous message few times, browsed the code again and now it's a bit more clear.

 

Coordinator
Feb 5, 2010 at 3:14 PM

Each node in your AST has to project itself to the CodeModel if you want to leverage the CodeModel to IL translator. For the most part, the standard AST base classes already take care of this and you just have to customize them by overriding methods and by providing your own LanguageSpecificCompilationHelper. So, only those nodes in you AST that do not derive from a standard base class that already does projection, need to worry about projection.

If your own AST nodes directly emit IL, then they will not be a good fit for the standard AST framework.

Feb 5, 2010 at 4:29 PM

I rewrote the compiler several times, so rewriting it again is not a problem. Each time I rewrote it I used a better method to emit CIL, a better representations and implemented some new feature that I need. This won't be the last time. I'm just trying to understand what's the best way to use CCI.

Previous version was based on CCI Metadata but it's old stuff. Current version already translates the language-specific AST into the classes in the Microsoft.Cci.Ast namespace.

Currently I have some elements in my AST that are projected in several different standard AST framework classes.

What I said was false, anyway: I can create a totally different implementation of IMethodCall and still subclass ConstructorIndexerOrMethodCall or at least Expression and have it interoperate with the rest of AstsProjectedAsCodeModel.

 

Feb 5, 2010 at 5:23 PM
Edited Feb 6, 2010 at 12:59 AM

I think I probably found a complete solution to my problem.

I was projecting an AST element that generates several type members at once in a quite complicated fashion.

The trick is that I have to create a special kind of type declaration to begin with. Then I should be able to do the rest in a way that works well with the whole framework.