def validate(self): if "_" in self.value: raise InvalidLiteral("Underscores not allowed in hex literals", self) if len(self.value) % 2: raise InvalidLiteral( "Hex notation requires an even number of digits", self)
def from_literal(cls, node: vy_ast.Constant) -> BaseTypeDefinition: obj = super().from_literal(node) if isinstance(node, vy_ast.Bytes) and len(node.value.hex()) != 64: raise InvalidLiteral("Invalid literal for type bytes32", node) if isinstance(node, vy_ast.Hex) and len(node.value) != 66: raise InvalidLiteral("Invalid literal for type bytes32", node) return obj
def hexstring(self): orignum = self.expr.node_source_code if len(orignum) == 42: if checksum_encode(orignum) != orignum: raise InvalidLiteral( "Address checksum mismatch. If you are sure this is the " f"right address, the correct checksummed form is: {checksum_encode(orignum)}", self.expr ) return LLLnode.from_list( int(self.expr.value, 16), typ=BaseType('address', is_literal=True), pos=getpos(self.expr), ) elif len(orignum) == 66: return LLLnode.from_list( int(self.expr.value, 16), typ=BaseType('bytes32', is_literal=True), pos=getpos(self.expr), ) else: raise InvalidLiteral( f"Cannot read 0x value with length {len(orignum)}. Expecting 42 (address " "incl 0x) or 66 (bytes32 incl 0x)", self.expr )
def validate(self): if len(self.value) % 2: raise InvalidLiteral("Hex notation requires an even number of digits", self) if len(self.value) == 42 and checksum_encode(self.value) != self.value: raise InvalidLiteral( "Address checksum mismatch. If you are sure this is the right " f"address, the correct checksummed form is: {checksum_encode(self.value)}", self, )
def as_wei_value(expr, args, kwargs, context): # Denominations wei_denominations = { ("wei", ): 1, ("femtoether", "kwei", "babbage"): 10**3, ("picoether", "mwei", "lovelace"): 10**6, ("nanoether", "gwei", "shannon"): 10**9, ( "microether", "szabo", ): 10**12, ( "milliether", "finney", ): 10**15, ("ether", ): 10**18, ("kether", "grand"): 10**21, } value, denom_name = args[0], args[1].decode() denom_divisor = next( (v for k, v in wei_denominations.items() if denom_name in k), False) if not denom_divisor: raise InvalidLiteral( f"Invalid denomination: {denom_name}, valid denominations are: " f"{','.join(x[0] for x in wei_denominations)}", expr.args[1]) # Compute the amount of wei and return that value if isinstance(value, (int, float)): expr_args_0 = expr.args[0] # On constant reference fetch value node of constant assignment. if context.constants.ast_is_constant(expr.args[0]): expr_args_0 = context.constants._constants_ast[expr.args[0].id] numstring, num, den = get_number_as_fraction(expr_args_0, context) if denom_divisor % den: max_len = len(str(denom_divisor)) - 1 raise InvalidLiteral( f"Wei value of denomination '{denom_name}' has maximum {max_len} decimal places", expr.args[0]) sub = num * denom_divisor // den elif value.typ.is_literal: if value.value <= 0: raise InvalidLiteral("Negative wei value not allowed", expr) sub = ['mul', value.value, denom_divisor] elif value.typ.typ == 'uint256': sub = ['mul', value, denom_divisor] else: sub = ['div', ['mul', value, denom_divisor], DECIMAL_DIVISOR] return LLLnode.from_list( sub, typ=BaseType('uint256', {'wei': 1}), location=None, pos=getpos(expr), )
def to_uint256(expr, args, kwargs, context): in_arg = args[0] input_type, _ = get_type(in_arg) if input_type == "num_literal": if isinstance(in_arg, int): if not SizeLimits.in_bounds("uint256", in_arg): raise InvalidLiteral(f"Number out of range: {in_arg}") return LLLnode.from_list( in_arg, typ=BaseType("uint256", ), pos=getpos(expr), ) elif isinstance(in_arg, Decimal): if not SizeLimits.in_bounds("uint256", math.trunc(in_arg)): raise InvalidLiteral( f"Number out of range: {math.trunc(in_arg)}") return LLLnode.from_list(math.trunc(in_arg), typ=BaseType("uint256"), pos=getpos(expr)) else: raise InvalidLiteral(f"Unknown numeric literal type: {in_arg}") elif isinstance(in_arg, LLLnode) and input_type in ("int128", "int256"): return LLLnode.from_list(["clampge", in_arg, 0], typ=BaseType("uint256"), pos=getpos(expr)) elif isinstance(in_arg, LLLnode) and input_type == "decimal": return LLLnode.from_list( ["div", ["clampge", in_arg, 0], DECIMAL_DIVISOR], typ=BaseType("uint256"), pos=getpos(expr), ) elif isinstance(in_arg, LLLnode) and input_type in ("bool", "uint8"): return LLLnode.from_list(in_arg, typ=BaseType("uint256"), pos=getpos(expr)) elif isinstance(in_arg, LLLnode) and input_type in ("bytes32", "address"): return LLLnode(value=in_arg.value, args=in_arg.args, typ=BaseType("uint256"), pos=getpos(expr)) elif isinstance(in_arg, LLLnode) and input_type == "Bytes": if in_arg.typ.maxlen > 32: raise InvalidLiteral( f"Cannot convert bytes array of max length {in_arg.typ.maxlen} to uint256", expr, ) return byte_array_to_num(in_arg, "uint256") else: raise InvalidLiteral(f"Invalid input for uint256: {in_arg}", expr)
def types_from_List(self, node): # literal array if not node.elements: raise InvalidLiteral("Cannot have an empty array", node) types_list = get_common_types(*node.elements) if types_list: return [ArrayDefinition(i, len(node.elements)) for i in types_list] raise InvalidLiteral("Array contains multiple, incompatible types", node)
def base_type_conversion(orig, frm, to, pos, in_function_call=False): orig = unwrap_location(orig) is_valid_int128_to_decimal = (is_base_type(frm, 'int128') and is_base_type( to, 'decimal')) and are_units_compatible(frm, to) if getattr(frm, 'is_literal', False): if frm.typ in ('int128', 'uint256'): if not SizeLimits.in_bounds(frm.typ, orig.value): raise InvalidLiteral(f"Number out of range: {orig.value}", pos) # Special Case: Literals in function calls should always convey unit type as well. if in_function_call and not (frm.unit == to.unit and frm.positional == to.positional): raise InvalidLiteral( f"Function calls require explicit unit definitions on calls, expected {to}", pos) if to.typ in ('int128', 'uint256'): if not SizeLimits.in_bounds(to.typ, orig.value): raise InvalidLiteral(f"Number out of range: {orig.value}", pos) if not isinstance(frm, (BaseType, NullType)) or not isinstance(to, BaseType): raise TypeMismatch( f"Base type conversion from or to non-base type: {frm} {to}", pos) elif is_base_type(frm, to.typ) and are_units_compatible(frm, to): return LLLnode(orig.value, orig.args, typ=to, add_gas_estimate=orig.add_gas_estimate) elif isinstance(frm, ContractType) and to == BaseType('address'): return LLLnode(orig.value, orig.args, typ=to, add_gas_estimate=orig.add_gas_estimate) elif is_valid_int128_to_decimal: return LLLnode.from_list( ['mul', orig, DECIMAL_DIVISOR], typ=BaseType('decimal', to.unit, to.positional), ) elif isinstance(frm, NullType): if to.typ not in ('int128', 'bool', 'uint256', 'address', 'bytes32', 'decimal'): # This is only to future proof the use of base_type_conversion. raise TypeMismatch( # pragma: no cover f"Cannot convert null-type object to type {to}", pos) return LLLnode.from_list(0, typ=to) # Integer literal conversion. elif (frm.typ, to.typ, frm.is_literal) == ('int128', 'uint256', True): return LLLnode(orig.value, orig.args, typ=to, add_gas_estimate=orig.add_gas_estimate) else: raise TypeMismatch( f"Typecasting from base type {frm} to {to} unavailable", pos)
def to_uint256(expr, args, kwargs, context): in_arg = args[0] input_type, _ = get_type(in_arg) _unit = in_arg.typ.unit if input_type in ('int128', 'decimal') else None if input_type == 'num_literal': if isinstance(in_arg, int): if not SizeLimits.in_bounds('uint256', in_arg): raise InvalidLiteral(f"Number out of range: {in_arg}") return LLLnode.from_list(in_arg, typ=BaseType('uint256', _unit), pos=getpos(expr)) elif isinstance(in_arg, float): if not SizeLimits.in_bounds('uint256', math.trunc(in_arg)): raise InvalidLiteral( f"Number out of range: {math.trunc(in_arg)}") return LLLnode.from_list(math.trunc(in_arg), typ=BaseType('uint256', _unit), pos=getpos(expr)) else: raise InvalidLiteral(f"Unknown numeric literal type: {in_arg}") elif isinstance(in_arg, LLLnode) and input_type == 'int128': return LLLnode.from_list(['clampge', in_arg, 0], typ=BaseType('uint256', _unit), pos=getpos(expr)) elif isinstance(in_arg, LLLnode) and input_type == 'decimal': return LLLnode.from_list( ['div', ['clampge', in_arg, 0], DECIMAL_DIVISOR], typ=BaseType('uint256', _unit), pos=getpos(expr)) elif isinstance(in_arg, LLLnode) and input_type == 'bool': return LLLnode.from_list(in_arg, typ=BaseType('uint256'), pos=getpos(expr)) elif isinstance(in_arg, LLLnode) and input_type in ('bytes32', 'address'): return LLLnode(value=in_arg.value, args=in_arg.args, typ=BaseType('uint256'), pos=getpos(expr)) elif isinstance(in_arg, LLLnode) and input_type == 'bytes': if in_arg.typ.maxlen > 32: raise InvalidLiteral( f"Cannot convert bytes array of max length {in_arg.typ.maxlen} to uint256", expr, ) return byte_array_to_num(in_arg, expr, 'uint256') else: raise InvalidLiteral(f"Invalid input for uint256: {in_arg}", expr)
def from_literal(cls, node: vy_ast.Constant) -> AddressDefinition: super().from_literal(node) addr = node.value if len(addr) != 42: raise InvalidLiteral("Invalid literal for type 'address'", node) if checksum_encode(addr) != addr: raise InvalidLiteral( "Address checksum mismatch. If you are sure this is the right " f"address, the correct checksummed form is: {checksum_encode(addr)}", node, ) return AddressDefinition()
def from_literal(cls, node: vy_ast.Constant) -> BaseTypeDefinition: obj = super().from_literal(node) val = node.value m = cls._length if len(val) != 2 + 2 * m: raise InvalidLiteral("Invalid literal for type bytes32", node) nibbles = val[2:] # strip leading 0x if nibbles not in (nibbles.lower(), nibbles.upper()): raise InvalidLiteral( f"Cannot mix uppercase and lowercase for bytes{m} literal", node) return obj
def decimal(self): numstring, num, den = get_number_as_fraction(self.expr, self.context) # if not SizeLimits.in_bounds('decimal', num // den): # if not SizeLimits.MINDECIMAL * den <= num <= SizeLimits.MAXDECIMAL * den: if not (SizeLimits.MINNUM * den <= num <= SizeLimits.MAXNUM * den): raise InvalidLiteral("Number out of range: " + numstring, self.expr) if DECIMAL_DIVISOR % den: raise InvalidLiteral( "Type 'decimal' has maximum 10 decimal places", self.expr) return LLLnode.from_list( num * DECIMAL_DIVISOR // den, typ=BaseType('decimal', is_literal=True), pos=getpos(self.expr), )
def dict_fail(self): warnings.warn( "Anonymous structs have been removed in" " favor of named structs, see VIP300", DeprecationWarning ) raise InvalidLiteral("Invalid literal.", self.expr)
def from_literal(cls, node: vy_ast.Constant) -> "BaseTypeDefinition": """ Generate a `BaseTypeDefinition` instance of this type from a literal constant. This method is called on every primitive class in order to determine potential types for a `Constant` AST node. Types that may be assigned from literals should include a `_valid_literal` attribute, containing a list of AST node classes that may be valid for this type. If the `_valid_literal` attribute is not included, the type cannot be assigned to a literal. Arguments --------- node : VyperNode `Constant` Vyper ast node, or a list or tuple of constants. Returns ------- BaseTypeDefinition BaseTypeDefinition related to the primitive that the method was called on. """ if not isinstance(node, vy_ast.Constant): raise UnexpectedNodeType( f"Attempted to validate a '{node.ast_type}' node.") if not isinstance(node, cls._valid_literal): raise InvalidLiteral(f"Invalid literal type for {cls.__name__}", node) return cls._type()
def validate(self): if self.value.as_tuple().exponent < -MAX_DECIMAL_PLACES: raise InvalidLiteral("Vyper supports a maximum of ten decimal points", self) if self.value < SizeLimits.MIN_INT128: raise OverflowException("Value is below lower bound for decimal types", self) if self.value > SizeLimits.MAX_INT128: raise OverflowException("Value exceeds upper bound for decimal types", self)
def from_literal(cls, node: vy_ast.Constant) -> AddressDefinition: super().from_literal(node) addr = node.value if len(addr) != 42: n_bytes = (len(addr) - 2) // 2 raise InvalidLiteral( f"Invalid address. Expected 20 bytes, got {n_bytes}.", node) if not is_checksum_encoded(addr): raise InvalidLiteral( "Address checksum mismatch. If you are sure this is the right " f"address, the correct checksummed form is: {checksum_encode(addr)}", node, ) return AddressDefinition()
def get_number_as_fraction(expr, context): context_line = context.origcode.splitlines()[expr.lineno - 1] context_slice = context_line[expr.col_offset:expr.end_col_offset] literal = Decimal(context_slice) sign, digits, exponent = literal.as_tuple() if exponent < -10: raise InvalidLiteral( f"`decimal` literal cannot have more than 10 decimal places: {literal}", expr) sign = (-1 if sign == 1 else 1 ) # Positive Decimal has `sign` of 0, negative `sign` of 1 # Decimal `digits` is a tuple of each digit, so convert to a regular integer top = int(Decimal((0, digits, 0))) top = sign * top * 10**(exponent if exponent > 0 else 0 ) # Convert to a fixed point integer bottom = (1 if exponent > 0 else 10**abs(exponent) ) # Make denominator a power of 10 assert Decimal(top) / Decimal(bottom) == literal # Sanity check # TODO: Would be best to raise >10 decimal place exception here # (unless Decimal is used more widely) return context_slice, top, bottom
def binary(self): orignum = self.expr.node_source_code str_val = orignum[2:] total_bits = len(orignum[2:]) total_bits = ( total_bits if total_bits % 8 == 0 else total_bits + 8 - (total_bits % 8) # ceil8 to get byte length. ) if len(orignum[2:] ) != total_bits: # Support only full formed bit definitions. raise InvalidLiteral( f"Bit notation requires a multiple of 8 bits / 1 byte. " f"{total_bits - len(orignum[2:])} bit(s) are missing.", self.expr, ) byte_len = int(total_bits / 8) placeholder = self.context.new_placeholder(ByteArrayType(byte_len)) seq = [] seq.append(['mstore', placeholder, byte_len]) for i in range(0, total_bits, 256): section = str_val[i:i + 256] int_val = int(section, 2) << (256 - len(section) ) # bytes are right padded. seq.append(['mstore', ['add', placeholder, i + 32], int_val]) return LLLnode.from_list( ['seq'] + seq + [placeholder], typ=ByteArrayType(byte_len), location='memory', pos=getpos(self.expr), annotation=f'Create ByteArray (Binary literal): {str_val}', )
def string_to_bytes(str): bytez = b"" for c in str: if ord(c) >= 256: raise InvalidLiteral(f"Cannot insert special character {c} into byte array") bytez += bytes([ord(c)]) bytez_length = len(bytez) return bytez, bytez_length
def from_literal(cls, node: vy_ast.Constant) -> AddressDefinition: super().from_literal(node) addr = node.value if len(addr) != 42: raise InvalidLiteral("Invalid literal for type 'address'", node) if checksum_encode(addr) != addr: # this should have been caught in `vyper.ast.nodes.Hex.validate` raise CompilerPanic("Address checksum mismatch") return AddressDefinition()
def base_type_conversion(orig, frm, to, pos, in_function_call=False): orig = unwrap_location(orig) # do the base type check so we can use BaseType attributes if not isinstance(frm, BaseType) or not isinstance(to, BaseType): raise TypeMismatch( f"Base type conversion from or to non-base type: {frm} {to}", pos) if getattr(frm, 'is_literal', False): if frm.typ in ('int128', 'uint256'): if not SizeLimits.in_bounds(frm.typ, orig.value): raise InvalidLiteral(f"Number out of range: {orig.value}", pos) if to.typ in ('int128', 'uint256'): if not SizeLimits.in_bounds(to.typ, orig.value): raise InvalidLiteral(f"Number out of range: {orig.value}", pos) is_decimal_int128_conversion = frm.typ == 'int128' and to.typ == 'decimal' is_same_type = frm.typ == to.typ is_literal_conversion = frm.is_literal and (frm.typ, to.typ) == ('int128', 'uint256') is_address_conversion = isinstance(frm, ContractType) and to.typ == 'address' if not (is_same_type or is_literal_conversion or is_address_conversion or is_decimal_int128_conversion): raise TypeMismatch( f"Typecasting from base type {frm} to {to} unavailable", pos) # handle None value inserted by `empty()` if orig.value is None: return LLLnode.from_list(0, typ=to) if is_decimal_int128_conversion: return LLLnode.from_list( ['mul', orig, DECIMAL_DIVISOR], typ=BaseType('decimal'), ) return LLLnode(orig.value, orig.args, typ=to, add_gas_estimate=orig.add_gas_estimate)
def ann_assign(self): with self.context.assignment_scope(): typ = parse_type( self.stmt.annotation, location='memory', custom_units=self.context.custom_units, custom_structs=self.context.structs, constants=self.context.constants, ) if isinstance(self.stmt.target, vy_ast.Attribute): raise TypeMismatch( f'May not set type for field {self.stmt.target.attr}', self.stmt, ) varname = self.stmt.target.id pos = self.context.new_variable(varname, typ) if self.stmt.value is None: raise StructureException( 'New variables must be initialized explicitly', self.stmt) sub = Expr(self.stmt.value, self.context).lll_node # Disallow assignment to None if isinstance(sub.typ, NullType): raise InvalidLiteral( ('Assignment to None is not allowed, use a default ' 'value or built-in `clear()`.'), self.stmt) is_literal_bytes32_assign = (isinstance(sub.typ, ByteArrayType) and sub.typ.maxlen == 32 and isinstance(typ, BaseType) and typ.typ == 'bytes32' and sub.typ.is_literal) # If bytes[32] to bytes32 assignment rewrite sub as bytes32. if is_literal_bytes32_assign: sub = LLLnode( bytes_to_int(self.stmt.value.s), typ=BaseType('bytes32'), pos=getpos(self.stmt), ) self._check_valid_assign(sub) self._check_same_variable_assign(sub) variable_loc = LLLnode.from_list( pos, typ=typ, location='memory', pos=getpos(self.stmt), ) o = make_setter(variable_loc, sub, 'memory', pos=getpos(self.stmt)) # o.pos = getpos(self.stmt) # TODO: Should this be here like in assign()? return o
def _check_valid_assign(self, sub): if (isinstance(self.stmt.annotation, vy_ast.Name) and self.stmt.annotation.id == 'bytes32'): # CMC 04/07/2020 this check could be much clearer, more like: # if isinstance(ByteArrayLike) and maxlen == 32 # or isinstance(BaseType) and typ.typ == 'bytes32' # then GOOD # else RAISE if isinstance(sub.typ, ByteArrayLike): if sub.typ.maxlen != 32: raise TypeMismatch( 'Invalid type, expected: bytes32. String is incorrect length.', self.stmt) return elif isinstance(sub.typ, BaseType): if sub.typ.typ != 'bytes32': raise TypeMismatch('Invalid type, expected: bytes32', self.stmt) return else: raise TypeMismatch("Invalid type, expected: bytes32", self.stmt) elif isinstance(self.stmt.annotation, vy_ast.Subscript): # check list assign: if not isinstance(sub.typ, (ListType, ByteArrayLike)): raise TypeMismatch( f'Invalid type, expected: {self.stmt.annotation.value.id},' f' got: {sub.typ}', self.stmt) elif sub.typ is None: # Check that the object to be assigned is not of NoneType raise TypeMismatch( f"Invalid type, expected {self.stmt.annotation.id}", self.stmt) elif isinstance(sub.typ, StructType): # This needs to get more sophisticated in the presence of # foreign structs. if not sub.typ.name == self.stmt.annotation.id: raise TypeMismatch( f"Invalid type, expected {self.stmt.annotation.id}", self.stmt) # Check that the integer literal, can be assigned to uint256 if necessary. elif (self.stmt.annotation.id, sub.typ.typ) == ('uint256', 'int128') and sub.typ.is_literal: if not SizeLimits.in_bounds('uint256', sub.value): raise InvalidLiteral( 'Invalid uint256 assignment, value not in uint256 range.', self.stmt) elif self.stmt.annotation.id != sub.typ.typ: raise TypeMismatch( f'Invalid type {sub.typ.typ}, expected: {self.stmt.annotation.id}', self.stmt, ) else: return True
def build_LLL(self, expr, args, kwargs, context): value, denom_name = args[0], args[1].decode() denom_divisor = next( (v for k, v in self.wei_denoms.items() if denom_name in k), False) if not denom_divisor: raise InvalidLiteral( f"Invalid denomination: {denom_name}, valid denominations are: " f"{','.join(x[0] for x in self.wei_denoms)}", expr.args[1]) # Compute the amount of wei and return that value if isinstance(value, (int, Decimal)): expr_args_0 = expr.args[0] # On constant reference fetch value node of constant assignment. if context.constants.ast_is_constant(expr.args[0]): expr_args_0 = context.constants._constants_ast[expr.args[0].id] numstring, num, den = get_number_as_fraction(expr_args_0, context) if denom_divisor % den: max_len = len(str(denom_divisor)) - 1 raise InvalidLiteral( f"Wei value of denomination '{denom_name}' has max {max_len} decimal places", expr.args[0]) sub = num * denom_divisor // den elif value.typ.is_literal: if value.value <= 0: raise InvalidLiteral("Negative wei value not allowed", expr) sub = ['mul', value.value, denom_divisor] elif value.typ.typ == 'uint256': sub = ['mul', value, denom_divisor] else: sub = ['div', ['mul', value, denom_divisor], DECIMAL_DIVISOR] return LLLnode.from_list( sub, typ=BaseType('uint256'), location=None, pos=getpos(expr), )
def _check_valid_assign(self, sub): if isinstance(self.stmt.annotation, vy_ast.Call): # unit style: num(wei) if self.stmt.annotation.func.id != sub.typ.typ and not sub.typ.is_literal: raise TypeMismatch( f'Invalid type, expected: {self.stmt.annotation.func.id}', self.stmt) elif (isinstance(self.stmt.annotation, vy_ast.Name) and self.stmt.annotation.id == 'bytes32'): if isinstance(sub.typ, ByteArrayLike): if sub.typ.maxlen != 32: raise TypeMismatch( 'Invalid type, expected: bytes32. String is incorrect length.', self.stmt) return elif isinstance(sub.typ, BaseType): if sub.typ.typ != 'bytes32': raise TypeMismatch('Invalid type, expected: bytes32', self.stmt) return else: raise TypeMismatch('Invalid type, expected: bytes32', self.stmt) elif isinstance(self.stmt.annotation, vy_ast.Subscript): if not isinstance(sub.typ, (ListType, ByteArrayLike)): # check list assign. raise TypeMismatch( f'Invalid type, expected: {self.stmt.annotation.value.id}', self.stmt) elif isinstance(sub.typ, StructType): # This needs to get more sophisticated in the presence of # foreign structs. if not sub.typ.name == self.stmt.annotation.id: raise TypeMismatch( f"Invalid type, expected {self.stmt.annotation.id}", self.stmt) # Check that the integer literal, can be assigned to uint256 if necessary. elif (self.stmt.annotation.id, sub.typ.typ) == ('uint256', 'int128') and sub.typ.is_literal: if not SizeLimits.in_bounds('uint256', sub.value): raise InvalidLiteral( 'Invalid uint256 assignment, value not in uint256 range.', self.stmt) elif self.stmt.annotation.id != sub.typ.typ and not sub.typ.unit: raise TypeMismatch( f'Invalid type {sub.typ.typ}, expected: {self.stmt.annotation.id}', self.stmt, ) else: return True
def _literal_int(expr, out_typ): # TODO: possible to reuse machinery from expr.py? int_info = out_typ._int_info if isinstance(expr, vy_ast.Hex): val = int(expr.value, 16) elif isinstance(expr, vy_ast.Bytes): val = int.from_bytes(expr.value, "big") else: # Int, Decimal val = int(expr.value) (lo, hi) = int_info.bounds if not (lo <= val <= hi): raise InvalidLiteral("Number out of range", expr) return IRnode.from_list(val, typ=out_typ)
def _literal_decimal(expr, out_typ): # TODO: possible to reuse machinery from expr.py? if isinstance(expr, vy_ast.Hex): val = decimal.Decimal(int(expr.value, 16)) else: val = decimal.Decimal(expr.value) # should work for Int, Decimal val = val * DECIMAL_DIVISOR if not SizeLimits.in_bounds("decimal", val): raise InvalidLiteral("Number out of range", expr) # sanity check type checker did its job assert math.ceil(val) == math.floor(val) return IRnode.from_list(int(val), typ=out_typ)
def types_from_Constant(self, node): # literal value (integer, string, etc) types_list = [] for primitive in types.get_primitive_types().values(): try: obj = primitive.from_literal(node) types_list.append(obj) except VyperException: continue if types_list: return types_list if isinstance(node, vy_ast.Num): raise OverflowException( "Numeric literal is outside of allowable range for number types", node, ) raise InvalidLiteral(f"Could not determine type for literal value '{node.value}'", node)
def constants(self): if self.expr.value is True: return LLLnode.from_list( 1, typ=BaseType('bool', is_literal=True), pos=getpos(self.expr), ) elif self.expr.value is False: return LLLnode.from_list( 0, typ=BaseType('bool', is_literal=True), pos=getpos(self.expr), ) elif self.expr.value is None: # block None raise InvalidLiteral('None is not allowed in vyper' '(use a default value or built-in `empty()`') else: raise Exception(f"Unknown name constant: {self.expr.value.value}")
def pack_logging_topics(event_id, args, expected_topics, context, pos): topics = [event_id] code_pos = pos for pos, expected_topic in enumerate(expected_topics): expected_type = expected_topic.typ arg = args[pos] value = Expr(arg, context).lll_node arg_type = value.typ if isinstance(arg_type, ByteArrayLike) and isinstance( expected_type, ByteArrayLike): if arg_type.maxlen > expected_type.maxlen: raise TypeMismatch( f"Topic input bytes are too big: {arg_type} {expected_type}", code_pos) if isinstance(arg, vy_ast.Str): bytez, bytez_length = string_to_bytes(arg.s) if len(bytez) > 32: raise InvalidLiteral( "Can only log a maximum of 32 bytes at a time.", code_pos) topics.append( bytes_to_int(bytez + b'\x00' * (32 - bytez_length))) else: if value.location == "memory": size = ['mload', value] elif value.location == "storage": size = ['sload', ['sha3_32', value]] topics.append(byte_array_to_num(value, arg, 'uint256', size)) else: if arg_type != expected_type: raise TypeMismatch( f"Invalid type for logging topic, got {arg_type} expected {expected_type}", value.pos) value = unwrap_location(value) value = base_type_conversion(value, arg_type, expected_type, pos=code_pos) topics.append(value) return topics