vyper icon indicating copy to clipboard operation
vyper copied to clipboard

feat[lang]: implement export bundles

Open charles-cooper opened this issue 1 year ago • 9 comments

What I did

implement exports and export bundles.

export bundles are a way for library authors to group together external functions in the ABI

example:

bundle: IERC_X  # declare a bundle

@internal
def foo() -> uint256:
    return 10

@external
def extern1():
    pass

@external
@Bundle(IERC_X)
def extern2():
    pass

@external
@Bundle(IERC_X, bind=False)  # extern3 ok to export on its own
def extern3():
    pass

@external
@Bundle(IERC_X, bind=True)  # extern4 cannot be exported on its own!
def extern4():
    pass

it can be used like this:

import library

exports: library.IERC_X

@external
def library_foo() -> uint256:
    return library.foo()

or like this:

import library

exports: library.extern1, library.extern2

@external
def library_foo() -> uint256:
    return library.foo()

but not like this(!):

import library

exports: library.extern4  # raises StructureException

@external
def library_foo() -> uint256:
    return library.foo()

How I did it

How to verify it

Commit message

Commit message for the final, squashed PR. (Optional, but reviewers will appreciate it! Please see our commit message style guide for what we would ideally like to see in a commit message.)

Description for the changelog

Cute Animal Picture

Put a link to a cute animal picture inside the parenthesis-->

charles-cooper avatar Dec 17 '23 17:12 charles-cooper

Codecov Report

Attention: 98 lines in your changes are missing coverage. Please review.

Comparison is base (c6f457a) 84.01% compared to head (782659b) 55.74%. Report is 2 commits behind head on master.

Files Patch % Lines
vyper/semantics/types/function.py 23.07% 40 Missing :warning:
vyper/semantics/analysis/module.py 12.50% 27 Missing and 1 partial :warning:
vyper/semantics/types/module.py 71.42% 8 Missing and 4 partials :warning:
vyper/ast/nodes.py 38.88% 9 Missing and 2 partials :warning:
vyper/codegen/module.py 80.00% 2 Missing and 1 partial :warning:
vyper/semantics/types/user.py 57.14% 3 Missing :warning:
vyper/semantics/types/base.py 66.66% 1 Missing :warning:

:exclamation: Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@             Coverage Diff             @@
##           master    #3698       +/-   ##
===========================================
- Coverage   84.01%   55.74%   -28.27%     
===========================================
  Files          92       92               
  Lines       13044    13166      +122     
  Branches     2928     2963       +35     
===========================================
- Hits        10959     7340     -3619     
- Misses       1653     5199     +3546     
- Partials      432      627      +195     

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

codecov-commenter avatar Dec 17 '23 17:12 codecov-commenter

Would prefer that we create less language keywords so we can namespace better:

from vyper.packaging import Bundle
IERC_X: Bundle  = Bundle() # declare a bundle

@internal
def foo() -> uint256:
    return 10

@external
def extern1():
    pass

@external
@IERC_X.add()
def extern2():
    pass

@external
@IERC_X.add(bind=False)  # extern3 ok to export on its own
def extern3():
    pass

@external
@IERC_X.add(bind=True)  # extern4 cannot be exported on its own!
def extern4():
    pass

fubuloubu avatar Dec 18 '23 22:12 fubuloubu

Would prefer that we create less language keywords so we can namespace better:

from vyper.packaging import Bundle
IERC_X: Bundle  = Bundle() # declare a bundle

@internal
def foo() -> uint256:
    return 10

@external
def extern1():
    pass

@external
@IERC_X.add()
def extern2():
    pass

@external
@IERC_X.add(bind=False)  # extern3 ok to export on its own
def extern3():
    pass

@external
@IERC_X.add(bind=True)  # extern4 cannot be exported on its own!
def extern4():
    pass

export and bundle are not protected keywords though.

i also don't really like putting Bundle behind a namespace because:

  • choosing what to expose in the ABI should be a first class concept in the language
  • the proposed syntax looks like it's part of the "standard library" and like you could implement your own export semantics as a decorator. you can't, it's a compiler intrinsic

charles-cooper avatar Dec 18 '23 23:12 charles-cooper

Well, would say that bundle as a keyword exists in multiple EIPs and would be careful about enshrining its use

fubuloubu avatar Dec 19 '23 00:12 fubuloubu

I mean we could pick another name. But my point is it's not a keyword, you can still define variables and functions etc named bundle.

charles-cooper avatar Dec 19 '23 01:12 charles-cooper

I mean we could pick another name. But my point is it's not a keyword, you can still define variables and functions etc named bundle.

I can create a function or state variable named implements too?

fubuloubu avatar Dec 19 '23 02:12 fubuloubu

I can create a function or state variable named implements too?

yep

charles-cooper avatar Dec 19 '23 02:12 charles-cooper

I can create a function or state variable named implements too?

yep

So, these two don't conflict?

# interface check
implements: ERC20

# state variable
implements: ERC20

fubuloubu avatar Dec 19 '23 03:12 fubuloubu

So, these two don't conflict?

# interface check
implements: ERC20

# state variable
implements: ERC20

aha yea they use a similar AST node as for state variable declarations so not those, but everything else -- function names, local variables, names of things

@external
def implements():
    pass
event implements:
    pass
@external
def foo(implements: uint256):
    pass

charles-cooper avatar Dec 19 '23 14:12 charles-cooper

closing this as superseded (for now) by https://github.com/vyperlang/vyper/pull/3786 and the spec could use some polishing, will revisit in 0.4.1

charles-cooper avatar Mar 06 '24 19:03 charles-cooper