Skip to content
This repository has been archived by the owner on Nov 11, 2021. It is now read-only.

GTScript unstructured prototype frontend #52

Merged
merged 58 commits into from
Sep 21, 2020
Merged

Conversation

tehrengruber
Copy link
Contributor

First prototype frontend from (unstructured) GTScript down to C++ code with working regression tests.

@tehrengruber tehrengruber marked this pull request as draft August 24, 2020 13:15
@tehrengruber tehrengruber force-pushed the gt4pyast_unstructured branch 4 times, most recently from 73bf1e6 to bb39143 Compare August 25, 2020 10:46
@tehrengruber tehrengruber requested review from havogt and DropD August 25, 2020 10:55
@tehrengruber tehrengruber marked this pull request as ready for review August 25, 2020 11:18
Copy link
Contributor

@havogt havogt left a comment

Choose a reason for hiding this comment

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

Some minor comments

examples/unstructured/frontend.py Outdated Show resolved Hide resolved
setup.cfg Outdated Show resolved Hide resolved
"Vertex": common.LocationType.Vertex,
"Edge": common.LocationType.Edge,
"Cell": common.LocationType.Cell,
# "Field": Field,
Copy link
Contributor

Choose a reason for hiding this comment

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

remove?

src/gt_frontend/gtscript.py Outdated Show resolved Hide resolved
src/gt_frontend/gtscript_to_gtir.py Show resolved Hide resolved
Copy link
Contributor

@DropD DropD left a comment

Choose a reason for hiding this comment

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

Type annotations are missing in a lot of places (specifically return types often even when argument types are annotated), mypy can be used to discover all instances of that.

Most modules seem to lack unit tests (seeing as they are new modules I would at least expect some changes to existing tests if not new test modules).

There are many, many "todo" comments. These must be addressed either by converting them into issues (low priority), deleting them (obsolete) or fixing them right away.

I commented on some instances but not all where functions are hard to test due to deep nesting of conditionals, often in combination with loops. This will become painfully obvious while writing unit tests or if they ever need to be debugged.

examples/unstructured/frontend.py Outdated Show resolved Hide resolved
setup.cfg Outdated Show resolved Hide resolved
examples/unstructured/frontend.py Outdated Show resolved Hide resolved
return False


# todo: pattern node ast.Name(bla=123) matches ast.Name(id="123") since bla is not an attribute
Copy link
Contributor

Choose a reason for hiding this comment

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

Open TODO, please explain what the steps are to close it and whether they have been taken already.



def match(concrete_node, pattern_node, captures=None) -> Tuple[bool, Dict[str, ast.AST]]:
if captures is None:
Copy link
Contributor

Choose a reason for hiding this comment

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

I am fairly certain this function is complex enough to warrant a docstring.

At first glance I have no Idea what this does and where it fits in.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, concrete_node and pattern_node should probably be annotated as Any, while captures looks like Optional[Dict]

Copy link
Contributor

Choose a reason for hiding this comment

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

I would also recomend thinking about splitting at least the more complex elif cases into functions for readability and also testability. Unit testing or even regression testing this function must be a nightmare.

src/gt_frontend/py_to_gtscript.py Outdated Show resolved Hide resolved
src/gt_frontend/py_to_gtscript.py Outdated Show resolved Hide resolved
ast.Div: gtc.common.BinaryOperator.DIV,
}

def transform(self, node, eligible_node_types=None):
Copy link
Contributor

Choose a reason for hiding this comment

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

In the interest of readability and testability I would think about reducing the amount of nested code paths maybe by splitting some conditional paths into smaller functions.

return self.leaf_map[type(node)]
else:
# visit node fields and transform
# todo: check if multiple nodes match and throw an error in that case
Copy link
Contributor

Choose a reason for hiding this comment

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

Open TODO: explain steps to resolve or steps already taken.

from gt_frontend import ast_node_matcher as anm


class TestAstNodeMatcher:
Copy link
Contributor

Choose a reason for hiding this comment

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

I feel this test suite could be simplified while still covering more cases by simplifying the match function.

Also: is there a reason for this to be a class and not just top-level test functions? There is no setup or teardown it seems. Or is this run using something other than pytest?

@havogt
Copy link
Contributor

havogt commented Aug 27, 2020

About the mypy comment: in the pre-commit config there is a section about mypy which is currently disabled due to one issue I couldn't resolve. Maybe you, @DropD, have an idea how to resolve that and we can activate it.

Master has exactly one error (with python 3.8)

src/eve/typing.py:25: error: unused 'type: ignore' comment
Found 1 error in 1 file (checked 13 source files)

Regarding todo's, I have several comments:

  • I agree that obsolete/easy to solve should be removed/resolved
  • I don't think we should open issues for TODOs that are low priority here, that's too noisy and the frontend should still be considered experimental
  • I propose to use the format TODO(github-user-name) for todos that you want to resolve later

