# Path: soap/common/base.py
# class Comparable(object):
#     __slots__ = ()
# 
#     def __ne__(self, other):
#         return not self.__eq__(other)
# 
#     def __ge__(self, other):
#         return not self.__lt__(other)
# 
#     def __gt__(self, other):
#         return not self.__eq__(other) and not self.__lt__(other)
# 
#     def __le__(self, other):
#         return not self.__gt__(other)
# 
# Path: soap/common/cache.py
# class Flyweight(object):
# 
#     _cache = weakref.WeakValueDictionary()
# 
#     def __new__(cls, *args, **kwargs):
#         if not args and not kwargs:
#             return object.__new__(cls)
#         key = pickle.dumps((cls, args, list(kwargs.items())))
#         v = cls._cache.get(key, None)
#         if v is not None:
#             return v
#         v = object.__new__(cls)
#         cls._cache[key] = v
#         return v
# 
# Path: soap/datatype.py
# def type_of(value):
#     if value is None:
#         return
#     if isinstance(value, IntegerInterval):
#         return int_type
#     if isinstance(value, ErrorSemantics):
#         return float_type
#     if isinstance(value, IntegerIntervalArray):
#         return IntegerArrayType(value.shape)
#     if isinstance(value, ErrorSemanticsArray):
#         return FloatArrayType(value.shape)
#     raise TypeError('Unrecognized type {}'.format(type(value)))
# 
# Path: soap/expression/common.py
# @cached
# def expression_factory(op, *args):
#     from soap.expression import operators
#     from soap.expression.arithmetic import (
#         UnaryArithExpr, BinaryArithExpr, TernaryArithExpr, SelectExpr
#     )
#     from soap.expression.boolean import (
#         UnaryBoolExpr, BinaryBoolExpr, TernaryBoolExpr
#     )
#     from soap.expression.fixpoint import FixExpr
#     from soap.expression.linalg import Subscript, AccessExpr, UpdateExpr
# 
#     global op_expr_cls_map
#     if not op_expr_cls_map:
#         op_expr_cls_map = {
#             operators.SUBSCRIPT_OP: Subscript,
#             operators.INDEX_ACCESS_OP: AccessExpr,
#             operators.INDEX_UPDATE_OP: UpdateExpr,
#             operators.FIXPOINT_OP: FixExpr,
#             operators.TERNARY_SELECT_OP: SelectExpr,
#         }
#     cls = op_expr_cls_map.get(op)
#     if cls:
#         return cls(*args)
# 
#     if op in operators.ARITHMETIC_OPERATORS:
#         class_list = [UnaryArithExpr, BinaryArithExpr, TernaryArithExpr]
#     elif op in operators.BOOLEAN_OPERATORS:
#         class_list = [UnaryBoolExpr, BinaryBoolExpr, TernaryBoolExpr]
#     else:
#         raise ValueError('Unknown operator {}.'.format(op))
#     try:
#         cls = class_list[len(args) - 1]
#     except IndexError:
#         raise ValueError('Too many arguments.')
#     return cls(op, *args)
# 
# def is_expression(e):
#     from soap.expression.base import Expression
#     from soap.expression.variable import Variable, VariableTuple
#     if not isinstance(e, Expression):
#         return False
#     if isinstance(e, Variable):
#         return False
#     if isinstance(e, VariableTuple):
#         return False
#     return True


from collections import namedtuple
from soap.common import Comparable, Flyweight
from soap.datatype import type_of
from soap.expression import expression_factory, is_expression
        from soap.semantics.state import MetaState
        from soap.semantics.resource import resource_count
    label_class = Label

    def __init__(self, description, out_vars=None):
        super().__init__()
        if not isinstance(description, str):
            description = 'c{}'.format(
                Label(description, None, None).label_value)
        self.description = description
        self.out_vars = out_vars
        self.lmap = _label_context_maps.setdefault(self.description, {})

    def Label(self, statement, bound, invariant):
        label_value = fresh_int(statement, _lmap=self.lmap)
        return self.label_class(
            statement, bound=bound, invariant=invariant,
            context_id=self.description, _label_value=label_value)

    def __eq__(self, other):
        if not isinstance(other, self.__class__):
            return False
        return self.description == other.description

    def __repr__(self):
        return '<{cls}:{description}>'.format(
            cls=self.__class__, description=self.description)


_label_semantics_tuple_type = namedtuple('LabelSemantics', ['label', 'env'])



