ref: 1a00720e1fc60ce82d95763a031efac9b71340ce
parent: e7a0f4791ce20c45129b536d01d1ec977d696521
author: Ori Bernstein <ori@eigenstate.org>
date: Fri Feb 20 18:09:17 EST 2015
Allow unlengthed arrays within structs. Added type[...] syntax to tell the compiler not to check the length of these arrays. The size of this array is 0, as far as the compiler is concerned. This is only allowed within structs. This allows us to do 2 things: - First, it allows us to handle the C idiom which puts a zero-length array at the end of a struct to store extra data, as follows: type trailing = struct length : byte data : byte[...] ;; - And, as a side effect, we can also fake out C style unions as follows: type withunion = struct a : foo[...] b : foo[...] c : foo[...] pad : byte[NBYTES] ;; This is ugly and error prone, and perhaps should be deprecated.
--- a/6/simp.c
+++ b/6/simp.c
@@ -725,6 +725,8 @@
Node *cmp, *die;
Node *ok, *fail;
+ if (!len)
+ return;
/* create expressions */
cmp = mkexpr(idx->loc, Olt, ptrsized(s, idx), ptrsized(s, len), NULL);
cmp->expr.type = mktype(len->loc, Tybool);
--- a/libstd/sys+linux-x64.myr
+++ b/libstd/sys+linux-x64.myr
@@ -79,7 +79,7 @@
off : uint64
reclen : uint16
etype : byte
- name : byte[0]
+ name : byte[...] /* special case; zero length => unchecked indexing */
;;
type utsname = struct
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -464,6 +464,7 @@
: functype {$$ = $1;}
| type Tosqbrac Tcolon Tcsqbrac {$$ = mktyslice($2->loc, $1);}
| type Tosqbrac expr Tcsqbrac {$$ = mktyarray($2->loc, $1, $3);}
+ | type Tosqbrac Tellipsis Tcsqbrac {$$ = mktyarray($2->loc, $1, NULL);}
| type Tderef {$$ = mktyptr($2->loc, $1);}
| Tat Tident {$$ = mktyparam($1->loc, $2->id);}
| name {$$ = mktyunres($1->loc, $1, NULL, 0);}
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -19,6 +19,7 @@
int ingeneric;
int sawret;
int indentdepth;
+ int intype;
Type *ret;
/* bound by patterns turn into decls in the action block */
@@ -362,8 +363,10 @@
t->resolved = 1;
/* Walk through aggregate type members */
if (t->type == Tystruct) {
+ st->intype++;
for (i = 0; i < t->nmemb; i++)
infernode(st, &t->sdecls[i], NULL, NULL);
+ st->intype--;
} else if (t->type == Tyunion) {
for (i = 0; i < t->nmemb; i++) {
t->udecls[i]->utype = t;
@@ -374,6 +377,8 @@
}
}
} else if (t->type == Tyarray) {
+ if (!st->intype && !t->asize)
+ lfatal(t->loc, "unsized array type outside of struct");
infernode(st, &t->asize, NULL, NULL);
}
@@ -1641,8 +1646,10 @@
if (t->type == Tyarray) {
typesub(st, t->asize);
} else if (t->type == Tystruct) {
+ st->intype++;
for (i = 0; i < t->nmemb; i++)
typesub(st, t->sdecls[i]);
+ st->intype--;
} else if (t->type == Tyunion) {
for (i = 0; i < t->nmemb; i++) {
if (t->udecls[i]->etype)