예제 #1
0
파일: classes.py 프로젝트: google/clif
def _generate_constructor(
        class_name: str, func_decl: ast_pb2.FuncDecl,
        class_decl: ast_pb2.ClassDecl, capsule_types: Set[str],
        trampoline_generated: bool) -> Generator[str, None, None]:
    """Generates pybind11 bindings code for a constructor.

  Multiple deinitions will be generated when the constructor contains unknown
  default value arguments.

  Args:
    class_name: Name of the class that defines the contructor.
    func_decl: Constructor declaration in proto format.
    class_decl: Class declaration in proto format.
    capsule_types: A set of C++ types that are defined as capsules.
    trampoline_generated: Did we generate a trampoline for this class?

  Yields:
    pybind11 function bindings code.
  """
    num_unknown = function_lib.num_unknown_default_values(func_decl)
    temp_func_decl = ast_pb2.FuncDecl()
    temp_func_decl.CopyFrom(func_decl)
    if num_unknown:
        for _ in range(num_unknown):
            yield from _generate_constructor_overload(class_name,
                                                      temp_func_decl,
                                                      class_decl,
                                                      capsule_types,
                                                      trampoline_generated)
            del temp_func_decl.params[-1]
    yield from _generate_constructor_overload(class_name, temp_func_decl,
                                              class_decl, capsule_types,
                                              trampoline_generated)
예제 #2
0
def MoveExtendPropertiesInPlace(ast):
    """See module docstring."""
    extend_property_decls = []
    extend_getter_decls = []
    for decl in ast.decls:
        member_delete_indices = []
        if decl.decltype != ast_pb2.Decl.Type.CLASS:
            continue
        for member_index, member in enumerate(decl.class_.members):
            if member.decltype != ast_pb2.Decl.Type.VAR:
                continue
            if not member.var.is_extend_variable:
                continue
            property_decl = ast_pb2.Decl()
            property_decl.CopyFrom(member)
            property_decl.var.name.native = (decl.class_.name.native +
                                             EXTEND_INFIX +
                                             member.var.name.native)
            if member.var.name.cpp_name == member.var.name.native:
                property_decl.var.name.cpp_name = (decl.class_.name.native +
                                                   EXTEND_INFIX +
                                                   member.var.name.cpp_name)

            p = _GenerateParameterSelf(decl.class_)
            property_decl.var.cpp_get.params.insert(0, p)
            property_decl.var.cpp_get.name.cpp_name = (
                decl.class_.name.native + EXTEND_INFIX +
                member.var.cpp_get.name.cpp_name)
            if member.var.HasField('cpp_set'):
                property_decl.var.cpp_set.name.cpp_name = (
                    decl.class_.name.native + EXTEND_INFIX +
                    member.var.cpp_set.name.cpp_name)
                p = _GenerateParameterSelf(decl.class_)
                property_decl.var.cpp_set.params.insert(0, p)
            extend_property_decls.append(property_decl)
            member_delete_indices.append(member_index)

            # generate property getters
            # (setters do not need this kind of functionality)
            getter_decl = ast_pb2.FuncDecl()
            getter_decl.CopyFrom(member.var.cpp_get)
            getter_decl.name.native = getter_decl.name.cpp_name = (
                decl.class_.name.native + EXTEND_INFIX +
                member.var.cpp_get.name.cpp_name)
            p = _GenerateParameterSelf(decl.class_)
            getter_decl.params.insert(0, p)
            getter_decl.is_extend_method = True
            func_decl = ast_pb2.Decl()
            func_decl.func.CopyFrom(getter_decl)
            func_decl.decltype = ast_pb2.Decl.Type.FUNC
            extend_getter_decls.append(func_decl)
        for member_index in reversed(member_delete_indices):
            del decl.class_.members[member_index]
    ast.decls.extend(extend_property_decls)
    ast.decls.extend(extend_getter_decls)
