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

AST module #991

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open

AST module #991

wants to merge 14 commits into from

Conversation

acbart
Copy link
Contributor

@acbart acbart commented Dec 18, 2019

With my semester wrapping up, I wanted to make some pull requests for features I added during the semester. This one is probably not the most important, but its a big part of BlockPy's toolchain, so I wanted to get a sense of your interest. Others include exec, more info in exceptions, and a fix to special method lookup in classes.

This PR adds in an importable ast module that has the most of the core functionality you'd expect from CPython's ast library, including AST node classes, a NodeVisitor class, and a parse function. It also expands nodes to include ending lines and columns in addition to the starting attributes.

If you're interested, I'm willing to spend some time cleaning up some of the code further - I am passing all the test cases I wrote, at least, and none of the existing tests seem to be broken. Not sure how compatible this is with the other pull requests open right now. Probably should merge them in first and then make further modifications as required.

@acbart
Copy link
Contributor Author

acbart commented Dec 18, 2019

The parser also collects comments now too. That's a necessary bit for BlockMirror's block/text conversion algorithm, though it might be esoteric for others.

Oh, and I think some code for modules ended up in here, which I can move to the exec PR. That's related to the crazy global mangling that has to go on to make things exec keep namespaces separate.

@rixner
Copy link
Contributor

rixner commented Feb 4, 2020

I am in favor of this pull request. I looked over the code and it seems like this doesn't disrupt anything else in the core and it adds new functionality we don't currently have.

However, I can't run it right now, perhaps because I resolved the conflicts incorrectly (I didn't try very hard, admittedly)? I'm also not sure why Travis is saying it passes the tests when there is a conflict?

Also, you changed Sk.builtin.module to take a module name as an argument, but you didn't change existing callers (I think there's only one in import.js) to properly pass the name.

Anyway, @acbart if you can resolve the conflicts and get things in a condition you are happy with, I will be happy to approve this!

@acbart
Copy link
Contributor Author

acbart commented Feb 24, 2020

Sorry I've been utterly unable to work on this lately! Our semester started a few weeks ago, which means my long winter break ended without the chance for me to contribute anything more while I was waiting for this to be approved. It seems like you've been able to incorporate some of my changes on your own, anyway. When the summer rolls around, hopefully I can get the rest of my changes integrated into wherever you end up.

@rixner
Copy link
Contributor

rixner commented Jul 8, 2020

I would still very much like to see this merged. @acbart do you have time to bring it up to date?

@acbart
Copy link
Contributor Author

acbart commented Jul 8, 2020

I plumb forgot about this, but I do have time now. When integrating @s-cork 's #1092 pull request I did have to make some changes to this module. Is it worth waiting till that PR is merged in before trying to get this merged in? Or vice versa?

@rixner
Copy link
Contributor

rixner commented Jul 8, 2020

I'd vote to clear the backlog of pull requests before we even consider #1092. So, my vote is this should go first.

@albertjan
Copy link
Member

@acbart can you do this module without adding end_line_no and end_col_offset change?

@rixner
Copy link
Contributor

rixner commented Jul 11, 2020

@albertjan is there a reason you don't want those changes? I think we want those. It's one of the things I needed to add for #1044.

@albertjan
Copy link
Member

albertjan commented Jul 11, 2020 via email

@acbart
Copy link
Contributor Author

acbart commented Jul 11, 2020

I appreciate wanting to have them be separate, but that would be an awful lot of work on changing something I've already done. Plus, I'd really like to have the line endings in upstream Skulpt, it's currently making it much harder for me to merge in upstream changes. I have a little time today to make the already requested changes and resolve the simple merge conflict that was there, but if you want that change, it'll be a lot longer before I'd have the time needed.

@acbart
Copy link
Contributor Author

acbart commented Jul 11, 2020

Okay, want to take another look? I'm passing all test cases and I don't think there are any conflicts to resolve.

src/ast.js Outdated
@@ -3363,5 +3378,115 @@ Sk.astDump = function (node) {
return _format(node, "");
};


