示例#1
0
文件: core.py 项目: fubuloubu/vyper
def LOAD(ptr: IRnode) -> IRnode:
    if ptr.location is None:
        raise CompilerPanic("cannot dereference non-pointer type")
    op = ptr.location.load_op
    if op is None:
        raise CompilerPanic(f"unreachable {ptr.location}")  # pragma: notest
    return IRnode.from_list([op, ptr])
示例#2
0
def calculate_largest_power(a: int, num_bits: int, is_signed: bool) -> int:
    """
    For a given base `a`, compute the maximum power `b` that will not
    produce an overflow in the equation `a ** b`

    Arguments
    ---------
    a : int
        Base value for the equation `a ** b`
    num_bits : int
        The maximum number of bits that the resulting value must fit in
    is_signed : bool
        Is the operation being performed on signed integers?

    Returns
    -------
    int
        Largest possible value for `b` where the result does not overflow
        `num_bits`
    """
    if num_bits % 8:
        raise CompilerPanic("Type is not a modulo of 8")

    value_bits = num_bits - (1 if is_signed else 0)
    if a >= 2**value_bits:
        raise TypeCheckFailure("Value is too large and will always throw")
    elif a < -(2**value_bits):
        raise TypeCheckFailure("Value is too small and will always throw")

    a_is_negative = a < 0
    a = abs(a)  # No longer need to know if it's signed or not
    if a in (0, 1):
        raise CompilerPanic("Exponential operation is useless!")

    # NOTE: There is an edge case if `a` were left signed where the following
    #       operation would not work (`ln(a)` is undefined if `a <= 0`)
    b = int(
        decimal.Decimal(value_bits) /
        (decimal.Decimal(a).ln() / decimal.Decimal(2).ln()))
    if b <= 1:
        return 1  # Value is assumed to be in range, therefore power of 1 is max

    # Do a bit of iteration to ensure we have the exact number
    num_iterations = 0
    while a**(b + 1) < 2**value_bits:
        b += 1
        num_iterations += 1
        assert num_iterations < 10000
    while a**b >= 2**value_bits:
        b -= 1
        num_iterations += 1
        assert num_iterations < 10000

    # Edge case: If a is negative and the values of a and b are such that:
    #               (a) ** (b + 1) == -(2 ** value_bits)
    #            we can actually squeak one more out of it because it's on the edge
    if a_is_negative and (-a)**(b + 1) == -(2**value_bits):  # NOTE: a = abs(a)
        return b + 1
    else:
        return b  # Exact
示例#3
0
文件: core.py 项目: skellet0r/vyper
def clamp_basetype(lll_node):
    t = lll_node.typ
    if not isinstance(t, BaseType):
        raise CompilerPanic(f"{t} passed to clamp_basetype")  # pragma: notest

    # copy of the input
    lll_node = unwrap_location(lll_node)

    if t.typ in ("int128"):
        return int_clamp(lll_node, 128, signed=True)
    if t.typ == "uint8":
        return int_clamp(lll_node, 8)
    if t.typ in ("decimal"):
        return [
            "clamp",
            ["mload", MemoryPositions.MINDECIMAL],
            lll_node,
            ["mload", MemoryPositions.MAXDECIMAL],
        ]

    if t.typ in ("address", ):
        return int_clamp(lll_node, 160)
    if t.typ in ("bool", ):
        return int_clamp(lll_node, 1)
    if t.typ in ("int256", "uint256", "bytes32"):
        return lll_node  # special case, no clamp.

    raise CompilerPanic(f"{t} passed to clamp_basetype")  # pragma: notest
示例#4
0
文件: core.py 项目: fubuloubu/vyper
def clamp_basetype(ir_node):
    t = ir_node.typ
    if not isinstance(t, BaseType):
        raise CompilerPanic(f"{t} passed to clamp_basetype")  # pragma: notest

    # copy of the input
    ir_node = unwrap_location(ir_node)

    if isinstance(t, EnumType):
        bits = len(t.members)
        # assert x >> bits == 0
        ret = int_clamp(ir_node, bits, signed=False)

    elif is_integer_type(t) or is_decimal_type(t):
        if t._num_info.bits == 256:
            ret = ir_node
        else:
            ret = int_clamp(ir_node,
                            t._num_info.bits,
                            signed=t._num_info.is_signed)

    elif is_bytes_m_type(t):
        if t._bytes_info.m == 32:
            ret = ir_node  # special case, no clamp.
        else:
            ret = bytes_clamp(ir_node, t._bytes_info.m)

    elif t.typ in ("address", ):
        ret = int_clamp(ir_node, 160)
    elif t.typ in ("bool", ):
        ret = int_clamp(ir_node, 1)
    else:  # pragma: nocover
        raise CompilerPanic(f"{t} passed to clamp_basetype")

    return IRnode.from_list(ret, typ=ir_node.typ)
