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

Implementing a structured traverser so the writer can have the full state #49

Merged
merged 2 commits into from
May 25, 2019

Conversation

tannergooding
Copy link
Member

This splits apart the visitor and the writer into two separate passes. Ultimately, this means that when writing files out to disk, we have the full state of the structure available for use.

During the initial traversal which builds the cursor tree, we are able to do some introspection about the cursor, such as being able to track the lhs and rhs of a binary operator, or being able to explicitly track function parameters or field declarations separately from other child cursors.

The writer then can worry about managing less state and only needs to track the output builders themselves plus which cursors have been visited.

This should also make it easier to process more complex expressions or statements in the writer.

@tannergooding
Copy link
Member Author

The cursor tree support is a bit verbose as I ensured it could build full trees for all the Windows SDK files.

Most of the information isn't used anywhere yet as I preserved the existing behavior/handling that the writer had (so no changes if you regenerate ClangSharp or LLVMSharp).

@tannergooding
Copy link
Member Author

Another way of looking at this is it is taking the Attached*Data types that were being used and is filling them out to be more general purpose and carry all the information they can.

private readonly Dictionary<string, OutputBuilder> _outputBuilders;
private readonly Stack<CXCursor> _processingCursors;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need to track most of this state anymore.


switch (cursor.Kind)
private string EscapeName(string name)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The helper functions for generating names are the same as before, but pulling from the Cursor types rather than directly from CXCursor.

{
return "ushort";
Unhandled(decl, pointeeType);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handling BinaryOperator is really simple now that we are directly tracking the LhsExpr and RhsExpr

{
return "ushort";
Unhandled(decl, pointeeType);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise for ParenExpr, plus we don't need to track how deep we are in the expression tree anymore.

{
return "ushort";
Unhandled(decl, pointeeType);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This handles nested declarations, if they exist and places them just after the list of fields.


case CXCursorKind.CXCursor_FieldDecl:
{
var fieldDecl = GetOrAddChild<FieldDecl>(childHandle);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most code paths in these types aren't consumed by generating LLVMSharp or ClangSharp, but they can be used for generating things like the Windows SDK.

Child cursors that represent useful information for a given cursor kind can be exposed directly to the writer, such as the FieldDecl here. The writer can then handle that data first before falling back to normal processing for any remaining children.

{
Debug.Assert(handle.Kind == CXCursorKind.CXCursor_IntegerLiteral);

_rawValue = new Lazy<string>(() => {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can also relegate cursor specific logic, like extracting the raw text for an IntegerLiteral to the type itself, since it isn't really related to the writer.


set
{
Debug.Assert(_expr is null);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are also able to do additional sanity checks, such as an UnaryOperator only having a single expression (which can itself have sub-expressions).

@mjsabby
Copy link
Contributor

mjsabby commented May 25, 2019

LGTM, took a while to review.

@tannergooding
Copy link
Member Author

took a while to review.

Thanks, and sorry for the big PR. Subsequent ones should hopefully be smaller now and should mostly be restricted to the writer understanding more metadata from the traversed tree.

@tannergooding tannergooding merged commit efd0434 into dotnet:master May 25, 2019
@tannergooding tannergooding deleted the structured-traversal branch May 29, 2019 00:29
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

Successfully merging this pull request may close these issues.

2 participants