[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 = ®exp_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