示例#5
0
def abi_type_of(lll_typ):
    if isinstance(lll_typ, BaseType):
        t = lll_typ.typ
        if "uint256" == t:
            return ABI_GIntM(256, False)
        elif "int128" == t:
            return ABI_GIntM(128, True)
        elif "address" == t:
            return ABI_Address()
        elif "bytes32" == t:
            return ABI_BytesM(32)
        elif "bool" == t:
            return ABI_Bool()
        elif "decimal" == t:
            return ABI_FixedMxN(168, 10, True)
        else:
            raise CompilerPanic(f"Unrecognized type {t}")
    elif isinstance(lll_typ, TupleLike):
        return ABI_Tuple([abi_type_of(t) for t in lll_typ.tuple_members()])
    elif isinstance(lll_typ, ListType):
        return ABI_StaticArray(abi_type_of(lll_typ.subtype), lll_typ.count)
    elif isinstance(lll_typ, ByteArrayType):
        return ABI_Bytes(lll_typ.maxlen)
    elif isinstance(lll_typ, StringType):
        return ABI_String(lll_typ.maxlen)
    else:
        raise CompilerPanic(f"Unrecognized type {lll_typ}")
示例#6
0
def clamp_basetype(ir_node):
    t = ir_node.typ
    if not isinstance(t, BaseType):
        raise CompilerPanic(f"{t} passed to clamp_basetype")  # pragma: notest

    # copy of the input
    ir_node = unwrap_location(ir_node)

    if is_integer_type(t) or is_decimal_type(t):
        if t._num_info.bits == 256:
            return ir_node
        else:
            return int_clamp(ir_node,
                             t._num_info.bits,
                             signed=t._num_info.is_signed)

    if is_bytes_m_type(t):
        if t._bytes_info.m == 32:
            return ir_node  # special case, no clamp.
        else:
            return bytes_clamp(ir_node, t._bytes_info.m)

    if t.typ in ("address", ):
        return int_clamp(ir_node, 160)
    if t.typ in ("bool", ):
        return int_clamp(ir_node, 1)

    raise CompilerPanic(f"{t} passed to clamp_basetype")  # pragma: notest
示例#7
0
文件: core.py 项目: skellet0r/vyper
def _get_element_ptr_tuplelike(parent, key, pos):
    typ = parent.typ
    assert isinstance(typ, TupleLike)

    if isinstance(typ, StructType):
        assert isinstance(key, str)
        subtype = typ.members[key]
        attrs = list(typ.tuple_keys())
        index = attrs.index(key)
        annotation = key
    else:
        assert isinstance(key, int)
        subtype = typ.members[key]
        attrs = list(range(len(typ.members)))
        index = key
        annotation = None

    # generated by empty() + make_setter
    if parent.value == "~empty":
        return LLLnode.from_list("~empty", typ=subtype)

    if parent.value == "multi":
        assert parent.encoding != Encoding.ABI, "no abi-encoded literals"
        return parent.args[index]

    ofst = 0  # offset from parent start

    if parent.encoding in (Encoding.ABI, Encoding.JSON_ABI):
        if parent.location == "storage":
            raise CompilerPanic("storage variables should not be abi encoded"
                                )  # pragma: notest

        member_t = typ.members[attrs[index]]

        for i in range(index):
            member_abi_t = typ.members[attrs[i]].abi_type
            ofst += member_abi_t.embedded_static_size()

        return _getelemptr_abi_helper(parent, member_t, ofst, pos)

    if parent.location == "storage":
        for i in range(index):
            ofst += typ.members[attrs[i]].storage_size_in_words
    elif parent.location in ("calldata", "memory", "code"):
        for i in range(index):
            ofst += typ.members[attrs[i]].memory_bytes_required
    else:
        raise CompilerPanic(
            f"bad location {parent.location}")  # pragma: notest

    return LLLnode.from_list(
        add_ofst(parent, ofst),
        typ=subtype,
        location=parent.location,
        encoding=parent.encoding,
        annotation=annotation,
        pos=pos,
    )
