ref: 8510d8a1f452aed36421c7562aa9c7caa5575a03
parent: b0625d73a94310205e64d3b153ddb6844921b09f
author: Ori Bernstein <[email protected]>
date: Sun Jun 17 08:09:51 EDT 2012
allow .len on arrays and slices in the frontend.
--- a/8/reduce.c
+++ b/8/reduce.c
@@ -74,10 +74,10 @@
len = strlen(Fprefix);
if (n->name.ns)
- len += strlen(n->name.ns);
+ len += strlen(n->name.ns) + 1; /* +1 for separator */
len += strlen(n->name.name);
- s = xalloc(len);
+ s = xalloc(len + 1);
s[0] = '\0';
sprintf(s, "%s", Fprefix);
if (n->name.ns)
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -92,6 +92,7 @@
%token<tok> Tvar /* var */
%token<tok> Tgeneric /* var */
%token<tok> Textern /* extern */
+%token<tok> Tcast /* castto */
%token<tok> Texport /* export */
%token<tok> Tprotect /* protect */
@@ -124,6 +125,7 @@
%type <node> funclit arraylit name block blockbody stmt label use
%type <node> decl declbody declcore structelt enumelt unionelt
%type <node> ifstmt forstmt whilestmt elifs optexprln
+%type <node> castexpr
%type <nodelist> arglist argdefs structbody enumbody unionbody params
@@ -379,8 +381,14 @@
| landexpr
;
-landexpr: landexpr Tland borexpr
+landexpr: landexpr Tland castexpr
{$$ = mkexpr($1->line, binop($2->type), $1, $3, NULL);}
+ | castexpr
+ ;
+
+castexpr: landexpr Tcast Toparen type Tcparen
+ {$$ = mkexpr($1->line, Ocast, $1, NULL);
+ $$->expr.type = $4;}
| borexpr
;
@@ -569,8 +577,9 @@
{
fprintf(stderr, "%d: %s", line, s);
if (curtok->str)
- fprintf(stderr, " near %s", curtok->str);
+ fprintf(stderr, " near \"%s\"", curtok->str);
fprintf(stderr, "\n");
+ exit(1);
}
static Op binop(int tt)
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -12,8 +12,8 @@
#include "parse.h"
-static Node **checkmemb;
-static size_t ncheckmemb;
+static Node **postcheck;
+static size_t npostcheck;
static void infernode(Node *n, Type *ret, int *sawret);
static void inferexpr(Node *n, Type *ret, int *sawret);
@@ -140,10 +140,15 @@
{
char *s;
switch (n->type) {
- case Nexpr: s = opstr(exprop(n)); break;
+ default: s = nodestr(n->type); break;
case Ndecl: s = declname(n); break;
case Nname: s = namestr(n); break;
- default: s = nodestr(n->type); break;
+ case Nexpr:
+ if (exprop(n) == Ovar)
+ s = namestr(n->expr.args[0]);
+ else
+ s = opstr(exprop(n));
+ break;
}
return s;
}
@@ -244,6 +249,8 @@
Stab *st;
Sym *s;
+ if (n->type != Nexpr)
+ return;
args = n->expr.args;
if (exprop(args[0]) != Ovar)
return;
@@ -253,6 +260,8 @@
return;
nsname = mknsname(n->line, namestr(name), namestr(args[1]));
s = getdcl(st, args[1]);
+ if (!s)
+ fatal(n->line, "Undeclared var %s.%s", nsname->name.ns, nsname->name.name);
var = mkexpr(n->line, Ovar, nsname, NULL);
var->expr.did = s->id;
settype(var, s->type);
@@ -353,7 +362,7 @@
/* special cases */
case Omemb: /* @a.Ident -> @b, verify type(@a.Ident)==@b later */
settype(n, mktyvar(n->line));
- lappend(&checkmemb, &ncheckmemb, n);
+ lappend(&postcheck, &npostcheck, n);
break;
case Osize: /* sizeof @a -> size */
die("inference of sizes not done yet");
@@ -362,7 +371,7 @@
unifycall(n);
break;
case Ocast: /* cast(@a, @b) -> @b */
- die("casts not implemented");
+ lappend(&postcheck, &npostcheck, n);
break;
case Oret: /* -> @a -> void */
if (sawret)
@@ -379,6 +388,9 @@
settype(n, mkty(-1, Tyvoid));
break;
case Ovar: /* a:@a -> @a */
+ /* if we created this from a namespaced var, the type should be
+ * set, and the normal lookup is expected to fail. Since we're
+ * already done with this node, we can just return. */
if (n->expr.type)
return;
s = getdcl(curstab(), args[0]);
@@ -490,8 +502,10 @@
setsuper(n->block.scope, curstab());
pushstab(n->block.scope);
inferstab(n->block.scope);
- for (i = 0; i < n->block.nstmts; i++)
+ for (i = 0; i < n->block.nstmts; i++) {
+ checkns(n->block.stmts[i], &n->block.stmts[i]);
infernode(n->block.stmts[i], ret, sawret);
+ }
popstab();
break;
case Nifstmt:
@@ -567,21 +581,38 @@
Node *memb;
Node *n;
Node **nl;
+ int found;
- for (i = 0; i < ncheckmemb; i++) {
- n = checkmemb[i];
- if (n->expr.type->type == Typtr)
+ for (i = 0; i < npostcheck; i++) {
+ n = postcheck[i];
+ if (exprop(n) != Omemb)
+ continue;
+ if (type(n)->type == Typtr)
n = n->expr.args[0];
- aggr = checkmemb[i]->expr.args[0];
- memb = checkmemb[i]->expr.args[1];
+ aggr = postcheck[i]->expr.args[0];
+ memb = postcheck[i]->expr.args[1];
- nl = aggrmemb(aggr->expr.type, &nn);
- for (j = 0; j < nn; j++) {
- if (!strcmp(namestr(memb), declname(nl[j]))) {
- unify(n, type(n), decltype(nl[j]));
- break;
+ found = 0;
+ if (type(aggr)->type == Tyslice || type(aggr)->type == Tyarray) {
+ if (!strcmp(namestr(memb), "len")) {
+ constrain(type(n), cstrtab[Tcnum]);
+ constrain(type(n), cstrtab[Tcint]);
+ constrain(type(n), cstrtab[Tctest]);
+ found = 1;
}
+ } else {
+ nl = aggrmemb(aggr->expr.type, &nn);
+ for (j = 0; j < nn; j++) {
+ if (!strcmp(namestr(memb), declname(nl[j]))) {
+ unify(n, type(n), decltype(nl[j]));
+ found = 1;
+ break;
+ }
+ }
}
+ if (!found)
+ fatal(aggr->line, "Type %s has no member \"%s\" near %s",
+ tystr(type(aggr)), ctxstr(memb), ctxstr(aggr));
}
}
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -222,7 +222,6 @@
extern int ncstrs;
extern int maxnid; /* the maximum node id generated so far */
-extern Type *littypes[]; /* literal type -> type map */
extern int ispureop[];
/* data structures */
--- a/parse/tok.c
+++ b/parse/tok.c
@@ -147,6 +147,7 @@
{"const", Tconst},
{"var", Tvar},
{"generic", Tgeneric},
+ {"castto", Tcast},
{"extern", Textern},
{"export", Texport},
{"protect", Tprotect},
--- a/parse/type.c
+++ b/parse/type.c
@@ -17,7 +17,6 @@
char *name;
};
-Type *littypes[Nlit] = {NULL,};
Type **tytab = NULL;
int ntypes;
Cstr **cstrtab;
--- a/parse/use.c
+++ b/parse/use.c
@@ -68,7 +68,7 @@
{
size_t i;
FILE *fd;
- char *p;
+ char *p, *q;
/* local (quoted) uses are always relative to the cwd */
fd = NULL;
@@ -77,14 +77,18 @@
/* nonlocal (barename) uses are always searched on the include path */
} else {
for (i = 0; i < nincpaths; i++) {
- p = strjoin(incpaths[i], use->use.name);
- fd = fopen(p, "r");
+ p = strjoin(incpaths[i], "/");
+ q = strjoin(p, use->use.name);
+ fd = fopen(q, "r");
if (fd) {
free(p);
+ free(q);
break;
}
}
}
+ if (!fd)
+ fatal(use->line, "Could not open %s", use->use.name);
if (!loaduse(fd, st))
die("Could not load usefile %s", use->use.name);