[augeas-devel] augeas: master - Carry the key type explicitly in lenses

David Lutterkort lutter at fedoraproject.org
Tue Sep 1 18:09:13 UTC 2009


Gitweb:        http://git.fedorahosted.org/git/augeas.git?p=augeas.git;a=commitdiff;h=c2ff7ee84c402bc88b1ef74cbb381b1c30541246
Commit:        c2ff7ee84c402bc88b1ef74cbb381b1c30541246
Parent:        eab014ed4358eb9d45bcea2c772526afbe2fe8bb
Author:        David Lutterkort <lutter at redhat.com>
AuthorDate:    Sun Dec 14 23:51:34 2008 -0800
Committer:     David Lutterkort <lutter at redhat.com>
CommitterDate: Mon Aug 31 14:36:27 2009 -0700

Carry the key type explicitly in lenses

Instead of computing the key type recursively, store it in lens->ktype. The
key type becomes the new abstract type (atype) when a lens is used inside a
subtree combinator.
---
 src/lens.c                              |  156 +++++++++----------------------
 src/lens.h                              |    1 +
 tests/modules/fail_multi_key_concat.aug |    3 +
 tests/modules/fail_multi_key_iter.aug   |    4 +
 4 files changed, 52 insertions(+), 112 deletions(-)