示例#8
0
文件: bases.py 项目: benjyz/vyper
 def set_position(self, position: DataPosition) -> None:
     if hasattr(self, "position"):
         raise CompilerPanic("Position was already assigned")
     if self.location != position._location:
         if self.location == DataLocation.UNSET:
             self.location = position._location
         else:
             raise CompilerPanic("Incompatible locations")
     self.position = position
示例#9
0
    def __init__(self, m_bits, n_places, signed):
        if not (0 < m_bits <= 256 and 0 == m_bits % 8):
            raise CompilerPanic("Invalid M for FixedMxN")
        if not (0 < n_places and n_places <= 80):
            raise CompilerPanic("Invalid N for FixedMxN")

        self.m_bits = m_bits
        self.n_places = n_places
        self.signed = signed
示例#10
0
文件: core.py 项目: fubuloubu/vyper
def STORE(ptr: IRnode, val: IRnode) -> IRnode:
    if ptr.location is None:
        raise CompilerPanic("cannot dereference non-pointer type")
    op = ptr.location.store_op
    if op is None:
        raise CompilerPanic(f"unreachable {ptr.location}")  # pragma: notest

    _check = _freshname(f"{op}_")
    return IRnode.from_list(["seq", eval_once_check(_check), [op, ptr, val]])
示例#11
0
 def set_reentrancy_key_position(self, position: StorageSlot) -> None:
     if hasattr(self, "reentrancy_key_position"):
         raise CompilerPanic("Position was already assigned")
     if self.nonreentrant is None:
         raise CompilerPanic(f"No reentrant key {self}")
     # sanity check even though implied by the type
     if position._location != DataLocation.STORAGE:
         raise CompilerPanic("Non-storage reentrant key")
     self.reentrancy_key_position = position
示例#12
0
    def set_min_length(self, min_length):
        """
        Sets the minimum length of the type.

        May only be used to increase the minimum length. May not be called if
        an exact length has been set.
        """
        if self._length:
            raise CompilerPanic("Type already has a fixed length")
        if self._min_length > min_length:
            raise CompilerPanic("Cannot reduce the min_length of ArrayValueType")
        self._min_length = min_length
示例#13
0
    def replace_in_tree(self, old_node: VyperNode,
                        new_node: VyperNode) -> None:
        """
        Perform an in-place substitution of a node within the tree.

        Parameters
        ----------
        old_node : VyperNode
            Node object to be replaced. If the node does not currently exist
            within the AST, a `CompilerPanic` is raised.
        new_node : VyperNode
            Node object to replace new_node.

        Returns
        -------
        None
        """
        parent = old_node._parent
        if old_node not in self.get_descendants(type(old_node)):
            raise CompilerPanic(
                "Node to be replaced does not exist within the tree")

        if old_node not in parent._children:
            raise CompilerPanic(
                "Node to be replaced does not exist within parent children")

        is_replaced = False
        for key in parent.get_fields():
            obj = getattr(parent, key, None)
            if obj == old_node:
                if is_replaced:
                    raise CompilerPanic(
                        "Node to be replaced exists as multiple members in parent"
                    )
                setattr(parent, key, new_node)
                is_replaced = True
            elif isinstance(obj, list) and obj.count(old_node):
                if is_replaced or obj.count(old_node) > 1:
                    raise CompilerPanic(
                        "Node to be replaced exists as multiple members in parent"
                    )
                obj[obj.index(old_node)] = new_node
                is_replaced = True
        if not is_replaced:
            raise CompilerPanic(
                "Node to be replaced does not exist within parent members")

        parent._children.remove(old_node)

        new_node._parent = parent
        new_node._depth = old_node._depth
        parent._children.add(new_node)
示例#14
0
文件: core.py 项目: fubuloubu/vyper
def bytes_clamp(ir_node: IRnode, n_bytes: int) -> IRnode:
    if not (0 < n_bytes <= 32):
        raise CompilerPanic(f"bad type: bytes{n_bytes}")
    with ir_node.cache_when_complex("val") as (b, val):
        assertion = ["assert", ["iszero", shl(n_bytes * 8, val)]]
        ret = b.resolve(["seq", assertion, val])
    return IRnode.from_list(ret, annotation=f"bytes{n_bytes}_clamp")
