parameters: (self, ln, ast, pb, ns=None)
return_statement: return pyname
docstring: Translate PYTD class IR ast to AST Decl protobuf.
docstring_summary: Translate PYTD class IR ast to AST Decl protobuf.
docstring_tokens: Translate PYTD class IR ast to AST Decl protobuf .
function: def _class(self, ln, ast, pb, ns=None):
      """Translate PYTD class IR ast to AST Decl protobuf."""
      assert isinstance(pb, ast_pb2.Decl), repr(pb)
      atln = ' at line %d' % ln
      pb.line_number = ln
      pb.decltype = pb.CLASS
      p = pb.class_
      cpp_name = ast.name[0]  # Save C++ name without FQ.
      is_iterator = ast.name[-1] == '__iter__'
      _set_name(
          p.name,
          ast.name,
          ns,
          allow_fqcppname=is_iterator,
          template_name=self._extract_template_base_name(cpp_name))
      pyname = p.name.native
      self.check_known_name(pyname, p.name.cpp_name)
      decorators = ast.decorators.asList()
      if not is_iterator:
        self._typetable.set_type(pyname, p.name.cpp_name)
        if 'final' in decorators:
          p.final = True
          decorators.remove('final')
        if 'enable_instance_dict' in decorators:
          p.enable_instance_dict = True
          decorators.remove('enable_instance_dict')
        if 'suppress_upcasts' in decorators:
          p.suppress_upcasts = True
          decorators.remove('suppress_upcasts')
      if decorators:
        raise NameError('Unknown class decorator(s)%s: %s'
                        % (atln, ', '.join(decorators)))
      _set_bases(p.bases, ast.bases, self._names, self._typetable)
  
      # Iterators don't add themselves to the type table (see above), so we can't
      # create a child scope based on them. Not that it matters: __iter__
      # classes aren't allowed to have anything in them.
      if not is_iterator:
        self._typetable.push_scope(pyname)
  
      if ast.docstring:
        p.docstring = ast.docstring[0][2]
  
      local_names = set()
      for decl in ast[-1]:
        if decl[0] == 'pass':
          # Pass is a special case as we don't want to add() to the proto.
          if len(ast[-1]) != 1:
            raise SyntaxError('pass must be the only class statement' + atln)
          continue
        line_number = self.line(decl[1])
        if is_iterator:
          if (len(ast[-1]) != 1 or
              decl[0] != 'func' or decl.name[-1] != '__next__'):
            raise SyntaxError('__iter__ class must only def __next__ at line %d'
                              % line_number)
        else:
          if decl[0] == 'implements':
            name = decl[2]
            self._macro_values = [pyname] + decl[3:]
            try:
              nargs, src, _ = self._macros[name]
            except KeyError:
              raise NameError('interface %s not defined' % name + atln)
            if len(self._macro_values) != nargs+1:
              raise NameError('interface %s needs %d args (%d given)'
                              % (name, len(self._macro_values)-1, nargs) + atln)
            for d in src:
              ln = self.line(d[1])
              if d[0] == 'func':
                if not self.unproperty(ln, d, pyname, p.members, local_names):
                  _add_uniq(pyname, local_names,
                            self._func(ln, d, p.members.add()))
              elif d[0] == 'var':
                _add_uniq(pyname, local_names, self._var(ln, d, p.members.add()))
              else:
                raise SyntaxError('implements %s contains disallowed %s%s'
                                  % (name, d[0], atln))
            self._macro_values = []
            continue
          if decl[0] == 'func' and self.unproperty(
              line_number, decl, pyname, p.members, local_names):
            continue
        name = getattr(self, '_'+decl[0])(line_number, decl, p.members.add())
        _add_uniq(pyname, local_names, name)
  
      funcs = [m.func for m in p.members if m.decltype == m.FUNC]
      is_sequential = any(f.name.native.endswith('#') for f in funcs)
      if is_sequential and any(f.name.native in _RIGHT_OPS for f in funcs):
        raise NameError("class %s %s can't be sequence and number"
                        ' at the same time' % (p.name.native, atln))
      for f in funcs:
        # Fix ctor name to be the class name.
        if f.name.native == '__init__':
          if (f.name.cpp_name and
              f.name.cpp_name not in [cpp_name, '__init__']):
            print('Arbitrary names (like "{0}") for {1} ctor not allowed.'
                  ' Set to {1}'.format(f.name.cpp_name, cpp_name),
                  file=sys.stderr)
          f.name.cpp_name = cpp_name
          f.constructor = True
        elif f.name.native == cpp_name:
          raise NameError('Use __init__ to wrap a "%s" constructor'%pyname + atln)
        elif f.name.cpp_name == cpp_name:
          # @add__init__ will reset cpp_name to be empty.
          raise NameError('Use @add__init__ to wrap additional "%s" constructor'
                          '(s).' % pyname + atln)
        elif not f.name.cpp_name:  # An additional ctor.
          f.name.cpp_name = cpp_name
          f.constructor = True
  
        # Fix 'self' for C++ operator function (implemented out of class).
        elif f.name.native in _RIGHT_OPS:
          if len(f.params) != 1:
            raise ValueError('%s must have only 1 input parameter'
                             % f.name.native + atln)
          f.cpp_opfunction = True  # Request a non-member function.
          self._set_this(f.params.add(), cpp_name, p.name.cpp_name)
        elif '::' in f.name.cpp_name:
          if not f.params:
            f.params.add()
          # else make room for param[0] by shifting 0->1, 1->2 and so on.
          elif len(f.params) == 1:
            f.params.extend([f.params[0]])
          else:
            pcopy = ast_pb2.FuncDecl()
            pcopy.params.extend(f.params)
            del f.params[1:]
            f.params.extend(pcopy.params)
            del pcopy
          f.cpp_opfunction = True  # Request a non-member function.
          self._set_this(f.params[0], cpp_name, p.name.cpp_name)
  
        # Fix 'item|add__' for a 'sequential' class.
        elif is_sequential and (f.name.native.endswith('item__') or
                                f.name.native.endswith('add__')):
          f.name.native += '#'  # Move '+' to tp_as_sequence slots.
  
      if not is_iterator:
        self._typetable.pop_scope()
      return pyname
