shithub: mc

Download patch

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);