示例#15
0
文件: core.py 项目: fubuloubu/vyper
def int_clamp(ir_node, bits, signed=False):
    """Generalized clamper for integer types. Takes the number of bits,
    whether it's signed, and returns an IR node which checks it is
    in bounds. (Consumers should use clamp_basetype instead which uses
    type-based dispatch and is a little safer.)
    """
    if bits >= 256:
        raise CompilerPanic(
            f"invalid clamp: {bits}>=256 ({ir_node})")  # pragma: notest
    with ir_node.cache_when_complex("val") as (b, val):
        if signed:
            # example for bits==128:
            # promote_signed_int(val, bits) is the "canonical" version of val
            # if val is in bounds, the bits above bit 128 should be equal.
            # (this works for both val >= 0 and val < 0. in the first case,
            # all upper bits should be 0 if val is a valid int128,
            # in the latter case, all upper bits should be 1.)
            assertion = ["assert", ["eq", val, promote_signed_int(val, bits)]]
        else:
            assertion = ["assert", ["iszero", shr(bits, val)]]

        ret = b.resolve(["seq", assertion, val])

    # TODO fix this annotation
    return IRnode.from_list(ret, annotation=f"int_clamp {ir_node.typ}")
示例#16
0
文件: core.py 项目: vyperlang/vyper
def STORE(ptr: IRnode, val: IRnode) -> IRnode:
    if ptr.location is None:
        raise CompilerPanic("cannot dereference non-pointer type")
    op = ptr.location.store_op
    if op is None:
        raise CompilerPanic(f"unreachable {ptr.location}")  # pragma: notest

    _check = _freshname(f"{op}_")

    store = [op, ptr, val]
    # don't use eval_once_check for memory, immutables because it interferes
    # with optimizer
    if ptr.location in (MEMORY, IMMUTABLES):
        return IRnode.from_list(store)

    return IRnode.from_list(["seq", eval_once_check(_check), store])
示例#17
0
 def increase_memory(self, size: int) -> Tuple[int, int]:
     if size % 32 != 0:
         raise CompilerPanic(
             'Memory misaligment, only multiples of 32 supported.')
     before_value = self.next_mem
     self.next_mem += size
     return before_value, self.next_mem
示例#18
0
文件: module.py 项目: fubuloubu/vyper
def _add_import(
    node: Union[vy_ast.Import, vy_ast.ImportFrom],
    module: str,
    name: str,
    alias: str,
    interface_codes: InterfaceDict,
    namespace: dict,
) -> None:
    if module == "vyper.interfaces":
        interface_codes = _get_builtin_interfaces()
    if name not in interface_codes:
        suggestions_str = get_levenshtein_error_suggestions(name, _get_builtin_interfaces(), 1.0)
        raise UndeclaredDefinition(f"Unknown interface: {name}. {suggestions_str}", node)

    if interface_codes[name]["type"] == "vyper":
        interface_ast = vy_ast.parse_to_ast(interface_codes[name]["code"], contract_name=name)
        type_ = namespace["interface"].build_primitive_from_node(interface_ast)
    elif interface_codes[name]["type"] == "json":
        type_ = namespace["interface"].build_primitive_from_abi(name, interface_codes[name]["code"])
    else:
        raise CompilerPanic(f"Unknown interface format: {interface_codes[name]['type']}")

    try:
        namespace[alias] = type_
    except VyperException as exc:
        raise exc.with_annotation(node) from None
示例#19
0
 def parse_Int(self):
     typ_ = self.expr._metadata.get("type")
     if typ_ is None:
         raise CompilerPanic("Type of integer literal is unknown")
     new_typ = new_type_to_old_type(typ_)
     new_typ.is_literal = True
     return IRnode.from_list(self.expr.n, typ=new_typ)
示例#20
0
    def allocate_memory(self, size: int) -> int:
        """
        Allocate `size` bytes in memory.

        *** No guarantees are made that allocated memory is clean! ***

        If no memory was previously de-allocated, memory is expanded
        and the free memory pointer is increased.

        If sufficient space is available within de-allocated memory, the lowest
        available offset is returned and that memory is now marked as allocated.

        Arguments
        ---------
        size : int
            The number of bytes to allocate. Must be divisible by 32.

        Returns
        -------
        int
            Start offset of the newly allocated memory.
        """
        if size % 32 != 0:
            raise CompilerPanic("Memory misaligment, only multiples of 32 supported.")

        # check for deallocated memory prior to expanding
        for i, free_memory in enumerate(self.deallocated_mem):
            if free_memory.size == size:
                del self.deallocated_mem[i]
                return free_memory.position
            if free_memory.size > size:
                return free_memory.partially_allocate(size)

        # if no deallocated slots are available, expand memory
        return self.expand_memory(size)