예제 #3
0
def _MoveExtendPropertiesInPlaceOneClass(
    extend_property_decls, extend_getter_decls, outer_class_names, class_decl):
  """Helper for MoveExtendPropertiesInPlace."""
  member_delete_indices = []
  for member_index, member in enumerate(class_decl.members):
    if member.decltype == ast_pb2.Decl.Type.CLASS:
      _MoveExtendPropertiesInPlaceOneClass(
          extend_property_decls, extend_getter_decls,
          outer_class_names+[class_decl.name], member.class_)
    if member.decltype != ast_pb2.Decl.Type.VAR:
      continue
    if not member.var.is_extend_variable:
      continue

    fq_native = '_'.join(
        [n.native for n in outer_class_names + [class_decl.name]])

    property_decl = ast_pb2.Decl()
    property_decl.CopyFrom(member)
    property_decl.var.name.native = (
        fq_native + EXTEND_INFIX + member.var.name.native)
    if member.var.name.cpp_name == member.var.name.native:
      property_decl.var.name.cpp_name = (
          fq_native + EXTEND_INFIX + member.var.name.cpp_name)

    p = _GenerateParameterSelf(class_decl, outer_class_names)
    property_decl.var.cpp_get.params.insert(0, p)
    property_decl.var.cpp_get.name.cpp_name = (
        fq_native + EXTEND_INFIX + member.var.cpp_get.name.cpp_name)
    if member.var.HasField('cpp_set'):
      property_decl.var.cpp_set.name.cpp_name = (
          fq_native + EXTEND_INFIX + member.var.cpp_set.name.cpp_name)
      p = _GenerateParameterSelf(class_decl, outer_class_names)
      property_decl.var.cpp_set.params.insert(0, p)
    extend_property_decls.append(property_decl)
    member_delete_indices.append(member_index)

    # generate property getters
    # (setters do not need this kind of functionality)
    getter_decl = ast_pb2.FuncDecl()
    getter_decl.CopyFrom(member.var.cpp_get)
    getter_decl.name.native = getter_decl.name.cpp_name = (
        fq_native + EXTEND_INFIX + member.var.cpp_get.name.cpp_name)
    p = _GenerateParameterSelf(class_decl, outer_class_names)
    getter_decl.params.insert(0, p)
    getter_decl.is_extend_method = True
    func_decl = ast_pb2.Decl()
    func_decl.func.CopyFrom(getter_decl)
    func_decl.decltype = ast_pb2.Decl.Type.FUNC
    extend_getter_decls.append(func_decl)

  for member_index in reversed(member_delete_indices):
    del class_decl.members[member_index]
예제 #4
0
파일: function.py 프로젝트: google/clif
def _generate_overload_for_unknown_default_function(
    num_unknown: int,
    module_name: str,
    func_decl: ast_pb2.FuncDecl,
    capsule_types: Set[str],
    class_decl: Optional[ast_pb2.ClassDecl] = None
) -> Generator[str, None, None]:
    """Generate multiple definitions for functions with unknown default values."""
    temp_func_decl = ast_pb2.FuncDecl()
    temp_func_decl.CopyFrom(func_decl)
    for _ in range(num_unknown):
        yield from _generate_function(module_name, temp_func_decl,
                                      capsule_types, class_decl)
        del temp_func_decl.params[-1]
    yield from _generate_function(module_name, temp_func_decl, capsule_types,
                                  class_decl)
예제 #5
0
 def assertFuncEqual(self, proto, code):
   ast = ast_pb2.FuncDecl()
   text_format.Parse(proto, ast)
   out = '\n'.join(self.m.WrapFunc(ast, -1, ''))+'\n'
   self.assertMultiLineEqual(out, textwrap.dedent(code))
예제 #6
0
파일: pytd2proto.py 프로젝트: yijunyu/clif
    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)
        pyname = p.name.native
        self.check_known_name(pyname)
        decorators = ast.decorators.asList()
        if not is_iterator:
            self._typetable[pyname] = [p.name.cpp_name]
            if 'final' in decorators:
                p.final = True
                decorators.remove('final')
        if decorators:
            raise NameError('Unknown class decorator(s)%s: %s' %
                            (atln, ', '.join(decorators)))
        _set_bases(p.bases, ast.bases, self._names, self._typetable)
        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)
                if not ast.bases:
                    raise SyntaxError(
                        'only derived class allowed to be empty' + 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)
        for m in p.members:

            # Fix ctor name to be the class name.
            if m.decltype != m.FUNC:
                continue
            if m.func.name.native == '__init__':
                if (m.func.name.cpp_name and m.func.name.cpp_name
                        not in [cpp_name, '__init__']):
                    print(
                        'Arbitrary names (like "{0}") for {1} ctor not allowed.'
                        ' Set to {1}'.format(m.func.name.cpp_name, cpp_name),
                        file=sys.stderr)
                m.func.name.cpp_name = cpp_name
                m.func.constructor = True
            elif m.func.name.native == cpp_name:
                raise NameError('Use __init__ to wrap a "%s" constructor' %
                                pyname + atln)
            elif m.func.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 m.func.name.cpp_name:  # An additional ctor.
                m.func.name.cpp_name = cpp_name
                m.func.constructor = True

            # Fix 'self' for C++ operator function (implemented out of class).
            elif m.func.name.native in _RIGHT_OPS:
                if len(m.func.params) != 1:
                    raise ValueError('%s must have only 1 input parameter' %
                                     m.func.name.native + atln)
                m.func.cpp_opfunction = True  # Mark a free function.
                _set_self(m.func.params.add(),
                          cpp_name)  # Add the instance parameter.
            elif '::' in m.func.name.cpp_name:
                if not m.func.params:
                    m.func.params.add()
                # else make room for param[0] by shifting 0->1, 1->2 and so on.
                elif len(m.func.params) == 1:
                    m.func.params.extend([m.func.params[0]])
                else:
                    pcopy = ast_pb2.FuncDecl()
                    pcopy.params.extend(m.func.params)
                    del m.func.params[1:]
                    m.func.params.extend(pcopy.params)
                    del pcopy
                m.func.cpp_opfunction = True  # Mark a free function.
                _set_self(m.func.params[0],
                          cpp_name)  # Set the instance parameter.
        _move_local_types(p.members, pyname + '.', cpp_name + '::',
                          self._typetable)
        return pyname