function_tokens: def _class ( self , ln , ast , pb , ns = None ) : assert isinstance ( pb , ast_pb2 . Decl ) , repr ( pb ) atln = ' at line %d' % ln pb . line_number = ln pb . decltype = pb . CLASS p = pb . class_ cpp_name = ast . name [ 0 ] # Save C++ name without FQ. is_iterator = ast . name [ - 1 ] == '__iter__' _set_name ( p . name , ast . name , ns , allow_fqcppname = is_iterator , template_name = self . _extract_template_base_name ( cpp_name ) ) pyname = p . name . native self . check_known_name ( pyname , p . name . cpp_name ) decorators = ast . decorators . asList ( ) if not is_iterator : self . _typetable . set_type ( pyname , p . name . cpp_name ) if 'final' in decorators : p . final = True decorators . remove ( 'final' ) if 'enable_instance_dict' in decorators : p . enable_instance_dict = True decorators . remove ( 'enable_instance_dict' ) if 'suppress_upcasts' in decorators : p . suppress_upcasts = True decorators . remove ( 'suppress_upcasts' ) if decorators : raise NameError ( 'Unknown class decorator(s)%s: %s' % ( atln , ', ' . join ( decorators ) ) ) _set_bases ( p . bases , ast . bases , self . _names , self . _typetable ) # Iterators don't add themselves to the type table (see above), so we can't # create a child scope based on them. Not that it matters: __iter__ # classes aren't allowed to have anything in them. if not is_iterator : self . _typetable . push_scope ( pyname ) if ast . docstring : p . docstring = ast . docstring [ 0 ] [ 2 ] local_names = set ( ) for decl in ast [ - 1 ] : if decl [ 0 ] == 'pass' : # Pass is a special case as we don't want to add() to the proto. if len ( ast [ - 1 ] ) != 1 : raise SyntaxError ( 'pass must be the only class statement' + atln ) continue line_number = self . line ( decl [ 1 ] ) if is_iterator : if ( len ( ast [ - 1 ] ) != 1 or decl [ 0 ] != 'func' or decl . name [ - 1 ] != '__next__' ) : raise SyntaxError ( '__iter__ class must only def __next__ at line %d' % line_number ) else : if decl [ 0 ] == 'implements' : name = decl [ 2 ] self . _macro_values = [ pyname ] + decl [ 3 : ] try : nargs , src , _ = self . _macros [ name ] except KeyError : raise NameError ( 'interface %s not defined' % name + atln ) if len ( self . _macro_values ) != nargs + 1 : raise NameError ( 'interface %s needs %d args (%d given)' % ( name , len ( self . _macro_values ) - 1 , nargs ) + atln ) for d in src : ln = self . line ( d [ 1 ] ) if d [ 0 ] == 'func' : if not self . unproperty ( ln , d , pyname , p . members , local_names ) : _add_uniq ( pyname , local_names , self . _func ( ln , d , p . members . add ( ) ) ) elif d [ 0 ] == 'var' : _add_uniq ( pyname , local_names , self . _var ( ln , d , p . members . add ( ) ) ) else : raise SyntaxError ( 'implements %s contains disallowed %s%s' % ( name , d [ 0 ] , atln ) ) self . _macro_values = [ ] continue if decl [ 0 ] == 'func' and self . unproperty ( line_number , decl , pyname , p . members , local_names ) : continue name = getattr ( self , '_' + decl [ 0 ] ) ( line_number , decl , p . members . add ( ) ) _add_uniq ( pyname , local_names , name ) funcs = [ m . func for m in p . members if m . decltype == m . FUNC ] is_sequential = any ( f . name . native . endswith ( '#' ) for f in funcs ) if is_sequential and any ( f . name . native in _RIGHT_OPS for f in funcs ) : raise NameError ( "class %s %s can't be sequence and number" ' at the same time' % ( p . name . native , atln ) ) for f in funcs : # Fix ctor name to be the class name. if f . name . native == '__init__' : if ( f . name . cpp_name and f . name . cpp_name not in [ cpp_name , '__init__' ] ) : print ( 'Arbitrary names (like "{0}") for {1} ctor not allowed.' ' Set to {1}' . format ( f . name . cpp_name , cpp_name ) , file = sys . stderr ) f . name . cpp_name = cpp_name f . constructor = True elif f . name . native == cpp_name : raise NameError ( 'Use __init__ to wrap a "%s" constructor' % pyname + atln ) elif f . name . cpp_name == cpp_name : # @add__init__ will reset cpp_name to be empty. raise NameError ( 'Use @add__init__ to wrap additional "%s" constructor' '(s).' % pyname + atln ) elif not f . name . cpp_name : # An additional ctor. f . name . cpp_name = cpp_name f . constructor = True # Fix 'self' for C++ operator function (implemented out of class). elif f . name . native in _RIGHT_OPS : if len ( f . params ) != 1 : raise ValueError ( '%s must have only 1 input parameter' % f . name . native + atln ) f . cpp_opfunction = True # Request a non-member function. self . _set_this ( f . params . add ( ) , cpp_name , p . name . cpp_name ) elif '::' in f . name . cpp_name : if not f . params : f . params . add ( ) # else make room for param[0] by shifting 0->1, 1->2 and so on. elif len ( f . params ) == 1 : f . params . extend ( [ f . params [ 0 ] ] ) else : pcopy = ast_pb2 . FuncDecl ( ) pcopy . params . extend ( f . params ) del f . params [ 1 : ] f . params . extend ( pcopy . params ) del pcopy f . cpp_opfunction = True # Request a non-member function. self . _set_this ( f . params [ 0 ] , cpp_name , p . name . cpp_name ) # Fix 'item|add__' for a 'sequential' class. elif is_sequential and ( f . name . native . endswith ( 'item__' ) or f . name . native . endswith ( 'add__' ) ) : f . name . native += '#' # Move '+' to tp_as_sequence slots. if not is_iterator : self . _typetable . pop_scope ( ) return pyname