示例#21
0
def _flip_comparison_op(opname):
    assert opname in COMPARISON_OPS
    if "g" in opname:
        return opname.replace("g", "l")
    if "l" in opname:
        return opname.replace("l", "g")
    raise CompilerPanic(f"bad comparison op {opname}")  # pragma: notest
示例#22
0
    def visit_Num(self, node):
        """
        Adjust numeric node class based on the value type.

        Python uses `Num` to represent floats and integers. Integers may also
        be given in binary, octal, decimal, or hexadecimal format. This method
        modifies `ast_type` to seperate `Num` into more granular Vyper node
        classes.
        """
        # modify vyper AST type according to the format of the literal value
        self.generic_visit(node)
        value = node.node_source_code

        # deduce non base-10 types based on prefix
        literal_prefixes = {'0x': "Hex", '0b': "Binary", '0o': "Octal"}
        if value.lower()[:2] in literal_prefixes:
            node.ast_type = literal_prefixes[value.lower()[:2]]
            node.n = value
        elif isinstance(node.n, float):
            node.ast_type = "Decimal"
            node.n = Decimal(value)
        elif isinstance(node.n, int):
            node.ast_type = "Int"
        else:
            raise CompilerPanic(f"Unexpected type for Constant value: {type(node.n).__name__}")

        return node
示例#23
0
def lazy_abi_decode(typ, src, pos=None):
    if isinstance(typ, (ListType, TupleLike)):
        if isinstance(typ, TupleLike):
            ts = typ.tuple_members()
        else:
            ts = [typ.subtyp for _ in range(typ.count)]
        ofst = 0
        os = []
        for t in ts:
            child_abi_t = abi_type_of(t)
            loc = _add_ofst(src, ofst)
            if child_abi_t.is_dynamic():
                # load the offset word, which is the
                # (location-independent) offset from the start of the
                # src buffer.
                dyn_ofst = unwrap_location(ofst)
                loc = _add_ofst(src, dyn_ofst)
            os.append(lazy_abi_decode(t, loc, pos))
            ofst += child_abi_t.embedded_static_size()

        return LLLnode.from_list(["multi"] + os, typ=typ, pos=pos)

    elif isinstance(typ, (BaseType, ByteArrayLike)):
        return unwrap_location(src)
    else:
        raise CompilerPanic(f"unknown type for lazy_abi_decode {typ}")
示例#24
0
    def from_AnnAssign(cls, node: vy_ast.AnnAssign) -> "ContractFunction":
        """
        Generate a `ContractFunction` object from an `AnnAssign` node.

        Used to create function definitions for public variables.

        Arguments
        ---------
        node : AnnAssign
            Vyper ast node to generate the function definition from.

        Returns
        -------
        ContractFunction
        """
        if not isinstance(node.annotation, vy_ast.Call):
            raise CompilerPanic("Annotation must be a call to public()")
        type_ = get_type_from_annotation(node.annotation.args[0],
                                         location=DataLocation.STORAGE)
        arguments, return_type = type_.get_signature()
        args_dict: OrderedDict = OrderedDict()
        for item in arguments:
            args_dict[f"arg{len(args_dict)}"] = item
        return cls(
            node.target.id,
            args_dict,
            len(arguments),
            return_type,
            function_visibility=FunctionVisibility.EXTERNAL,
            state_mutability=StateMutability.NONPAYABLE,
        )
示例#25
0
文件: module.py 项目: erdnaag/vyper
def _add_import(
    node: Union[vy_ast.Import, vy_ast.ImportFrom],
    module: str,
    name: str,
    interface_codes: InterfaceDict,
    namespace: dict,
) -> None:
    if module == "vyper.interfaces":
        interface_codes = _get_builtin_interfaces()
    if name not in interface_codes:
        raise UndeclaredDefinition(f"Unknown interface: {name}", node)
    try:
        if interface_codes[name]["type"] == "vyper":
            interface_ast = vy_ast.parse_to_ast(interface_codes[name]["code"])
            interface_ast.name = name
            type_ = namespace["interface"].build_primitive_from_node(interface_ast)
        elif interface_codes[name]["type"] == "json":
            type_ = namespace["interface"].build_primitive_from_abi(
                name, interface_codes[name]["code"]
            )
        else:
            raise CompilerPanic(f"Unknown interface format: {interface_codes[name]['type']}")
        namespace[name] = type_
    except VyperException as exc:
        raise exc.with_annotation(node) from None