Sk.INHERITANCE_MAP = {
Copy link
Member

Choose a reason for hiding this comment

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

what does this do is this automatically generated?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not automatically generated. I believe this data ended up here largely out of convenience that came when authoring it, and I'm thinking now it needs to be moved into the src/lib/ast.js file instead. The idea is that this encodes the inheritance relationships that exist between nodes. Want it moved to the library AST file?

@@ -68,6 +69,11 @@ function findInDfa (a, obj) {
return false;
}

// Add a comment
Copy link
Member

Choose a reason for hiding this comment

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

our parser throws out comments? Does the cpython parser leave them in?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If I recall, both Skulpt and cpython toss the comments out.

Copy link
Member

Choose a reason for hiding this comment

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

But you keep them in here? But I don't see where you use them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't use them anywhere in here, but they're essential for BlockMirror's ability to take Skulpt parse trees and convert them into Blockly code. I know this may not be useful to anyone else, so I suppose it's worth talking about removing. Personally, I think it's nice to have them collected, especially if you ever want to add special behavior like #: type comments.

Copy link

Choose a reason for hiding this comment

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

Is there a better solution to parse comment ? I think this is not the optimal way

@albertjan
Copy link
Member

albertjan commented Jul 11, 2020

Can you see how many of these tests pass? https://github.com/python/cpython/blob/3.8/Lib/test/test_ast.py feel free to comment out anything that doesn't apply or that skulpt can't handle.

@acbart
Copy link
Contributor Author

acbart commented Jul 14, 2020

To answer the question of how many tests pass: apparently almost none of them (I think 3 passed).

  1. I haven't implemented any of the functionality for things like fix_missing_locations, get_source_segment, and get_docstring.
  2. I added in a little functionality to create nodes manually (limited utility for my purposes), but that doesn't prepopulate their fields.
  3. There's some wacky inheritance things that happen with the new Constant nodes that I don't think we should bother with until we have proper metaclassing. It's weird.
  4. I believe I messed up the keyword arguments for parse and dump, but I don't know what the exact style is supposed to be. Is that documented somewhere?

Only 4 seems worth fixing to me, right now. I think someone else will have to feel strongly about 1-3, since I have no particular reason to make them happen.

@albertjan
Copy link
Member

Thanks @acbart. I'll try to have look tomorrow.

}
this["$d"] = {__name__: name};
this["$d"]["__dict__"] = this["$d"];
return this;
};
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we have the __dict__ here? this would return a javascript object to the user no?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I totally defer to you on this one, I figured whatever I had in here would have to be heavily changed for your new PRs anyway. This is just what I had at this point in time. I note that my own local Skulpt (which integrates most of your changes, but not the latest ones) actually looks like this:

Sk.builtin.module = Sk.abstr.buildNativeClass("module", {
// ...
        tp$init: function(args, kwargs) {
            Sk.abstr.checkArgsLen(this.tp$name, args, 1, 3);
            this["$d"] = {
                "__name__": args[0],
                "__package__": Sk.builtin.none.none$,
            };
            return Sk.builtin.none.none$;
        },

Copy link
Contributor

Choose a reason for hiding this comment

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

Nice. Yeah, For this pr I'd remove the __dict__ since the user won't get a python object if they try to access it. I guess this really should be a python dictionary in the future...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Does b92c363 handle this? I feel silly for letting my module stuff slip into this PR, it's not really all that relevant, ultimately.

@rixner rixner mentioned this pull request Aug 5, 2020
('Expression', ('Tuple', (1, 0), [], ('Load',))),
('Expression', ('Call', (1, 0), ('Attribute', (1, 0), ('Attribute', (1, 0), ('Attribute', (1, 0), ('Name', (1, 0), 'a', ('Load',)), 'b', ('Load',)), 'c', ('Load',)), 'd', ('Load',)), [('Subscript', (1, 8), ('Attribute', (1, 8), ('Name', (1, 8), 'a', ('Load',)), 'b', ('Load',)), ('Slice', ('Constant', (1, 12), 1, None), ('Constant', (1, 14), 2, None), None), ('Load',))], [])),
]
main()
Copy link
Contributor

Choose a reason for hiding this comment

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

for this pr we'd need this unit test module to pass. I'd suggest commenting out all the tests that don't pass here...

@@ -0,0 +1,94 @@
import ast
Copy link
Contributor

Choose a reason for hiding this comment

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

these tests don't fit with the style of skulpt.
Can we turn these into unit tests?

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.

5 participants