tehrengruber and others added 13 commits September 20, 2020 23:41
…ed code) (#54)

* Allow injection of static code blocks at the beginning of the generated code in UsidCodeGenerator

* Remove check in `UsidCodeGenerator` for conformance with sid concept as it triggers a compilation error in nvcc (workaround with templated function call instead of decltype possible, but withdrawn)

* Fix hardcoded name for temporary field in UsidCodeGenerator

* Added gtc regression test for FVM nabla operator (gtscript -> generated code)
 Note: driver code borrowed from cpputils regression tests via symlink for now

* Fix cmake not rebuilding on changes in cpputils and gtc regression tests

* Update src/gtc/unstructured/usid_codegen.py

Co-authored-by: Hannes Vogt <[email protected]>

* Update src/gtc/unstructured/usid_codegen.py

Co-authored-by: Hannes Vogt <[email protected]>

* Fix `ModuleNotFoundError: No module named 'eve'` in CI

* Added __init__.py to gt_frontent

* Remove obsolete hash_path in gtc regression tests cmake

* Revert "Fix `ModuleNotFoundError: No module named 'eve'` in CI"

This reverts commit cd7531d.

* CI: pip install eve (#57)

Co-authored-by: Hannes Vogt <[email protected]>
Copy link
Contributor

@egparedes egparedes left a comment

Choose a reason for hiding this comment

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

I add some comments but I would say that it looks good enough to be merged right now in order to avoid merge conflicts later.

General Python issues:

  • missing type annotations
  • all the instance attributes should be initialized in the __init__ method (an empty initialization with None is also ok)
  • use f-strings instead of str.format() whenever possible, since it usually enhances readibility (and it's slightly faster)
  • it should be discussed if Protocols or AbstractBaseClasses could be enough to describe the "parser type system" instead of the current metaclass-based hierarchy

Format issues:

  • docstrings should end with a period .
  • several wrongly capitalized names like UsidGpuCodeGenerator or GtirToNir (according to PEP8: "when using acronyms in CapWords, capitalize all the letters of the acronym. Thus HTTPServerError is better than HttpServerError")
  • "To Do" comments should use Hannes suggestion: TODO(github-handle)
  • I would try to split the code in more logical blocks using empty lines. Sources sometimes look a bit too crammed

Naming suggestions:

  • py_to_gtscript -> python_to_gtscript (and also change the class names inside)

setup.cfg Outdated Show resolved Hide resolved
src/gt_frontend/__init__.py Outdated Show resolved Hide resolved
from gtc.unstructured.usid_codegen import UsidGpuCodeGenerator


class GTScriptCompilationTask:
Copy link
Contributor

Choose a reason for hiding this comment

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

Some points about this class:

  • I don't see the point of storing the intermediate results .gtir, .gtscript_ast as instance state if it is not used at all. If there is a point to do it, the you they should be already initialized in the __init__ method with an empty initialization to None
  • Is this class aimed to be instantiated and kept around after use because the state is meaningful or it is meant to be a cheap "use and thow-away" object? I would provide a class method like apply in visitors for the second use-case, and maybe change the generate method name to __call__ in the first one
  • I find a bit confusing the definition of the default value for the code_generator in two different methods. Again, if the class is meant to be instantiated and used like a regular object, I think I would add the code_generator parameter to the constructor, if it is a single use instance, I would add the default value only to the public method and make the argument compulsory in the private one, to simplify the understanding of the code and avoid setting different default values for the same object in different places

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The intermediate results are stored since they are used in the unit tests. I spent absolutely no time in making this clean since the complete class will disappear with the PassManager to be introduced in Eve and the build stages approach @DropD introduced in GT4Py. I've added a todo comment in the meantime.

src/gt_frontend/py_to_gtscript.py Outdated Show resolved Hide resolved
src/gt_frontend/py_to_gtscript.py Outdated Show resolved Hide resolved
src/gt_frontend/gtscript_ast.py Outdated Show resolved Hide resolved
src/gt_frontend/gtscript_ast.py Outdated Show resolved Hide resolved
self.types[item] = val
return self.types[item]

def materialize_constant(self, name, expected_type=None):
Copy link
Contributor

Choose a reason for hiding this comment

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

A bit weird name for just a getter method with validation. I would use something simpler:

Suggested change
def materialize_constant(self, name, expected_type=None):
def get_constant(self, name, expected_type=None):

Also the docstrings seems to be out of date

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The naming was intentional here to remind myself that this would currently be the place were constant folding would take place (for which I don't know yet what the right place is). It's just that there is nothing to "fold" since the values are externally supplied. I extended the docstring to emphasize this and added a todo.

src/gt_frontend/gtscript_to_gtir.py Outdated Show resolved Hide resolved
src/gt_frontend/ast_node_matcher.py Show resolved Hide resolved
@tehrengruber
Copy link
Contributor Author

After countless remarks and commits this PR has reached a level of maturity I believe it to be ready to be merged into master. It is still a prototype with many (but clearly documented) todos, but avoiding merge conflicts and keeping the review of further changes reviewable has priority. The remaining remarks will then be addressed in a seperate PR.

@tehrengruber tehrengruber merged commit 8c58566 into master Sep 21, 2020
@havogt havogt deleted the gt4pyast_unstructured branch November 3, 2020 10:41
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants