content: class A[TA,TB,TC]:
      a: TA
      b: TB
      c: TC
  
      def dump(a, b, c):
          print a, b, c
  
      # non-generic method:
      def m0(self: A[TA,TB,TC], a: int):
          print a
  
      # basic generics:
      def m1[X](self: A[TA,TB,TC], other: A[X,X,X]):
          print other.a, other.b, other.c
  
      # non-generic method referencing outer generics:
      def m2(a: TA, b: TB, c: TC):
          A.dump(a, b, c)
  
      # generic args:
      def m3(self, other):
          return self.a
  
      # lots of nesting:
      def m4[TD](self: A[TA,TB,TC], d: TD):
          def m5[TA,TB,TC,TD,TE](a: TA, b: TB, c: TC, d: TD, e: TE):
              print a, b, c, d, e
          m5(self.a, self.b, self.c, d, d)
  
      # instantiating the type:
      def m5(self):
          x = A(self.a, self.b, self.c)
          A.dump(x.a, x.b, x.c)
  
      # deeply nested generic type:
      def m6[T](v: array[array[array[T]]]):
          return v[0][0][0]
  
  # explicit realization:
  def m7(T: type, S: type):
      print "works"
  
  class B1[T]:
      a: T
      def foo[S](self: S) -> B1[int]:
          return B1[int](111)
  
  class B2[T]:
      a: T
      def foo[S](self: B2[S]):
          return B2[int](222)
  
  a1 = A(42, 3.14, "hello")
  a2 = A(1, 2, 3)
  b1 = B1[bool](True).foo()
  b2 = B2[str]("x").foo()
  
  v1 = array[array[array[str]]](1)
  v2 = array[array[str]](1)
  v3 = array[str](1)
  v1[0] = v2
  v2[0] = v3
  v3[0] = "world"
  f = a2.m0
  
  a1.m1(a2)                           # EXPECT: 1 2 3
  A[int,float,str].m2(1, 1.0, "one")  # EXPECT: 1 1 one
  A[int,int,int].m2(11, 22, 33)       # EXPECT: 11 22 33
  print a1.m3(a2)                     # EXPECT: 42
  print a1.m3(a2)                     # EXPECT: 42
  print a2.m3(a1)                     # EXPECT: 1
  a1.m4(True)                         # EXPECT: 42 3.14 hello True True
  a1.m4([1])                          # EXPECT: 42 3.14 hello [1] [1]
  a2.m4("x")                          # EXPECT: 1 2 3 x x
  a1.m5()                             # EXPECT: 42 3.14 hello
  a2.m5()                             # EXPECT: 1 2 3
  print A.m6(v1)                      # EXPECT: world
  m7(str,float)                       # EXPECT: works
  m7(str,float)                       # EXPECT: works
  m7(float,str)                       # EXPECT: works
  f(99)                               # EXPECT: 99
  print b1.foo().a                    # EXPECT: 111
  print b2.foo().a                    # EXPECT: 222
  
  
  # recursive generics with different inner type parameter
  def foo(a):
      if not a:
          foo(True)
      print a
  # EXPECT: True
  # EXPECT: 0
  foo(0)
  
  def bar(a):
      def baz(x):
          if not x:
              bar(True)
          print(x)
      baz(a)
  # EXPECT: True
  # EXPECT: 0
  bar(0)
  