schema tree REFACTOR overloaded implemented flag (#1223)

It no longer needs to be overloaded by
marking modules that are currently being
implemented. Instead, there is a set with
al such modules.
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 49e2dd6..5f11d5b 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -811,44 +811,75 @@
     return LY_SUCCESS;
 }
 
-LY_ERR
-lys_set_implemented_internal(struct lys_module *mod, uint8_t value)
+API LY_ERR
+lys_set_implemented(struct lys_module *mod)
 {
+    LY_ERR ret = LY_SUCCESS, r;
     struct lys_module *m;
+    uint32_t i, idx;
 
     LY_CHECK_ARG_RET(NULL, mod, LY_EINVAL);
 
     if (mod->implemented) {
+        /* mod is already implemented */
         return LY_SUCCESS;
     }
 
     /* we have module from the current context */
     m = ly_ctx_get_module_implemented(mod->ctx, mod->name);
     if (m) {
-        if (m != mod) {
-            /* check collision with other implemented revision */
-            LOGERR(mod->ctx, LY_EDENIED, "Module \"%s\" is present in the context in other implemented revision (%s).",
-                   mod->name, mod->revision ? mod->revision : "module without revision");
-            return LY_EDENIED;
-        } else {
-            /* mod is already implemented */
-            return LY_SUCCESS;
-        }
+        assert(m != mod);
+
+        /* check collision with other implemented revision */
+        LOGERR(mod->ctx, LY_EDENIED, "Module \"%s%s%s\" is present in the context in other implemented revision (%s).",
+                mod->name, mod->revision ? "@" : "", mod->revision ? mod->revision : "", m->revision ? m->revision : "none");
+        return LY_EDENIED;
     }
 
+    /* add the module into newly implemented module set */
+    LY_CHECK_RET(ly_set_add(&mod->ctx->implementing, mod, LY_SET_OPT_USEASLIST, NULL));
+
     /* mark the module implemented, check for collision was already done */
-    mod->implemented = value;
+    mod->implemented = 1;
 
     /* compile the schema */
-    LY_CHECK_RET(lys_compile(mod, LYSC_OPT_INTERNAL));
+    ret = lys_compile(mod, 0);
 
-    return LY_SUCCESS;
-}
+    if (mod == mod->ctx->implementing.objs[0]) {
+        /* the first module being implemented, consolidate the set */
+        if (ret) {
+            /* failure, full compile revert */
+            for (i = 0; i < mod->ctx->list.count; ++i) {
+                m = mod->ctx->list.objs[i];
+                if (ly_set_contains(&mod->ctx->implementing, m, &idx)) {
+                    assert(m->implemented);
 
-API LY_ERR
-lys_set_implemented(struct lys_module *mod)
-{
-    return lys_set_implemented_internal(mod, 1);
+                    /* make the module correctly non-implemented again */
+                    m->implemented = 0;
+                    ly_set_rm_index(&mod->ctx->implementing, idx, NULL);
+                    lys_precompile_augments_deviations_revert(mod->ctx, m);
+                }
+
+                /* free the compiled version of the module, if any */
+                lysc_module_free(m->compiled, NULL);
+                m->compiled = NULL;
+
+                if (m->implemented) {
+                    /* recompile, must succeed because it was already compiled; hide messages because any
+                     * warnings were already printed, are not really relevant, and would hide the real error */
+                    uint32_t prev_lo = ly_log_options(0);
+                    r = lys_compile(m, 0);
+                    ly_log_options(prev_lo);
+                    if (r) {
+                        LOGERR(mod->ctx, r, "Recompilation of module \"%s\" failed.", m->name);
+                    }
+                }
+            }
+        }
+
+        ly_set_erase(&mod->ctx->implementing, NULL);
+    }
+    return ret;
 }
 
 static LY_ERR
@@ -1048,9 +1079,6 @@
             ret = LY_EDENIED;
             goto error;
         }
-
-        /* being implemented */
-        mod->implemented = ctx->module_set_id;
     }
 
     /* check for duplicity in the context */
@@ -1118,7 +1146,7 @@
 
     lys_parser_fill_filepath(ctx, in, &mod->filepath);
 
-    if (!mod->implemented) {
+    if (!implement) {
         /* pre-compile features and identities of the module */
         LY_CHECK_GOTO(ret = lys_feature_precompile(NULL, ctx, mod, mod->parsed->features, &mod->features), error);
         LY_CHECK_GOTO(ret = lys_identity_precompile(NULL, ctx, mod, mod->parsed->identities, &mod->identities), error);
@@ -1137,7 +1165,7 @@
     /* resolve imports and includes */
     LY_CHECK_GOTO(ret = lys_resolve_import_include(pctx, mod->parsed), error_ctx);
 
-    if (!mod->implemented) {
+    if (!implement) {
         /* pre-compile features and identities of any submodules */
         LY_ARRAY_FOR(mod->parsed->includes, u) {
             LY_CHECK_GOTO(ret = lys_feature_precompile(NULL, ctx, mod, mod->parsed->includes[u].submodule->features,
@@ -1150,10 +1178,9 @@
     /* check name collisions - typedefs and TODO groupings */
     LY_CHECK_GOTO(ret = lysp_check_typedefs(pctx, mod->parsed), error_ctx);
 
-    /* compile */
-    if (!mod->compiled) {
-        ret = lys_compile(mod, 0);
-        LY_CHECK_GOTO(ret, error_ctx);
+    if (implement) {
+        /* implement (compile) */
+        LY_CHECK_GOTO(ret = lys_set_implemented(mod), error_ctx);
     }
 
     if (format == LYS_IN_YANG) {