lys_make_implemented_r(struct lys_module *module, struct unres_schema *unres)
{
    struct ly_ctx *ctx;
    struct lys_node *root, *next, *node;
    struct lys_module *target_module;
    uint16_t i, j, k;

    assert(module->implemented);
    ctx = module->ctx;

    for (i = 0; i < ctx->models.used; ++i) {
        if (module == ctx->models.list[i]) {
            continue;
        }

        if (!strcmp(module->name, ctx->models.list[i]->name) && ctx->models.list[i]->implemented) {
            LOGERR(ctx, LY_EINVAL, "Module \"%s\" in another revision already implemented.", module->name);
            return EXIT_FAILURE;
        }
    }

    for (i = 0; i < module->augment_size; i++) {

        /* make target module implemented if was not */
        assert(module->augment[i].target);
        target_module = lys_node_module(module->augment[i].target);
        if (!target_module->implemented) {
            target_module->implemented = 1;
            if (unres_schema_add_node(target_module, unres, NULL, UNRES_MOD_IMPLEMENT, NULL) == -1) {
                return -1;
            }
        }

        /* apply augment */
        if ((module->augment[i].flags & LYS_NOTAPPLIED) && apply_aug(&module->augment[i], unres)) {
            return -1;
        }
    }

    /* identities */
    for (i = 0; i < module->ident_size; i++) {
        for (j = 0; j < module->ident[i].base_size; j++) {
            resolve_identity_backlink_update(&module->ident[i], module->ident[i].base[j]);
        }
    }

    /* process augments in submodules */
    for (i = 0; i < module->inc_size && module->inc[i].submodule; ++i) {
        module->inc[i].submodule->implemented = 1;

        for (j = 0; j < module->inc[i].submodule->augment_size; j++) {

            /* make target module implemented if it was not */
            assert(module->inc[i].submodule->augment[j].target);
            target_module = lys_node_module(module->inc[i].submodule->augment[j].target);
            if (!target_module->implemented) {
                target_module->implemented = 1;
                if (unres_schema_add_node(target_module, unres, NULL, UNRES_MOD_IMPLEMENT, NULL) == -1) {
                    return -1;
                }
            }

            /* apply augment */
            if ((module->inc[i].submodule->augment[j].flags & LYS_NOTAPPLIED) && apply_aug(&module->inc[i].submodule->augment[j], unres)) {
                return -1;
            }
        }

        /* identities */
        for (j = 0; j < module->inc[i].submodule->ident_size; j++) {
            for (k = 0; k < module->inc[i].submodule->ident[j].base_size; k++) {
                resolve_identity_backlink_update(&module->inc[i].submodule->ident[j],
                                                 module->inc[i].submodule->ident[j].base[k]);
            }
        }
    }

    LY_TREE_FOR(module->data, root) {
        /* handle leafrefs and recursively change the implemented flags in the leafref targets */
        LY_TREE_DFS_BEGIN(root, next, node) {
            if (node->nodetype == LYS_GROUPING) {
                goto nextsibling;
            }
            if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
                if (((struct lys_node_leaf *)node)->type.base == LY_TYPE_LEAFREF) {
                    if (unres_schema_add_node(module, unres, &((struct lys_node_leaf *)node)->type,
                                              UNRES_TYPE_LEAFREF, node) == -1) {
                        return -1;
                    }
                }
            }

            /* modified LY_TREE_DFS_END */
            next = node->child;
            /* child exception for leafs, leaflists and anyxml without children */
            if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA)) {
                next = NULL;
            }
            if (!next) {
nextsibling:
                /* no children */
                if (node == root) {
                    /* we are done, root has no children */
                    break;
                }
                /* try siblings */
                next = node->next;
            }
            while (!next) {
                /* parent is already processed, go to its sibling */
                node = lys_parent(node);
                /* no siblings, go back through parents */
                if (lys_parent(node) == lys_parent(root)) {
                    /* we are done, no next element to process */
                    break;
                }
                next = node->next;
            }
        }
    }

    return EXIT_SUCCESS;
}