schema CHANGE integrate statement parser with the compilation process

Does not cover all the statements - focused mainly for yang-data
extension, so it handles schema nodes processing.
diff --git a/src/schema_compile.c b/src/schema_compile.c
index 07133d7..51ea049 100644
--- a/src/schema_compile.c
+++ b/src/schema_compile.c
@@ -619,125 +619,149 @@
 }
 
 LY_ERR
-lys_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext_instance *ext, struct lysc_ext_substmt *substmts)
+lys_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext_instance *ext_p, struct lysc_ext_instance *ext)
 {
     LY_ERR ret = LY_EVALID, r;
     LY_ARRAY_COUNT_TYPE u;
     struct lysp_stmt *stmt;
-    struct lysp_qname *iffeatures, *iffeat;
     void *parsed = NULL, **compiled = NULL;
-    ly_bool enabled;
 
     /* check for invalid substatements */
-    for (stmt = ext->child; stmt; stmt = stmt->next) {
+    for (stmt = ext_p->child; stmt; stmt = stmt->next) {
         if (stmt->flags & (LYS_YIN_ATTR | LYS_YIN_ARGUMENT)) {
             continue;
         }
-        LY_ARRAY_FOR(substmts, u) {
-            if (substmts[u].stmt == stmt->kw) {
+        LY_ARRAY_FOR(ext->substmts, u) {
+            if (ext->substmts[u].stmt == stmt->kw) {
                 break;
             }
         }
-        if (u == LY_ARRAY_COUNT(substmts)) {
+        if (u == LY_ARRAY_COUNT(ext->substmts)) {
             LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\" as a child of \"%s%s%s\" extension instance.",
-                    stmt->stmt, ext->name, ext->argument ? " " : "", ext->argument ? ext->argument : "");
+                    stmt->stmt, ext_p->name, ext_p->argument ? " " : "", ext_p->argument ? ext_p->argument : "");
             goto cleanup;
         }
     }
 
     /* TODO store inherited data, e.g. status first, but mark them somehow to allow to overwrite them and not detect duplicity */
 
+    /* note into the compile context that we are processing extension now */
+    ctx->ext = ext;
+
     /* keep order of the processing the same as the order in the defined substmts,
      * the order is important for some of the statements depending on others (e.g. type needs status and units) */
-    LY_ARRAY_FOR(substmts, u) {
-        ly_bool stmt_present = 0;
 
-        for (stmt = ext->child; stmt; stmt = stmt->next) {
-            if (substmts[u].stmt != stmt->kw) {
+    LY_ARRAY_FOR(ext->substmts, u) {
+        uint64_t stmt_counter = 0;
+
+        for (stmt = ext_p->child; stmt; stmt = stmt->next) {
+            if (ext->substmts[u].stmt != stmt->kw) {
                 continue;
             }
 
-            stmt_present = 1;
-            if (substmts[u].storage) {
+            parsed = NULL;
+            stmt_counter++;
+            if (ext->substmts[u].storage) {
                 switch (stmt->kw) {
-                case LY_STMT_STATUS:
-                    assert(substmts[u].cardinality < LY_STMT_CARD_SOME);
-                    LY_CHECK_ERR_GOTO(r = lysp_stmt_parse(ctx, stmt, &substmts[u].storage, /* TODO */ NULL), ret = r, cleanup);
+                case LY_STMT_ACTION:
+                case LY_STMT_ANYDATA:
+                case LY_STMT_ANYXML:
+                case LY_STMT_CONTAINER:
+                case LY_STMT_CHOICE:
+                case LY_STMT_LEAF:
+                case LY_STMT_LEAF_LIST:
+                case LY_STMT_LIST:
+                case LY_STMT_NOTIFICATION:
+                case LY_STMT_RPC:
+                case LY_STMT_USES:
+                    r = lysp_stmt_parse(ctx, stmt, &parsed, NULL);
+                    LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
+
+                    /* set storage as an alternative document root in the compile context */
+                    r = lys_compile_node(ctx, parsed, NULL, 0, NULL);
+                    lysp_node_free(ctx->ctx, parsed);
+                    LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
                     break;
                 case LY_STMT_DESCRIPTION:
                 case LY_STMT_REFERENCE:
                 case LY_STMT_UNITS: {
-                    const char **units;
+                    const char **str_p;
 
-                    if (substmts[u].cardinality < LY_STMT_CARD_SOME) {
+                    if (ext->substmts[u].cardinality < LY_STMT_CARD_SOME) {
                         /* single item */
-                        if (*((const char **)substmts[u].storage)) {
+                        if (*((const char **)ext->substmts[u].storage)) {
                             LOGVAL(ctx->ctx, LY_VCODE_DUPSTMT, stmt->stmt);
                             goto cleanup;
                         }
-                        units = (const char **)substmts[u].storage;
+                        str_p = (const char **)ext->substmts[u].storage;
                     } else {
                         /* sized array */
-                        const char ***units_array = (const char ***)substmts[u].storage;
-                        LY_ARRAY_NEW_GOTO(ctx->ctx, *units_array, units, ret, cleanup);
+                        const char ***strings_array = (const char ***)ext->substmts[u].storage;
+                        LY_ARRAY_NEW_GOTO(ctx->ctx, *strings_array, str_p, ret, cleanup);
                     }
-                    r = lydict_insert(ctx->ctx, stmt->arg, 0, units);
+                    r = lydict_insert(ctx->ctx, stmt->arg, 0, str_p);
                     LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
                     break;
                 }
-                case LY_STMT_TYPE: {
-                    uint16_t *flags = lys_compile_extension_instance_storage(LY_STMT_STATUS, substmts);
-                    const char **units = lys_compile_extension_instance_storage(LY_STMT_UNITS, substmts);
-
-                    if (substmts[u].cardinality < LY_STMT_CARD_SOME) {
-                        /* single item */
-                        if (*(struct lysc_type **)substmts[u].storage) {
-                            LOGVAL(ctx->ctx, LY_VCODE_DUPSTMT, stmt->stmt);
-                            goto cleanup;
-                        }
-                        compiled = substmts[u].storage;
-                    } else {
-                        /* sized array */
-                        struct lysc_type ***types = (struct lysc_type ***)substmts[u].storage, **type = NULL;
-                        LY_ARRAY_NEW_GOTO(ctx->ctx, *types, type, ret, cleanup);
-                        compiled = (void *)type;
-                    }
+                case LY_STMT_IF_FEATURE: {
+                    ly_bool enabled;
 
                     r = lysp_stmt_parse(ctx, stmt, &parsed, NULL);
                     LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
-                    r = lys_compile_type(ctx, NULL, flags ? *flags : 0, ext->name, parsed, (struct lysc_type **)compiled,
-                            units && !*units ? units : NULL, NULL);
-                    lysp_type_free(ctx->ctx, parsed);
-                    free(parsed);
-                    LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
-                    break;
-                }
-                case LY_STMT_IF_FEATURE:
-                    iffeatures = NULL;
-                    LY_ARRAY_NEW_GOTO(ctx->ctx, iffeatures, iffeat, ret, cleanup);
-                    iffeat->str = stmt->arg;
-                    iffeat->mod = ctx->pmod;
-                    r = lys_eval_iffeatures(ctx->ctx, iffeatures, &enabled);
-                    LY_ARRAY_FREE(iffeatures);
+
+                    r = lys_eval_iffeatures(ctx->ctx, parsed, &enabled);
+                    FREE_ARRAY(ctx->ctx, (struct lysp_qname *)parsed, lysp_qname_free);
                     LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
                     if (!enabled) {
                         /* it is disabled, remove the whole extension instance */
                         return LY_ENOT;
                     }
                     break;
+                }
+                case LY_STMT_STATUS:
+                    assert(ext->substmts[u].cardinality < LY_STMT_CARD_SOME);
+                    LY_CHECK_ERR_GOTO(r = lysp_stmt_parse(ctx, stmt, &ext->substmts[u].storage, /* TODO */ NULL), ret = r, cleanup);
+                    break;
+                case LY_STMT_TYPE: {
+                    uint16_t *flags = lys_compile_extension_instance_storage(LY_STMT_STATUS, ext->substmts);
+                    const char **units = lys_compile_extension_instance_storage(LY_STMT_UNITS, ext->substmts);
+
+                    if (ext->substmts[u].cardinality < LY_STMT_CARD_SOME) {
+                        /* single item */
+                        if (*(struct lysc_type **)ext->substmts[u].storage) {
+                            LOGVAL(ctx->ctx, LY_VCODE_DUPSTMT, stmt->stmt);
+                            goto cleanup;
+                        }
+                        compiled = ext->substmts[u].storage;
+                    } else {
+                        /* sized array */
+                        struct lysc_type ***types = (struct lysc_type ***)ext->substmts[u].storage, **type = NULL;
+                        LY_ARRAY_NEW_GOTO(ctx->ctx, *types, type, ret, cleanup);
+                        compiled = (void *)type;
+                    }
+
+                    r = lysp_stmt_parse(ctx, stmt, &parsed, NULL);
+                    LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
+                    r = lys_compile_type(ctx, NULL, flags ? *flags : 0, ext_p->name, parsed, (struct lysc_type **)compiled,
+                            units && !*units ? units : NULL, NULL);
+                    lysp_type_free(ctx->ctx, parsed);
+                    free(parsed);
+                    LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
+                    break;
+                }
                 /* TODO support other substatements (parse stmt to lysp and then compile lysp to lysc),
                  * also note that in many statements their extensions are not taken into account  */
                 default:
                     LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG, "Statement \"%s\" is not supported as an extension (found in \"%s%s%s\") substatement.",
-                            stmt->stmt, ext->name, ext->argument ? " " : "", ext->argument ? ext->argument : "");
+                            stmt->stmt, ext_p->name, ext_p->argument ? " " : "", ext_p->argument ? ext_p->argument : "");
                     goto cleanup;
                 }
             }
         }
 
-        if (((substmts[u].cardinality == LY_STMT_CARD_MAND) || (substmts[u].cardinality == LY_STMT_CARD_SOME)) && !stmt_present) {
+        if (((ext->substmts[u].cardinality == LY_STMT_CARD_MAND) || (ext->substmts[u].cardinality == LY_STMT_CARD_SOME)) && !stmt_counter) {
             LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG, "Missing mandatory keyword \"%s\" as a child of \"%s%s%s\".",
-                    ly_stmt2str(substmts[u].stmt), ext->name, ext->argument ? " " : "", ext->argument ? ext->argument : "");
+                    ly_stmt2str(ext->substmts[u].stmt), ext_p->name, ext_p->argument ? " " : "", ext_p->argument ? ext_p->argument : "");
             goto cleanup;
         }
     }
@@ -745,6 +769,7 @@
     ret = LY_SUCCESS;
 
 cleanup:
+    ctx->ext = NULL;
     return ret;
 }