Skip to content

Commit

Permalink
Merge branch 'master' into feat/reject-implements-empty
Browse files Browse the repository at this point in the history
  • Loading branch information
charles-cooper authored Nov 21, 2024
2 parents 12da260 + e0fc53a commit 6ef5011
Show file tree
Hide file tree
Showing 38 changed files with 921 additions and 394 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
[![Build Status](https://github.com/vyperlang/vyper/workflows/Test/badge.svg)](https://github.com/vyperlang/vyper/actions/workflows/test.yml)
[![Documentation Status](https://readthedocs.org/projects/vyper/badge/?version=latest)](http://docs.vyperlang.org/en/latest/?badge=latest "ReadTheDocs")
[![Discord](https://img.shields.io/discord/969926564286459934.svg?label=%23vyper)](https://discord.gg/6tw7PTM7C2)
[![Telegram](https://img.shields.io/badge/Vyperholics🐍-Telegram-blue)](https://t.me/vyperlang)

[![PyPI](https://badge.fury.io/py/vyper.svg)](https://pypi.org/project/vyper "PyPI")
[![Docker](https://img.shields.io/docker/cloud/build/vyperlang/vyper)](https://hub.docker.com/r/vyperlang/vyper "DockerHub")
Expand Down
2 changes: 1 addition & 1 deletion docs/built-in-functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1023,7 +1023,7 @@ Utilities
>>> ExampleContract.foo()
0xa9059cbb

.. py:function:: abi_encode(*args, ensure_tuple: bool = True) -> Bytes[<depends on input>]
.. py:function:: abi_encode(*args, ensure_tuple: bool = True, method_id: Bytes[4] = None) -> Bytes[<depends on input>]
Takes a variable number of args as input, and returns the ABIv2-encoded bytestring. Used for packing arguments to raw_call, EIP712 and other cases where a consistent and efficient serialization method is needed.
Once this function has seen more use we provisionally plan to put it into the ``ethereum.abi`` namespace.
Expand Down
7 changes: 6 additions & 1 deletion docs/compiling-a-contract.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Include the ``-f`` flag to specify which output formats to return. Use ``vyper -

.. code:: shell
$ vyper -f abi,abi_python,bytecode,bytecode_runtime,blueprint_bytecode,interface,external_interface,ast,annotated_ast,integrity,ir,ir_json,ir_runtime,asm,opcodes,opcodes_runtime,source_map,source_map_runtime,archive,solc_json,method_identifiers,userdoc,devdoc,metadata,combined_json,layout yourFileName.vy
$ vyper -f abi,abi_python,bb,bb_runtime,bytecode,bytecode_runtime,blueprint_bytecode,cfg,cfg_runtime,interface,external_interface,ast,annotated_ast,integrity,ir,ir_json,ir_runtime,asm,opcodes,opcodes_runtime,source_map,source_map_runtime,archive,solc_json,method_identifiers,userdoc,devdoc,metadata,combined_json,layout yourFileName.vy
.. note::
The ``opcodes`` and ``opcodes_runtime`` output of the compiler has been returning incorrect opcodes since ``0.2.0`` due to a lack of 0 padding (patched via `PR 3735 <https://github.com/vyperlang/vyper/pull/3735>`_). If you rely on these functions for debugging, please use the latest patched versions.
Expand Down Expand Up @@ -134,6 +134,11 @@ In codesize optimized mode, the compiler will try hard to minimize codesize by
* out-lining code, and
* using more loops for data copies.

Enabling Experimental Code Generation
===========================

When compiling, you can use the CLI flag ``--experimental-codegen`` or its alias ``--venom`` to activate the new `Venom IR <https://github.com/vyperlang/vyper/blob/master/vyper/venom/README.md>`_.
Venom IR is inspired by LLVM IR and enables new advanced analysis and optimizations.

.. _evm-version:

Expand Down
10 changes: 10 additions & 0 deletions docs/structure-of-a-contract.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ EVM Version

The EVM version can be set with the ``evm-version`` pragma, which is documented in :ref:`evm-version`.

Experimental Code Generation
-----------------
The new experimental code generation feature can be activated using the following directive:

.. code-block:: vyper
#pragma experimental-codegen
Alternatively, you can use the alias ``"venom"`` instead of ``"experimental-codegen"`` to enable this feature.

Imports
=======

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

extras_require["dev"] = extras_require["dev"] + extras_require["test"] + extras_require["lint"]

with open("README.md", "r") as f:
with open("README.md", "r", encoding="utf-8") as f:
long_description = f.read()


Expand Down
4 changes: 0 additions & 4 deletions tests/functional/codegen/features/test_constructor.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import pytest

from tests.evm_backends.base_env import _compile
from vyper.exceptions import StackTooDeep
from vyper.utils import method_id


Expand Down Expand Up @@ -169,7 +166,6 @@ def get_foo() -> uint256:
assert c.get_foo() == 39


@pytest.mark.venom_xfail(raises=StackTooDeep, reason="stack scheduler regression")
def test_nested_dynamic_array_constructor_arg_2(env, get_contract):
code = """
foo: int128
Expand Down
2 changes: 0 additions & 2 deletions tests/functional/codegen/types/test_dynamic_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
CompilerPanic,
ImmutableViolation,
OverflowException,
StackTooDeep,
StateAccessViolation,
TypeMismatch,
)
Expand Down Expand Up @@ -737,7 +736,6 @@ def test_array_decimal_return3() -> DynArray[DynArray[decimal, 2], 2]:
]


@pytest.mark.venom_xfail(raises=StackTooDeep, reason="stack scheduler regression")
def test_mult_list(get_contract):
code = """
nest3: DynArray[DynArray[DynArray[uint256, 2], 2], 2]
Expand Down
7 changes: 4 additions & 3 deletions tests/functional/grammar/test_grammar.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from vyper.ast import Module, parse_to_ast
from vyper.ast.grammar import parse_vyper_source, vyper_grammar
from vyper.ast.pre_parser import pre_parse
from vyper.ast.pre_parser import PreParser


def test_basic_grammar():
Expand Down Expand Up @@ -102,6 +102,7 @@ def has_no_docstrings(c):
max_examples=500, suppress_health_check=[HealthCheck.too_slow, HealthCheck.filter_too_much]
)
def test_grammar_bruteforce(code):
pre_parse_result = pre_parse(code + "\n")
tree = parse_to_ast(pre_parse_result.reformatted_code)
pre_parser = PreParser()
pre_parser.parse(code + "\n")
tree = parse_to_ast(pre_parser.reformatted_code)
assert isinstance(tree, Module)
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,6 @@ def foo():

@pytest.mark.parametrize("bad_code", fail_list)
def test_undeclared_def_exception(bad_code):
with pytest.raises(UndeclaredDefinition):
with pytest.raises(UndeclaredDefinition) as e:
compiler.compile_code(bad_code)
assert "(hint: )" not in str(e.value)
15 changes: 15 additions & 0 deletions tests/functional/syntax/exceptions/test_unknown_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import pytest

from vyper import compiler
from vyper.exceptions import UnknownType


def test_unknown_type_exception():
code = """
@internal
def foobar(token: IERC20):
pass
"""
with pytest.raises(UnknownType) as e:
compiler.compile_code(code)
assert "(hint: )" not in str(e.value)
11 changes: 6 additions & 5 deletions tests/unit/ast/test_annotate_and_optimize_ast.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import ast as python_ast

from vyper.ast.parse import annotate_python_ast, pre_parse
from vyper.ast.parse import PreParser, annotate_python_ast


class AssertionVisitor(python_ast.NodeVisitor):
Expand Down Expand Up @@ -28,12 +28,13 @@ def foo() -> int128:


def get_contract_info(source_code):
pre_parse_result = pre_parse(source_code)
py_ast = python_ast.parse(pre_parse_result.reformatted_code)
pre_parser = PreParser()
pre_parser.parse(source_code)
py_ast = python_ast.parse(pre_parser.reformatted_code)

annotate_python_ast(py_ast, pre_parse_result.reformatted_code, pre_parse_result)
annotate_python_ast(py_ast, pre_parser.reformatted_code, pre_parser)

return py_ast, pre_parse_result.reformatted_code
return py_ast, pre_parser.reformatted_code


def test_it_annotates_ast_with_source_code():
Expand Down
38 changes: 34 additions & 4 deletions tests/unit/ast/test_pre_parser.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import pytest

from vyper import compile_code
from vyper.ast.pre_parser import pre_parse, validate_version_pragma
from vyper.ast.pre_parser import PreParser, validate_version_pragma
from vyper.compiler.phases import CompilerData
from vyper.compiler.settings import OptimizationLevel, Settings
from vyper.exceptions import StructureException, VersionException
Expand Down Expand Up @@ -174,9 +174,10 @@ def test_prerelease_invalid_version_pragma(file_version, mock_version):
@pytest.mark.parametrize("code, pre_parse_settings, compiler_data_settings", pragma_examples)
def test_parse_pragmas(code, pre_parse_settings, compiler_data_settings, mock_version):
mock_version("0.3.10")
pre_parse_result = pre_parse(code)
pre_parser = PreParser()
pre_parser.parse(code)

assert pre_parse_result.settings == pre_parse_settings
assert pre_parser.settings == pre_parse_settings

compiler_data = CompilerData(code)

Expand All @@ -191,6 +192,26 @@ def test_parse_pragmas(code, pre_parse_settings, compiler_data_settings, mock_ve
assert compiler_data.settings == compiler_data_settings


pragma_venom = [
"""
#pragma venom
""",
"""
#pragma experimental-codegen
""",
]


@pytest.mark.parametrize("code", pragma_venom)
def test_parse_venom_pragma(code):
pre_parser = PreParser()
pre_parser.parse(code)
assert pre_parser.settings.experimental_codegen is True

compiler_data = CompilerData(code)
assert compiler_data.settings.experimental_codegen is True


invalid_pragmas = [
# evm-versionnn
"""
Expand Down Expand Up @@ -218,13 +239,22 @@ def test_parse_pragmas(code, pre_parse_settings, compiler_data_settings, mock_ve
# pragma evm-version cancun
# pragma evm-version shanghai
""",
# duplicate setting of venom
"""
#pragma venom
#pragma experimental-codegen
""",
"""
#pragma venom
#pragma venom
""",
]


@pytest.mark.parametrize("code", invalid_pragmas)
def test_invalid_pragma(code):
with pytest.raises(StructureException):
pre_parse(code)
PreParser().parse(code)


def test_version_exception_in_import(make_input_bundle):
Expand Down
36 changes: 36 additions & 0 deletions tests/unit/cli/vyper_json/test_compile_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
compile_json,
exc_handler_to_dict,
get_inputs,
get_settings,
)
from vyper.compiler import OUTPUT_FORMATS, compile_code, compile_from_file_input
from vyper.compiler.input_bundle import JSONInputBundle
Expand Down Expand Up @@ -319,3 +320,38 @@ def test_compile_json_with_abi_top(make_input_bundle):
"""
input_bundle = make_input_bundle({"stream.json": stream, "code.vy": code})
vyper.compiler.compile_code(code, input_bundle=input_bundle)


def test_compile_json_with_experimental_codegen():
code = {
"language": "Vyper",
"sources": {"foo.vy": {"content": "@external\ndef foo() -> bool:\n return True"}},
"settings": {
"evmVersion": "cancun",
"optimize": "gas",
"venom": True,
"search_paths": [],
"outputSelection": {"*": ["ast"]},
},
}

settings = get_settings(code)
assert settings.experimental_codegen is True


def test_compile_json_with_both_venom_aliases():
code = {
"language": "Vyper",
"sources": {"foo.vy": {"content": ""}},
"settings": {
"evmVersion": "cancun",
"optimize": "gas",
"experimentalCodegen": False,
"venom": False,
"search_paths": [],
"outputSelection": {"*": ["ast"]},
},
}
with pytest.raises(JSONError) as e:
get_settings(code)
assert e.value.args[0] == "both experimentalCodegen and venom cannot be set"
7 changes: 4 additions & 3 deletions tests/unit/compiler/venom/test_branch_optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@ def test_simple_jump_case():
fn.append_basic_block(br2)

p1 = bb.append_instruction("param")
p2 = bb.append_instruction("param")
op1 = bb.append_instruction("store", p1)
op2 = bb.append_instruction("store", 64)
op3 = bb.append_instruction("add", op1, op2)
jnz_input = bb.append_instruction("iszero", op3)
bb.append_instruction("jnz", jnz_input, br1.label, br2.label)

br1.append_instruction("add", op3, 10)
br1.append_instruction("add", op3, p1)
br1.append_instruction("stop")
br2.append_instruction("add", op3, p1)
br2.append_instruction("add", op3, p2)
br2.append_instruction("stop")

term_inst = bb.instructions[-1]
Expand All @@ -47,6 +48,6 @@ def test_simple_jump_case():

# Test that the dfg is updated correctly
dfg = ac.request_analysis(DFGAnalysis)
assert dfg is old_dfg, "DFG should not be invalidated by BranchOptimizationPass"
assert dfg is not old_dfg, "DFG should be invalidated by BranchOptimizationPass"
assert term_inst in dfg.get_uses(op3), "jnz not using the new condition"
assert term_inst not in dfg.get_uses(jnz_input), "jnz still using the old condition"
9 changes: 5 additions & 4 deletions tests/unit/compiler/venom/test_sccp.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,8 @@ def test_cont_phi_case():
assert sccp.lattice[IRVariable("%2")].value == 32
assert sccp.lattice[IRVariable("%3")].value == 64
assert sccp.lattice[IRVariable("%4")].value == 96
assert sccp.lattice[IRVariable("%5", version=1)].value == 106
assert sccp.lattice[IRVariable("%5", version=2)] == LatticeEnum.BOTTOM
assert sccp.lattice[IRVariable("%5", version=2)].value == 106
assert sccp.lattice[IRVariable("%5", version=1)] == LatticeEnum.BOTTOM
assert sccp.lattice[IRVariable("%5")].value == 2


Expand Down Expand Up @@ -207,8 +207,9 @@ def test_cont_phi_const_case():
assert sccp.lattice[IRVariable("%2")].value == 32
assert sccp.lattice[IRVariable("%3")].value == 64
assert sccp.lattice[IRVariable("%4")].value == 96
assert sccp.lattice[IRVariable("%5", version=1)].value == 106
assert sccp.lattice[IRVariable("%5", version=2)].value == 97
# dependent on cfg traversal order
assert sccp.lattice[IRVariable("%5", version=2)].value == 106
assert sccp.lattice[IRVariable("%5", version=1)].value == 97
assert sccp.lattice[IRVariable("%5")].value == 2


Expand Down
Loading

0 comments on commit 6ef5011

Please sign in to comment.