示例#26
0
def validate_call_args(node: vy_ast.Call,
                       arg_count: Union[int, tuple],
                       kwargs: Optional[list] = None) -> None:
    """
    Validate positional and keyword arguments of a Call node.

    This function does not handle type checking of arguments, it only checks
    correctness of the number of arguments given and keyword names.

    Arguments
    ---------
    node : Call
        Vyper ast Call node to be validated.
    arg_count : int | tuple
        The required number of positional arguments. When given as a tuple the
        value is interpreted as the minimum and maximum number of arguments.
    kwargs : list, optional
        A list of valid keyword arguments. When arg_count is a tuple and the
        number of positional arguments exceeds the minimum, the excess values are
        considered to fill the first values on this list.

    Returns
    -------
        None. Raises an exception when the arguments are invalid.
    """
    if kwargs is None:
        kwargs = []
    if not isinstance(node, vy_ast.Call):
        raise StructureException("Expected Call", node)
    if not isinstance(arg_count, (int, tuple)):
        raise CompilerPanic(
            f"Invalid type for arg_count: {type(arg_count).__name__}")

    if isinstance(arg_count, int) and len(node.args) != arg_count:
        raise ArgumentException(
            f"Invalid argument count: expected {arg_count}, got {len(node.args)}",
            node)
    elif (isinstance(arg_count, tuple)
          and not arg_count[0] <= len(node.args) <= arg_count[1]):
        raise ArgumentException(
            f"Invalid argument count: expected between "
            f"{arg_count[0]} and {arg_count[1]}, got {len(node.args)}",
            node,
        )

    if not kwargs and node.keywords:
        raise ArgumentException("Keyword arguments are not accepted here",
                                node.keywords[0])
    for key in node.keywords:
        if key.arg is None:
            raise StructureException("Use of **kwargs is not supported",
                                     key.value)
        if key.arg not in kwargs:
            raise ArgumentException(f"Invalid keyword argument '{key.arg}'",
                                    key)
        if (isinstance(arg_count, tuple)
                and kwargs.index(key.arg) < len(node.args) - arg_count[0]):
            raise ArgumentException(
                f"'{key.arg}' was given as a positional argument", key)
示例#27
0
 def __init__(
     self, typ, unit=False, positional=False, override_signature=False, is_literal=False
 ):
     self.typ = typ
     if unit or positional:
         raise CompilerPanic("Units are no longer supported")
     self.override_signature = override_signature
     self.is_literal = is_literal
示例#28
0
文件: types.py 项目: skellet0r/vyper
 def storage_size_in_words(self) -> int:
     """
     Returns the number of words required to allocate in storage for this type
     """
     r = self.memory_bytes_required
     if r % 32 != 0:
         raise CompilerPanic("Memory bytes must be multiple of 32")
     return r // 32
示例#29
0
文件: core.py 项目: fubuloubu/vyper
def needs_clamp(t, encoding):
    if encoding == Encoding.VYPER:
        return False
    if encoding != Encoding.ABI:
        raise CompilerPanic("unreachable")  # pragma: notest
    if isinstance(t, (ByteArrayLike, DArrayType)):
        return True
    if isinstance(t, EnumType):
        return len(t.members) < 256
    if isinstance(t, BaseType):
        return t.typ not in ("int256", "uint256", "bytes32")
    if isinstance(t, SArrayType):
        return needs_clamp(t.subtype, encoding)
    if isinstance(t, TupleLike):
        return any(needs_clamp(m, encoding) for m in t.tuple_members())

    raise CompilerPanic("unreachable")  # pragma: notest
示例#30
0
 def pp_constancy(self):
     if self.in_assertion:
         return "an assertion"
     elif self.in_range_expr:
         return "a range expression"
     elif self.constancy == Constancy.Constant:
         return "a constant function"
     raise CompilerPanic(f"unknown constancy in pp_constancy: {self.constancy}")