#include "limbo.h" char *storename[Dend]={ /* Dtype */ "type", /* Dfn */ "function", /* Dglobal */ "global", /* Darg */ "argument", /* Dlocal */ "local", /* Dconst */ "con", /* Dfield */ "field", /* Dtag */ "pick tag", /* Dimport */ "import", /* Dunbound */ "unbound", /* Dundef */ "undefined", /* Dwundef */ "undefined",}; char *storeart[Dend] ={ /* Dtype */ "a ", /* Dfn */ "a ", /* Dglobal */ "a ", /* Darg */ "an ", /* Dlocal */ "a ", /* Dconst */ "a ", /* Dfield */ "a ", /* Dtag */ "a", /* Dimport */ "an ", /* Dunbound */ "", /* Dundef */ "", /* Dwundef */ "",}; int storespace[Dend] ={ /* Dtype */ 0, /* Dfn */ 0, /* Dglobal */ 1, /* Darg */ 1, /* Dlocal */ 1, /* Dconst */ 0, /* Dfield */ 1, /* Dtag */ 0, /* Dimport */ 0, /* Dunbound */ 0, /* Dundef */ 0, /* Dwundef */ 0,}; static Decl *scopes[MaxScope];static Decl *tails[MaxScope];static Node *scopenode[MaxScope];static uchar scopekind[MaxScope];static Decl zdecl; static void freeloc(Decl*); voidpopscopes(void){ Decl *d; Dlist *id; /* * clear out any decls left in syms */ while(scope >= ScopeBuiltin){ for(d = scopes[scope--]; d != nil; d = d->next){ if(d->sym != nil){ d->sym->decl = d->old; d->old = nil; } } } for(id = impdecls; id != nil; id = id->next){ for(d = id->d->ty->ids; d != nil; d = d->next){ d->sym->decl = nil; d->old = nil; } } impdecls = nil; scope = ScopeBuiltin; scopes[ScopeBuiltin] = nil; tails[ScopeBuiltin] = nil;} voiddeclstart(void){ Decl *d; iota = mkids(&nosrc, enter("iota", 0), tint, nil); iota->init = mkconst(&nosrc, 0); scope = ScopeNils; scopes[ScopeNils] = nil; tails[ScopeNils] = nil; nildecl = mkdecl(&nosrc, Dglobal, tany); nildecl->sym = enter("nil", 0); installids(Dglobal, nildecl); d = mkdecl(&nosrc, Dglobal, tstring); d->sym = enter("", 0); installids(Dglobal, d); scope = ScopeGlobal; scopes[ScopeGlobal] = nil; tails[ScopeGlobal] = nil;} voidredecl(Decl *d){ Decl *old; old = d->sym->decl; if(old->store == Dwundef) return; error(d->src.start, "redeclaration of %K, previously declared as %k on line %L", d, old, old->src.start);} voidcheckrefs(Decl *d){ Decl *id, *m; long refs; for(; d != nil; d = d->next){ if(d->das) d->refs--; switch(d->store){ case Dtype: refs = d->refs; if(d->ty->kind == Tadt){ for(id = d->ty->ids; id != nil; id = id->next){ d->refs += id->refs; if(id->store != Dfn) continue; if(id->init == nil && id->link == nil && d->importid == nil) error(d->src.start, "function %s.%s not defined", d->sym->name, id->sym->name); if(superwarn && !id->refs && d->importid == nil) warn(d->src.start, "function %s.%s not referenced", d->sym->name, id->sym->name); } } if(d->ty->kind == Tmodule){ for(id = d->ty->ids; id != nil; id = id->next){ refs += id->refs; if(id->iface != nil) id->iface->refs += id->refs; if(id->store == Dtype){ for(m = id->ty->ids; m != nil; m = m->next){ refs += m->refs; if(m->iface != nil) m->iface->refs += m->refs; } } } d->refs = refs; } if(superwarn && !refs && d->importid == nil) warn(d->src.start, "%K not referenced", d); break; case Dglobal: if(!superwarn) break; case Dlocal: case Darg: if(!d->refs && d->sym != nil && d->sym->name != nil && d->sym->name[0] != '.') warn(d->src.start, "%K not referenced", d); break; case Dconst: if(superwarn && !d->refs && d->sym != nil) warn(d->src.start, "%K not referenced", d); if(d->ty == tstring && d->init != nil) d->init->decl->refs += d->refs; break; case Dfn: if(d->init == nil && d->importid == nil) error(d->src.start, "%K not defined", d); if(superwarn && !d->refs) warn(d->src.start, "%K not referenced", d); break; case Dimport: if(superwarn && !d->refs) warn(d->src.start, "%K not referenced", d); break; } if(d->das) d->refs++; }} Node*vardecl(Decl *ids, Type *t){ Node *n; n = mkn(Ovardecl, mkn(Oseq, nil, nil), nil); n->decl = ids; n->ty = t; return n;} voidvardecled(Node *n){ Decl *ids, *last; Type *t; int store; store = Dlocal; if(scope == ScopeGlobal) store = Dglobal; if(n->ty->kind == Texception && n->ty->cons){ store = Dconst; fatal("Texception in vardecled"); } ids = n->decl; installids(store, ids); t = n->ty; for(last = ids; ids != nil; ids = ids->next){ ids->ty = t; last = ids; } n->left->decl = last;} Node*condecl(Decl *ids, Node *init){ Node *n; n = mkn(Ocondecl, mkn(Oseq, nil, nil), init); n->decl = ids; return n;} voidcondecled(Node *n){ Decl *ids, *last; ids = n->decl; installids(Dconst, ids); for(last = ids; ids != nil; ids = ids->next){ ids->ty = tunknown; last = ids; } n->left->decl = last;} Node*exdecl(Decl *ids, Decl *tids){ Node *n; Type *t; t = mktype(&ids->src.start, &ids->src.stop, Texception, nil, tids); t->cons = 1; n = mkn(Oexdecl, mkn(Oseq, nil, nil), nil); n->decl = ids; n->ty = t; return n;} voidexdecled(Node *n){ Decl *ids, *last; Type *t; ids = n->decl; installids(Dconst, ids); t = n->ty; for(last = ids; ids != nil; ids = ids->next){ ids->ty = t; last = ids; } n->left->decl = last;} Node*importdecl(Node *m, Decl *ids){ Node *n; n = mkn(Oimport, mkn(Oseq, nil, nil), m); n->decl = ids; return n;} voidimportdecled(Node *n){ Decl *ids, *last; ids = n->decl; installids(Dimport, ids); for(last = ids; ids != nil; ids = ids->next){ ids->ty = tunknown; last = ids; } n->left->decl = last;} Node*mkscope(Node *body){ Node *n; n = mkn(Oscope, nil, body); if(body != nil) n->src = body->src; return n;} Node*fndecl(Node *n, Type *t, Node *body){ n = mkbin(Ofunc, n, body); n->ty = t; return n;} voidfndecled(Node *n){ Decl *d; Node *left; left = n->left; if(left->op == Oname){ d = left->decl->sym->decl; if(d == nil || d->store == Dimport){ d = mkids(&left->src, left->decl->sym, n->ty, nil); installids(Dfn, d); } left->decl = d; d->refs++; } if(left->op == Odot) pushscope(nil, Sother); if(n->ty->polys != nil){ pushscope(nil, Sother); installids(Dtype, n->ty->polys); } pushscope(nil, Sother); installids(Darg, n->ty->ids); n->ty->ids = popscope(); if(n->ty->val != nil) mergepolydecs(n->ty); if(n->ty->polys != nil) n->ty->polys = popscope(); if(left->op == Odot) popscope();} /* * check the function declaration only * the body will be type checked later by fncheck */Decl *fnchk(Node *n){ int bad; Decl *d, *inadt, *adtp; Type *t; bad = 0; d = n->left->decl; if(n->left->op == Odot) d = n->left->right->decl; if(d == nil) fatal("decl() fnchk nil"); n->left->decl = d; if(d->store == Dglobal || d->store == Dfield) d->store = Dfn; if(d->store != Dfn || d->init != nil){ nerror(n, "redeclaration of function %D, previously declared as %k on line %L", d, d, d->src.start); if(d->store == Dfn && d->init != nil) bad = 1; } d->init = n; t = n->ty; inadt = d->dot; if(inadt != nil && (inadt->store != Dtype || inadt->ty->kind != Tadt)) inadt = nil; if(n->left->op == Odot){ pushscope(nil, Sother); adtp = outerpolys(n->left); if(adtp != nil) installids(Dtype, adtp); if(!polyequal(adtp, n->decl)) nerror(n, "adt polymorphic type mismatch"); n->decl = nil; } t = validtype(t, inadt); if(n->left->op == Odot) popscope(); if(debug['d']) print("declare function %D ty %T newty %T\n", d, d->ty, t); t = usetype(t); if(!polyequal(d->ty->polys, t->polys)) nerror(n, "function polymorphic type mismatch"); if(!tcompat(d->ty, t, 0)) nerror(n, "type mismatch: %D defined as %T declared as %T on line %L", d, t, d->ty, d->src.start); else if(!raisescompat(d->ty->u.eraises, t->u.eraises)) nerror(n, "raises mismatch: %D", d); if(t->varargs != 0) nerror(n, "cannot define functions with a '*' argument, such as %D", d); t->u.eraises = d->ty->u.eraises; d->ty = t; d->offset = idoffsets(t->ids, MaxTemp, IBY2WD); d->src = n->src; d->locals = nil; n->ty = t; return bad ? nil: d;} Node*globalas(Node *dst, Node *v, int valok){ Node *tv; if(v == nil) return nil; if(v->op == Oas || v->op == Odas){ v = globalas(v->left, v->right, valok); if(v == nil) return nil; }else if(valok && !initable(dst, v, 0)) return nil; switch(dst->op){ case Oname: if(dst->decl->init != nil) nerror(dst, "duplicate assignment to %V, previously assigned on line %L", dst, dst->decl->init->src.start); if(valok) dst->decl->init = v; return v; case Otuple: if(valok && v->op != Otuple) fatal("can't deal with %n in tuple case of globalas", v); tv = v->left; for(dst = dst->left; dst != nil; dst = dst->right){ globalas(dst->left, tv->left, valok); if(valok) tv = tv->right; } return v; } fatal("can't deal with %n in globalas", dst); return nil;} intneedsstore(Decl *d){ if(!d->refs) return 0; if(d->importid != nil) return 0; if(storespace[d->store]) return 1; return 0;} /* * return the list of all referenced storage variables */Decl*vars(Decl *d){ Decl *v, *n; while(d != nil && !needsstore(d)) d = d->next; for(v = d; v != nil; v = v->next){ while(v->next != nil){ n = v->next; if(needsstore(n)) break; v->next = n->next; } } return d;Lines 1–500 of 1367. Load more
#include "limbo.h" char *storename[Dend]= { /* Dtype */ "type", /* Dfn */ "function", /* Dglobal */ "global", /* Darg */ "argument", /* Dlocal */ "local", /* Dconst */ "con", /* Dfield */ "field", /* Dtag */ "pick tag", /* Dimport */ "import", /* Dunbound */ "unbound", /* Dundef */ "undefined", /* Dwundef */ "undefined", }; char *storeart[Dend] = { /* Dtype */ "a ", /* Dfn */ "a ", /* Dglobal */ "a ", /* Darg */ "an ", /* Dlocal */ "a ", /* Dconst */ "a ", /* Dfield */ "a ", /* Dtag */ "a", /* Dimport */ "an ", /* Dunbound */ "", /* Dundef */ "", /* Dwundef */ "", }; int storespace[Dend] = { /* Dtype */ 0, /* Dfn */ 0, /* Dglobal */ 1, /* Darg */ 1, /* Dlocal */ 1, /* Dconst */ 0, /* Dfield */ 1, /* Dtag */ 0, /* Dimport */ 0, /* Dunbound */ 0, /* Dundef */ 0, /* Dwundef */ 0, }; static Decl *scopes[MaxScope]; static Decl *tails[MaxScope]; static Node *scopenode[MaxScope]; static uchar scopekind[MaxScope]; static Decl zdecl; static void freeloc(Decl*); void popscopes(void) { Decl *d; Dlist *id; /* * clear out any decls left in syms */ while(scope >= ScopeBuiltin){ for(d = scopes[scope--]; d != nil; d = d->next){ if(d->sym != nil){ d->sym->decl = d->old; d->old = nil; } } } for(id = impdecls; id != nil; id = id->next){ for(d = id->d->ty->ids; d != nil; d = d->next){ d->sym->decl = nil; d->old = nil; } } impdecls = nil; scope = ScopeBuiltin; scopes[ScopeBuiltin] = nil; tails[ScopeBuiltin] = nil; } void declstart(void) { Decl *d; iota = mkids(&nosrc, enter("iota", 0), tint, nil); iota->init = mkconst(&nosrc, 0); scope = ScopeNils; scopes[ScopeNils] = nil; tails[ScopeNils] = nil; nildecl = mkdecl(&nosrc, Dglobal, tany); nildecl->sym = enter("nil", 0); installids(Dglobal, nildecl); d = mkdecl(&nosrc, Dglobal, tstring); d->sym = enter("", 0); installids(Dglobal, d); scope = ScopeGlobal; scopes[ScopeGlobal] = nil; tails[ScopeGlobal] = nil; } void redecl(Decl *d) { Decl *old; old = d->sym->decl; if(old->store == Dwundef) return; error(d->src.start, "redeclaration of %K, previously declared as %k on line %L", d, old, old->src.start); } void checkrefs(Decl *d) { Decl *id, *m; long refs; for(; d != nil; d = d->next){ if(d->das) d->refs--; switch(d->store){ case Dtype: refs = d->refs; if(d->ty->kind == Tadt){ for(id = d->ty->ids; id != nil; id = id->next){ d->refs += id->refs; if(id->store != Dfn) continue; if(id->init == nil && id->link == nil && d->importid == nil) error(d->src.start, "function %s.%s not defined", d->sym->name, id->sym->name); if(superwarn && !id->refs && d->importid == nil) warn(d->src.start, "function %s.%s not referenced", d->sym->name, id->sym->name); } } if(d->ty->kind == Tmodule){ for(id = d->ty->ids; id != nil; id = id->next){ refs += id->refs; if(id->iface != nil) id->iface->refs += id->refs; if(id->store == Dtype){ for(m = id->ty->ids; m != nil; m = m->next){ refs += m->refs; if(m->iface != nil) m->iface->refs += m->refs; } } } d->refs = refs; } if(superwarn && !refs && d->importid == nil) warn(d->src.start, "%K not referenced", d); break; case Dglobal: if(!superwarn) break; case Dlocal: case Darg: if(!d->refs && d->sym != nil && d->sym->name != nil && d->sym->name[0] != '.') warn(d->src.start, "%K not referenced", d); break; case Dconst: if(superwarn && !d->refs && d->sym != nil) warn(d->src.start, "%K not referenced", d); if(d->ty == tstring && d->init != nil) d->init->decl->refs += d->refs; break; case Dfn: if(d->init == nil && d->importid == nil) error(d->src.start, "%K not defined", d); if(superwarn && !d->refs) warn(d->src.start, "%K not referenced", d); break; case Dimport: if(superwarn && !d->refs) warn(d->src.start, "%K not referenced", d); break; } if(d->das) d->refs++; } } Node* vardecl(Decl *ids, Type *t) { Node *n; n = mkn(Ovardecl, mkn(Oseq, nil, nil), nil); n->decl = ids; n->ty = t; return n; } void vardecled(Node *n) { Decl *ids, *last; Type *t; int store; store = Dlocal; if(scope == ScopeGlobal) store = Dglobal; if(n->ty->kind == Texception && n->ty->cons){ store = Dconst; fatal("Texception in vardecled"); } ids = n->decl; installids(store, ids); t = n->ty; for(last = ids; ids != nil; ids = ids->next){ ids->ty = t; last = ids; } n->left->decl = last; } Node* condecl(Decl *ids, Node *init) { Node *n; n = mkn(Ocondecl, mkn(Oseq, nil, nil), init); n->decl = ids; return n; } void condecled(Node *n) { Decl *ids, *last; ids = n->decl; installids(Dconst, ids); for(last = ids; ids != nil; ids = ids->next){ ids->ty = tunknown; last = ids; } n->left->decl = last; } Node* exdecl(Decl *ids, Decl *tids) { Node *n; Type *t; t = mktype(&ids->src.start, &ids->src.stop, Texception, nil, tids); t->cons = 1; n = mkn(Oexdecl, mkn(Oseq, nil, nil), nil); n->decl = ids; n->ty = t; return n; } void exdecled(Node *n) { Decl *ids, *last; Type *t; ids = n->decl; installids(Dconst, ids); t = n->ty; for(last = ids; ids != nil; ids = ids->next){ ids->ty = t; last = ids; } n->left->decl = last; } Node* importdecl(Node *m, Decl *ids) { Node *n; n = mkn(Oimport, mkn(Oseq, nil, nil), m); n->decl = ids; return n; } void importdecled(Node *n) { Decl *ids, *last; ids = n->decl; installids(Dimport, ids); for(last = ids; ids != nil; ids = ids->next){ ids->ty = tunknown; last = ids; } n->left->decl = last; } Node* mkscope(Node *body) { Node *n; n = mkn(Oscope, nil, body); if(body != nil) n->src = body->src; return n; } Node* fndecl(Node *n, Type *t, Node *body) { n = mkbin(Ofunc, n, body); n->ty = t; return n; } void fndecled(Node *n) { Decl *d; Node *left; left = n->left; if(left->op == Oname){ d = left->decl->sym->decl; if(d == nil || d->store == Dimport){ d = mkids(&left->src, left->decl->sym, n->ty, nil); installids(Dfn, d); } left->decl = d; d->refs++; } if(left->op == Odot) pushscope(nil, Sother); if(n->ty->polys != nil){ pushscope(nil, Sother); installids(Dtype, n->ty->polys); } pushscope(nil, Sother); installids(Darg, n->ty->ids); n->ty->ids = popscope(); if(n->ty->val != nil) mergepolydecs(n->ty); if(n->ty->polys != nil) n->ty->polys = popscope(); if(left->op == Odot) popscope(); } /* * check the function declaration only * the body will be type checked later by fncheck */ Decl * fnchk(Node *n) { int bad; Decl *d, *inadt, *adtp; Type *t; bad = 0; d = n->left->decl; if(n->left->op == Odot) d = n->left->right->decl; if(d == nil) fatal("decl() fnchk nil"); n->left->decl = d; if(d->store == Dglobal || d->store == Dfield) d->store = Dfn; if(d->store != Dfn || d->init != nil){ nerror(n, "redeclaration of function %D, previously declared as %k on line %L", d, d, d->src.start); if(d->store == Dfn && d->init != nil) bad = 1; } d->init = n; t = n->ty; inadt = d->dot; if(inadt != nil && (inadt->store != Dtype || inadt->ty->kind != Tadt)) inadt = nil; if(n->left->op == Odot){ pushscope(nil, Sother); adtp = outerpolys(n->left); if(adtp != nil) installids(Dtype, adtp); if(!polyequal(adtp, n->decl)) nerror(n, "adt polymorphic type mismatch"); n->decl = nil; } t = validtype(t, inadt); if(n->left->op == Odot) popscope(); if(debug['d']) print("declare function %D ty %T newty %T\n", d, d->ty, t); t = usetype(t); if(!polyequal(d->ty->polys, t->polys)) nerror(n, "function polymorphic type mismatch"); if(!tcompat(d->ty, t, 0)) nerror(n, "type mismatch: %D defined as %T declared as %T on line %L", d, t, d->ty, d->src.start); else if(!raisescompat(d->ty->u.eraises, t->u.eraises)) nerror(n, "raises mismatch: %D", d); if(t->varargs != 0) nerror(n, "cannot define functions with a '*' argument, such as %D", d); t->u.eraises = d->ty->u.eraises; d->ty = t; d->offset = idoffsets(t->ids, MaxTemp, IBY2WD); d->src = n->src; d->locals = nil; n->ty = t; return bad ? nil: d; } Node* globalas(Node *dst, Node *v, int valok) { Node *tv; if(v == nil) return nil; if(v->op == Oas || v->op == Odas){ v = globalas(v->left, v->right, valok); if(v == nil) return nil; }else if(valok && !initable(dst, v, 0)) return nil; switch(dst->op){ case Oname: if(dst->decl->init != nil) nerror(dst, "duplicate assignment to %V, previously assigned on line %L", dst, dst->decl->init->src.start); if(valok) dst->decl->init = v; return v; case Otuple: if(valok && v->op != Otuple) fatal("can't deal with %n in tuple case of globalas", v); tv = v->left; for(dst = dst->left; dst != nil; dst = dst->right){ globalas(dst->left, tv->left, valok); if(valok) tv = tv->right; } return v; } fatal("can't deal with %n in globalas", dst); return nil; } int needsstore(Decl *d) { if(!d->refs) return 0; if(d->importid != nil) return 0; if(storespace[d->store]) return 1; return 0; } /* * return the list of all referenced storage variables */ Decl* vars(Decl *d) { Decl *v, *n; while(d != nil && !needsstore(d)) d = d->next; for(v = d; v != nil; v = v->next){ while(v->next != nil){ n = v->next; if(needsstore(n)) break; v->next = n->next; } } return d;