# Path: soap/common/base.py
# class Comparable(object):
#     __slots__ = ()
# 
#     def __ne__(self, other):
#         return not self.__eq__(other)
# 
#     def __ge__(self, other):
#         return not self.__lt__(other)
# 
#     def __gt__(self, other):
#         return not self.__eq__(other) and not self.__lt__(other)
# 
#     def __le__(self, other):
#         return not self.__gt__(other)
# 
# Path: soap/common/cache.py
# class Flyweight(object):
# 
#     _cache = weakref.WeakValueDictionary()
# 
#     def __new__(cls, *args, **kwargs):
#         if not args and not kwargs:
#             return object.__new__(cls)
#         key = pickle.dumps((cls, args, list(kwargs.items())))
#         v = cls._cache.get(key, None)
#         if v is not None:
#             return v
#         v = object.__new__(cls)
#         cls._cache[key] = v
#         return v
# 
# Path: soap/datatype.py
# def type_of(value):
#     if value is None:
#         return
#     if isinstance(value, IntegerInterval):
#         return int_type
#     if isinstance(value, ErrorSemantics):
#         return float_type
#     if isinstance(value, IntegerIntervalArray):
#         return IntegerArrayType(value.shape)
#     if isinstance(value, ErrorSemanticsArray):
#         return FloatArrayType(value.shape)
#     raise TypeError('Unrecognized type {}'.format(type(value)))
# 
# Path: soap/expression/common.py
# @cached
# def expression_factory(op, *args):
#     from soap.expression import operators
#     from soap.expression.arithmetic import (
#         UnaryArithExpr, BinaryArithExpr, TernaryArithExpr, SelectExpr
#     )
#     from soap.expression.boolean import (
#         UnaryBoolExpr, BinaryBoolExpr, TernaryBoolExpr
#     )
#     from soap.expression.fixpoint import FixExpr
#     from soap.expression.linalg import Subscript, AccessExpr, UpdateExpr
# 
#     global op_expr_cls_map
#     if not op_expr_cls_map:
#         op_expr_cls_map = {
#             operators.SUBSCRIPT_OP: Subscript,
#             operators.INDEX_ACCESS_OP: AccessExpr,
#             operators.INDEX_UPDATE_OP: UpdateExpr,
#             operators.FIXPOINT_OP: FixExpr,
#             operators.TERNARY_SELECT_OP: SelectExpr,
#         }
#     cls = op_expr_cls_map.get(op)
#     if cls:
#         return cls(*args)
# 
#     if op in operators.ARITHMETIC_OPERATORS:
#         class_list = [UnaryArithExpr, BinaryArithExpr, TernaryArithExpr]
#     elif op in operators.BOOLEAN_OPERATORS:
#         class_list = [UnaryBoolExpr, BinaryBoolExpr, TernaryBoolExpr]
#     else:
#         raise ValueError('Unknown operator {}.'.format(op))
#     try:
#         cls = class_list[len(args) - 1]
#     except IndexError:
#         raise ValueError('Too many arguments.')
#     return cls(op, *args)
# 
# def is_expression(e):
#     from soap.expression.base import Expression
#     from soap.expression.variable import Variable, VariableTuple
#     if not isinstance(e, Expression):
#         return False
#     if isinstance(e, Variable):
#         return False
#     if isinstance(e, VariableTuple):
#         return False
#     return True


# Path: soap/semantics/label.py
from collections import namedtuple
from soap.common import Comparable, Flyweight
from soap.datatype import type_of
from soap.expression import expression_factory, is_expression
        from soap.semantics.state import MetaState
        from soap.semantics.resource import resource_count

    label_class = Label

    def __init__(self, description, out_vars=None):
        super().__init__()
        if not isinstance(description, str):
            description = 'c{}'.format(
                Label(description, None, None).label_value)
        self.description = description
        self.out_vars = out_vars
        self.lmap = _label_context_maps.setdefault(self.description, {})

    def Label(self, statement, bound, invariant):
        label_value = fresh_int(statement, _lmap=self.lmap)
        return self.label_class(
            statement, bound=bound, invariant=invariant,
            context_id=self.description, _label_value=label_value)

    def __eq__(self, other):
        if not isinstance(other, self.__class__):
            return False
        return self.description == other.description

    def __repr__(self):
        return '<{cls}:{description}>'.format(
            cls=self.__class__, description=self.description)


_label_semantics_tuple_type = namedtuple('LabelSemantics', ['label', 'env'])



class LabelSemantics(_label_semantics_tuple_type, Flyweight, Comparable):