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

[Relay][Prelude] Use the Relay parser to define the Relay prelude #3043

Merged
merged 26 commits into from
Jun 11, 2019

Conversation

jroesch
Copy link
Member

@jroesch jroesch commented Apr 18, 2019

The current Relay prelude is huge pain to modify and doesn't always result in correct ASTs requiring painful hand modifications each time we update it.

It would be far more useful to make use of the Relay parser to load the Prelude from disk.

This PR makes it possible to partially load a Relay Prelude from disk. The PR also includes some modifications to the Relay parser to support defining more code in Relay.

This should help motivate one piece of the final push on the Relay Text format (see #3016).

My goal is to make it possible to define a limited form of TensorArray using this in the coming days.

cc @wweic @joshpoll @MarisaKirisame

@jroesch jroesch self-assigned this Apr 18, 2019
@MarisaKirisame
Copy link
Contributor

AFAICT relay dont has a way of defining adt.
@joshpoll maybe we can add that?

@slyubomirsky
Copy link
Contributor

Finalizing a Relay ADT syntax would be of great help to docs too

tests/python/relay/test_prelude.py Outdated Show resolved Hide resolved
if mod is None:
mod = Module({})

file = os.path.join(__PRELUDE_PATH__, "prelude.rly")
Copy link
Contributor

Choose a reason for hiding this comment

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

file is a builtin. rename

Copy link
Contributor

Choose a reason for hiding this comment

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

Done


raise ParseError("Unknown builtin type: {}".format(ident_type))
print(type_ident)
Copy link
Contributor

Choose a reason for hiding this comment

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

remove

Copy link
Contributor

Choose a reason for hiding this comment

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

Done

@@ -454,15 +467,21 @@ def visitIncompleteType(self, ctx):
return None

def visitIdentType(self, ctx):
# TODO(@jroesch) Identifier Type doesn't make sense should be Type Identifier.
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we resolve this TODO in this PR?

Copy link
Contributor

Choose a reason for hiding this comment

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

Will do

Copy link
Contributor

Choose a reason for hiding this comment

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

Done

python/tvm/relay/_parser.py Show resolved Hide resolved
Copy link
Contributor

@joshpoll joshpoll left a comment

Choose a reason for hiding this comment

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

Please bump the version number.

@@ -111,8 +111,8 @@ expr
// | 'debug' # debug
;

func: 'fn' '(' argList ')' ('->' type_)? body ;
defn: 'def' ident '(' argList ')' ('->' type_)? body ;
func: 'fn' (typeParamSeq)? '(' argList ')' ('->' type_)? body ;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
func: 'fn' (typeParamSeq)? '(' argList ')' ('->' type_)? body ;
func: 'fn' typeParamSeq? '(' argList ')' ('->' type_)? body ;

Copy link
Contributor

Choose a reason for hiding this comment

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

Done

func: 'fn' '(' argList ')' ('->' type_)? body ;
defn: 'def' ident '(' argList ')' ('->' type_)? body ;
func: 'fn' (typeParamSeq)? '(' argList ')' ('->' type_)? body ;
defn: 'def' ident (typeParamSeq)? '(' argList ')' ('->' type_)? body ;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
defn: 'def' ident (typeParamSeq)? '(' argList ')' ('->' type_)? body ;
defn: 'def' ident typeParamSeq? '(' argList ')' ('->' type_)? body ;

Copy link
Contributor

Choose a reason for hiding this comment

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

Done

@@ -140,7 +146,7 @@ type_
| 'Tensor' '[' shapeSeq ',' type_ ']' # tensorType
// currently unused
// | identType '[' (type_ (',' type_)*)? ']' # callType
| 'fn' '(' (type_ (',' type_)*)? ')' '->' type_ # funcType
| 'fn' (typeParamSeq)? '(' (type_ (',' type_)*)? ')' '->' type_ # funcType
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
| 'fn' (typeParamSeq)? '(' (type_ (',' type_)*)? ')' '->' type_ # funcType
| 'fn' typeParamSeq? '(' (type_ (',' type_)*)? ')' '->' type_ # funcType

Copy link
Contributor

Choose a reason for hiding this comment

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

Done

tests/python/relay/test_prelude.py Outdated Show resolved Hide resolved
python/tvm/relay/prelude.rly Outdated Show resolved Hide resolved
@slyubomirsky
Copy link
Contributor

slyubomirsky commented May 30, 2019

@jroesch has asked me to take over this PR so I will work on addressing feedback and fixing linting errors to get this to a mergeable state soon. The next step would be to add ADTs and matching to the text format so the entire prelude can be written in the text format (I think that should be a separate PR)

@slyubomirsky
Copy link
Contributor

Pinging reviewers: @wweic @joshpoll @MarisaKirisame

@@ -19,7 +19,7 @@

grammar Relay;

SEMVER: 'v0.0.1' ;
SEMVER: 'v0.0.1.1' ;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
SEMVER: 'v0.0.1.1' ;
SEMVER: 'v0.0.2' ;

This is the convention for pre-release semver.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks, done

typeParamSeq
: '[' ']'
| '[' ident ']'
| '[' ident (',' ident)+ ']'
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
| '[' ident (',' ident)+ ']'
| '[' ident (',' ident)* ']'

to merge this case and the previous one.

Copy link
Contributor

Choose a reason for hiding this comment

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

tuples need something different b/c they require a trailing comma

Copy link
Contributor

Choose a reason for hiding this comment

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

Good idea. Done

typeParamSeq
: '[' ']'
| '[' ident ']'
| '[' ident (',' ident)+ ']'
Copy link
Contributor

Choose a reason for hiding this comment

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

tuples need something different b/c they require a trailing comma

@@ -28,7 +28,7 @@
else:
raises_parse_error = lambda x: x

SEMVER = "v0.0.1"
SEMVER = "v0.0.1.1"
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
SEMVER = "v0.0.1.1"
SEMVER = "v0.0.2"

def visitTypeIdent(self, ctx):
'''
Handle type identifier.
type: (RelayParser.TypeIdentContext) -> Union[ty.TensorType, str]
Copy link
Contributor

Choose a reason for hiding this comment

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

this type annotation should be # type: (RelayParser.IdentTypeContext) -> Union[ty.TensorType, str] and go above and outside the doc string. cf: https://mypy.readthedocs.io/en/latest/cheat_sheet.html

Copy link
Contributor

Choose a reason for hiding this comment

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

Pylint complained when I had it that way

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, it complained because I had the annotation after the docstring, not before

Copy link
Contributor

Choose a reason for hiding this comment

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

Done

return ty.scalar_type(type_ident)

type_param = lookup(self.type_param_scopes, type_ident)
if type_param:
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
if type_param:
if type_param is not None:

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks, done

__PRELUDE_PATH__ = os.path.dirname(os.path.realpath(__file__))

def load_prelude(mod=None):
'''Parses the portions of the Prelude written in Relay's text format and adds
Copy link
Contributor

Choose a reason for hiding this comment

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

newline after '''. Consider using either ''' or """ for all docstrings in this file

Copy link
Contributor

Choose a reason for hiding this comment

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

Done

@slyubomirsky
Copy link
Contributor

slyubomirsky commented May 30, 2019

Thanks for the feedback. I also removed test_prelude because it is redundant, since test_adt tests the prelude functions, which would require loading the file

@slyubomirsky
Copy link
Contributor

Fixing the previous test failure led me to realize that we have an issue with the parser flag: If we want to have the Prelude and other important Relay functionality written using the text format, should the parser be an optional flag? I changed the prelude to check whether the parser is enabled and default to the old manually written ASTs, but this does not seem like a particularly good practice, since it requires us to maintain two definitions, one of which is indeed a manually assembled AST. What do you all believe is a good approach moving forward? (addressed to the reviewers, also @jroesch and @tqchen)

@jroesch
Copy link
Member Author

jroesch commented May 30, 2019

We should conditionally support generating the parser, when we check in we should generate a copy, commit it, and mark the files as binaries in my opinion, it satisfies both design tensions.

@slyubomirsky
Copy link
Contributor

slyubomirsky commented May 30, 2019

I agree that there should be a pre-generated parser available for users who do not intend to modify the grammar or parser. It would be good not to have to introduce ANTLR as a mandatory dependency for users who want to use Relay's text format. Does everyone agree that we should have a pre-generated parser committed and marked as a binary?

@slyubomirsky
Copy link
Contributor

I've now added the parser to the repo so users can always run the parser, even if they don't have ANTLR enabled in their build. It will be easy to revert that commit if this choice is objectionable

@wweic
Copy link
Contributor

wweic commented May 31, 2019

I think having a pre-generated parser is a good idea, it will also enable running text format unit test for every tvm user without ANTLR installed.

@slyubomirsky
Copy link
Contributor

Would appreciate input from anyone knowledgeable whether the generated parser files should have the Apache headers on them (we'd need to script for them to be appended during the build if so)

@@ -0,0 +1,209 @@
# Generated from /home/sslyu/tvm/python/tvm/relay/grammar/Relay.g4 by ANTLR 4.7.2
Copy link
Member Author

Choose a reason for hiding this comment

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

Can you mark these all as binary files?

Copy link
Contributor

Choose a reason for hiding this comment

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

I did in .gitattributes, but it didn't change how they display on Github. I will try this as well: https://help.github.com/en/articles/customizing-how-changed-files-appear-on-github

@@ -113,7 +98,7 @@ def test_comments():
UNIT
)

@if_parser_enabled

def test_int_literal():
assert isinstance(relay.fromtext(SEMVER+"1"), relay.Constant)
assert isinstance(relay.fromtext(SEMVER+"1").data, tvm.ndarray.NDArray)
Copy link
Contributor

Choose a reason for hiding this comment

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

I know this isn't the point of this PR, but can we have relay.fromtext(SEMVER + _) as a helper function for this test file? It's a bit of an eye sore.

Copy link
Contributor

Choose a reason for hiding this comment

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

Done

@slyubomirsky
Copy link
Contributor

No idea what's with the test failure but it definitely appears unrelated

@eqy eqy merged commit c4245e3 into apache:master Jun 11, 2019
wweic pushed a commit to wweic/tvm that referenced this pull request Jun 26, 2019
…ache#3043)

* Add ability to load Prelude from disk

* Port over id

* Define compose

* Linting errors and style changes

* Eliminate unnecessary parens

* Rename identType to typeIdent (makes more sense)

* Another unnecessary paren

* Bump the version number for the text format

* Ensure .rly (Relay text files) are permitted

* Correct release number and simplify grammar rule

* Correct load_prelude docstring

* Corrections to _parser

* Add Apache headers to prelude source file

* Remove test_prelude (redundant)

* Correct misleading error message

* Add check that parser is enabled in Prelude

* Commit pre-generated parser, ensure generated files are treated as binaries, and have parser tests always fire

* Permit parser files and git attributes files

* Exclude gitattributes and parser files from apache check

* Another attempt at appeasing Apache audit checker

* Corrections to rat-excludes

* Apache should be truly appeased now

* Ignore Relay parser files by name

* Mark parser files as generated so they don't show up on Github

* Add parsing helper function for tests

* Mark parser files as not detectable
wweic pushed a commit to neo-ai/tvm that referenced this pull request Jun 27, 2019
…ache#3043)

* Add ability to load Prelude from disk

* Port over id

* Define compose

* Linting errors and style changes

* Eliminate unnecessary parens

* Rename identType to typeIdent (makes more sense)

* Another unnecessary paren

* Bump the version number for the text format

* Ensure .rly (Relay text files) are permitted

* Correct release number and simplify grammar rule

* Correct load_prelude docstring

* Corrections to _parser

* Add Apache headers to prelude source file

* Remove test_prelude (redundant)

* Correct misleading error message

* Add check that parser is enabled in Prelude

* Commit pre-generated parser, ensure generated files are treated as binaries, and have parser tests always fire

* Permit parser files and git attributes files

* Exclude gitattributes and parser files from apache check

* Another attempt at appeasing Apache audit checker

* Corrections to rat-excludes

* Apache should be truly appeased now

* Ignore Relay parser files by name

* Mark parser files as generated so they don't show up on Github

* Add parsing helper function for tests

* Mark parser files as not detectable
@jroesch jroesch deleted the text-prelude branch February 4, 2021 04:40
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.

7 participants