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

rename validate_expected_type to infer_type and have it return a type -- clean diff #21

Closed

Conversation

charles-cooper
Copy link
Owner

it also tags the node with the inferred type

What I did

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-->

this commit implements "singleton modules with ownership hierarchy" as
described in vyperlang#3722.

to accomplish this, two new language constructs are added: `UsesDecl`
and `InitializesDecl`. these are exposed to the user as `uses:` and
`initializes:`. they are also accompanied by new `AnalysisResult` data
structures: `UsesInfo` and `InitializesInfo`.

`uses` and `initializes` can be thought of as a constraint system on the
module system. a `uses: my-module` annotation is required if
`my_module`'s state is accessed (read or written), and
`initializes: my_module` is required to call `my_module.__init__()`. a
module can be `use`d any number of times; it can only be `initialize`d
once. a module which has been used (directly, or transitively) by the
compilation target (main entry point module), must be `initialize`d
exactly once. `initializes:` is also required to declare which modules
it has been `initialize`d with. for example, if `mod1` declares it
`uses: mod2`, then any `initializes: mod1` statement must declare
*which* instance of `mod2` it has been initialized with. although there
is only ever a single instance of `mod2`, this user-facing requirement
improves readability by forcing the user to be aware of what the state
access dependencies are for a given, `initialize`d module.

the `NamedExpr` node ("walrus operator") has been added to the AST to
support the initializer syntax. (note: the walrus operator is used,
because the originally proposed syntax, `mod1[mod2 = mod2]` is rejected
by the python parser).

a new compiler pass, `vyper/semantics/analysis/global.py` has been
added to implement the global initializer constraint, as it cannot be
defined recursively (without a global context).

since `__init__()` functions can now be called from other `__init__()`
functions (which is not allowed for normal `@external` functions!), a
new `@deploy` visibility has been added to vyper's visibility system.
`@deploy` functions can be called from other `@deploy` functions, and
never from `@external` or `@internal` functions. they also have special
treatment in the ABI relative to other `@external` functions.

`initializes:` is useful since it also serves the purpose of being a
storage allocator directive. wherever `initializes:` is placed, is where
the module will be placed in storage (and code, transient storage, or
any other future storage locations).

this commit refactors the storage allocator so that it recurses into
child modules whenever it sees an `initializes:` statement. it refactors
several data structures surrounding the storage allocator, including
removing inheritance on the `DataPosition` data structure (which has
also been renamed to `VarOffset`). some utility functions have been
added for calculating the size of a given variable, which also get used
in codegen (`get_element_ptr()`).

additional work/refactoring in this commit:
- new analysis machinery for detecting reads/writes for all `ExprInfo`s
- dynamic programming on the `get_expr_info()` routine
- refactoring of `visit_Expr`, which fixes call mutability analysis
- move `StringEnum` back to vyper/utils.py
- remove the "TYPE_DEFINITION" kludge in certain builtins, replace with
  usage of `TYPE_T`
- improve `tag_exceptions()` formatting
- remove `Context.globals`, as we rely on the results of the front-end
  analyser now.
- remove dead variable: `Context.in_assertion`
- refactor `generate_ir_for_function` into
  `generate_ir_for_external_function` and
  `generate_ir_for_internal_function`
- move `get_nonreentrant_lock` to `function_definitions/common.py`
- simplify layout allocation across locations into single function
- add `VyperType.get_size_in()` and `VarInfo.get_size()` helper
  functions so we don't need to do as much switch/case in implementation
  functions
- refactor `codegen/core.py` functions to use `VyperType.get_size()`
- fix interfaces access from `.vyi` files
@charles-cooper charles-cooper force-pushed the feat/infer_expected_types branch from c33e768 to 6b9fff2 Compare February 10, 2024 16:43
charles-cooper and others added 11 commits February 11, 2024 07:08
this is a regression introduced in c6b29c7; the exception thrown by
`validate_expected_type()` was updated to be `TypeMismatch`, but this
test was not correspondingly updated.
and remove the separate mypy rule. this makes the development workflow a
bit faster
* fix error message for `implements: module`
currently, the compiler will panic when it encounters this case.
add a suggestion to rename the interface file to `.vyi`.
also catch all invalid types with a compiler panic.
* add a helpful hint for imports from `vyper.interfaces`
hint to try `ethereum.ercs`
this makes it easier to install vyper packages from pip and import them
using a regular python workflow.

misc:
- improve how paths appear in error messages; try hard to make them
  relative paths.
- add `chdir_tmp_path` fixture which chdirs to the `tmp_path` fixture
  for the duration of the test.
this commit fixes several bugs with analysis of iterator modification in
loops. to do so, it refactors the analysis code to track reads/writes
more accurately, and uses analysis machinery instead of AST queries to
perform the check. it enriches ExprInfo with an `attr` attribute, so
this can be used to detect if an ExprInfo is derived from an
`Attribute`.

ExprInfo could be further enriched with `Subscript` info
so that the Attribute/Subscript chain can be reliably recovered just
from ExprInfos, especially in the future if other functions rely on
being able to recover the attribute chain.

this commit also modifies `validate_functions` so that it validates the
functions in dependency (call graph traversal) order rather than the
order they appear in the AST.

refactors:
- add `enter_for_loop()` context manager for convenience+clarity
- remove `ExprInfo.attribute_chain`, it was too confusing
- hide `ContractFunctionT` member variables (`_variable_reads`,
  `_variable_writes`, `_used_modules`) behind public-facing API
- remove `get_root_varinfo()` in favor of a helper
  `_get_variable_access()` function which detects access on variable
  sub-members (e.g., structs).
this commit removes "fine-grained" nonreentrancy locks (i.e., reentrancy
locks with names) from vyper. they aren't really used (all known
production contracts just use a single global named lock) , and in any
case such a use case should better be implemented manually by the user.

this simplifies the language and allows moderate simplification to the
storage allocator, although some complexity is added because the global
restriction has to have special handling (it cannot be handled simply in
the recursion into child modules).

refactors:
- the routine for allocating nonreentrant keys has been refactored into
  a helper function.
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