text: # Copyright (c) 2017-2021 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
  # SPDX-License-Identifier: Apache-2.0
  
  """
  DAML-LF Archive types
  ---------------------
  """
  
  # NOTE TO IMPLEMENTORS: A future version of this file is intended to be code-generated instead of
  # manually maintained. The makeup of this file is intentionally highly formulaic in order to
  # facilitate a smooth transition to automatically-generated data structures.
  #
  # On a similar note, it is important to be careful about imports in this file; it is simpler to
  # validate an automatically generated file with no dependencies. Also, this file is imported in a
  # lot of places in the dazl codebase, so imports in this file could frequently lead to import
  # cycles.
  #
  # The few local imports in this file should be inlined by a codegen process instead to keep this
  # file self-contained.
  
  from dataclasses import dataclass
  from enum import IntEnum as _IntEnum
  from io import StringIO
  import threading
  from typing import Any, Callable, NewType, Optional, Sequence, Tuple, Union
  import typing as _typing
  
  from ._base import MISSING, T, _Missing
  
  __all__ = [
      "Archive",
      "Binding",
      "Block",
      "BuiltinFunction",
      "Case",
      "CaseAlt",
      "DefDataType",
      "DefTemplate",
      "DefTypeSyn",
      "DefValue",
      "DottedName",
      "Expr",
      "FeatureFlags",
      "FieldWithExpr",
      "FieldWithType",
      "KeyExpr",
      "Kind",
      "Location",
      "Module",
      "ModuleRef",
      "Package",
      "PackageMetadata",
      "PackageRef",
      "PrimCon",
      "PrimLit",
      "PrimType",
      "Pure",
      "Scenario",
      "TemplateChoice",
      "Type",
      "TypeConName",
      "TypeSynName",
      "TypeVarWithKind",
      "UNIT",
      "Unit",
      "Update",
      "ValName",
      "VarWithType",
  ]
  
  _T = _typing.TypeVar("_T")
  
  
  class Unit:
      __slots__ = ()
  
  
  UNIT = Unit()
  
  # Reference to a package via a package identifier. The identifier is the ascii7
  # lowercase hex-encoded hash of the package contents found in the DAML LF Archive.
  PackageRef = NewType("PackageRef", str)
  
  
  class DottedName:
      __slots__ = ("segments",)
  
      segments: Sequence[str]
  
      def __init__(self, segments: Sequence[str] = ()):
          object.__setattr__(self, "segments", tuple(segments))
  
      def __str__(self):
          return ".".join(self.segments)
  
      def __bool__(self):
          return bool(self.segments)
  
      def __eq__(self, other):
          return isinstance(other, DottedName) and self.segments == other.segments
  
      def __lt__(self, other):
          return self.segments < other.segments
  
      def __le__(self, other):
          return self.segments <= other.segments
  
      def __gt__(self, other):
          return self.segments > other.segments
  
      def __ge__(self, other):
          return self.segments >= other.segments
  
      def __hash__(self):
          return hash(self.segments)
  
  
  class ModuleRef:
      """
      A reference to a module.
  
      In dazl v8.0.0, ModuleRef will become a `NewType(str)`, so making assumptions about the
      structure of this type should be avoided, and accessor methods should be instead used for
      callers that care about the structure of these names.
      """
  
      __slots__ = "_package_id", "_module_name"
  
      def __init__(self, package_id: "PackageRef", module_name: "DottedName"):
          from ..util.typing import safe_cast
  
          self._package_id = PackageRef(safe_cast(str, package_id))
          self._module_name = safe_cast(DottedName, module_name)
  
      def __eq__(self, other):
          return (
              isinstance(other, ModuleRef)
              and self._package_id == other._package_id
              and self._module_name == other._module_name
          )
  
      def __lt__(self, other):
          return self._package_id < other._package_id or (
              self._package_id == other._package_id and self._module_name < other._module_name
          )
  
      def __le__(self, other):
          return self._package_id < other._package_id or (
              self._package_id == other._package_id and self._module_name <= other._module_name
          )
  
      def __gt__(self, other):
          return self._package_id > other._package_id or (
              self._package_id == other._package_id and self._module_name > other._module_name
          )
  
      def __ge__(self, other):
          return self._package_id > other._package_id or (
              self._package_id == other._package_id and self._module_name >= other._module_name
          )
  
      def __hash__(self):
          return hash(self._package_id) ^ hash(self._module_name)
  
      def __str__(self):
          if self._module_name:
              return f"{self._package_id}:{self._module_name}"
          else:
              return self._package_id
  
      def __repr__(self):
          return f"ModuleRef(package_id={self._package_id!r}, " f"module_name={self._module_name})"
  
  
  class _Name:
      """
      A reference by name to another object.
  
      This implementation powers all of a TypeConName, TypeSynName, and ValName.
  
      In dazl 7.0.0, these will become `NewType(str)`, so making assumptions about the structure of
      this type should be avoided, and accessor methods should be instead used for callers that care
      about the structure of these names.
      """
  
      __slots__ = "_module", "_name"
  
      def __init__(self, module: "ModuleRef", name: "Sequence[str]"):
          from collections.abc import Collection
  
          from ..util.typing import safe_cast
  
          if not isinstance(name, Collection):
              raise TypeError(f"Tuple of strings required here (got {name!r} instead)")
  
          self._module = safe_cast(ModuleRef, module)
          self._name = tuple(name)  # type: Tuple[str, ...]
  
      def __eq__(self, other):
          return (
              isinstance(other, type(self))
              and self._module == other._module
              and self._name == other._name
          )
  
      def __ne__(self, other):
          return (
              not isinstance(other, type(self))
              or self._module != other._module
              or self._name != other._name
          )
  
      def __lt__(self, other):
          if not isinstance(other, _Name):
              raise TypeError("must compare Name to other names")
  
          return self._module < other._module or (
              self._module == other._module and self._name < other._name
          )
  
      def __le__(self, other):
          if not isinstance(other, _Name):
              raise TypeError("must compare Name to other names")
          return self._module <= other._module or (
              self._module == other._module and self._name <= other._name
          )
  
      def __gt__(self, other):
          if not isinstance(other, _Name):
              raise TypeError("must compare Name to other names")
          return self._module > other._module or (
              self._module == other._module and self._name > other._name
          )
  
      def __ge__(self, other):
          if not isinstance(other, _Name):
              raise TypeError("must compare Name to other names")
  
          return self._module >= other._module or (
              self._module == other._module and self._name >= other._name
          )
  
      def __hash__(self):
          return hash(self._module) ^ hash(self._name)
  
      def __str__(self):
          return f"{self._module}:{'.'.join(self._name)}"
  
      def __repr__(self):
          return f"{type(self).__name__}({str(self)!r})"
  
  
  class TypeConName(_Name):
      """
      A reference to a type constructor.
      """
  
  
  class TypeSynName(_Name):
      """
      A reference to a type synonym.
      """
  
  
  class ValName(_Name):
      """
      A reference to a value.
      """
  
  
  @dataclass(frozen=True)
  class FieldWithType:
      field: str
      type: "Type"
  
  
  @dataclass(frozen=True)
  class VarWithType:
      var: str
      type: "Type"
  
  
  @dataclass(frozen=True)
  class TypeVarWithKind:
      var: str
      kind: "Kind"
  
      def __str__(self):
          return f"{self.var} : {self.kind}"
  
      def __repr__(self):
          return f"TypeVarWithKind({self})"
  
  
  @dataclass(frozen=True)
  class FieldWithExpr:
      field: str
      expr: "Expr"
  
      def __repr__(self):
          return f"FieldWithExpr({self.field}={self.expr})"
  
  
  @dataclass(frozen=True)
  class Binding:
      binder: "VarWithType"
      bound: "Expr"
  
  
  class Kind:
      __slots__ = "_Sum_name", "_Sum_value"
      _Sum_name: str
      _Sum_value: Any
  
      class Arrow:
          params: "Sequence[Kind]"
          result: "Kind"
  
          def __init__(self, params: "Sequence[Kind]", result: "Kind"):
              self.params = params
              self.result = result
  
      def __init__(
          self,
          star: "Union[Unit, _Missing]" = MISSING,
          arrow: "Union[Arrow, _Missing]" = MISSING,
          nat: "Union[Unit, _Missing]" = MISSING,
      ):
          if star is not MISSING:
              object.__setattr__(self, "_Sum_name", "star")
              object.__setattr__(self, "_Sum_value", star)
          elif arrow is not MISSING:
              object.__setattr__(self, "_Sum_name", "arrow")
              object.__setattr__(self, "_Sum_value", arrow)
          elif nat is not MISSING:
              object.__setattr__(self, "_Sum_name", "nat")
              object.__setattr__(self, "_Sum_value", nat)
          else:
              raise ValueError("at least one must be specified")
  
      @property
      def star(self) -> "Optional[Unit]":
          return self._Sum_value if self._Sum_name == "star" else None
  
      @property
      def arrow(self) -> "Optional[Arrow]":
          return self._Sum_value if self._Sum_name == "arrow" else None
  
      @property
      def nat(self) -> "Optional[Unit]":
          return self._Sum_value if self._Sum_name == "nat" else None
  
      def __repr__(self):
          if self._Sum_name == "star":
              return "*"
          else:
              arrow = self.arrow
              params = [repr(i) for i in (*arrow.params, arrow.result)]
              return " -> ".join((f"({i})" if " " in i else i for i in params))
  
  
  class PrimType(_IntEnum):
      UNIT = 0
      BOOL = 1
      INT64 = 2
      DECIMAL = 3
      CHAR = 4
      TEXT = 5
      TIMESTAMP = 6
      RELTIME = 7
      PARTY = 8
      LIST = 9
      UPDATE = 10
      SCENARIO = 11
      DATE = 12
      CONTRACT_ID = 13
      OPTIONAL = 14
      ARROW = 15
      TEXTMAP = 16
      NUMERIC = 17
      ANY = 18
      TYPE_REP = 19
      GENMAP = 20
      BIGNUMERIC = 21
      ROUNDING_MODE = 22
      ANY_EXCEPTION = 23
  
  
  # noinspection PyShadowingBuiltins
  class Type:
      @dataclass(frozen=True)
      class Var:
          var: "str"
          args: "Sequence[Type]"
  
      class Con:
          tycon: "TypeConName"
          args: "Sequence[Type]"
  
          def __init__(self, tycon: "TypeConName", args: "Sequence[Type]"):
              self.tycon = tycon
              self.args = tuple(args)
  
          def __repr__(self):
              return f"Type.Con(tycon={self.tycon}, args={self.args})"
  
      @dataclass(frozen=True)
      class Syn:
          tysyn: "TypeSynName"
          args: "Sequence[Type]"
  
      class Prim:
          prim: "PrimType"
          args: "Sequence[Type]"
  
          def __init__(self, prim: "PrimType", args: "Sequence[Type]"):
              self.prim = prim
              self.args = tuple(args)
  
          def __repr__(self):
              return f"Type.Prim(prim={self.prim!r}, args={self.args!r})"
  
      class Fun:
          params: "Sequence[Type]"
          result: "Type"
  
          def __init__(self, params: "Sequence[Type]", result: "Type"):
              self.params = params
              self.result = result
  
      class Forall:
          vars: "Sequence[TypeVarWithKind]"
          body: "Type"
  
          # noinspection PyShadowingBuiltins
          def __init__(self, vars: "Sequence[TypeVarWithKind]", body: "Type"):
              self.vars = vars
              self.body = body
  
      class Struct:
          fields: "Sequence[FieldWithType]"
  
          def __init__(self, fields: "Sequence[FieldWithType]"):
              self.fields = tuple(fields)
  
      __slots__ = "_Sum_name", "_Sum_value"
      _Sum_name: str
      _Sum_value: Any
  
      def __init__(
          self,
          var: "Union[Type.Var, _Missing]" = MISSING,
          con: "Union[Type.Con, _Missing]" = MISSING,
          prim: "Union[Type.Prim, _Missing]" = MISSING,
          forall: "Union[Type.Forall, _Missing]" = MISSING,
          struct: "Union[Type.Struct, _Missing]" = MISSING,
          nat: "Union[int, _Missing]" = MISSING,
          syn: "Union[Type.Syn, _Missing]" = MISSING,
      ):
          if var is not MISSING:
              object.__setattr__(self, "_Sum_name", "var")
              object.__setattr__(self, "_Sum_value", var)
          elif con is not MISSING:
              object.__setattr__(self, "_Sum_name", "con")
              object.__setattr__(self, "_Sum_value", con)
          elif prim is not MISSING:
              object.__setattr__(self, "_Sum_name", "prim")
              object.__setattr__(self, "_Sum_value", prim)
          elif forall is not MISSING:
              object.__setattr__(self, "_Sum_name", "forall")
              object.__setattr__(self, "_Sum_value", forall)
          elif struct is not MISSING:
              object.__setattr__(self, "_Sum_name", "struct")
              object.__setattr__(self, "_Sum_value", struct)
          elif nat is not MISSING:
              object.__setattr__(self, "_Sum_name", "nat")
              object.__setattr__(self, "_Sum_value", nat)
          elif syn is not MISSING:
              object.__setattr__(self, "_Sum_name", "syn")
              object.__setattr__(self, "_Sum_value", syn)
          else:
              raise ValueError("unknown sum type")
  
      @property
      def var(self) -> "Type.Var":
          return self._Sum_value if self._Sum_name == "var" else None
  
      @property
      def con(self) -> "Type.Con":
          return self._Sum_value if self._Sum_name == "con" else None
  
      @property
      def prim(self) -> "Type.Prim":
          return self._Sum_value if self._Sum_name == "prim" else None
  
      @property
      def forall(self) -> "Type.Forall":
          return self._Sum_value if self._Sum_name == "forall" else None
  
      @property
      def struct(self) -> "Type.Struct":
          return self._Sum_value if self._Sum_name == "struct" else None
  
      @property
      def nat(self) -> int:
          return self._Sum_value if self._Sum_name == "nat" else None
  
      @property
      def syn(self) -> "Type.Syn":
          return self._Sum_value if self._Sum_name == "syn" else None
  
      # noinspection PyPep8Naming
      def Sum_match(
          self,
          var: "Callable[[Type.Var], T]",
          con: "Callable[[Type.Con], T]",
          prim: "Callable[[Type.Prim], T]",
          forall: "Callable[[Type.Forall], T]",
          struct: "Callable[[Type.Struct], T]",
          nat: "Callable[[int], T]",
          syn: "Callable[[Type.Syn], T]",
      ) -> "T":
          if self._Sum_name == "var":
              return var(self._Sum_value)
          elif self._Sum_name == "con":
              return con(self._Sum_value)
          elif self._Sum_name == "prim":
              return prim(self._Sum_value)
          elif self._Sum_name == "forall":
              return forall(self._Sum_value)
          elif self._Sum_name == "struct":
              return struct(self._Sum_value)
          elif self._Sum_name == "nat":
              return nat(self._Sum_value)
          elif self._Sum_name == "syn":
              return syn(self._Sum_value)
          else:
              raise Exception(f"invalid _Sum_name value: {self._Sum_name}")
  
      def __setattr__(self, key, value):
          raise Exception("Type is a read-only object")
  
      def __str__(self):
          """
          Return a str representation of this :class:`Type`. This is intentionally made to look more
          similar to DAML syntax.
          """
          # This import is done inside the function instead of outside to avoid circular references
          from ..pretty import DAML_PRETTY_PRINTER
  
          return DAML_PRETTY_PRINTER.visit_type(self)
  
      def __repr__(self):
          """
          Return a str representation of this :class:`Type`. This is intentionally made to look more
          similar to DAML syntax.
          """
          # This import is done inside the function instead of outside to avoid circular references
          from ..pretty import DAML_PRETTY_PRINTER
  
          # If rendering the type fails, print _something_; crashing in a repr(...) could be quite
          # obnoxious for users of this library
          # noinspection PyBroadException
          try:
              return f"Type({DAML_PRETTY_PRINTER.visit_type(self)})"
          except:  # noqa
              return "Type(...)"
  
  
  class PrimLit:
      __slots__ = "_Sum_name", "_Sum_value"
      _Sum_name: str
      _Sum_value: Any
  
      class RoundingMode(_IntEnum):
          UP = 0
          DOWN = 1
          CEILING = 2
          FLOOR = 3
          HALF_UP = 4
          HALF_DOWN = 5
          HALF_EVEN = 6
          UNNECESSARY = 7
  
      def __init__(
          self,
          int64: "Union[int, _Missing]" = MISSING,
          decimal: "Union[str, _Missing]" = MISSING,
          text: "Union[str, _Missing]" = MISSING,
          timestamp: "Union[float, _Missing]" = MISSING,
          party: "Union[str, _Missing]" = MISSING,
          date: "Union[int, _Missing]" = MISSING,
          numeric: "Union[str, _Missing]" = MISSING,
          rounding_mode: "Union[RoundingMode, _Missing]" = MISSING,
      ):
          if int64 is not MISSING:
              object.__setattr__(self, "_Sum_name", "int64")
              object.__setattr__(self, "_Sum_value", int64)
          elif decimal is not MISSING:
              object.__setattr__(self, "_Sum_name", "decimal")
              object.__setattr__(self, "_Sum_value", decimal)
          elif text is not MISSING:
              object.__setattr__(self, "_Sum_name", "text")
              object.__setattr__(self, "_Sum_value", text)
          elif timestamp is not MISSING:
              object.__setattr__(self, "_Sum_name", "timestamp")
              object.__setattr__(self, "_Sum_value", timestamp)
          elif party is not MISSING:
              object.__setattr__(self, "_Sum_name", "party")
              object.__setattr__(self, "_Sum_value", party)
          elif date is not MISSING:
              object.__setattr__(self, "_Sum_name", "date")
              object.__setattr__(self, "_Sum_value", date)
          elif numeric is not MISSING:
              object.__setattr__(self, "_Sum_name", "numeric")
              object.__setattr__(self, "_Sum_value", numeric)
          elif numeric is not MISSING:
              object.__setattr__(self, "_Sum_name", "rounding_mode")
              object.__setattr__(self, "_Sum_value", rounding_mode)
  
      @property
      def int64(self) -> "Optional[int]":
          return self._Sum_value if self._Sum_name == "int64" else None
  
      @property
      def decimal(self) -> "Optional[str]":
          """
          our decimal type would fit in an int128, but sadly Protobuf does not
          have one. so, string it is. note that we can't store the whole and
          decimal part in two numbers either, because 10^28 > 2^63.
          """
          return self._Sum_value if self._Sum_name == "decimal" else None
  
      @property
      def text(self) -> "Optional[str]":
          return self._Sum_value if self._Sum_name == "text" else None
  
      @property
      def timestamp(self) -> "Optional[float]":
          """
          microseconds since the UNIX epoch. can go backwards. fixed
          since the vast majority of values will be greater than
          2^28, since currently the number of microseconds since the
          epoch is greater than that. Range: 0001-01-01T00:00:00Z to
          9999-12-31T23:59:59.999999Z, so that we can convert to/from
          https://www.ietf.org/rfc/rfc3339.txt
          """
          return self._Sum_value if self._Sum_name == "timestamp" else None
  
      @property
      def party(self) -> "Optional[str]":
          return self._Sum_value if self._Sum_name == "party" else None
  
      @property
      def date(self) -> "Optional[int]":
          """
          days since the unix epoch. can go backwards. limited from
          0001-01-01 to 9999-12-31, also to be compatible with
          https://www.ietf.org/rfc/rfc3339.txt
          """
          return self._Sum_value if self._Sum_name == "date" else None
  
      @property
      def numeric(self) -> "Optional[str]":
          """
          Serialization of number with precision 38 and scale between 0 and 37
  
          Must be a string that matched
              `-?([0-1]\\d*|0)\\.(\\d*)
  
          The number of decimal digits indicate the scale of the number.
          """
          return self._Sum_value if self._Sum_name == "numeric" else None
  
      @property
      def rounding_mode(self) -> "Optional[RoundingMode]":
          """
          Rounding mode for arithmetic operation
  
          Available in versions >= 1.13
          """
          return self._Sum_value if self._Sum_name == "rounding_mode" else None
  
  
  # noinspection PyShadowingBuiltins
  class Location:
      class Range:
          __slots__ = ("start_line", "start_col", "end_line", "end_col")
  
          def __init__(
              self, start_line: int = 0, start_col: int = 0, end_line: int = 0, end_col: int = 0
          ):
              object.__setattr__(self, "start_line", start_line)
              object.__setattr__(self, "start_col", start_col)
              object.__setattr__(self, "end_line", end_line)
              object.__setattr__(self, "end_col", end_col)
  
          start_line: int
          start_col: int
          end_line: int
          end_col: int
  
      module: "ModuleRef"
      range: "Range"
  
      def __init__(
          self,
          module: "Union[ModuleRef, _Missing]" = MISSING,
          range: "Union[Range, _Missing]" = MISSING,
      ):
          object.__setattr__(self, "module", module)
          object.__setattr__(self, "range", range)
  
  
  # noinspection PyShadowingBuiltins
  class Expr:
      class RecCon:
          tycon: "Type.Con"
          fields: "Sequence[FieldWithExpr]"
  
          def __init__(self, tycon: "Type.Con", fields: "Sequence[FieldWithExpr]"):
              self.tycon = tycon
              self.fields = tuple(fields)
  
          def __repr__(self):
              return f"Expr.RecCon(tycon={self.tycon}, fields={self.fields})"
  
      @dataclass(frozen=True)
      class RecProj:
          tycon: "Type.Con"  # Always fully applied string
          field: str
          record: "Expr"
  
          def __repr__(self):
              with StringIO() as buf:
                  buf.write("Expr.RecProj(")
                  if self.tycon is not None:
                      buf.write("tycon=")
                      buf.write(repr(self.tycon))
                      buf.write(", ")
                  buf.write("record=")
                  buf.write(repr(self.record))
                  buf.write(", field=")
                  buf.write(repr(self.field))
                  buf.write(")")
                  return buf.getvalue()
  
      # Set `field` in `record` to `update`.
      @dataclass(frozen=True)
      class RecUpd:
          tycon: "Type.Con"
          field: str
          record: "Expr"
          update: "Expr"
  
      class VariantCon:
          tycon: "Type.Con"  # Always fully applied
          variant_con: str
          variant_arg: "Expr"
  
          def __init__(self, tycon: "Type.Con", variant_con: str, variant_arg: "Expr"):
              self.tycon = tycon
              self.variant_con = variant_con
              self.variant_arg = variant_arg
  
      @dataclass(frozen=True)
      class EnumCon:
          tycon: "TypeConName"  # Always fully applied
          enum_con: str
  
      @dataclass(frozen=True)
      class StructCon:
          fields: "Sequence[FieldWithExpr]"  # length > 0
  
      @dataclass(frozen=True)
      class StructProj:
          field: str
          struct: "Expr"
  
      # Set `field` in `tuple` to `update`.
      @dataclass(frozen=True)
      class StructUpd:
          field: str
          struct: "Expr"
          update: "Expr"
  
      @dataclass(frozen=True)
      class App:
          fun: "Expr"
          args: "Sequence[Expr]"  # length > 0
  
      class TyApp:
          expr: "Expr"
          types: "Sequence[Type]"  # length > 0
  
          def __init__(self, expr: "Expr", types: "Sequence[Type]"):
              from ..util.typing import safe_cast
  
              object.__setattr__(self, "expr", safe_cast(Expr, expr))
              object.__setattr__(self, "types", tuple(types))
  
          def __repr__(self):
              return f"Expr.TyApp(types={self.types}, expr={self.expr})"
  
      class Abs:
          param: "Sequence[VarWithType]"  # length > 0
          body: "Expr"
  
          def __init__(self, param: "Sequence[VarWithType]", body: "Expr"):
              from ..util.typing import safe_cast
  
              object.__setattr__(self, "param", param)
              object.__setattr__(self, "body", safe_cast(Expr, body))
  
          def __repr__(self):
              with StringIO() as buf:
                  buf.write("Expr.Abs(𝜆 ")
                  buf.write(" ".join(vwt.var for vwt in self.param))
                  buf.write(" . ")
                  buf.write(repr(self.body))
                  buf.write(")")
                  return buf.getvalue()
  
      @dataclass(frozen=True)
      class TyAbs:
          param: "Sequence[TypeVarWithKind]"
          body: "Expr"
  
      @dataclass(frozen=True)
      class Nil:
          type: "Type"
  
          __slots__ = ("type",)
  
          # noinspection PyShadowingBuiltins
          def __init__(self, type: "Type"):
              object.__setattr__(self, "type", type)
  
          def __repr__(self):
              return "Nil()"
  
      @dataclass(frozen=True)
      class Cons:
          type: "Type"
          front: "Sequence[Expr]"  # length > 0
          tail: "Expr"
  
          def __repr__(self):
              with StringIO() as buf:
                  buf.write("Expr.Cons(front=")
                  buf.write(repr(list(self.front)))
                  buf.write(", tail=")
                  buf.write(repr(self.tail))
                  buf.write(")")
                  return buf.getvalue()
  
      # noinspection PyPep8Naming
      class OptionalNone:
          type: "Type"
  
          # noinspection PyShadowingBuiltins
          def __init__(self, type: "Type"):
              self.type = type
  
          def __repr__(self):
              return f"Expr.None(: {self.type})"
  
      class OptionalSome:
          type: "Type"
          body: "Expr"
  
          # noinspection PyShadowingBuiltins
          def __init__(self, type: "Type", body: "Expr"):
              self.type = type
              self.body = body
  
          def __repr__(self):
              return f"Expr.Some({self.body!r} : {self.type})"
  
      class ToAny:
          type: "Type"
          expr: "Expr"
  
          # noinspection PyShadowingBuiltins
          def __init__(self, type: "Type", expr: "Expr"):
              self.type = type
              self.expr = expr
  
      class FromAny:
          type: "Type"
          expr: "Expr"
  
          # noinspection PyShadowingBuiltins
          def __init__(self, type: "Type", expr: "Expr"):
              self.type = type
              self.expr = expr
  
      class ToAnyException:
          type: "Type"
          expr: "Expr"
  
          # noinspection PyShadowingBuiltins
          def __init__(self, type: "Type", expr: "Expr"):
              self.type = type
              self.expr = expr
  
      class FromAnyException:
          type: "Type"
          expr: "Expr"
  
          # noinspection PyShadowingBuiltins
          def __init__(self, type: "Type", expr: "Expr"):
              self.type = type
              self.expr = expr
  
      class ToTextTemplateId:
          type: "Type"
  
          # noinspection PyShadowingBuiltins
          def __init__(self, type: "Type"):
              self.type = type
  
      class Throw:
          return_type: "Type"
          exception_type: "Type"
          exception_expr: "Expr"
  
          def __init__(self, return_type: "Type", exception_type: "Type", exception_expr: "Expr"):
              self.return_type = return_type
              self.exception_type = exception_type
              self.exception_expr = exception_expr
  
      class Experimental:
          name: str
          type: "Type"
  
          # noinspection PyShadowingBuiltins
          def __init__(self, name: str, type: "Type"):
              self.name = name
              self.type = type
  
      __slots__ = "location", "_Sum_name", "_Sum_value"
      location: Location
      _Sum_name: str
      _Sum_value: Any
  
      def __init__(
          self,
          *,
          var: "Union[str, _Missing]" = MISSING,
          val: "Union[ValName, _Missing]" = MISSING,
          builtin: "Union[BuiltinFunction, _Missing]" = MISSING,
          prim_con: "Union[PrimCon, _Missing]" = MISSING,
          prim_lit: "Union[PrimLit, _Missing]" = MISSING,
          rec_con: "Union[RecCon, _Missing]" = MISSING,
          rec_proj: "Union[RecProj, _Missing]" = MISSING,
          rec_upd: "Union[RecUpd, _Missing]" = MISSING,
          variant_con: "Union[VariantCon, _Missing]" = MISSING,
          enum_con: "Union[EnumCon, _Missing]" = MISSING,
          struct_con: "Union[StructCon, _Missing]" = MISSING,
          struct_proj: "Union[StructProj, _Missing]" = MISSING,
          struct_upd: "Union[StructUpd, _Missing]" = MISSING,
          app: "Union[App, _Missing]" = MISSING,
          ty_app: "Union[TyApp, _Missing]" = MISSING,
          abs: "Union[Abs, _Missing]" = MISSING,
          ty_abs: "Union[TyAbs, _Missing]" = MISSING,
          case: "Union[Case, _Missing]" = MISSING,
          let: "Union[Block, _Missing]" = MISSING,
          nil: "Union[Nil, _Missing]" = MISSING,
          cons: "Union[Cons, _Missing]" = MISSING,
          update: "Union[Update, _Missing]" = MISSING,
          scenario: "Union[Scenario, _Missing]" = MISSING,
          optional_none: "Union[OptionalNone, _Missing]" = MISSING,
          optional_some: "Union[OptionalSome, _Missing]" = MISSING,
          to_any: "Union[ToAny, _Missing]" = MISSING,
          from_any: "Union[FromAny, _Missing]" = MISSING,
          type_rep: "Union[Type, _Missing]" = MISSING,
          to_any_exception: "Union[Expr.ToAnyException, _Missing]" = MISSING,
          from_any_exception: "Union[Expr.FromAnyException, _Missing]" = MISSING,
          throw: "Union[Expr.Throw, _Missing]" = MISSING,
          experimental: "Union[Expr.Experimental, _Missing]" = MISSING,
          location: "Optional[Location]" = None,
      ):
          object.__setattr__(self, "location", location)
          if var is not MISSING:
              object.__setattr__(self, "_Sum_name", "var")
              object.__setattr__(self, "_Sum_value", var)
          elif val is not MISSING:
              object.__setattr__(self, "_Sum_name", "val")
              object.__setattr__(self, "_Sum_value", val)
          elif builtin is not MISSING:
              object.__setattr__(self, "_Sum_name", "builtin")
              object.__setattr__(self, "_Sum_value", builtin)
          elif prim_con is not MISSING:
              object.__setattr__(self, "_Sum_name", "prim_con")
              object.__setattr__(self, "_Sum_value", prim_con)
          elif prim_lit is not MISSING:
              object.__setattr__(self, "_Sum_name", "prim_lit")
              object.__setattr__(self, "_Sum_value", prim_lit)
          elif rec_con is not MISSING:
              object.__setattr__(self, "_Sum_name", "rec_con")
              object.__setattr__(self, "_Sum_value", rec_con)
          elif rec_proj is not MISSING:
              object.__setattr__(self, "_Sum_name", "rec_proj")
              object.__setattr__(self, "_Sum_value", rec_proj)
          elif variant_con is not MISSING:
              object.__setattr__(self, "_Sum_name", "variant_con")
              object.__setattr__(self, "_Sum_value", variant_con)
          elif enum_con is not MISSING:
              object.__setattr__(self, "_Sum_name", "enum_con")
              object.__setattr__(self, "_Sum_value", enum_con)
          elif struct_con is not MISSING:
              object.__setattr__(self, "_Sum_name", "struct_con")
              object.__setattr__(self, "_Sum_value", struct_con)
          elif struct_proj is not MISSING:
              object.__setattr__(self, "_Sum_name", "struct_proj")
              object.__setattr__(self, "_Sum_value", struct_proj)
          elif app is not MISSING:
              object.__setattr__(self, "_Sum_name", "app")
              object.__setattr__(self, "_Sum_value", app)
          elif ty_app is not MISSING:
              object.__setattr__(self, "_Sum_name", "ty_app")
              object.__setattr__(self, "_Sum_value", ty_app)
          elif abs is not MISSING:
              object.__setattr__(self, "_Sum_name", "abs")
              object.__setattr__(self, "_Sum_value", abs)
          elif ty_abs is not MISSING:
              object.__setattr__(self, "_Sum_name", "ty_abs")
              object.__setattr__(self, "_Sum_value", ty_abs)
          elif case is not MISSING:
              object.__setattr__(self, "_Sum_name", "case")
              object.__setattr__(self, "_Sum_value", case)
          elif let is not MISSING:
              object.__setattr__(self, "_Sum_name", "let")
              object.__setattr__(self, "_Sum_value", let)
          elif nil is not MISSING:
              object.__setattr__(self, "_Sum_name", "nil")
              object.__setattr__(self, "_Sum_value", nil)
          elif cons is not MISSING:
              object.__setattr__(self, "_Sum_name", "cons")
              object.__setattr__(self, "_Sum_value", cons)
          elif update is not MISSING:
              object.__setattr__(self, "_Sum_name", "update")
              object.__setattr__(self, "_Sum_value", update)
          elif scenario is not MISSING:
              object.__setattr__(self, "_Sum_name", "scenario")
              object.__setattr__(self, "_Sum_value", scenario)
          elif rec_upd is not MISSING:
              object.__setattr__(self, "_Sum_name", "rec_upd")
              object.__setattr__(self, "_Sum_value", rec_upd)
          elif struct_upd is not MISSING:
              object.__setattr__(self, "_Sum_name", "struct_upd")
              object.__setattr__(self, "_Sum_value", struct_upd)
          elif optional_none is not MISSING:
              object.__setattr__(self, "_Sum_name", "optional_none")
              object.__setattr__(self, "_Sum_value", optional_none)
          elif optional_some is not MISSING:
              object.__setattr__(self, "_Sum_name", "optional_some")
              object.__setattr__(self, "_Sum_value", optional_some)
          elif to_any is not MISSING:
              object.__setattr__(self, "_Sum_name", "to_any")
              object.__setattr__(self, "_Sum_value", to_any)
          elif from_any is not MISSING:
              object.__setattr__(self, "_Sum_name", "from_any")
              object.__setattr__(self, "_Sum_value", from_any)
          elif to_any_exception is not MISSING:
              object.__setattr__(self, "_Sum_name", "to_any_exception")
              object.__setattr__(self, "_Sum_value", to_any_exception)
          elif from_any_exception is not MISSING:
              object.__setattr__(self, "_Sum_name", "from_any_exception")
              object.__setattr__(self, "_Sum_value", from_any_exception)
          elif type_rep is not MISSING:
              object.__setattr__(self, "_Sum_name", "type_rep")
              object.__setattr__(self, "_Sum_value", type_rep)
          elif experimental is not MISSING:
              object.__setattr__(self, "_Sum_name", "experimental")
              object.__setattr__(self, "_Sum_value", experimental)
          elif throw is not MISSING:
              object.__setattr__(self, "_Sum_name", "throw")
              object.__setattr__(self, "_Sum_value", throw)
          else:
              raise ValueError(f"At least one valid Sum value must be supplied!")
  
      def __setattr__(self, key, value):
          raise Exception("Expr is read-only")
  
      @property
      def var(self) -> "Optional[str]":
          return self._Sum_value if self._Sum_name == "var" else None
  
      @property
      def val(self) -> "Optional[ValName]":
          return self._Sum_value if self._Sum_name == "val" else None
  
      @property
      def builtin(self) -> "Optional[BuiltinFunction]":
          return self._Sum_value if self._Sum_name == "builtin" else None
  
      @property
      def prim_con(self) -> "Optional[PrimCon]":
          return self._Sum_value if self._Sum_name == "prim_con" else None
  
      @property
      def prim_lit(self) -> "Optional[PrimLit]":
          return self._Sum_value if self._Sum_name == "prim_lit" else None
  
      @property
      def rec_con(self) -> "Optional[Expr.RecCon]":
          return self._Sum_value if self._Sum_name == "rec_con" else None
  
      @property
      def rec_proj(self) -> "Optional[RecProj]":
          return self._Sum_value if self._Sum_name == "rec_proj" else None
  
      @property
      def variant_con(self) -> "Optional[VariantCon]":
          return self._Sum_value if self._Sum_name == "variant_con" else None
  
      @property
      def enum_con(self) -> "Optional[EnumCon]":
          return self._Sum_value if self._Sum_name == "enum_con" else None
  
      @property
      def struct_con(self) -> "Optional[StructCon]":
          return self._Sum_value if self._Sum_name == "struct_con" else None
  
      @property
      def struct_proj(self) -> "Optional[StructProj]":
          return self._Sum_value if self._Sum_name == "struct_proj" else None
  
      @property
      def app(self) -> "Optional[App]":
          return self._Sum_value if self._Sum_name == "app" else None
  
      @property
      def ty_app(self) -> "Optional[Expr.TyApp]":
          return self._Sum_value if self._Sum_name == "ty_app" else None
  
      @property
      def abs(self) -> "Optional[Expr.Abs]":
          return self._Sum_value if self._Sum_name == "abs" else None
  
      @property
      def ty_abs(self) -> "Optional[Expr.TyAbs]":
          return self._Sum_value if self._Sum_name == "ty_abs" else None
  
      @property
      def case(self) -> "Optional[Case]":
          return self._Sum_value if self._Sum_name == "case" else None
  
      @property
      def let(self) -> "Optional[Block]":
          return self._Sum_value if self._Sum_name == "let" else None
  
      @property
      def nil(self) -> "Optional[Expr.Nil]":
          return self._Sum_value if self._Sum_name == "nil" else None
  
      @property
      def cons(self) -> "Optional[Expr.Cons]":
          return self._Sum_value if self._Sum_name == "cons" else None
  
      @property
      def update(self) -> "Optional[Update]":
          return self._Sum_value if self._Sum_name == "update" else None
  
      @property
      def scenario(self) -> "Optional[Scenario]":
          return self._Sum_value if self._Sum_name == "scenario" else None
  
      @property
      def rec_upd(self) -> "Optional[RecUpd]":
          return self._Sum_value if self._Sum_name == "rec_upd" else None
  
      @property
      def struct_upd(self) -> "Optional[StructUpd]":
          return self._Sum_value if self._Sum_name == "struct_upd" else None
  
      @property
      def optional_none(self) -> "Optional[OptionalNone]":
          return self._Sum_value if self._Sum_name == "optional_none" else None
  
      @property
      def optional_some(self) -> "Optional[OptionalSome]":
          return self._Sum_value if self._Sum_name == "optional_some" else None
  
      @property
      def to_any(self) -> "Optional[ToAny]":
          return self._Sum_value if self._Sum_name == "to_any" else None
  
      @property
      def from_any(self) -> "Optional[FromAny]":
          return self._Sum_value if self._Sum_name == "from_any" else None
  
      @property
      def to_text_template_id(self) -> "Optional[ToTextTemplateId]":
          return self._Sum_value if self._Sum_name == "to_text_template_id" else None
  
      @property
      def type_rep(self) -> "Optional[Type]":
          return self._Sum_value if self._Sum_name == "type_rep" else None
  
      @property
      def throw(self) -> "Optional[Throw]":
          return self._Sum_value if self._Sum_name == "throw" else None
  
      # noinspection PyPep8Naming
      def Sum_match(
          self,
          var: "_typing.Callable[[str], _T]",
          val: "_typing.Callable[[ValName], _T]",
          builtin: "_typing.Callable[[BuiltinFunction], _T]",
          prim_con: "_typing.Callable[[PrimCon], _T]",
          prim_lit: "_typing.Callable[[PrimLit], _T]",
          rec_con: "_typing.Callable[[Expr.RecCon], _T]",
          rec_proj: "_typing.Callable[[Expr.RecProj], _T]",
          rec_upd: "_typing.Callable[[Expr.RecUpd], _T]",
          variant_con: "_typing.Callable[[Expr.VariantCon], _T]",
          enum_con: "_typing.Callable[[Expr.EnumCon], _T]",
          struct_con: "_typing.Callable[[Expr.StructCon], _T]",
          struct_proj: "_typing.Callable[[Expr.StructProj], _T]",
          struct_upd: "_typing.Callable[[Expr.StructUpd], _T]",
          app: "_typing.Callable[[Expr.App], _T]",
          ty_app: "_typing.Callable[[Expr.TyApp], _T]",
          abs: "_typing.Callable[[Expr.Abs], _T]",
          ty_abs: "_typing.Callable[[Expr.TyAbs], _T]",
          case: "_typing.Callable[[Case], _T]",
          let: "_typing.Callable[[Block], _T]",
          nil: "_typing.Callable[[Expr.Nil], _T]",
          cons: "_typing.Callable[[Expr.Cons], _T]",
          update: "_typing.Callable[[Update], _T]",
          scenario: "_typing.Callable[[Scenario], _T]",
          optional_none: "_typing.Callable[[Expr.OptionalNone], _T]",
          optional_some: "_typing.Callable[[Expr.OptionalSome], _T]",
          to_any: "_typing.Callable[[Expr.ToAny], _T]",
          from_any: "_typing.Callable[[Expr.FromAny], _T]",
          type_rep: "_typing.Callable[[Type], _T]",
          to_any_exception: "_typing.Callable[[Expr.ToAnyException], _T]",
          from_any_exception: "_typing.Callable[[Expr.FromAnyException], _T]",
          throw: "_typing.Callable[[Expr.Throw], _T]",
          experimental: "_typing.Callable[[Expr.Experimental], _T]",
      ) -> "T":
          if self._Sum_name == "var":
              return var(self.var)  # type: ignore
          elif self._Sum_name == "val":
              return val(self.val)  # type: ignore
          elif self._Sum_name == "builtin":
              return builtin(self.builtin)  # type: ignore
          elif self._Sum_name == "prim_con":
              return prim_con(self.prim_con)  # type: ignore
          elif self._Sum_name == "prim_lit":
              return prim_lit(self.prim_lit)  # type: ignore
          elif self._Sum_name == "rec_con":
              return rec_con(self.rec_con)  # type: ignore
          elif self._Sum_name == "rec_proj":
              return rec_proj(self.rec_proj)  # type: ignore
          elif self._Sum_name == "variant_con":
              return variant_con(self.variant_con)  # type: ignore
          elif self._Sum_name == "enum_con":
              return enum_con(self.enum_con)  # type: ignore
          elif self._Sum_name == "struct_con":
              return struct_con(self.struct_con)  # type: ignore
          elif self._Sum_name == "struct_proj":
              return struct_proj(self.struct_proj)  # type: ignore
          elif self._Sum_name == "app":
              return app(self.app)  # type: ignore
          elif self._Sum_name == "ty_app":
              return ty_app(self.ty_app)  # type: ignore
          elif self._Sum_name == "abs":
              return abs(self.abs)  # type: ignore
          elif self._Sum_name == "ty_abs":
              return ty_abs(self.ty_abs)  # type: ignore
          elif self._Sum_name == "case":
              return case(self.case)  # type: ignore
          elif self._Sum_name == "let":
              return let(self.let)  # type: ignore
          elif self._Sum_name == "nil":
              return nil(self.nil)  # type: ignore
          elif self._Sum_name == "cons":
              return cons(self.cons)  # type: ignore
          elif self._Sum_name == "update":
              return update(self.update)  # type: ignore
          elif self._Sum_name == "scenario":
              return scenario(self.scenario)  # type: ignore
          elif self._Sum_name == "rec_upd":
              return rec_upd(self.rec_upd)  # type: ignore
          elif self._Sum_name == "struct_upd":
              return struct_upd(self.struct_upd)  # type: ignore
          elif self._Sum_name == "optional_none":
              return optional_none(self.optional_none)  # type: ignore
          elif self._Sum_name == "optional_some":
              return optional_some(self.optional_some)  # type: ignore
          elif self._Sum_name == "to_any":
              return to_any(self.to_any)  # type: ignore
          elif self._Sum_name == "from_any":
              return from_any(self.from_any)  # type: ignore
          elif self._Sum_name == "to_any_exception":
              return to_any_exception(self.to_any_exception)  # type: ignore
          elif self._Sum_name == "from_any_exception":
              return from_any_exception(self.from_any_exception)  # type: ignore
          elif self._Sum_name == "to_text_template_id":
              return to_text_template_id(self.to_text_template_id)  # type: ignore
          elif self._Sum_name == "type_rep":
              return type_rep(self.type_rep)  # type: ignore
          elif self._Sum_name == "throw":
              return throw(self.throw)  # type: ignore
          elif self._Sum_name == "experimental":
              return experimental(self.experimental)  # type: ignore
          else:
              raise Exception
  
      def __repr__(self):
          return f"Expr({self._Sum_name}={self._Sum_value!r})"
  
  
  class CaseAlt:
      class Variant:
          con: "TypeConName"
          variant: str
          binder: str
  
          def __init__(self, con, variant, binder):
              self.con = con
              self.variant = variant
              self.binder = binder
  
      @dataclass(frozen=True)
      class Enum:
          con: TypeConName
          constructor: str
  
      @dataclass(frozen=True)
      class Cons:
          var_head: str
          var_tail: str
  
      @dataclass(frozen=True)
      class OptionalSome:
          var_body: str
  
      __slots__ = "body", "_Sum_name", "_Sum_value"
      body: "Expr"
      _Sum_name: str
      _Sum_value: Any
  
      def __init__(
          self,
          default: "Union[Unit, _Missing]" = MISSING,
          variant: "Union[Variant, _Missing]" = MISSING,
          prim_con: "Union[PrimCon, _Missing]" = MISSING,
          nil: "Union[Unit, _Missing]" = MISSING,
          cons: "Union[Cons, _Missing]" = MISSING,
          optional_none: "Union[Unit, _Missing]" = MISSING,
          optional_some: "Union[OptionalSome, _Missing]" = MISSING,
          body: "Union[Expr, _Missing]" = MISSING,
          enum: "Union[Enum, _Missing]" = MISSING,
      ):
          object.__setattr__(self, "body", body)
          if default is not MISSING:
              object.__setattr__(self, "_Sum_name", "default")
              object.__setattr__(self, "_Sum_value", default)
          elif variant is not MISSING:
              object.__setattr__(self, "_Sum_name", "variant")
              object.__setattr__(self, "_Sum_value", variant)
          elif prim_con is not MISSING:
              object.__setattr__(self, "_Sum_name", "prim_con")
              object.__setattr__(self, "_Sum_value", prim_con)
          elif nil is not MISSING:
              object.__setattr__(self, "_Sum_name", "nil")
              object.__setattr__(self, "_Sum_value", nil)
          elif cons is not MISSING:
              object.__setattr__(self, "_Sum_name", "cons")
              object.__setattr__(self, "_Sum_value", cons)
          elif optional_none is not MISSING:
              object.__setattr__(self, "_Sum_name", "optional_none")
              object.__setattr__(self, "_Sum_value", optional_none)
          elif optional_some is not MISSING:
              object.__setattr__(self, "_Sum_name", "optional_some")
              object.__setattr__(self, "_Sum_value", optional_some)
          elif enum is not MISSING:
              object.__setattr__(self, "_Sum_name", "enum")
              object.__setattr__(self, "_Sum_value", enum)
  
      @property
      def default(self) -> "Optional[Unit]":
          return self._Sum_value if self._Sum_name == "default" else None
  
      @property
      def variant(self) -> "Optional[Variant]":
          return self._Sum_value if self._Sum_name == "variant" else None
  
      @property
      def prim_con(self) -> "Optional[PrimCon]":
          return self._Sum_value if self._Sum_name == "prim_con" else None
  
      @property
      def nil(self) -> "Optional[Unit]":
          return self._Sum_value if self._Sum_name == "nil" else None
  
      @property
      def cons(self) -> "Optional[Cons]":
          return self._Sum_value if self._Sum_name == "cons" else None
  
      @property
      def optional_none(self) -> "Optional[Unit]":
          return self._Sum_value if self._Sum_name == "optional_none" else None
  
      @property
      def optional_some(self) -> "Optional[OptionalSome]":
          return self._Sum_value if self._Sum_name == "optional_some" else None
  
      @property
      def enum(self) -> "Optional[Enum]":
          return self._Sum_value if self._Sum_name == "enum" else None
  
      # noinspection PyPep8Naming
      def Sum_match(
          self,
          default: "Callable[[Unit], T]",
          variant: "Callable[[Variant], T]",
          prim_con: "Callable[[PrimCon], T]",
          nil: "Callable[[Unit], T]",
          cons: "Callable[[Cons], T]",
          optional_none: "Callable[[Unit], T]",
          optional_some: "Callable[[OptionalSome], T]",
          enum: "Callable[[Enum], T]",
      ):
          if self._Sum_name == "default":
              return default(self.default)  # type: ignore
          elif self._Sum_name == "variant":
              return variant(self.variant)  # type: ignore
          elif self._Sum_name == "prim_con":
              return prim_con(self.prim_con)  # type: ignore
          elif self._Sum_name == "nil":
              return nil(self.nil)  # type: ignore
          elif self._Sum_name == "cons":
              return cons(self.cons)  # type: ignore
          elif self._Sum_name == "optional_none":
              return optional_none(self.optional_none)  # type: ignore
          elif self._Sum_name == "optional_some":
              return optional_some(self.optional_some)  # type: ignore
          elif self._Sum_name == "enum":
              return enum(self.enum)  # type: ignore
          else:
              raise Exception
  
  
  @dataclass(frozen=True)
  class Case:
      # noinspection SpellCheckingInspection
      scrut: "Expr"
      alts: "Sequence[CaseAlt]"  # length > 0
  
  
  @dataclass(frozen=True)
  class Block:
      # A block of bindings and an expression.
      # Encodes a sequence of binds in e.g. a let or update block.
      bindings: "Sequence[Binding]"  # length > 0
      body: "Expr"
  
  
  @dataclass(frozen=True)
  class Pure:
      type: "Type"
      expr: "Expr"
  
  
  class Update:
      class Create:
          template: "TypeConName"
          expr: "Expr"
  
          def __init__(self, template: "TypeConName", expr: "Expr"):
              self.template = template
              self.expr = expr
  
      class Exercise:
          template: "TypeConName"
          choice: str
          cid: "Expr"
          arg: "Expr"
  
          def __init__(self, template: "TypeConName", choice: str, cid: "Expr", arg: "Expr"):
              self.template = template
              self.choice = choice
              self.cid = cid
              self.arg = arg
  
      class ExerciseByKey:
          template: "TypeConName"
          choice: str
          key: "Expr"
          arg: "Expr"
  
          def __init__(self, template: "TypeConName", choice: str, key: "Expr", arg: "Expr"):
              self.template = template
              self.choice = choice
              self.key = key
              self.arg = arg
  
      class Fetch:
          template: "TypeConName"
          cid: "Expr"
  
          def __init__(self, template, cid):
              self.template = template
              self.cid = cid
  
      class EmbedExpr:
          type: "Type"  # the expression should be of type `Scenario type`
          body: "Expr"
  
          # noinspection PyShadowingBuiltins
          def __init__(self, type: "Type", body: "Expr"):
              self.type = type
              self.body = body
  
      class RetrieveByKey:
          template: "TypeConName"
          key: "Expr"
  
          def __init__(self, template: "TypeConName", key: "Expr"):
              self.template = template
              self.key = key
  
      class TryCatch:
          return_type: Type
          try_expr: Expr
          var: str
          catch_expr: Expr
  
          def __init__(self, return_type: Type, try_expr: Expr, var: str, catch_expr: Expr):
              self.return_type = return_type
              self.try_expr = try_expr
              self.var = var
              self.catch_expr = catch_expr
  
      __slots__ = "_Sum_name", "_Sum_value"
      _Sum_name: str
      _Sum_value: Any
  
      def __init__(
          self,
          pure: "Union[Pure, _Missing]" = MISSING,
          block: "Union[Block, _Missing]" = MISSING,
          create: "Union[Update.Create, _Missing]" = MISSING,
          exercise: "Union[Update.Exercise, _Missing]" = MISSING,
          exercise_by_key: "Union[Update.ExerciseByKey, _Missing]" = MISSING,
          fetch: "Union[Update.Fetch, _Missing]" = MISSING,
          get_time: "Union[Unit, _Missing]" = MISSING,
          lookup_by_key: "Union[Update.RetrieveByKey, _Missing]" = MISSING,
          fetch_by_key: "Union[Update.RetrieveByKey, _Missing]" = MISSING,
          embed_expr: "Union[Update.EmbedExpr, _Missing]" = MISSING,
          try_catch: "Union[Update.TryCatch, _Missing]" = MISSING,
      ):
          if pure is not MISSING:
              object.__setattr__(self, "_Sum_name", "pure")
              object.__setattr__(self, "_Sum_value", pure)
          elif block is not MISSING:
              object.__setattr__(self, "_Sum_name", "block")
              object.__setattr__(self, "_Sum_value", block)
          elif create is not MISSING:
              object.__setattr__(self, "_Sum_name", "create")
              object.__setattr__(self, "_Sum_value", create)
          elif exercise is not MISSING:
              object.__setattr__(self, "_Sum_name", "exercise")
              object.__setattr__(self, "_Sum_value", exercise)
          elif exercise_by_key is not MISSING:
              object.__setattr__(self, "_Sum_name", "exercise_by_key")
              object.__setattr__(self, "_Sum_value", exercise_by_key)
          elif fetch is not MISSING:
              object.__setattr__(self, "_Sum_name", "fetch")
              object.__setattr__(self, "_Sum_value", fetch)
          elif get_time is not MISSING:
              object.__setattr__(self, "_Sum_name", "get_time")
              object.__setattr__(self, "_Sum_value", get_time)
          elif lookup_by_key is not MISSING:
              object.__setattr__(self, "_Sum_name", "lookup_by_key")
              object.__setattr__(self, "_Sum_value", lookup_by_key)
          elif fetch_by_key is not MISSING:
              object.__setattr__(self, "_Sum_name", "fetch_by_key")
              object.__setattr__(self, "_Sum_value", fetch_by_key)
          elif embed_expr is not MISSING:
              object.__setattr__(self, "_Sum_name", "embed_expr")
              object.__setattr__(self, "_Sum_value", embed_expr)
          elif try_catch is not MISSING:
              object.__setattr__(self, "_Sum_name", "try_catch")
              object.__setattr__(self, "_Sum_value", try_catch)
  
      @property
      def pure(self) -> "Optional[Pure]":
          """this is purely for compact serialization -- specifically to
          reduce the AST depth. it adds no expressive power."""
          return self._Sum_value if self._Sum_name == "pure" else None  # type: ignore
  
      @property
      def block(self) -> "Optional[Block]":
          return self._Sum_value if self._Sum_name == "block" else None  # type: ignore
  
      @property
      def create(self) -> "Optional[Create]":
          return self._Sum_value if self._Sum_name == "create" else None  # type: ignore
  
      @property
      def exercise(self) -> "Optional[Exercise]":
          return self._Sum_value if self._Sum_name == "exercise" else None  # type: ignore
  
      @property
      def fetch(self) -> "Optional[Fetch]":
          return self._Sum_value if self._Sum_name == "fetch" else None  # type: ignore
  
      @property
      def get_time(self) -> "Optional[Unit]":
          return self._Sum_value if self._Sum_name == "get_time" else None  # type: ignore
  
      @property
      def lookup_by_key(self) -> "Optional[RetrieveByKey]":
          return self._Sum_value if self._Sum_name == "lookup_by_key" else None  # type: ignore
  
      @property
      def fetch_by_key(self) -> "Optional[RetrieveByKey]":
          return self._Sum_value if self._Sum_name == "fetch_by_key" else None  # type: ignore
  
      @property
      def embed_expr(self) -> "Optional[EmbedExpr]":
          """see similar constructor in `Scenario` on why this is useful."""
          return self._Sum_value if self._Sum_name == "embed_expr" else None  # type: ignore
  
      def Sum_match(
          self,
          pure: "Callable[[Pure], T]",
          block: "Callable[[Block], T]",
          create: "Callable[[Create], T]",
          exercise: "Callable[[Exercise], T]",
          fetch: "Callable[[Fetch], T]",
          get_time: "Callable[[Unit], T]",
          lookup_by_key: "Callable[[RetrieveByKey], T]",
          fetch_by_key: "Callable[[RetrieveByKey], T]",
          embed_expr: "Callable[[EmbedExpr], T]",
      ) -> T:
          if self._Sum_name == "pure":
              return pure(self._Sum_value)  # type: ignore
          if self._Sum_name == "block":
              return block(self._Sum_value)  # type: ignore
          if self._Sum_name == "create":
              return create(self._Sum_value)  # type: ignore
          if self._Sum_name == "exercise":
              return exercise(self._Sum_value)  # type: ignore
          if self._Sum_name == "fetch":
              return fetch(self._Sum_value)  # type: ignore
          if self._Sum_name == "get_time":
              return get_time(self._Sum_value)  # type: ignore
          if self._Sum_name == "lookup_by_key":
              return lookup_by_key(self._Sum_value)  # type: ignore
          if self._Sum_name == "fetch_by_key":
              return fetch_by_key(self._Sum_value)  # type: ignore
          if self._Sum_name == "embed_expr":
              return embed_expr(self._Sum_value)  # type: ignore
          else:
              raise ValueError(f"Unknown Update.Sum case: {self._Sum_name}")
  
  
  class Scenario:
      class Commit:
          party: "Expr"
          expr: "Expr"
          ret_type: "Type"
  
          def __init__(self, party: "Expr", expr: "Expr", ret_type: "Type"):
              self.party = party
              self.expr = expr
              self.ret_type = ret_type
  
      class EmbedExpr:
          type: "Type"  # the expression should be of type `Scenario type`
          body: "Expr"
  
          # noinspection PyShadowingBuiltins
          def __init__(self, type: "Type", body: "Expr"):
              self.type = type
              self.body = body
  
      __slots__ = "_Sum_name", "_Sum_value"
      _Sum_name: str
      _Sum_value: Any
  
      def __init__(
          self,
          pure: "Union[Pure, _Missing]" = MISSING,
          block: "Union[Block, _Missing]" = MISSING,
          commit: "Union[Commit, _Missing]" = MISSING,
          must_fail_at: "Union[Commit, _Missing]" = MISSING,
          pass_: "Union[Expr, _Missing]" = MISSING,
          get_time: "Union[Unit, _Missing]" = MISSING,
          get_party: "Union[Expr, _Missing]" = MISSING,
          embed_expr: "Union[EmbedExpr, _Missing]" = MISSING,
      ):
          if pure is not MISSING:
              object.__setattr__(self, "_Sum_name", "pure")
              object.__setattr__(self, "_Sum_value", pure)
          elif block is not MISSING:
              object.__setattr__(self, "_Sum_name", "block")
              object.__setattr__(self, "_Sum_value", block)
          elif commit is not MISSING:
              object.__setattr__(self, "_Sum_name", "commit")
              object.__setattr__(self, "_Sum_value", commit)
          elif must_fail_at is not MISSING:
              object.__setattr__(self, "_Sum_name", "mustFailAt")
              object.__setattr__(self, "_Sum_value", must_fail_at)
          elif pass_ is not MISSING:
              object.__setattr__(self, "_Sum_name", "pass")
              object.__setattr__(self, "_Sum_value", pass_)
          elif get_time is not MISSING:
              object.__setattr__(self, "_Sum_name", "get_time")
              object.__setattr__(self, "_Sum_value", get_time)
          elif get_party is not MISSING:
              object.__setattr__(self, "_Sum_name", "get_party")
              object.__setattr__(self, "_Sum_value", get_party)
          elif embed_expr is not MISSING:
              object.__setattr__(self, "_Sum_name", "embed_expr")
              object.__setattr__(self, "_Sum_value", embed_expr)
  
      @property
      def pure(self) -> "Optional[Pure]":
          """this is purely for compact serialization -- specifically to
          reduce the AST depth. it adds no expressive power."""
          return self._Sum_value if self._Sum_name == "pure" else None
  
      @property
      def block(self) -> "Optional[Block]":
          return self._Sum_value if self._Sum_name == "block" else None
  
      @property
      def commit(self) -> "Optional[Commit]":
          return self._Sum_value if self._Sum_name == "create" else None
  
      @property
      def must_fail_at(self) -> "Optional[Commit]":
          return self._Sum_value if self._Sum_name == "mustFailAt" else None
  
      @property
      def pass_(self) -> "Optional[Expr]":
          return self._Sum_value if self._Sum_name == "pass" else None
  
      @property
      def get_time(self) -> "Optional[Unit]":
          """The expression is of type `Text`."""
          return self._Sum_value if self._Sum_name == "get_time" else None
  
      @property
      def get_party(self) -> "Optional[Expr]":
          return self._Sum_value if self._Sum_name == "get_party" else None
  
      @property
      def embed_expr(self) -> "Optional[EmbedExpr]":
          """
          Embed an expression of type Scenario. note that this construct is useful
          to explicitly mark the start of scenario execution, which is useful in
          top level definitions. for example if we hav
  
          def test : Scenario Unit = if <blah> then <this> else <that>
  
          this is not a value, since it's headed with an `if`, but we can turn
          it into a value by wrapping the `if` with this constructor. in that
          case, the `if` will be executed every time the scenario runs --
          as expected.
          """
          return self._Sum_value if self._Sum_name == "embed_expr" else None
  
      def Sum_match(
          self,
          pure: "Callable[[Pure], T]",
          block: "Callable[[Block], T]",
          commit: "Callable[[Commit], T]",
          must_fail_at: "Callable[[Commit], T]",
          pass_: "Callable[[Expr], T]",
          get_time: "Callable[[Unit], T]",
          get_party: "Callable[[Expr], T]",
          embed_expr: "Callable[[EmbedExpr], T]",
      ) -> T:
          if self._Sum_name == "pure":
              return pure(self._Sum_value)
          if self._Sum_name == "block":
              return block(self._Sum_value)
          if self._Sum_name == "commit":
              return commit(self._Sum_value)
          if self._Sum_name == "mustFailAt":
              return must_fail_at(self._Sum_value)
          if self._Sum_name == "pass":
              return pass_(self._Sum_value)
          if self._Sum_name == "get_time":
              return get_time(self._Sum_value)
          if self._Sum_name == "get_party":
              return get_party(self._Sum_value)
          if self._Sum_name == "embed_expr":
              return embed_expr(self._Sum_value)
          else:
              raise ValueError(f"unknown Scenario.Sum case: {self._Sum_name!r}")
  
  
  class BuiltinFunction(_IntEnum):
      ADD_DECIMAL = 0
      SUB_DECIMAL = 1
      MUL_DECIMAL = 2
      DIV_DECIMAL = 3
      ROUND_DECIMAL = 6
      ADD_NUMERIC = 107
      SUB_NUMERIC = 108
      MUL_NUMERIC = 109
      DIV_NUMERIC = 110
      ROUND_NUMERIC = 111
      CAST_NUMERIC = 121
      SHIFT_NUMERIC = 122
      ADD_INT64 = 7
      SUB_INT64 = 8
      MUL_INT64 = 9
      DIV_INT64 = 10
      MOD_INT64 = 11
      EXP_INT64 = 12
      FOLDL = 20
      FOLDR = 21
      TEXTMAP_EMPTY = 96
      TEXTMAP_INSERT = 97
      TEXTMAP_LOOKUP = 98
      TEXTMAP_DELETE = 99
      TEXTMAP_TO_LIST = 100
      TEXTMAP_SIZE = 101
      GENMAP_EMPTY = 124
      GENMAP_INSERT = 125
      GENMAP_LOOKUP = 126
      GENMAP_DELETE = 127
      GENMAP_KEYS = 128
      GENMAP_VALUES = 129
      GENMAP_SIZE = 130
      EXPLODE_TEXT = 23
      APPEND_TEXT = 24
      ERROR = 25
      ANY_EXCEPTION_MESSAGE = 147
      LEQ_INT64 = 33
      LEQ_DECIMAL = 34
      LEQ_NUMERIC = 112
      LEQ_TEXT = 36
      LEQ_TIMESTAMP = 37
      LEQ_DATE = 67
      LEQ_PARTY = 89
      LESS_INT64 = 39
      LESS_DECIMAL = 40
      LESS_NUMERIC = 113
      LESS_TEXT = 42
      LESS_TIMESTAMP = 43
      LESS_DATE = 68
      LESS_PARTY = 90
      GEQ_INT64 = 45
      GEQ_DECIMAL = 46
      GEQ_NUMERIC = 114
      GEQ_TEXT = 48
      GEQ_TIMESTAMP = 49
      GEQ_DATE = 69
      GEQ_PARTY = 91
      GREATER_INT64 = 51
      GREATER_DECIMAL = 52
      GREATER_NUMERIC = 115
      GREATER_TEXT = 54
      GREATER_TIMESTAMP = 55
      GREATER_DATE = 70
      GREATER_PARTY = 92
      INT64_TO_TEXT = 57
      DECIMAL_TO_TEXT = 58
      NUMERIC_TO_TEXT = 116
      TEXT_TO_TEXT = 60
      TIMESTAMP_TO_TEXT = 61
      DATE_TO_TEXT = 71
      PARTY_TO_QUOTED_TEXT = 63
      PARTY_TO_TEXT = 94
      TEXT_TO_PARTY = 95
      TEXT_TO_INT64 = 103
      TEXT_TO_DECIMAL = 104
      TEXT_TO_NUMERIC = 117
      CONTRACT_ID_TO_TEXT = 136
      SHA256_TEXT = 93
      DATE_TO_UNIX_DAYS = 72
      UNIX_DAYS_TO_DATE = 73
      TIMESTAMP_TO_UNIX_MICROSECONDS = 74
      UNIX_MICROSECONDS_TO_TIMESTAMP = 75
      INT64_TO_DECIMAL = 76
      DECIMAL_TO_INT64 = 77
      INT64_TO_NUMERIC = 118
      NUMERIC_TO_INT64 = 119
      IMPLODE_TEXT = 78
      EQUAL_INT64 = 79
      EQUAL_DECIMAL = 80
      EQUAL_NUMERIC = 120
      EQUAL_TEXT = 81
      EQUAL_TIMESTAMP = 82
      EQUAL_DATE = 83
      EQUAL_PARTY = 84
      EQUAL_BOOL = 85
      EQUAL_CONTRACT_ID = 86
      EQUAL_LIST = 87
      EQUAL_TYPE_REP = 123
      EQUAL = 131
      LESS_EQ = 132
      LESS = 133
      GREATER_EQ = 134
      GREATER = 135
      TRACE = 88
      COERCE_CONTRACT_ID = 102
      CODE_POINTS_TO_TEXT = 105
      TEXT_POINTS_TO_CODE = 106
      SCALE_BIGNUMERIC = 137
      PRECISION_BIGNUMERIC = 138
      ADD_BIGNUMERIC = 139
      SUB_BIGNUMERIC = 140
      MUL_BIGNUMERIC = 141
      DIV_BIGNUMERIC = 142
      SHIFT_RIGHT_BIGNUMERIC = 143
      BIGNUMERIC_TO_NUMERIC = 144
      NUMERIC_TO_BIGNUMERIC = 145
      BIGNUMERIC_TO_TEXT = 146
  
  
  class PrimCon(_IntEnum):
      CON_UNIT = 0
      CON_FALSE = 1
      CON_TRUE = 2
  
  
  @dataclass(frozen=True)
  class TemplateChoice:
      """Template choice definition."""
  
      # Name of the choice.
      name: str
  
      # Indicator whether exercising the choice consumes the contract instance.
      consuming: bool
  
      # The controllers of the choice. They have type `List Party` and the
      # template parameter in scope, but not the choice parameter. All of these
      # controllers need to authorize the exercising of this choice (aka
      # conjunctive choice controllers).
      controllers: "Expr"
  
      observers: "Optional[Expr]"
  
      # Name to which the choice argument is bound and its type.
      arg_binder: "VarWithType"
  
      # Return type of the choice.
      ret_type: "Type"
  
      # Follow-up update of the choice. It has type `Update <ret_type>` and both
      # the template parameter and the choice parameter in scope.
      update: "Expr"
  
      # Name to bind the ContractId of the contract this choice is exercised on to.
      self_binder: str
  
      location: "Location"
  
  
  @dataclass(init=False, frozen=True)
  class KeyExpr:
      _Sum_name: str
      _Sum_value: "Union[KeyExpr.Projections, KeyExpr.Record]"
  
      @dataclass(init=False, frozen=True)
      class Projections:
          projections: "Sequence[KeyExpr.Projection]"
  
          def __init__(self, projections: "Sequence[KeyExpr.Projection]"):
              object.__setattr__(self, "projections", tuple(projections))
  
      @dataclass(init=False, frozen=True)
      class Projection:
          tycon: "Type.Con"
          field: str
  
          def __init__(self, tycon: "Type.Con", field: str):
              object.__setattr__(self, "tycon", tycon)
              object.__setattr__(self, "field", field)
  
      @dataclass(init=False, frozen=True)
      class Record:
          tycon: "Type.Con"
          fields: "Sequence[KeyExpr.RecordField]"
  
          def __init__(self, tycon: "Type.Con", fields: "Sequence[KeyExpr.RecordField]"):
              object.__setattr__(self, "tycon", tycon)
              object.__setattr__(self, "fields", tuple(fields))
  
      @dataclass(frozen=True)
      class RecordField:
          field: str
          expr: "KeyExpr"
  
      def __init__(self, projections=MISSING, record=MISSING):
          if projections is not MISSING:
              object.__setattr__(self, "_Sum_name", "projections")
              object.__setattr__(self, "_Sum_value", projections)
          elif record is not MISSING:
              object.__setattr__(self, "_Sum_name", "record")
              object.__setattr__(self, "_Sum_value", record)
          else:
              raise ValueError("one of projections or record must be set")
  
      @property
      def projections(self) -> "Optional[KeyExpr.Projections]":
          return self.projections if self._Sum_name == "projections" else None
  
      @property
      def record(self) -> "Optional[KeyExpr.Record]":
          return self.record if self._Sum_name == "record" else None
  
  
  @dataclass(frozen=True)
  class DefTemplate:
      """Contract template definition"""
  
      @dataclass(frozen=True)
      class DefKey:
          type: "Type"
          _key_expr_name: str
          _key_expr_value: Union[KeyExpr, Expr]
          maintainers: "Expr"
  
          def __init__(self, type=MISSING, key=MISSING, complex_key=MISSING, maintainers=MISSING):
              object.__setattr__(self, "type", type)
              if key is not MISSING:
                  object.__setattr__(self, "_key_expr_name", "key")
                  object.__setattr__(self, "_key_expr_value", key)
              elif complex_key is not MISSING:
                  object.__setattr__(self, "_key_expr_name", "complex_key")
                  object.__setattr__(self, "_key_expr_value", complex_key)
              else:
                  raise ValueError("one of key/complex_key must be set")
              object.__setattr__(self, "maintainers", maintainers)
  
          @property
          def key(self) -> "Optional[KeyExpr]":
              if self._key_expr_name == "key":
                  return self._key_expr_value  # type: ignore
              else:
                  return None
  
          @property
          def complex_key(self) -> "Optional[Expr]":
              if self._key_expr_name == "complex_key":
                  return self._key_expr_value  # type: ignore
              else:
                  return None
  
      # The type constructor for the template, acting as both
      # the name of the template and the type of the template argument.
      tycon: "DottedName"
  
      # Name to which the template argument is bound.
      param: str
  
      # Optional pre-condition that the template argument must satisfy.
      # When present, it has type `Bool` and the template parameter in scope.
      precond: "Expr"
  
      # The signatories of the contract. They have type `List Party` and the
      # template parameter in scope.
      signatories: "Expr"
  
      # The agreement text associated with the contract. It has type `Text` and
      # the template parameter in scope.
      agreement: "Expr"
  
      # The choices available in the resulting contract.
      choices: "Sequence[TemplateChoice]"
  
      # The observers of the contract. They have type `List Party` and the
      # template parameter in scope.
      observers: "Expr"
  
      location: "Location"
  
      # The key definition for the template, if present
      key: "Optional[DefKey]"
  
  
  class DefDataType:
      """
      A record, variant, or enum data type definition.
      """
  
      class Fields:
          fields: "Sequence[FieldWithType]"
  
          def __init__(self, fields: "Sequence[FieldWithType]"):
              self.fields = fields
  
      class EnumConstructors:
          constructors: "Sequence[str]"
  
          def __init__(self, constructors: "Sequence[str]"):
              self.constructors = constructors
  
      name: DottedName
      params: "Sequence[TypeVarWithKind]"
      _DataCons_name: str
      _DataCons_value: "Any"
      serializable: bool
      location: "Location"
  
      def __init__(
          self,
          name: "Union[DottedName, _Missing]" = MISSING,
          params: "Union[Sequence[TypeVarWithKind], _Missing]" = MISSING,
          record: "Union[DefDataType.Fields, _Missing]" = MISSING,
          variant: "Union[DefDataType.Fields, _Missing]" = MISSING,
          enum: "Union[DefDataType.EnumConstructors, _Missing]" = MISSING,
          synonym: "Union[Type, _Missing]" = MISSING,
          serializable: "Union[bool, _Missing]" = MISSING,
          location: "Union[Location, _Missing]" = MISSING,
      ):
          self.name = name  # type: ignore
          self.params = params  # type: ignore
          if record is not MISSING:
              self._DataCons_name = "record"
              self._DataCons_value = record  # type: ignore
          elif variant is not MISSING:
              self._DataCons_name = "variant"
              self._DataCons_value = variant  # type: ignore
          elif enum is not MISSING:
              self._DataCons_name = "enum"
              self._DataCons_value = enum  # type: ignore
          elif synonym is not MISSING:
              self._DataCons_name = "synonym"
              self._DataCons_value = synonym  # type: ignore
          self.serializable = serializable  # type: ignore
          self.location = location  # type: ignore
  
      @property
      def record(self) -> "Optional[DefDataType.Fields]":
          return self._DataCons_value if self._DataCons_name == "record" else None
  
      @property
      def variant(self) -> "Optional[DefDataType.Fields]":
          return self._DataCons_value if self._DataCons_name == "variant" else None
  
      @property
      def enum(self) -> "Optional[DefDataType.EnumConstructors]":
          if self._DataCons_name == "enum":
              return self._DataCons_value  # type: ignore
          else:
              return None
  
      @property
      def synonym(self) -> "Optional[Type]":
          if self._DataCons_name == "synonym":
              return self._DataCons_value  # type: ignore
          else:
              return None
  
  
  @dataclass(frozen=True)
  class DefTypeSyn:
      name: "DottedName"
      params: "Sequence[TypeVarWithKind]"
      type: "Type"
      location: "Optional[Location]"
  
  
  class DefValue:
      """Value definition"""
  
      class NameWithType:
          """
          The reason why we have this type instead of just flattening name and type in
          DefValue is that it was VarWithType before, and we want to be binary-compatible
          with it.
          """
  
          name: "Sequence[str]"
          type: "Type"
  
          # noinspection PyShadowingBuiltins
          def __init__(self, name: "Sequence[str]", type: "Type"):
              self.name = tuple(name)
              self.type = type
  
      name_with_type: "DefValue.NameWithType"
  
      _lazy_lock: threading.RLock
      _expr: "Optional[Expr]"
      _expr_fn: "Callable[[], Expr]"
  
      # If true, the value must not contain any party literals and not reference
      # values which contain party literals.
      # This flag is used to simplify package validation by not requiring an
      # inference but only a check. Such a check must validate that this flag is
      # set correctly and that templates do not reference values which have this
      # flag set to false.
      no_party_literals: bool
      is_test: bool
      location: "Optional[Location]"
  
      __slots__ = (
          "name_with_type",
          "_lazy_lock",
          "_expr",
          "_expr_fn",
          "no_party_literals",
          "is_test",
          "location",
      )
  
      def __init__(
          self,
          name_with_type: "DefValue.NameWithType",
          expr: "Union[Expr, Callable[[], Expr]]",
          no_party_literals: bool,
          is_test: bool,
          location: "Optional[Location]" = None,
      ):
          object.__setattr__(self, "name_with_type", name_with_type)
          object.__setattr__(self, "_lazy_lock", threading.RLock())
          object.__setattr__(self, "_expr", None)
          object.__setattr__(self, "_expr_fn", (lambda: expr) if isinstance(expr, Expr) else expr)
          object.__setattr__(self, "no_party_literals", no_party_literals)
          object.__setattr__(self, "is_test", is_test)
          object.__setattr__(self, "location", location)
  
      @property
      def expr(self) -> "Expr":
          expr = self._expr
          if expr is not None:
              return expr
  
          with self._lazy_lock:
              expr = self._expr
              if expr is None:
                  expr = self._expr_fn()  # type: ignore
                  object.__setattr__(self, "_expr", expr)
              return expr
  
      def __setattr__(self, key, value):
          raise AttributeError
  
      def __hash__(self):
          return hash(
              (
                  self.name_with_type,
                  self.no_party_literals,
                  self.is_test,
                  self.location,
              )
          )
  
      def __repr__(self):
          return f"DefValue(name_with_type={self.name_with_type!r}, expr=..., no_party_literals={self.no_party_literals!r}, is_test={self.is_test!r}, location={self.location!r})"
  
  
  @dataclass(frozen=True)
  class FeatureFlags:
      forbid_party_literals: bool
      dont_divulge_contract_ids_in_create_arguments: bool
      dont_disclose_nonconsuming_choices_to_observers: bool
  
  
  @dataclass(frozen=True)
  class Module:
      name: "DottedName"
      flags: "FeatureFlags"
      synonyms: "Sequence[DefTypeSyn]"
      data_types: "Sequence[DefDataType]"
      values: "Sequence[DefValue]"
      templates: "Sequence[DefTemplate]"
  
  
  @dataclass(frozen=True)
  class Package:
      modules: "Sequence[Module]"
      metadata: "Optional[PackageMetadata]"
  
  
  @dataclass(frozen=True)
  class PackageMetadata:
      name: str
      version: str
  
  
  @dataclass(frozen=True)
  class Archive:
      hash: "PackageRef"
      package: "Package"
  