struct parse_context *c = config2context(config);
###### Parser: code
-
+ #define _GNU_SOURCE
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
Named type are stored in a simple linked list. Objects of each type are
"values" which are often passed around by value.
+There are both explicitly named types, and anonymous types. Anonymous
+cannot be accessed by name, but are used internally and have a name
+which might be reported in error messages.
+
###### ast
struct value {
struct text name;
struct type *next;
int size, align;
+ int anon;
void (*init)(struct type *type, struct value *val);
void (*prepare_type)(struct parse_context *c, struct type *type, int parse_time);
void (*print)(struct type *type, struct value *val, FILE *f);
struct type *typelist;
+###### includes
+ #include <stdarg.h>
+
###### ast functions
static struct type *find_type(struct parse_context *c, struct text s)
{
- struct type *l = c->typelist;
+ struct type *t = c->typelist;
- while (l &&
- text_cmp(l->name, s) != 0)
- l = l->next;
- return l;
+ while (t && (t->anon ||
+ text_cmp(t->name, s) != 0))
+ t = t->next;
+ return t;
}
- static struct type *add_type(struct parse_context *c, struct text s,
- struct type *proto)
+ static struct type *_add_type(struct parse_context *c, struct text s,
+ struct type *proto, int anon)
{
struct type *n;
n = calloc(1, sizeof(*n));
*n = *proto;
n->name = s;
+ n->anon = anon;
n->next = c->typelist;
c->typelist = n;
return n;
}
+ static struct type *add_type(struct parse_context *c, struct text s,
+ struct type *proto)
+ {
+ return _add_type(c, s, proto, 0);
+ }
+
+ static struct type *add_anon_type(struct parse_context *c,
+ struct type *proto, char *name, ...)
+ {
+ struct text t;
+ va_list ap;
+
+ va_start(ap, name);
+ vasprintf(&t.txt, name, ap);
+ va_end(ap);
+ t.len = strlen(name);
+ return _add_type(c, t, proto, 1);
+ }
+
static void free_type(struct type *t)
{
/* The type is always a reference to something in the
{
if (!type)
fputs("*unknown*type*", f); // NOTEST
- else if (type->name.len)
+ else if (type->name.len && !type->anon)
fprintf(f, "%.*s", type->name.len, type->name.txt);
else if (type->print_type)
type->print_type(type, f);
else
- fputs("*invalid*type*", f); // NOTEST
+ fputs("*invalid*type*", f);
}
static void val_init(struct type *type, struct value *val)
context.typelist = t->next;
if (t->free_type)
t->free_type(t);
+ if (t->anon)
+ free(t->name.txt);
free(t);
}
struct binding *b = type->array.vsize->name;
fprintf(f, "%.*s%s]", b->name.len, b->name.txt,
type->array.unspec ? "::" : "");
- } else
+ } else if (type->array.size)
fprintf(f, "%d]", type->array.size);
+ else
+ fprintf(f, "]");
type_print(type->array.member, f);
}
| [ NUMBER ] Type ${ {
char tail[3];
mpq_t num;
- struct text noname = { "", 0 };
struct type *t;
+ int elements = 0;
- $0 = t = add_type(c, noname, &array_prototype);
- t->array.member = $<4;
- t->array.vsize = NULL;
if (number_parse(num, tail, $2.txt) == 0)
tok_err(c, "error: unrecognised number", &$2);
else if (tail[0]) {
tok_err(c, "error: unsupported number suffix", &$2);
mpq_clear(num);
} else {
- t->array.size = mpz_get_ui(mpq_numref(num));
+ elements = mpz_get_ui(mpq_numref(num));
if (mpz_cmp_ui(mpq_denref(num), 1) != 0) {
tok_err(c, "error: array size must be an integer",
&$2);
&$2);
mpq_clear(num);
}
+
+ $0 = t = add_anon_type(c, &array_prototype, "array[%d]", elements );
+ t->array.size = elements;
+ t->array.member = $<4;
+ t->array.vsize = NULL;
t->array.static_size = 1;
t->size = t->array.size * t->array.member->size;
t->align = t->array.member->align;
| [ IDENTIFIER ] Type ${ {
struct variable *v = var_ref(c, $2.txt);
- struct text noname = { "", 0 };
if (!v)
tok_err(c, "error: name undeclared", &$2);
else if (!v->constant)
tok_err(c, "error: array size must be a constant", &$2);
- $0 = add_type(c, noname, &array_prototype);
+ $0 = add_anon_type(c, &array_prototype, "array[%.*s]", $2.txt.len, $2.txt.txt);
$0->array.member = $<4;
$0->array.size = 0;
$0->array.vsize = v;
| [ IDENTIFIER :: OptType ] Type ${ {
struct variable *v = var_decl(c, $ID.txt);
- struct text noname = { "", 0 };
v->type = $<OT;
v->constant = 1;
if (!v->type)
v->type = Tnum;
- $0 = add_type(c, noname, &array_prototype);
+ $0 = add_anon_type(c, &array_prototype, "array[var]");
$0->array.member = $<6;
$0->array.size = 0;
$0->array.unspec = 1;
while (target != 0) {
int i = 0;
for (t = context.typelist; t ; t=t->next)
- if (t->print_type_decl && !t->check_args && t->name.txt[0] != ' ') {
+ if (!t->anon && t->print_type_decl &&
+ !t->check_args) {
i += 1;
if (i == target)
break;
/* Create a 'struct' type from the results list, which
* is a list for 'struct var'
*/
- struct text result_type_name = { " function_result", 5 };
- struct type *t = add_type(c, result_type_name, &structure_prototype);
+ struct type *t = add_anon_type(c, &structure_prototype,
+ " function result");
int cnt = 0;
struct binode *b;
struct binode *results,
struct exec *code)
{
- struct text funcname = {" func", 5};
if (name) {
struct value fn = {.function = code};
struct type *t;
var_block_close(c, CloseFunction, code);
- t = add_type(c, funcname, &function_prototype);
+ t = add_anon_type(c, &function_prototype,
+ "func %.*s", name->name->name.len,
+ name->name->name.txt);
name->type = t;
t->function.params = reorder_bilist(args);
if (!ret) {
int ok = 1;
int arg = 0;
struct type *argv_type;
- struct text argv_type_name = { " argv", 5 };
- argv_type = add_type(c, argv_type_name, &array_prototype);
+ argv_type = add_anon_type(c, &array_prototype, "argv");
argv_type->array.member = Tstr;
argv_type->array.unspec = 1;