'Handle non-literal function\'s default arguments.'

def analyse_default_args(self, env):

    nonliteral_objects = []
    nonliteral_other = []
    default_args = []
    default_kwargs = []
    annotations = []
    must_use_constants = (env.is_c_class_scope or (self.def_node.is_wrapper and env.is_module_scope))
    for arg in self.def_node.args:
        if (arg.default and (not must_use_constants)):
            if (not arg.default.is_literal):
                arg.is_dynamic = True
                if arg.type.is_pyobject:
                    nonliteral_objects.append(arg)
                else:
                    nonliteral_other.append(arg)
            else:
                arg.default = DefaultLiteralArgNode(arg.pos, arg.default)
            if arg.kw_only:
                default_kwargs.append(arg)
            else:
                default_args.append(arg)
        if arg.annotation:
            arg.annotation = arg.annotation.analyse_types(env)
            if (not arg.annotation.type.is_pyobject):
                arg.annotation = arg.annotation.coerce_to_pyobject(env)
            annotations.append((arg.pos, arg.name, arg.annotation))
    for arg in (self.def_node.star_arg, self.def_node.starstar_arg):
        if (arg and arg.annotation):
            arg.annotation = arg.annotation.analyse_types(env)
            if (not arg.annotation.type.is_pyobject):
                arg.annotation = arg.annotation.coerce_to_pyobject(env)
            annotations.append((arg.pos, arg.name, arg.annotation))
    if self.def_node.return_type_annotation:
        annotations.append((self.def_node.return_type_annotation.pos, StringEncoding.EncodedString('return'), self.def_node.return_type_annotation))
    if (nonliteral_objects or nonliteral_other):
        module_scope = env.global_scope()
        cname = module_scope.next_id(Naming.defaults_struct_prefix)
        scope = Symtab.StructOrUnionScope(cname)
        self.defaults = []
        for arg in nonliteral_objects:
            entry = scope.declare_var(arg.name, arg.type, None, (Naming.arg_prefix + arg.name), allow_pyobject=True)
            self.defaults.append((arg, entry))
        for arg in nonliteral_other:
            entry = scope.declare_var(arg.name, arg.type, None, (Naming.arg_prefix + arg.name), allow_pyobject=False)
            self.defaults.append((arg, entry))
        entry = module_scope.declare_struct_or_union(None, 'struct', scope, 1, None, cname=cname)
        self.defaults_struct = scope
        self.defaults_pyobjects = len(nonliteral_objects)
        for (arg, entry) in self.defaults:
            arg.default_value = ('%s->%s' % (Naming.dynamic_args_cname, entry.cname))
        self.def_node.defaults_struct = self.defaults_struct.name
    if (default_args or default_kwargs):
        if (self.defaults_struct is None):
            if default_args:
                defaults_tuple = TupleNode(self.pos, args=[arg.default for arg in default_args])
                self.defaults_tuple = defaults_tuple.analyse_types(env).coerce_to_pyobject(env)
            if default_kwargs:
                defaults_kwdict = DictNode(self.pos, key_value_pairs=[DictItemNode(arg.pos, key=IdentifierStringNode(arg.pos, value=arg.name), value=arg.default) for arg in default_kwargs])
                self.defaults_kwdict = defaults_kwdict.analyse_types(env)
        else:
            if default_args:
                defaults_tuple = DefaultsTupleNode(self.pos, default_args, self.defaults_struct)
            else:
                defaults_tuple = NoneNode(self.pos)
            if default_kwargs:
                defaults_kwdict = DefaultsKwDictNode(self.pos, default_kwargs, self.defaults_struct)
            else:
                defaults_kwdict = NoneNode(self.pos)
            defaults_getter = Nodes.DefNode(self.pos, args=[], star_arg=None, starstar_arg=None, body=Nodes.ReturnStatNode(self.pos, return_type=py_object_type, value=TupleNode(self.pos, args=[defaults_tuple, defaults_kwdict])), decorators=None, name=StringEncoding.EncodedString('__defaults__'))
            module_scope = env.global_scope()
            defaults_getter.analyse_declarations(module_scope)
            defaults_getter = defaults_getter.analyse_expressions(module_scope)
            defaults_getter.body = defaults_getter.body.analyse_expressions(defaults_getter.local_scope)
            defaults_getter.py_wrapper_required = False
            defaults_getter.pymethdef_required = False
            self.def_node.defaults_getter = defaults_getter
    if annotations:
        annotations_dict = DictNode(self.pos, key_value_pairs=[DictItemNode(pos, key=IdentifierStringNode(pos, value=name), value=value) for (pos, name, value) in annotations])
        self.annotations_dict = annotations_dict.analyse_types(env)