diff --git a/src/lens.c b/src/lens.c
index 295baef..255ecc6 100644
--- a/src/lens.c
+++ b/src/lens.c
@@ -32,7 +32,6 @@ static struct value *typecheck_concat(struct info *,
 static struct value *typecheck_iter(struct info *info, struct lens *l);
 static struct value *typecheck_maybe(struct info *info, struct lens *l);
 
-static struct regexp *lns_key_regexp(struct lens *l, struct value **exn);
 static struct regexp *make_key_regexp(struct info *info, const char *pat);
 
 /* Lens names for pretty printing */
@@ -41,6 +40,11 @@ static const char *const tags[] = {
     "subtree", "star", "maybe"
 };
 
+static const struct string digits_string = {
+    .ref = REF_MAX, .str = (char *) "[0-9]+/"
+};
+static const struct string *const digits_pat = &digits_string;
+
 /* Construct a finite automaton from REGEXP and return it in *FA.
  *
  * Return NULL if REGEXP is valid, if the regexp REGEXP has syntax errors,
@@ -149,6 +153,10 @@ static struct lens *make_lens_binop(enum lens_tag tag, struct info *info,
         types[i] = lens->children[i]->atype;
     lens->atype = (*combinator)(info, lens->nchildren, types);
 
+    for (int i=0; i < lens->nchildren; i++)
+        types[i] = lens->children[i]->ktype;
+    lens->ktype = (*combinator)(info, lens->nchildren, types);
+
     FREE(types);
 
     for (int i=0; i < lens->nchildren; i++)
@@ -207,16 +215,10 @@ struct value *lns_make_concat(struct info *info,
 
 struct value *lns_make_subtree(struct info *info, struct lens *l) {
     struct lens *lens;
-    struct value *exn;
-    struct regexp *atype;
-
-    atype = lns_key_regexp(l, &exn);
-    if (exn != NULL)
-        return exn;
 
     lens = make_lens_unop(L_SUBTREE, info, l);
     lens->ctype = ref(l->ctype);
-    lens->atype = atype;
+    lens->atype = ref(l->ktype);
     lens->value = lens->key = 0;
     if (lens->atype == NULL)
         lens->atype = make_key_regexp(info, "");
@@ -242,6 +244,7 @@ struct value *lns_make_star(struct info *info, struct lens *l, int check) {
     lens = make_lens_unop(L_STAR, info, l);
     lens->ctype = regexp_iter(info, l->ctype, 0, -1);
     lens->atype = regexp_iter(info, l->atype, 0, -1);
+    lens->ktype = regexp_iter(info, l->ktype, 0, -1);
     return make_lens_value(lens);
 }
 
@@ -269,6 +272,7 @@ struct value *lns_make_maybe(struct info *info, struct lens *l, int check) {
     lens = make_lens_unop(L_MAYBE, info, l);
     lens->ctype = regexp_maybe(info, l->ctype);
     lens->atype = regexp_maybe(info, l->atype);
+    lens->ktype = regexp_maybe(info, l->ktype);
     lens->value = l->value;
     lens->key = l->key;
     return make_lens_value(lens);
@@ -277,6 +281,18 @@ struct value *lns_make_maybe(struct info *info, struct lens *l, int check) {
 /*
  * Lens primitives
  */
+
+static struct regexp *make_regexp_from_string(struct info *info,
+                                              struct string *string) {
+    struct regexp *r;
+    make_ref(r);
+    if (r != NULL) {
+        r->info = ref(info);
+        r->pattern = ref(string);
+    }
+    return r;
+}
+
 struct value *lns_make_prim(enum lens_tag tag, struct info *info,
                             struct regexp *regexp, struct string *string) {
     struct lens *lens = NULL;
@@ -337,6 +353,7 @@ struct value *lns_make_prim(enum lens_tag tag, struct info *info,
     lens->value = (tag == L_STORE);
     lens->consumes_value = (tag == L_STORE);
     lens->atype = regexp_make_empty(info);
+    /* Set the ctype */
     if (tag == L_DEL || tag == L_STORE || tag == L_KEY) {
         lens->ctype = ref(regexp);
     } else if (tag == L_LABEL || tag == L_SEQ || tag == L_COUNTER) {
@@ -344,6 +361,25 @@ struct value *lns_make_prim(enum lens_tag tag, struct info *info,
     } else {
         assert(0);
     }
+
+    /* Set the ktype */
+    if (tag == L_SEQ) {
+        lens->ktype =
+            make_regexp_from_string(info, (struct string *) digits_pat);
+    } else if (tag == L_KEY) {
+        lens->ktype = make_key_regexp(info, lens->regexp->pattern->str);
+    } else if (tag == L_LABEL) {
+        struct regexp *r = make_regexp_literal(info, lens->string->str);
+        if (r == NULL)
+            goto error;
+        if (REALLOC_N(r->pattern->str, strlen(r->pattern->str) + 2) == -1) {
+            unref(r, regexp);
+            goto error;
+        }
+        strcat(r->pattern->str, "/");
+        lens->ktype = r;
+    }
+
     return make_lens_value(lens);
  error:
     fa_free(fa_isect);
@@ -551,110 +587,6 @@ static struct regexp *make_key_regexp(struct info *info, const char *pat) {
     return regexp;
 }
 
-static struct regexp *make_regexp_from_string(struct info *info,
-                                              struct string *string) {
-    struct regexp *r;
-    make_ref(r);
-    if (r != NULL) {
-        r->info = ref(info);
-        r->pattern = ref(string);
-    }
-    return r;
-}
-
-/* Calculate the regexp that matches the labels if the trees that L can
-   generate.
-
-   We have some headache here because of the behavior of STORE: since STORE
-   creates a tree with no label (a leaf, really), its key regexp should be
-   "/", but only of there is no KEY or LABEL statement that fills in the
-   label of the tree that STORE created.
- */
-static struct regexp *lns_key_regexp(struct lens *l, struct value **exn) {
-    static const struct string digits_string = {
-        .ref = REF_MAX, .str = (char *) "[0-9]+/"
-    };
-    static const struct string *const digits_pat = &digits_string;
-
-    *exn = NULL;
-    switch(l->tag) {
-    case L_STORE:
-    case L_DEL:
-    case L_COUNTER:
-        return NULL;
-    case L_SEQ:
-        return make_regexp_from_string(l->info, (struct string *) digits_pat);
-    case L_KEY:
-        return make_key_regexp(l->info, l->regexp->pattern->str);
-    case L_LABEL:
-        {
-            struct regexp *r = make_regexp_literal(l->info, l->string->str);
-            if (r == NULL)
-                return NULL;
-            if (REALLOC_N(r->pattern->str, strlen(r->pattern->str) + 2) == -1) {
-                unref(r, regexp);
-                return NULL;
-            }
-            strcat(r->pattern->str, "/");
-            return r;
-        }
-    case L_CONCAT:
-        {
-            struct regexp *k = NULL;
-            for (int i=0; i < l->nchildren; i++) {
-                struct regexp *r = lns_key_regexp(l->children[i], exn);
-                if (*exn != NULL) {
-                    free_regexp(k);
-                    return NULL;
-                }
-                if (r != NULL) {
-                    if (k != NULL) {
-                        *exn = make_exn_value(ref(l->info),
-                                              "More than one key");
-                        unref(r, regexp);
-                        unref(k, regexp);
-                        return NULL;
-                    } else {
-                        k = r;
-                    }
-                }
-            }
-            return k;
-        }
-        break;
-    case L_UNION:
-        {
-            struct regexp *k = NULL;
-            for (int i=0; i < l->nchildren; i++) {
-                struct regexp *r = lns_key_regexp(l->children[i], exn);
-                if (*exn != NULL)
-                    return NULL;
-                if (r != NULL) {
-                    if (k == NULL) {
-                        k = r;
-                    } else {
-                        struct regexp *u = regexp_union(l->info, k, r);
-                        unref(k, regexp);
-                        unref(r, regexp);
-                        k = u;
-                    }
-                }
-            }
-            return k;
-        }
-        break;
-    case L_SUBTREE:
-        return NULL;
-        break;
-    case L_STAR:
-    case L_MAYBE:
-        return lns_key_regexp(l->child, exn);
-    default:
-        assert(0);
-    }
-    return NULL;
-}
-
 void free_lens(struct lens *lens) {
     if (lens == NULL)
         return;
diff --git a/src/lens.h b/src/lens.h
index a8a0f9e..37fc26c 100644
--- a/src/lens.h
+++ b/src/lens.h
@@ -46,6 +46,7 @@ struct lens {
     struct info              *info;
     struct regexp            *ctype;
     struct regexp            *atype;
+    struct regexp            *ktype;
     unsigned int              value : 1;
     unsigned int              key : 1;
     unsigned int              consumes_value : 1;
diff --git a/tests/modules/fail_multi_key_concat.aug b/tests/modules/fail_multi_key_concat.aug
new file mode 100644
index 0000000..7a3b147
--- /dev/null
+++ b/tests/modules/fail_multi_key_concat.aug
@@ -0,0 +1,3 @@
+module Fail_multi_key_concat =
+
+  let lns = key /a/ . key /b/
diff --git a/tests/modules/fail_multi_key_iter.aug b/tests/modules/fail_multi_key_iter.aug
new file mode 100644
index 0000000..c333626
--- /dev/null
+++ b/tests/modules/fail_multi_key_iter.aug
@@ -0,0 +1,4 @@
+module Fail_multi_key_iter =
+
+  let lns = ( key /a/ ) *
+




More information about the augeas-devel mailing list