diff --git a/docs/resources.rst b/docs/resources.rst index 7bb3c99df4..c2b0e3e427 100644 --- a/docs/resources.rst +++ b/docs/resources.rst @@ -23,7 +23,7 @@ Frameworks and tooling - `VyperDeployer – A helper smart contract to compile and test Vyper contracts in Foundry `_ - `🐍 snekmate – Vyper smart contract building blocks `_ - `Serpentor – A set of smart contracts tools for governance `_ -- `Smart contract development frameworks and tools for Vyper on Ethreum.org `_ +- `Smart contract development frameworks and tools for Vyper on Ethereum.org `_ - `Vyper Online Compiler - an online platform for compiling and deploying Vyper smart contracts `_ Security diff --git a/docs/types.rst b/docs/types.rst index 8bc7b7d3e1..5038e78240 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -675,6 +675,6 @@ All type conversions in Vyper must be made explicitly using the built-in ``conve * Narrowing conversions (e.g., ``int256 -> int128``) check that the input is in bounds for the output type. * Converting between bytes and int types results in sign-extension if the output type is signed. For instance, converting ``0xff`` (``bytes1``) to ``int8`` returns ``-1``. * Converting between bytes and int types which have different sizes follows the rule of going through the closest integer type, first. For instance, ``bytes1 -> int16`` is like ``bytes1 -> int8 -> int16`` (signextend, then widen). ``uint8 -> bytes20`` is like ``uint8 -> uint160 -> bytes20`` (rotate left 12 bytes). -* Enums can be converted to and from ``uint256`` only. +* Flags can be converted to and from ``uint256`` only. A small Python reference implementation is maintained as part of Vyper's test suite, it can be found `here `__. The motivation and more detailed discussion of the rules can be found `here `__. diff --git a/vyper/builtins/_convert.py b/vyper/builtins/_convert.py index 998cbbc9f6..adc2c233b8 100644 --- a/vyper/builtins/_convert.py +++ b/vyper/builtins/_convert.py @@ -308,7 +308,7 @@ def _to_int(expr, arg, out_typ): elif is_flag_type(arg.typ): if out_typ != UINT256_T: _FAIL(arg.typ, out_typ, expr) - # pretend enum is uint256 + # pretend flag is uint256 arg = IRnode.from_list(arg, typ=UINT256_T) # use int_to_int rules arg = _int_to_int(arg, out_typ) @@ -442,12 +442,12 @@ def to_bytes(expr, arg, out_typ): @_input_types(IntegerT) -def to_enum(expr, arg, out_typ): +def to_flag(expr, arg, out_typ): if arg.typ != UINT256_T: _FAIL(arg.typ, out_typ, expr) - if len(out_typ._enum_members) < 256: - arg = int_clamp(arg, bits=len(out_typ._enum_members), signed=False) + if len(out_typ._flag_members) < 256: + arg = int_clamp(arg, bits=len(out_typ._flag_members), signed=False) return IRnode.from_list(arg, typ=out_typ) @@ -469,7 +469,7 @@ def convert(expr, context): elif out_typ == AddressT(): ret = to_address(arg_ast, arg, out_typ) elif is_flag_type(out_typ): - ret = to_enum(arg_ast, arg, out_typ) + ret = to_flag(arg_ast, arg, out_typ) elif is_integer_type(out_typ): ret = to_int(arg_ast, arg, out_typ) elif is_bytes_m_type(out_typ): diff --git a/vyper/codegen/core.py b/vyper/codegen/core.py index 1a090ac316..8a186fe683 100644 --- a/vyper/codegen/core.py +++ b/vyper/codegen/core.py @@ -860,7 +860,7 @@ def needs_clamp(t, encoding): if isinstance(t, (_BytestringT, DArrayT)): return True if isinstance(t, FlagT): - return len(t._enum_members) < 256 + return len(t._flag_members) < 256 if isinstance(t, SArrayT): return needs_clamp(t.value_type, encoding) if is_tuple_like(t): @@ -1132,7 +1132,7 @@ def clamp_basetype(ir_node): ir_node = unwrap_location(ir_node) if isinstance(t, FlagT): - bits = len(t._enum_members) + bits = len(t._flag_members) # assert x >> bits == 0 ret = int_clamp(ir_node, bits, signed=False) diff --git a/vyper/codegen/expr.py b/vyper/codegen/expr.py index 13e1309e6d..6a444181c2 100644 --- a/vyper/codegen/expr.py +++ b/vyper/codegen/expr.py @@ -212,15 +212,15 @@ def parse_Name(self): def parse_Attribute(self): typ = self.expr._metadata["type"] - # MyEnum.foo + # MyFlag.foo if ( isinstance(typ, FlagT) and isinstance(self.expr.value, vy_ast.Name) and typ.name == self.expr.value.id ): # 0, 1, 2, .. 255 - enum_id = typ._enum_members[self.expr.attr] - value = 2**enum_id # 0 => 0001, 1 => 0010, 2 => 0100, etc. + flag_id = typ._flag_members[self.expr.attr] + value = 2**flag_id # 0 => 0001, 1 => 0010, 2 => 0100, etc. return IRnode.from_list(value, typ=typ) # x.balance: balance of address x @@ -420,7 +420,7 @@ def parse_BinOp(self): op = shr if not left.typ.is_signed else sar return IRnode.from_list(op(right, left), typ=new_typ) - # enums can only do bit ops, not arithmetic. + # flags can only do bit ops, not arithmetic. assert is_numeric_type(left.typ) with left.cache_when_complex("x") as (b1, x), right.cache_when_complex("y") as (b2, y): @@ -645,10 +645,10 @@ def parse_UnaryOp(self): if isinstance(self.expr.op, vy_ast.Invert): if isinstance(operand.typ, FlagT): - n_members = len(operand.typ._enum_members) + n_members = len(operand.typ._flag_members) # use (xor 0b11..1 operand) to flip all the bits in # `operand`. `mask` could be a very large constant and - # hurt codesize, but most user enums will likely have few + # hurt codesize, but most user flags will likely have few # enough members that the mask will not be large. mask = (2**n_members) - 1 return IRnode.from_list(["xor", mask, operand], typ=operand.typ) diff --git a/vyper/semantics/README.md b/vyper/semantics/README.md index 3b7acf9469..7a8a384c6d 100644 --- a/vyper/semantics/README.md +++ b/vyper/semantics/README.md @@ -16,7 +16,7 @@ Vyper abstract syntax tree (AST). * [`primitives.py`](types/primitives.py): Address, boolean, fixed length byte, integer and decimal types * [`shortcuts.py`](types/shortcuts.py): Helper constants for commonly used types * [`subscriptable.py`](types/subscriptable.py): Mapping, array and tuple types - * [`user.py`](types/user.py): Enum, event, interface and struct types + * [`user.py`](types/user.py): Flag, event, interface and struct types * [`utils.py`](types/utils.py): Functions for generating and fetching type objects * [`analysis/`](analysis): Subpackage for type checking and syntax verification logic * [`annotation.py`](analysis/annotation.py): Annotates statements and expressions with the appropriate type information diff --git a/vyper/semantics/analysis/local.py b/vyper/semantics/analysis/local.py index cc08b3b95a..0ce966d1c6 100644 --- a/vyper/semantics/analysis/local.py +++ b/vyper/semantics/analysis/local.py @@ -764,7 +764,7 @@ def visit_Compare(self, node: vy_ast.Compare, typ: VyperType) -> None: else: rtyp = get_exact_type_from_node(node.right) if isinstance(rtyp, FlagT): - # enum membership - `some_enum in other_enum` + # flag membership - `some_flag in other_flag` ltyp = rtyp else: # array membership - `x in my_list_variable` diff --git a/vyper/semantics/analysis/utils.py b/vyper/semantics/analysis/utils.py index 21ca7a8d3f..f102b1f13b 100644 --- a/vyper/semantics/analysis/utils.py +++ b/vyper/semantics/analysis/utils.py @@ -376,7 +376,7 @@ def types_from_Name(self, node): # when this is a type, we want to lower it if isinstance(t, VyperType): # TYPE_T is used to handle cases where a type can occur in call or - # attribute conditions, like Enum.foo or MyStruct({...}) + # attribute conditions, like Flag.foo or MyStruct({...}) return [TYPE_T(t)] return [t.typ] diff --git a/vyper/semantics/types/base.py b/vyper/semantics/types/base.py index 37de263319..4213535af7 100644 --- a/vyper/semantics/types/base.py +++ b/vyper/semantics/types/base.py @@ -389,7 +389,7 @@ def infer_kwarg_types(self, node): raise StructureException("Value is not callable", node) # dispatch into get_type_member if it's dereferenced, ex. - # MyEnum.FOO + # MyFlag.FOO def get_member(self, key, node): if hasattr(self.typedef, "get_type_member"): return self.typedef.get_type_member(key, node) diff --git a/vyper/semantics/types/user.py b/vyper/semantics/types/user.py index f09a97d0b9..68150f924b 100644 --- a/vyper/semantics/types/user.py +++ b/vyper/semantics/types/user.py @@ -44,23 +44,23 @@ def __hash__(self): return hash(id(self)) -# note: enum behaves a lot like uint256, or uints in general. +# note: flag behaves a lot like uint256, or uints in general. class FlagT(_UserType): # this is a carveout because currently we allow dynamic arrays of - # enums, but not static arrays of enums + # flags, but not static arrays of flags _as_darray = True _is_prim_word = True _as_hashmap_key = True def __init__(self, name: str, members: dict) -> None: if len(members.keys()) > 256: - raise FlagDeclarationException("Enums are limited to 256 members!") + raise FlagDeclarationException("Flags are limited to 256 members!") super().__init__(members=None) self._id = name - self._enum_members = members + self._flag_members = members # use a VyperType for convenient access to the `get_member` function # also conveniently checks well-formedness of the members namespace @@ -74,8 +74,8 @@ def get_type_member(self, key: str, node: vy_ast.VyperNode) -> "VyperType": return self def __repr__(self): - arg_types = ",".join(repr(a) for a in self._enum_members) - return f"enum {self.name}({arg_types})" + arg_types = ",".join(repr(a) for a in self._flag_members) + return f"flag {self.name}({arg_types})" @property def abi_type(self): @@ -107,29 +107,29 @@ def validate_comparator(self, node): @classmethod def from_FlagDef(cls, base_node: vy_ast.FlagDef) -> "FlagT": """ - Generate an `Enum` object from a Vyper ast node. + Generate an `Flag` object from a Vyper ast node. Arguments --------- - base_node : EnumDef - Vyper ast node defining the enum + base_node : FlagDef + Vyper ast node defining the flag Returns ------- - Enum + Flag """ members: dict = {} if len(base_node.body) == 1 and isinstance(base_node.body[0], vy_ast.Pass): - raise FlagDeclarationException("Enum must have members", base_node) + raise FlagDeclarationException("Flag must have members", base_node) for i, node in enumerate(base_node.body): if not isinstance(node, vy_ast.Expr) or not isinstance(node.value, vy_ast.Name): - raise FlagDeclarationException("Invalid syntax for enum member", node) + raise FlagDeclarationException("Invalid syntax for flag member", node) member_name = node.value.id if member_name in members: raise FlagDeclarationException( - f"Enum member '{member_name}' has already been declared", node.value + f"Flag member '{member_name}' has already been declared", node.value ) members[member_name] = i