summaryrefslogtreecommitdiff
path: root/parse
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2017-07-27 01:11:33 -0700
committerOri Bernstein <ori@eigenstate.org>2017-07-27 01:57:52 -0700
commitc5245eaa80064b77186fa286f8e5e8bca73309ab (patch)
tree3dbaf773b4cc3c1a501f12805c7d3bee2e3f81ad /parse
parent0087d35b4f6393aa46c5ac757f77c5087f2add19 (diff)
downloadmc-c5245eaa80064b77186fa286f8e5e8bca73309ab.tar.gz
std.change std.name std.lookup std.rules.
std.no std.on std.every std.name std.you std.use. The rules for an un-namespaced name now are as follows: 1) Attempt to look up a name in the current file. 2) Check all namespaces for a unique name. If the name is not globally unique, give an error.
Diffstat (limited to 'parse')
-rw-r--r--parse/infer.c2
-rw-r--r--parse/parse.h20
-rw-r--r--parse/stab.c124
3 files changed, 98 insertions, 48 deletions
diff --git a/parse/infer.c b/parse/infer.c
index c99262e..fc6e13e 100644
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -1355,7 +1355,7 @@ inferpat(Node **np, Node *val, Node ***bind, size_t *nbind)
ns = curstab();
if (args[0]->name.ns)
ns = getns(file, args[0]->name.ns);
- s = getdcl(ns, args[0]);
+ s = getnsdcl(ns, args[0]);
if (s && !s->decl.ishidden) {
if (s->decl.isgeneric)
t = tysubst(s->decl.type, s->decl.type);
diff --git a/parse/parse.h b/parse/parse.h
index 07ec44a..90fd2fe 100644
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -90,13 +90,14 @@ struct Stab {
char *name;
char isfunc;
- /* Contents of stab.
- * types and values are in separate namespaces. */
- Htab *dcl;
- Htab *env; /* the syms we close over, if we're a function */
+ /* symbols */
+ Htab *dcl; /* decls */
Htab *ty; /* types */
Htab *tr; /* traits */
Htab *uc; /* union constructors */
+
+ /* not quite symbols */
+ Htab *env; /* the syms closed over, if this is a function stab */
Htab *lbl; /* labels */
Htab *impl; /* trait implementations: really a set of implemented traits. */
};
@@ -396,15 +397,16 @@ void forcedcl(Stab *st, Node *dcl);
void putucon(Stab *st, Ucon *uc);
void putlbl(Stab *st, char *name, Node *lbl);
-Stab *getns(Node *file, char *n);
+void *getnsdcl(Stab *st, Node *n);
Node *getdcl(Stab *st, Node *n);
-Node *getclosed(Stab *st, Node *n);
-Node **getclosure(Stab *st, size_t *n);
-Type *gettype_l(Stab *st, Node *n);
Type *gettype(Stab *st, Node *n);
-Node *getimpl(Stab *st, Node *impl);
Trait *gettrait(Stab *st, Node *n);
Ucon *getucon(Stab *st, Node *n);
+
+Stab *getns(Node *file, char *n);
+Node *getclosed(Stab *st, Node *n);
+Node **getclosure(Stab *st, size_t *n);
+Node *getimpl(Stab *st, Node *impl);
Node *getlbl(Stab *st, Srcloc loc, char *name);
Stab *curstab(void);
diff --git a/parse/stab.c b/parse/stab.c
index dea101a..ff4fdbe 100644
--- a/parse/stab.c
+++ b/parse/stab.c
@@ -16,6 +16,7 @@
/* Allows us to look up types/traits by name nodes */
typedef struct Tydefn Tydefn;
typedef struct Traitdefn Traitdefn;
+
struct Tydefn {
Srcloc loc;
Node *name;
@@ -213,27 +214,6 @@ getclosure(Stab *st, size_t *n)
* not in the current scope, it is recorded
* in the scope's closure.
*/
-Node *
-getdcl(Stab *st, Node *n)
-{
- Node *s;
- Stab *fn;
-
- fn = NULL;
- do {
- s = htget(st->dcl, n);
- if (s) {
- /* record that this is in the closure of this scope */
- if (fn && !s->decl.isglobl && !s->decl.isgeneric)
- htput(fn->env, s->decl.name, s);
- return s;
- }
- if (!fn && st->env)
- fn = st;
- st = st->super;
- } while (st);
- return NULL;
-}
void
putlbl(Stab *st, char *name, Node *lbl)
@@ -254,18 +234,50 @@ getlbl(Stab *st, Srcloc loc, char *name)
return htget(st->lbl, name);
}
-Type *
-gettype_l(Stab *st, Node *n)
+int
+hastype(Stab *st, Node *n)
{
- Tydefn *t;
+ do {
+ if (hthas(st->ty, n))
+ return 1;
+ st = st->super;
+ } while (st);
+ return 0;
+}
- if ((t = htget(st->ty, n)))
- return t->type;
- return NULL;
+/* because of function casting rules, it's cleaner to do this as a macro */
+static void*
+getunique(void *(*fn)(Stab *, Node*), char *name, Stab *st, Node *n)
+{
+ size_t i, nk;
+ void *p, *sym;
+ char *foundns;
+ void **k;
+ Stab *s;
+
+ p = fn(st, n);
+ /* file can be null early on, when initializing the type tables */
+ if (p || n->name.ns || !file)
+ return p;
+
+ /* if a name is globally unique, we can refer to it without a namespace */
+ sym = NULL;
+ k = htkeys(file->file.ns, &nk);
+ for (i = 0; i < nk; i++) {
+ s = htget(file->file.ns, k[i]);
+ p = fn(s, n);
+ if (p) {
+ if (sym)
+ fatal(n, "ambiguous %s %s, defined in %s and %s\n", name, namestr(n), k[i], foundns);
+ foundns = k[i];
+ sym = p;
+ }
+ }
+ return sym;
}
-Type *
-gettype(Stab *st, Node *n)
+static void*
+getnstype(Stab *st, Node *n)
{
Tydefn *t;
@@ -277,19 +289,43 @@ gettype(Stab *st, Node *n)
return NULL;
}
-int
-hastype(Stab *st, Node *n)
+Type*
+gettype(Stab *st, Node *n)
{
+ return getunique(getnstype, "type", st, n);
+}
+
+void*
+getnsdcl(Stab *st, Node *n)
+{
+ Node *s;
+ Stab *fn;
+
+ fn = NULL;
do {
- if (hthas(st->ty, n))
- return 1;
+ s = htget(st->dcl, n);
+ if (s) {
+ /* record that this is in the closure of this scope */
+ if (fn && !s->decl.isglobl && !s->decl.isgeneric)
+ htput(fn->env, s->decl.name, s);
+ return s;
+ }
+ if (!fn && st->env)
+ fn = st;
st = st->super;
} while (st);
- return 0;
+ return NULL;
}
-Ucon *
-getucon(Stab *st, Node *n)
+
+Node*
+getdcl(Stab *st, Node *n)
+{
+ return getunique(getnsdcl, "decl", st, n);
+}
+
+static void*
+getnsucon(Stab *st, Node *n)
{
Ucon *uc;
@@ -301,8 +337,14 @@ getucon(Stab *st, Node *n)
return NULL;
}
-Trait *
-gettrait(Stab *st, Node *n)
+Ucon*
+getucon(Stab *st, Node *n)
+{
+ return getunique(getnsucon, "union constructor", st, n);
+}
+
+static void*
+getnstrait(Stab *st, Node *n)
{
Traitdefn *c;
@@ -316,6 +358,12 @@ gettrait(Stab *st, Node *n)
return NULL;
}
+Trait*
+gettrait(Stab *st, Node *n)
+{
+ return getunique(getnstrait, "trait", st, n);
+}
+
Stab *
getns(Node *file, char *name) {
return htget(file->file.ns, name);