diff options
author | Ori Bernstein <ori@eigenstate.org> | 2015-06-28 14:26:16 -0700 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2015-06-28 14:26:16 -0700 |
commit | b05bd318302a3b5043a56479d20261d81bc27012 (patch) | |
tree | e6a6532e0fd6255321fd6335464e8e57c28548cf | |
parent | d17587d89ed49739392eb6d768d583c7f5955d2c (diff) | |
download | mc-b05bd318302a3b5043a56479d20261d81bc27012.tar.gz |
Implement '__init__' functions.
-rw-r--r-- | 6/asm.h | 1 | ||||
-rw-r--r-- | 6/gen.c | 23 | ||||
-rw-r--r-- | 6/gengas.c | 22 | ||||
-rw-r--r-- | 6/genp9.c | 22 | ||||
-rw-r--r-- | 6/main.c | 18 | ||||
-rw-r--r-- | libstd/alloc.myr | 18 | ||||
-rw-r--r-- | libstd/fmt.myr | 13 | ||||
-rw-r--r-- | mbld/deps.myr | 3 | ||||
-rw-r--r-- | mbld/main.myr | 1 | ||||
-rw-r--r-- | muse/muse.c | 2 | ||||
-rw-r--r-- | parse/gram.y | 22 | ||||
-rw-r--r-- | parse/infer.c | 13 | ||||
-rw-r--r-- | parse/parse.h | 33 | ||||
-rw-r--r-- | parse/specialize.c | 68 | ||||
-rw-r--r-- | parse/stab.c | 25 | ||||
-rw-r--r-- | parse/use.c | 26 | ||||
-rw-r--r-- | rt/_myrrt-plan9.s | 1 | ||||
-rw-r--r-- | rt/start-linux.s | 2 | ||||
-rw-r--r-- | support/vim/indent/myr.vim | 11 |
19 files changed, 230 insertions, 94 deletions
@@ -236,6 +236,7 @@ extern Node *abortoob; extern int extracheck; extern Asmsyntax asmsyntax; +void fillglobls(Stab *st, Htab *globls); void simpglobl(Node *dcl, Htab *globls, Func ***fn, size_t *nfn, Node ***blob, size_t *nblob); void selfunc(Isel *is, Func *fn, Htab *globls, Htab *strtab); void gen(Node *file, char *out); @@ -15,6 +15,29 @@ #include "asm.h" #include "../config.h" +void fillglobls(Stab *st, Htab *globls) +{ + void **k; + size_t i, nk; + Stab *stab; + Node *s; + + k = htkeys(st->dcl, &nk); + for (i = 0; i < nk; i++) { + s = htget(st->dcl, k[i]); + htput(globls, s, asmname(s)); + } + free(k); + + k = htkeys(st->ns, &nk); + for (i = 0; i < nk; i++) { + stab = htget(st->ns, k[i]); + fillglobls(stab, globls); + } + + free(k); +} + static int islocal(Node *dcl) { if (dcl->decl.vis != Visintern) @@ -40,28 +40,6 @@ static char* modenames[] = { static void locprint(FILE *fd, Loc *l, char spec); -static void fillglobls(Stab *st, Htab *globls) -{ - void **k; - size_t i, nk; - Stab *stab; - Node *s; - - k = htkeys(st->dcl, &nk); - for (i = 0; i < nk; i++) { - s = htget(st->dcl, k[i]); - htput(globls, s, asmname(s)); - } - free(k); - - k = htkeys(st->ns, &nk); - for (i = 0; i < nk; i++) { - stab = htget(st->ns, k[i]); - fillglobls(stab, globls); - } - free(k); -} - static void initconsts(Htab *globls) { Type *ty; @@ -39,28 +39,6 @@ static char* modenames[] = { static void locprint(FILE *fd, Loc *l, char spec); -static void fillglobls(Stab *st, Htab *globls) -{ - void **k; - size_t i, nk; - Stab *stab; - Node *s; - - k = htkeys(st->dcl, &nk); - for (i = 0; i < nk; i++) { - s = htget(st->dcl, k[i]); - htput(globls, s, asmname(s)); - } - free(k); - - k = htkeys(st->ns, &nk); - for (i = 0; i < nk; i++) { - stab = htget(st->ns, k[i]); - fillglobls(stab, globls); - } - free(k); -} - static void initconsts(Htab *globls) { Type *ty; @@ -117,6 +117,20 @@ static char *gentemp(char *buf, size_t bufsz, char *path, char *suffix) return buf; } +static int hasmain(Node *file) +{ + Node *n, *name; + + name = mknsname(Zloc, "", "main"); + n = getdcl(file->file.globls, name); + if (!n) + return 0; + n = n->decl.name; + if (n->name.ns) + return 0; + return 1; +} + static void genuse(char *path) { FILE *f; @@ -208,7 +222,9 @@ int main(int argc, char **argv) if (debugopt['T']) dump(file, stdout); infer(file); - tagexports(file->file.globls, 0); + if (hasmain(file)) + geninit(file); + tagexports(file, 0); /* after all type inference */ if (debugopt['t']) dump(file, stdout); diff --git a/libstd/alloc.myr b/libstd/alloc.myr index 306667d..ed3b023 100644 --- a/libstd/alloc.myr +++ b/libstd/alloc.myr @@ -54,7 +54,6 @@ const Pagesz = 4*KiB const Align = 16 /* minimum allocation alignment */ var buckets : bucket[32] /* excessive */ -var initdone : bool type slheader = struct cap : size /* capacity in bytes */ @@ -80,6 +79,14 @@ type chunk = struct /* NB: must be smaller than sizeof(slab) */ next : chunk# /* the next chunk in the free list */ ;; +const __init__ = { + var i + + for i = 0; i < buckets.len && (Align << i) <= Bktmax; i++ + bktinit(&buckets[i], Align << i) + ;; +} + /* Allocates an object of type @a, returning a pointer to it. */ generic alloc = {-> @a# -> bytealloc(sizeof(@a)) castto(@a#) @@ -209,14 +216,7 @@ const zfill = {sl /* Allocates a blob that is 'sz' bytes long. Dies if the allocation fails */ const bytealloc = {sz - var i, bkt, p - - if !initdone - for i = 0; i < buckets.len && (Align << i) <= Bktmax; i++ - bktinit(&buckets[i], Align << i) - ;; - initdone = true - ;; + var bkt, p if (sz <= Bktmax) bkt = &buckets[bktnum(sz)] diff --git a/libstd/fmt.myr b/libstd/fmt.myr index 2fba705..b786e98 100644 --- a/libstd/fmt.myr +++ b/libstd/fmt.myr @@ -47,6 +47,10 @@ pkg std = $noret const fatalv : (fmt : byte[:], ap : valist# -> void) ;; +const __init__ = { + fmtmap = mkht(strhash, streq) +} + type fmtdesc = struct fn : (sb : strbuf#, ap : valist#, opts : (byte[:],byte[:])[:] -> void) optdesc : (byte[:], bool)[:] @@ -67,14 +71,9 @@ const fatalv = {fmt, ap exit(1) } -var fmtmapinited : bool = false var fmtmap : htab(byte[:], fmtdesc)# const fmtinstall = {ty, fn, optdesc - if !fmtmapinited - fmtmapinited = true - fmtmap = mkht(strhash, streq) - ;; htput(fmtmap, ty, [.fn=fn, .optdesc=optdesc]) } @@ -149,10 +148,6 @@ const sbfmtv = {sb, fmt, ap -> size orig = fmt nparams = ap.tc.nelt nfmt = 0 - if !fmtmapinited - fmtmapinited = true - fmtmap = mkht(strhash, streq) - ;; while fmt.len != 0 (c, fmt) = striter(fmt) match c diff --git a/mbld/deps.myr b/mbld/deps.myr index c1174df..2d8ad04 100644 --- a/mbld/deps.myr +++ b/mbld/deps.myr @@ -234,7 +234,8 @@ const scrapelibs = {dg, lib, incs | `std.None: std.fatal("library {}: could not read usefile\n", lib) ;; match bio.getbe32(f) - | `std.Some 1: /* nothing: version matches. */ + | `std.Some 2: /* nothing: version matches. */ + | `std.Some 1: std.fput(1, "library {}: warning: old usefile version\n", lib) | `std.Some 0: std.fput(1, "library {}: warning: old usefile version\n", lib) | `std.Some _: std.fatal("library {}: usefile version unknown\n", lib) | `std.None: std.fatal("library {}: corrutpt or invalid usefile\n", lib) diff --git a/mbld/main.myr b/mbld/main.myr index cde2766..efa9ea6 100644 --- a/mbld/main.myr +++ b/mbld/main.myr @@ -38,6 +38,7 @@ const main = {args : byte[:][:] ][:] ]) + targname = "" bld.initopts() for opt in cmd.opts match opt diff --git a/muse/muse.c b/muse/muse.c index ab08c53..96d1f43 100644 --- a/muse/muse.c +++ b/muse/muse.c @@ -92,7 +92,7 @@ int main(int argc, char **argv) for (i = 0; i < ctx.nargs; i++) mergeuse(ctx.args[i]); infer(file); - tagexports(file->file.globls, 1); + tagexports(file, 1); f = fopen(outfile, "w"); if (debugopt['s'] || show) dumpstab(file->file.globls, stdout); diff --git a/parse/gram.y b/parse/gram.y index c241951..63781fa 100644 --- a/parse/gram.y +++ b/parse/gram.y @@ -26,6 +26,7 @@ static Node *mkpseudodecl(Type *t); static void installucons(Stab *st, Type *t); static void addtrait(Type *t, char *str); static void setattrs(Node *dcl, char **attrs, size_t nattrs); +static void setupinit(Node *n); %} @@ -219,11 +220,15 @@ toplev : package Node *n; for (i = 0; i < $1.nn; i++) { + if (!strcmp(declname($1.nl[i]), "__init__")) + setupinit($1.nl[i]); /* putdcl can merge, so we need to getdcl after */ putdcl(file->file.globls, $1.nl[i]); n = getdcl(file->file.globls, $1.nl[i]->decl.name); lappend(&file->file.stmts, &file->file.nstmts, n); $1.nl[i]->decl.isglobl = 1; + if ($1.nl[i]->decl.isinit) + file->file.localinit = $1.nl[i]; } } | /* empty */ @@ -916,6 +921,23 @@ label : Tcolon Tident %% +static void setupinit(Node *n) +{ + char name[1024]; + char *p; + + snprintf(name, sizeof name, "%s$__init__", file->file.files[0]); + p = name; + while (*p) { + if (!isalnum(*p) && *p != '_') + *p = '$'; + p++; + } + n->decl.isinit = 1; + n->decl.vis = Vishidden; + n->decl.name->name.name = strdup(name); +} + static void addtrait(Type *t, char *str) { size_t i; diff --git a/parse/infer.c b/parse/infer.c index ed4e58c..9cb8fe7 100644 --- a/parse/infer.c +++ b/parse/infer.c @@ -2217,14 +2217,16 @@ static void nodetag(Stab *st, Node *n, int ingeneric, int hidelocal) } } -void tagexports(Stab *st, int hidelocal) +void tagexports(Node *file, int hidelocal) { + size_t i, j, n; + Trait *tr; + Stab *st; void **k; Node *s; Type *t; - Trait *tr; - size_t i, j, n; + st = file->file.globls; k = htkeys(st->dcl, &n); for (i = 0; i < n; i++) { s = getdcl(st, k[i]); @@ -2241,6 +2243,11 @@ void tagexports(Stab *st, int hidelocal) } free(k); + for (i = 0; i < file->file.ninit; i++) + nodetag(st, file->file.init[i], 0, hidelocal); + if (file->file.localinit) + nodetag(st, file->file.localinit, 0, hidelocal); + k = htkeys(st->tr, &n); for (i = 0; i < n; i++) { tr = gettrait(st, k[i]); diff --git a/parse/parse.h b/parse/parse.h index 445f501..c544f6c 100644 --- a/parse/parse.h +++ b/parse/parse.h @@ -4,7 +4,7 @@ # define FATAL #endif -#define Abiversion 1 +#define Abiversion 2 typedef uint8_t byte; typedef unsigned int uint; @@ -219,8 +219,10 @@ struct Node { size_t nlibdeps; Node **stmts; /* all top level statements */ size_t nstmts; + Node **init; /* a list of all __init__ function names of our deps. NB, this is a Nname, not an Ndecl */ + size_t ninit; + Node *localinit; /* and the local one, if any */ Stab *globls; /* global symtab */ - int hasinit; /* did we declare __init__? */ } file; struct { @@ -306,16 +308,19 @@ struct Node { impl. */ Trait *trait; - char vis; - char isglobl; - char isconst; - char isgeneric; - char isextern; - char ispkglocal; - char ishidden; - char isimport; - char isnoret; - char isexportinit; + char vis; + + /* flags */ + char isglobl; + char isconst; + char isgeneric; + char isextern; + char ispkglocal; + char ishidden; + char isimport; + char isnoret; + char isexportinit; + char isinit; } decl; struct { @@ -473,6 +478,7 @@ void puttrait(Stab *st, Node *n, Trait *trait); void putimpl(Stab *st, Node *impl); void updatetype(Stab *st, Node *n, Type *t); void putdcl(Stab *st, Node *dcl); +void putnsdcl(Node *dcl); void forcedcl(Stab *st, Node *dcl); void putucon(Stab *st, Ucon *uc); @@ -577,12 +583,13 @@ Op exprop(Node *n); Node *specializedcl(Node *n, Type *to, Node **name); Type *tyspecialize(Type *t, Htab *tymap, Htab *delayed); Node *genericname(Node *n, Type *t); +void geninit(Node *file); /* usefiles */ int loaduse(char *path, FILE *f, Stab *into, Vis vis); void readuse(Node *use, Stab *into, Vis vis); void writeuse(FILE *fd, Node *file); -void tagexports(Stab *st, int hidelocal); +void tagexports(Node *file, int hidelocal); /* typechecking/inference */ void infer(Node *file); diff --git a/parse/specialize.c b/parse/specialize.c index 6cf5aa9..ecf25ec 100644 --- a/parse/specialize.c +++ b/parse/specialize.c @@ -430,3 +430,71 @@ Node *specializedcl(Node *g, Type *to, Node **name) popstab(); return d; } + +/* + * Not really specialization, but close enough. + * + * Generate an init function that's the equivalent of + * this code: + * + * const __init__ { + * file1$myr$__init__ + * file2$myr$__init__ + * ... + * } + */ +static Node *initdecl(Node *file, Node *name, Type *tyvoidfn) +{ + Node *dcl; + + dcl = getdcl(file->file.globls, name); + if (!dcl) { + dcl = mkdecl(Zloc, name, tyvoidfn); + dcl->decl.isconst = 1; + dcl->decl.isinit = 1; + putnsdcl(dcl); + } + return dcl; +} + +static void callinit(Node *block, Node *init, Type *tyvoid, Type *tyvoidfn) +{ + Node *call, *var; + + var = mkexpr(Zloc, Ovar, init->decl.name, NULL); + call = mkexpr(Zloc, Ocall, var, NULL); + + var->expr.type = tyvoidfn; + call->expr.type = tyvoid; + var->expr.did = init->decl.did; + var->expr.isconst = 1; + lappend(&block->block.stmts, &block->block.nstmts, call); +} + +void geninit(Node *file) +{ + Node *name, *decl, *func, *block, *init; + Type *tyvoid, *tyvoidfn; + size_t i; + + name = mkname(Zloc, "__init__"); + decl = mkdecl(Zloc, name, mktyvar(Zloc)); + block = mkblock(Zloc, mkstab()); + block->block.scope->super = file->file.globls; + tyvoid = mktype(Zloc, Tyvoid); + tyvoidfn = mktyfunc(Zloc, NULL, 0, tyvoid); + + for (i = 0; i < file->file.ninit; i++) { + init = initdecl(file, file->file.init[i], tyvoidfn); + callinit(block, init, tyvoid, tyvoidfn); + } + if (file->file.localinit) + callinit(block, file->file.localinit, tyvoid, tyvoidfn); + func = mkfunc(Zloc, NULL, 0, mktype(Zloc, Tyvoid), block); + func->expr.type = tyvoidfn; + decl->decl.init = mkexpr(Zloc, Olit, func, NULL); + decl->decl.isconst = 1; + decl->decl.type = tyvoidfn; + + lappend(&file->file.stmts, &file->file.nstmts, decl); +} diff --git a/parse/stab.c b/parse/stab.c index e527da2..c4f0a2c 100644 --- a/parse/stab.c +++ b/parse/stab.c @@ -253,6 +253,13 @@ static int mergedecl(Node *old, Node *new) return 1; } +void forcedcl (Stab *st, Node *s) { + if (st->name) + setns(s->decl.name, st->name); + htput(st->dcl, s->decl.name, s); + assert(htget(st->dcl, s->decl.name) != NULL); +} + void putdcl(Stab *st, Node *s) { Node *old; @@ -264,11 +271,19 @@ void putdcl(Stab *st, Node *s) fatal(old, "%s already declared on %s:%d", namestr(s->decl.name), fname(s->loc), lnum(s->loc)); } -void forcedcl (Stab *st, Node *s) { - if (st->name) - setns(s->decl.name, st->name); - htput(st->dcl, s->decl.name, s); - assert(htget(st->dcl, s->decl.name) != NULL); +void putnsdcl(Node *dcl) +{ + Node *name; + Stab *ns; + + name = dcl->decl.name; + ns = getns_str(file->file.globls, name->name.ns); + if (!ns) { + ns = mkstab(); + updatens(ns, name->name.ns); + putns(file->file.globls, ns); + } + putdcl(ns, dcl); } void updatetype(Stab *st, Node *n, Type *t) diff --git a/parse/use.c b/parse/use.c index 13bda4b..88fdfa0 100644 --- a/parse/use.c +++ b/parse/use.c @@ -25,6 +25,7 @@ static Node *unpickle(FILE *fd); static Htab *tydedup; /* map from name -> type, contains all Tynames loaded ever */ static Htab *tidmap; /* map from tid -> type */ static Htab *trmap; /* map from trait id -> trait */ +static Htab *initmap; /* map from init name -> int */ #define Builtinmask (1 << 30) static Type ***typefixdest; /* list of types we need to replace */ @@ -161,6 +162,7 @@ static void wrsym(FILE *fd, Node *val) wrbool(fd, val->decl.ispkglocal); wrbool(fd, val->decl.isnoret); wrbool(fd, val->decl.isexportinit); + wrbool(fd, val->decl.isinit); if (val->decl.isexportinit) { pickle(fd, val->decl.init); } @@ -189,6 +191,7 @@ static Node *rdsym(FILE *fd, Trait *ctx) n->decl.isnoret = rdbool(fd); n->decl.isimport = 1; n->decl.isexportinit = rdbool(fd); + n->decl.isinit = rdbool(fd); if (n->decl.isexportinit) n->decl.init = unpickle(fd); return n; @@ -818,7 +821,7 @@ int loaduse(char *path, FILE *f, Stab *st, Vis vis) intptr_t tid; size_t i; char *pkg; - Node *dcl, *impl; + Node *dcl, *impl, *init; Stab *s; Type *ty; Trait *tr; @@ -859,6 +862,8 @@ int loaduse(char *path, FILE *f, Stab *st, Vis vis) } tidmap = mkht(ptrhash, ptreq); trmap = mkht(ptrhash, ptreq); + if (!initmap) + initmap = mkht(namehash, nameeq); /* builtin traits */ for (i = 0; i < Ntraits; i++) htput(trmap, itop(i), traittab[i]); @@ -882,6 +887,13 @@ foundlib: dcl->decl.vis = vis; putdcl(s, dcl); break; + case 'S': + init = unpickle(f); + if (!hthas(initmap, init)) { + htput(initmap, init, init); + lappend(&file->file.init, &file->file.ninit, init); + } + break; case 'R': tr = traitunpickle(f); tr->vis = vis; @@ -1038,13 +1050,21 @@ void writeuse(FILE *f, Node *file) if (s->decl.vis == Visintern || s->decl.vis == Visbuiltin) continue; /* trait functions get written out with their traits */ - if (s->decl.trait) + if (s->decl.trait || s->decl.isinit) continue; - if (s->decl.isgeneric) + else if (s->decl.isgeneric) wrbyte(f, 'G'); else wrbyte(f, 'D'); wrsym(f, s); } + for (i = 0; i < file->file.ninit; i++) { + wrbyte(f, 'S'); + pickle(f, file->file.init[i]); + } + if (file->file.localinit) { + wrbyte(f, 'S'); + pickle(f, file->file.localinit->decl.name); + } free(k); } diff --git a/rt/_myrrt-plan9.s b/rt/_myrrt-plan9.s index 7fd14a3..4f21b9c 100644 --- a/rt/_myrrt-plan9.s +++ b/rt/_myrrt-plan9.s @@ -57,6 +57,7 @@ TEXT _main(SB), 1, $(2*8+NPRIVATES*8) PUSHQ R13 PUSHQ DX + CALL __init__(SB) CALL main(SB) POPQ DX POPQ R13 diff --git a/rt/start-linux.s b/rt/start-linux.s index 7583466..963d21b 100644 --- a/rt/start-linux.s +++ b/rt/start-linux.s @@ -67,6 +67,8 @@ _start: pushq %rdx /* enter the main program */ + call __init__ + /* enter the main program */ call main /* exit(0) */ xorq %rdi,%rdi diff --git a/support/vim/indent/myr.vim b/support/vim/indent/myr.vim index d20010a..356f9ea 100644 --- a/support/vim/indent/myr.vim +++ b/support/vim/indent/myr.vim @@ -66,9 +66,9 @@ function! GetMyrIndent(ln) \ '\<while\>','\<for\>', '\<match\>', \ '\<struct\>', '\<union\>', \ '{', '\[', '(', '^\s*|.*:', '=\s*$'] - let outpat = ['}', ']', ')', ';;'] + let outpat = ['}', ']', ')'] let outalone = ['\<else\>', '\<elif\>.*', ';;', '|.*', - \ '].*', ').*', '}.*'] + \ '].*', '}.*'] let width = &tabstop let n_in = s:CountMatches(prevln, ln - i, inpat) @@ -84,9 +84,10 @@ function! GetMyrIndent(ln) let n_out = n_out + 1 endif - " we already outdented if we had an outalone - if s:LineMatch(prevln, outalone) != 0 - let n_out = 0 + " we already outdented if we had an outalone, but since all + " outpats are also outalones, we don't want to double count. + if s:LineMatch(prevln, outalone) != 0 && n_out > 0 + let n_out = n_out - 1 endif let n_out = n_out + s:LineMatch(curln, outalone) |