schema compile CHANGE order keys at the beginning of the children list
diff --git a/src/parser_xml.c b/src/parser_xml.c
index e236b69..e6feea0 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -243,14 +243,20 @@
         if (parent) {
             if (prev && cur->schema->nodetype == LYS_LEAF && (cur->schema->flags & LYS_KEY)) {
                 /* it is key and we need to insert it into a correct place */
-                struct lysc_node_leaf **keys = ((struct lysc_node_list*)parent->schema)->keys;
+                struct lysc_node *key_s;
                 unsigned int cur_index, key_index;
                 struct lyd_node *key;
 
-                for (cur_index = 0; keys[cur_index] != (struct lysc_node_leaf*)cur->schema; ++cur_index);
-                for (key = prev; !(key->schema->flags & LYS_KEY) && key->prev != prev; key = key->prev);
+                for (cur_index = 0, key_s = ((struct lysc_node_list*)parent->schema)->child;
+                        key_s && key_s != cur->schema;
+                        ++cur_index, key_s = key_s->next);
+                for (key = prev;
+                        !(key->schema->flags & LYS_KEY) && key->prev != prev;
+                        key = key->prev);
                 for (; key->schema->flags & LYS_KEY; key = key->prev) {
-                    for (key_index = 0; keys[key_index] != (struct lysc_node_leaf*)key->schema; ++key_index);
+                    for (key_index = 0, key_s = ((struct lysc_node_list*)parent->schema)->child;
+                            key_s && key_s != key->schema;
+                            ++key_index, key_s = key_s->next);
                     if (key_index < cur_index) {
                         /* cur key is supposed to be placed after the key */
                         cur->next = key->next;
diff --git a/src/plugins_types.c b/src/plugins_types.c
index 0972653..e7860cd 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -1730,10 +1730,13 @@
                 }
                 if (token[0] != '[') {
                     /* now we should have all the keys */
-                    if (LY_ARRAY_SIZE(((struct lysc_node_list*)node_s)->keys) != predicates.count) {
+                    unsigned int keys_count = 0;
+                    for (struct lysc_node *key = ((struct lysc_node_list*)node_s)->child;
+                            key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY);
+                            keys_count++, key = key->next);
+                    if (keys_count != predicates.count) {
                         asprintf(&errmsg, "Invalid instance-identifier \"%.*s\" value - missing %u key(s) for the list instance \"%.*s\".",
-                                 (int)value_len, value, LY_ARRAY_SIZE(((struct lysc_node_list*)node_s)->keys) - predicates.count,
-                                 (int)(token - node_start), node_start);
+                                 (int)value_len, value, keys_count - predicates.count, (int)(token - node_start), node_start);
                         goto error;
                     }
                 }
diff --git a/src/printer_yang.c b/src/printer_yang.c
index c6851db..8736639 100755
--- a/src/printer_yang.c
+++ b/src/printer_yang.c
@@ -1725,11 +1725,11 @@
     LY_ARRAY_FOR(list->musts, u) {
         yprc_must(ctx, &list->musts[u], NULL);
     }
-    if (list->keys) {
+    if (!(list->flags & LYS_KEYLESS)) {
         ypr_open(ctx->out, &flag);
         ly_print(ctx->out, "%*skey \"", INDENT);
-        LY_ARRAY_FOR(list->keys, u) {
-            ly_print(ctx->out, "%s%s", u > 0 ? ", " : "", list->keys[u]->name);
+        for (struct lysc_node *key = list->child; key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY); key = key->next) {
+            ly_print(ctx->out, "%s%s", u > 0 ? ", " : "", key->name);
         }
         ly_print(ctx->out, "\";\n");
     }
diff --git a/src/tree_data.c b/src/tree_data.c
index 27742cb..289f70c 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -566,11 +566,11 @@
         iter1 = ((struct lyd_node_inner*)node1)->child;
         iter2 = ((struct lyd_node_inner*)node2)->child;
 
-        if (((struct lysc_node_list*)node1->schema)->keys && !(options & LYD_COMPARE_FULL_RECURSION)) {
+        if (!(node1->schema->flags & LYS_KEYLESS) && !(options & LYD_COMPARE_FULL_RECURSION)) {
             /* lists with keys, their equivalence is based on their keys */
-            unsigned int u;
-
-            LY_ARRAY_FOR(((struct lysc_node_list*)node1->schema)->keys, u) {
+            for (struct lysc_node *key = ((struct lysc_node_list*)node1->schema)->child;
+                    key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY);
+                    key = key->next) {
                 if (lyd_compare(iter1, iter2, options)) {
                     return LY_ENOT;
                 }
@@ -714,15 +714,19 @@
                 last = lyd_dup_recursive(child, inner, last, options);
                 LY_CHECK_GOTO(!last, error);
             }
-        } else if (dup->schema->nodetype == LYS_LIST && ((struct lysc_node_list*)dup->schema)->keys) {
+        } else if (dup->schema->nodetype == LYS_LIST && !(dup->schema->flags & LYS_KEYLESS)) {
             /* always duplicate keys of a list */
-            unsigned int u;
-
             child = orig->child;
-            LY_ARRAY_FOR(((struct lysc_node_list*)dup->schema)->keys, u) {
+            for (struct lysc_node *key = ((struct lysc_node_list*)dup->schema)->child;
+                    key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY);
+                    key = key->next) {
                 if (!child) {
                     /* possibly not keys are present in filtered tree */
                     break;
+                } else if (child->schema != key) {
+                    /* possibly not all keys are present in filtered tree,
+                     * but there can be also some non-key nodes */
+                    continue;
                 }
                 last = lyd_dup_recursive(child, inner, last, options);
                 child = child->next;
@@ -786,7 +790,7 @@
                 repeat = 0;
                 /* get know if there is a keyless list which we will have to rehash */
                 for (struct lyd_node_inner *piter = parent; piter; piter = piter->parent) {
-                    if (piter->schema->nodetype == LYS_LIST && !((struct lysc_node_list*)piter->schema)->keys) {
+                    if (piter->schema->nodetype == LYS_LIST && (piter->schema->flags & LYS_KEYLESS)) {
                         keyless_parent_list = 1;
                         break;
                     }
@@ -845,7 +849,7 @@
     if (keyless_parent_list) {
         /* rehash */
         for (; local_parent; local_parent = local_parent->parent) {
-            if (local_parent->schema->nodetype == LYS_LIST && !((struct lysc_node_list*)local_parent->schema)->keys) {
+            if (local_parent->schema->nodetype == LYS_LIST && (local_parent->schema->flags & LYS_KEYLESS)) {
                 lyd_hash((struct lyd_node*)local_parent);
             }
         }
diff --git a/src/tree_data_hash.c b/src/tree_data_hash.c
index 37d6337..33104cc 100644
--- a/src/tree_data_hash.c
+++ b/src/tree_data_hash.c
@@ -51,10 +51,16 @@
 
     if (node->schema->nodetype == LYS_LIST) {
         struct lyd_node_inner *list = (struct lyd_node_inner*)node;
-        if (((struct lysc_node_list*)node->schema)->keys) {
+        if (!(node->schema->flags & LYS_KEYLESS)) {
             /* list's hash is made of its keys */
-            unsigned int keys_count = LY_ARRAY_SIZE(((struct lysc_node_list*)node->schema)->keys);
-            for (iter = list->child; iter && keys_count; --keys_count, iter = iter->next) {
+            struct lysc_node *key;
+            for (key = ((struct lysc_node_list*)node->schema)->child, iter = list->child;
+                    key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY) && iter;
+                    key = key->next, iter = iter->next) {
+                for ( ; iter && iter->schema != key; iter = iter->next);
+                if (!iter) {
+                    break;
+                }
                 int dynamic = 0;
                 struct lysc_type *type = ((struct lysc_node_leaf*)iter->schema)->type;
                 const char *value = type->plugin->print(&((struct lyd_node_term*)iter)->value, LYD_JSON, json_print_get_prefix, NULL, &dynamic);
diff --git a/src/tree_schema.h b/src/tree_schema.h
index 004a195..9c3346f 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -462,6 +462,7 @@
  *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *      10 LYS_SET_DFLT     | | |x|x| | |x| | | | | | | | |
  *         LYS_ISENUM       | | | | | | | | | | | | | | |x|
+ *         LYS_KEYLESS      | | | | |x| | | | | | | | | | |
  *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *      11 LYS_SET_UNITS    | | |x|x| | | | | | | | | | | |
  *                          +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -494,6 +495,7 @@
 #define LYS_PRESENCE     0x80        /**< flag for presence property of a container, applicable only to ::lysc_node_container */
 #define LYS_UNIQUE       0x80        /**< flag for leafs being part of a unique set, applicable only to ::lysc_node_leaf */
 #define LYS_KEY          0x100       /**< flag for leafs being a key of a list, applicable only to ::lysc_node_leaf */
+#define LYS_KEYLESS      0x200       /**< flag for list without any key, applicable only to ::lysc_node_list */
 #define LYS_FENABLED     0x100       /**< feature enabled flag, applicable only to ::lysc_feature */
 #define LYS_ORDBY_SYSTEM 0x80        /**< ordered-by user lists, applicable only to ::lysc_node_leaflist/::lysp_node_leaflist and
                                           ::lysc_node_list/::lysp_node_list */
@@ -1322,7 +1324,6 @@
     struct lysc_action *actions;     /**< list of actions ([sized array](@ref sizedarrays)) */
     struct lysc_notif *notifs;       /**< list of notifications ([sized array](@ref sizedarrays)) */
 
-    struct lysc_node_leaf **keys;    /**< list of pointers to the keys ([sized array](@ref sizedarrays)) */
     struct lysc_node_leaf ***uniques; /**< list of sized arrays of pointers to the unique nodes ([sized array](@ref sizedarrays)) */
     uint32_t min;                    /**< min-elements constraint */
     uint32_t max;                    /**< max-elements constraint */
diff --git a/src/tree_schema_compile.c b/src/tree_schema_compile.c
index 9d1639d..bea32c1 100644
--- a/src/tree_schema_compile.c
+++ b/src/tree_schema_compile.c
@@ -2107,7 +2107,7 @@
     const struct lysc_node *src_node, *dst_node;
     const char *path_key_expr, *pke_start, *src, *src_prefix, *dst, *dst_prefix;
     size_t src_len, src_prefix_len, dst_len, dst_prefix_len;
-    unsigned int dest_parent_times, c, u;
+    unsigned int dest_parent_times, c;
     const char *start, *end, *pke_end;
     struct ly_set keys = {0};
     int i;
@@ -2167,10 +2167,11 @@
             mod = start_node->module;
         }
         src_node = NULL;
-        if (context_node->keys) {
-            for (u = 0; u < LY_ARRAY_SIZE(context_node->keys); ++u) {
-                if (!strncmp(src, context_node->keys[u]->name, src_len) && context_node->keys[u]->name[src_len] == '\0') {
-                    src_node = (const struct lysc_node*)context_node->keys[u];
+        if (!(context_node->flags & LYS_KEYLESS)) {
+            struct lysc_node *key;
+            for (key = context_node->child; key && key->nodetype == LYS_LEAF && (key->flags & LYS_KEY); key = key->next) {
+                if (!strncmp(src, key->name, src_len) && key->name[src_len] == '\0') {
+                    src_node = key;
                     break;
                 }
             }
@@ -3785,7 +3786,7 @@
     struct lysp_node_list *list_p = (struct lysp_node_list*)node_p;
     struct lysc_node_list *list = (struct lysc_node_list*)node;
     struct lysp_node *child_p;
-    struct lysc_node_leaf **key;
+    struct lysc_node_leaf *key, *prev_key = NULL;
     size_t len;
     unsigned int u;
     const char *keystr, *delim;
@@ -3811,6 +3812,10 @@
 
     /* find all the keys (must be direct children) */
     keystr = list_p->key;
+    if (!keystr) {
+        /* keyless list */
+        list->flags |= LYS_KEYLESS;
+    }
     while (keystr) {
         delim = strpbrk(keystr, " \t\n");
         if (delim) {
@@ -3823,42 +3828,41 @@
         }
 
         /* key node must be present */
-        LY_ARRAY_NEW_RET(ctx->ctx, list->keys, key, LY_EMEM);
-        *key = (struct lysc_node_leaf*)lys_child(node, node->module, keystr, len, LYS_LEAF, LYS_GETNEXT_NOCHOICE | LYS_GETNEXT_NOSTATECHECK);
-        if (!(*key)) {
+        key = (struct lysc_node_leaf*)lys_child(node, node->module, keystr, len, LYS_LEAF, LYS_GETNEXT_NOCHOICE | LYS_GETNEXT_NOSTATECHECK);
+        if (!(key)) {
             LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
                    "The list's key \"%.*s\" not found.", len, keystr);
             return LY_EVALID;
         }
         /* keys must be unique */
-        for(u = 0; u < LY_ARRAY_SIZE(list->keys) - 1; ++u) {
-            if (*key == list->keys[u]) {
-                LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
-                       "Duplicated key identifier \"%.*s\".", len, keystr);
-                return LY_EVALID;
-            }
+        if (key->flags & LYS_KEY) {
+            /* the node was already marked as a key */
+            LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
+                   "Duplicated key identifier \"%.*s\".", len, keystr);
+            return LY_EVALID;
         }
-        lysc_update_path(ctx, (struct lysc_node*)list, (*key)->name);
+
+        lysc_update_path(ctx, (struct lysc_node*)list, key->name);
         /* key must have the same config flag as the list itself */
-        if ((list->flags & LYS_CONFIG_MASK) != ((*key)->flags & LYS_CONFIG_MASK)) {
+        if ((list->flags & LYS_CONFIG_MASK) != (key->flags & LYS_CONFIG_MASK)) {
             LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS, "Key of the configuration list must not be status leaf.");
             return LY_EVALID;
         }
         if (ctx->mod_def->version < LYS_VERSION_1_1) {
             /* YANG 1.0 denies key to be of empty type */
-            if ((*key)->type->basetype == LY_TYPE_EMPTY) {
+            if (key->type->basetype == LY_TYPE_EMPTY) {
                 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
                        "List's key cannot be of \"empty\" type until it is in YANG 1.1 module.");
                 return LY_EVALID;
             }
         } else {
             /* when and if-feature are illegal on list keys */
-            if ((*key)->when) {
+            if (key->when) {
                 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
                        "List's key must not have any \"when\" statement.");
                 return LY_EVALID;
             }
-            if ((*key)->iffeatures) {
+            if (key->iffeatures) {
                 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
                        "List's key must not have any \"if-feature\" statement.");
                 return LY_EVALID;
@@ -3867,20 +3871,58 @@
 
         /* check status */
         LY_CHECK_RET(lysc_check_status(ctx, list->flags, list->module, list->name,
-                                       (*key)->flags, (*key)->module, (*key)->name));
+                                       key->flags, key->module, key->name));
 
         /* ignore default values of the key */
-        if ((*key)->dflt) {
-            (*key)->dflt->realtype->plugin->free(ctx->ctx, (*key)->dflt);
-            lysc_type_free(ctx->ctx, (*key)->dflt->realtype);
-            free((*key)->dflt);
-            (*key)->dflt = NULL;
-            (*key)->dflt_mod = NULL;
+        if (key->dflt) {
+            key->dflt->realtype->plugin->free(ctx->ctx, key->dflt);
+            lysc_type_free(ctx->ctx, key->dflt->realtype);
+            free(key->dflt);
+            key->dflt = NULL;
+            key->dflt_mod = NULL;
         }
         /* mark leaf as key */
-        (*key)->flags |= LYS_KEY;
+        key->flags |= LYS_KEY;
+
+        /* move it to the correct position */
+        if ((prev_key && (struct lysc_node*)prev_key != key->prev) || (!prev_key && key->prev->next)) {
+            /* fix links in closest previous siblings of the key */
+            if (key->next) {
+                key->next->prev = key->prev;
+            } else {
+                /* last child */
+                list->child->prev = key->prev;
+            }
+            if (key->prev->next) {
+                key->prev->next = key->next;
+            }
+            /* fix links in the key */
+            if (prev_key) {
+                key->prev = (struct lysc_node*)prev_key;
+                key->next = prev_key->next;
+            } else {
+                key->prev = list->child->prev;
+                key->next = list->child;
+            }
+            /* fix links in closes future siblings of the key */
+            if (prev_key) {
+                if (prev_key->next) {
+                    prev_key->next->prev = (struct lysc_node*)key;
+                } else {
+                    list->child->prev = (struct lysc_node*)key;
+                }
+                prev_key->next = (struct lysc_node*)key;
+            } else {
+                list->child->prev = (struct lysc_node*)key;
+            }
+            /* fix links in parent */
+            if (!key->prev->next) {
+                list->child = (struct lysc_node*)key;
+            }
+        }
 
         /* next key value */
+        prev_key = key;
         keystr = delim;
         lysc_update_path(ctx, NULL, NULL);
     }
diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c
index 8383c19..adbc70b 100644
--- a/src/tree_schema_free.c
+++ b/src/tree_schema_free.c
@@ -731,7 +731,6 @@
     }
     FREE_ARRAY(ctx, node->musts, lysc_must_free);
 
-    LY_ARRAY_FREE(node->keys);
     LY_ARRAY_FOR(node->uniques, u) {
         LY_ARRAY_FREE(node->uniques[u]);
     }
diff --git a/tests/src/test_tree_schema_compile.c b/tests/src/test_tree_schema_compile.c
index 9f93ae1..1be0815 100644
--- a/tests/src/test_tree_schema_compile.c
+++ b/tests/src/test_tree_schema_compile.c
@@ -600,28 +600,29 @@
     struct ly_ctx *ctx;
     struct lys_module *mod;
     struct lysc_node_list *list;
+    struct lysc_node *child;
 
     assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
 
     assert_non_null(mod = lys_parse_mem(ctx, "module a {namespace urn:a;prefix a;feature f;"
-                                        "list l1 {key \"x y\"; ordered-by user; leaf x {type string; when 1;}leaf y{type string;if-feature f;}}"
+                                        "list l1 {key \"x y\"; ordered-by user; leaf y{type string;if-feature f;} leaf x {type string; when 1;}}"
                                         "list l2 {config false;leaf value {type string;}}}", LYS_IN_YANG));
     list = (struct lysc_node_list*)mod->compiled->data;
     assert_non_null(list);
-    assert_non_null(list->keys);
-    assert_int_equal(2, LY_ARRAY_SIZE(list->keys));
-    assert_string_equal("x", list->keys[0]->name);
-    assert_string_equal("y", list->keys[1]->name);
+    assert_non_null(list->child);
+    assert_string_equal("x", list->child->name);
+    assert_true(list->child->flags & LYS_KEY);
+    assert_string_equal("y", list->child->next->name);
+    assert_true(list->child->next->flags & LYS_KEY);
     assert_non_null(list->child);
     assert_int_equal(LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_USER, list->flags);
     assert_true(list->child->flags & LYS_KEY);
     assert_true(list->child->next->flags & LYS_KEY);
     list = (struct lysc_node_list*)mod->compiled->data->next;
     assert_non_null(list);
-    assert_null(list->keys);
     assert_non_null(list->child);
-    assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM | LYS_SET_CONFIG, list->flags);
     assert_false(list->child->flags & LYS_KEY);
+    assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM | LYS_SET_CONFIG | LYS_KEYLESS, list->flags);
 
     assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;"
                                         "list l {key a; unique \"a c/b:b\"; unique \"c/e d\";"
@@ -630,11 +631,9 @@
     list = (struct lysc_node_list*)mod->compiled->data;
     assert_non_null(list);
     assert_string_equal("l", list->name);
-    assert_non_null(list->keys);
-    assert_int_equal(1, LY_ARRAY_SIZE(list->keys));
-    assert_string_equal("a", list->keys[0]->name);
-    assert_true(list->keys[0]->flags & LYS_KEY);
-    assert_null(list->keys[0]->dflt);
+    assert_string_equal("a", list->child->name);
+    assert_true(list->child->flags & LYS_KEY);
+    assert_null(((struct lysc_node_leaf*)list->child)->dflt);
     assert_non_null(list->uniques);
     assert_int_equal(2, LY_ARRAY_SIZE(list->uniques));
     assert_int_equal(2, LY_ARRAY_SIZE(list->uniques[0]));
@@ -653,11 +652,28 @@
     list = (struct lysc_node_list*)mod->compiled->data;
     assert_non_null(list);
     assert_string_equal("l", list->name);
-    assert_non_null(list->keys);
-    assert_int_equal(1, LY_ARRAY_SIZE(list->keys));
-    assert_string_equal("a", list->keys[0]->name);
-    assert_true(list->keys[0]->flags & LYS_KEY);
-    assert_int_equal(LY_TYPE_EMPTY, list->keys[0]->type->basetype);
+    assert_string_equal("a", list->child->name);
+    assert_true(list->child->flags & LYS_KEY);
+    assert_int_equal(LY_TYPE_EMPTY, ((struct lysc_node_leaf*)list->child)->type->basetype);
+
+    /* keys order */
+    assert_non_null(mod = lys_parse_mem(ctx, "module d {yang-version 1.1;namespace urn:d;prefix d;"
+                                        "list l {key \"d b c\";leaf a {type string;} leaf b {type string;} leaf c {type string;} leaf d {type string;}}}", LYS_IN_YANG));
+    list = (struct lysc_node_list*)mod->compiled->data;
+    assert_non_null(list);
+    assert_string_equal("l", list->name);
+    assert_non_null(child = list->child);
+    assert_string_equal("d", child->name);
+    assert_true(child->flags & LYS_KEY);
+    assert_non_null(child = child->next);
+    assert_string_equal("b", child->name);
+    assert_true(child->flags & LYS_KEY);
+    assert_non_null(child = child->next);
+    assert_string_equal("c", child->name);
+    assert_true(child->flags & LYS_KEY);
+    assert_non_null(child = child->next);
+    assert_string_equal("a", child->name);
+    assert_false(child->flags & LYS_KEY);
 
     /* invalid */
     assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;list l;}", LYS_IN_YANG));