[augeas-devel] augeas: master - Add a unit type

David Lutterkort lutter at fedoraproject.org
Sun Jan 17 22:23:58 UTC 2010


Gitweb:        http://git.fedorahosted.org/git/augeas.git?p=augeas.git;a=commitdiff;h=6de28531fe3203032c8d3e9895da3f27eb62cf5b
Commit:        6de28531fe3203032c8d3e9895da3f27eb62cf5b
Parent:        3c9c9da314aac8d422f80bc7be1655079064cbbc
Author:        David Lutterkort <lutter at redhat.com>
AuthorDate:    Fri Jan 15 16:53:32 2010 -0800
Committer:     David Lutterkort <lutter at redhat.com>
CommitterDate: Fri Jan 15 17:02:20 2010 -0800

Add a unit type

The literal '()' is the only member of the unit type. Composition is now
allowed if the first expression is of type unit, i.e. '() ; something' is
legal.
---
 src/parser.y                |   10 ++++++++++
 src/syntax.c                |   33 ++++++++++++++++++++++++---------
 src/syntax.h                |    8 ++++++--
 tests/modules/pass_unit.aug |    6 ++++++
 4 files changed, 46 insertions(+), 11 deletions(-)

diff --git a/src/parser.y b/src/parser.y
index 604b003..bada158 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -133,6 +133,7 @@ static void augl_error(struct info *locp, struct term **term,
  static struct term *make_unop(enum term_tag tag,
                               struct term *exp, struct info *locp);
  static struct term *make_ident(char *qname, struct info *locp);
+ static struct term *make_unit_term(struct info *locp);
  static struct term *make_string_term(char *value, struct info *locp);
  static struct term *make_regexp_term(char *pattern,
                                       int nocase, struct info *locp);
@@ -251,6 +252,8 @@ aexp: qid
       { $$ = $2; }
     | '[' exp ']'
       { $$ = make_unop(A_BRACKET, $2, &@$); }
+    | '(' ')'
+      { $$ = make_unit_term(&@$); }
 
 rexp: aexp rep
       { $$ = make_rep($1, $2, &@$); }
@@ -514,6 +517,13 @@ static struct term *make_ident(char *qname, struct info *locp) {
   return term;
 }
 
+static struct term *make_unit_term(struct info *locp) {
+  struct term *term = make_term_locp(A_VALUE, locp);
+  term->value = make_unit(ref(term->info));
+  term->type = make_base_type(T_UNIT);
+  return term;
+}
+
 static struct term *make_string_term(char *value, struct info *locp) {
   struct term *term = make_term_locp(A_VALUE, locp);
   term->value = make_value(V_STRING, ref(term->info));
diff --git a/src/syntax.c b/src/syntax.c
index d4e3282..1abffd9 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -52,6 +52,7 @@ static const struct type tree_type      = { .ref = UINT_MAX, .tag = T_TREE };
 static const struct type filter_type    = { .ref = UINT_MAX, .tag = T_FILTER };
 static const struct type transform_type =
                                        { .ref = UINT_MAX, .tag = T_TRANSFORM };
+static const struct type unit_type      = { .ref = UINT_MAX, .tag = T_UNIT };
 
 const struct type *const t_string    = &string_type;
 const struct type *const t_regexp    = &regexp_type;
@@ -59,10 +60,11 @@ const struct type *const t_lens      = &lens_type;
 const struct type *const t_tree      = &tree_type;
 const struct type *const t_filter    = &filter_type;
 const struct type *const t_transform = &transform_type;
+const struct type *const t_unit      = &unit_type;
 
 static const char *const type_names[] = {
     "string", "regexp", "lens", "tree", "filter",
-    "transform", "function", NULL
+    "transform", "unit", "function", NULL
 };
 
 /* The anonymous identifier which we will never bind */
@@ -294,6 +296,8 @@ void free_value(struct value *v) {
     case V_EXN:
         free_exn(v->exn);
         break;
+    case V_UNIT:
+        break;
     default:
         assert(0);
     }
@@ -344,6 +348,10 @@ struct value *make_value(enum value_tag tag, struct info *info) {
     return value;
 }
 
+struct value *make_unit(struct info *info) {
+    return make_value(V_UNIT, info);
+}
+
 struct term *make_app_term(struct term *lambda, struct term *arg,
                            struct info *info) {
   struct term *app = make_term(A_APP, info);
@@ -728,6 +736,9 @@ static void print_value(FILE *out, struct value *v) {
             v->exn->seen = 1;
         }
         break;
+    case V_UNIT:
+        fprintf(out, "()");
+        break;
     default:
         assert(0);
         break;
@@ -799,6 +810,8 @@ struct type *make_base_type(enum type_tag tag) {
         return (struct type *) t_filter;
     else if (tag == T_TRANSFORM)
         return (struct type *) t_transform;
+    else if (tag == T_UNIT)
+        return (struct type *) t_unit;
     assert(0);
     abort();
 }
@@ -842,15 +855,11 @@ static int subtype(struct type *t1, struct type *t2) {
        of strings/regexps to lenses (yet) */
     if (t1->tag == T_STRING)
         return (t2->tag == T_STRING || t2->tag == T_REGEXP);
-    if (t1->tag == T_REGEXP)
-        return t2->tag == T_REGEXP;
-    if (t1->tag == T_LENS)
-        return t2->tag == T_LENS;
     if (t1->tag == T_ARROW && t2->tag == T_ARROW) {
         return subtype(t2->dom, t1->dom)
             && subtype(t1->img, t2->img);
     }
-    return 0;
+    return t1->tag == t2->tag;
 }
 
 static int type_equal(struct type *t1, struct type *t2) {
@@ -926,6 +935,8 @@ static struct type *value_type(struct value *v) {
         return make_base_type(T_FILTER);
     case V_TRANSFORM:
         return make_base_type(T_TRANSFORM);
+    case V_UNIT:
+        return make_base_type(T_UNIT);
     case V_NATIVE:
         return ref(v->native->type);
     case V_CLOS:
@@ -1118,6 +1129,10 @@ static int check_compose(struct term *term, struct ctx *ctx) {
         if (! subtype(tl->img, tr->dom))
             goto print_error;
         term->type = make_arrow_type(tl->dom, tr->img);
+    } else if (tl->tag == T_UNIT) {
+        if (! check_exp(term->right, ctx))
+            return 0;
+        term->type = ref(term->right->type);
     } else {
         goto print_error;
     }
@@ -1474,9 +1489,9 @@ static struct value *compile_compose(struct term *exp, struct ctx *ctx) {
         v = make_closure(func, ctx->local);
         unref(func, term);
     } else {
-        fatal_error(info, "Tried to compose a %s and a %s to yield a %s",
-                    type_name(exp->left->type), type_name(exp->right->type),
-                    type_name(t));
+        v = compile_exp(exp->info, exp->left, ctx);
+        unref(v, value);
+        v = compile_exp(exp->info, exp->right, ctx);
     }
     return v;
 }
diff --git a/src/syntax.h b/src/syntax.h
index de5806a..f39c7ef 100644
--- a/src/syntax.h
+++ b/src/syntax.h
@@ -149,7 +149,8 @@ enum value_tag {
     V_TRANSFORM,
     V_NATIVE,
     V_EXN,
-    V_CLOS
+    V_CLOS,
+    V_UNIT
 };
 
 #define EXN(v) ((v)->tag == V_EXN)
@@ -158,6 +159,7 @@ struct value {
     unsigned int   ref;
     struct info   *info;
     enum value_tag tag;
+    /* Nothing in this union for V_UNIT */
     union {
         struct string  *string;  /* V_STRING */
         struct regexp  *regexp;  /* V_REGEXP */
@@ -189,7 +191,8 @@ enum type_tag {
     T_TREE,
     T_FILTER,
     T_TRANSFORM,
-    T_ARROW
+    T_ARROW,
+    T_UNIT
 };
 
 struct type {
@@ -228,6 +231,7 @@ struct term *make_term(enum term_tag tag, struct info *info);
 void free_term(struct term *term);
 struct term *make_param(char *name, struct type *type, struct info *info);
 struct value *make_value(enum value_tag tag, struct info *info);
+struct value *make_unit(struct info *info);
 struct term *make_app_term(struct term *func, struct term *arg,
                            struct info *info);
 struct term *make_app_ident(char *id, struct term *func, struct info *info);
diff --git a/tests/modules/pass_unit.aug b/tests/modules/pass_unit.aug
new file mode 100644
index 0000000..ea865bb
--- /dev/null
+++ b/tests/modules/pass_unit.aug
@@ -0,0 +1,6 @@
+module Pass_Unit =
+
+(* The unit literal *)
+let _ = ()
+(* Check that composition allows units on the left *)
+let _ = () ; () ; (); "something"




More information about the augeas-devel mailing list