ref: 36cfe833d4df23b2e0da38942c8d51de0bd72f6d
dir: /parse/type.c/
#include <stdlib.h> #include <stdio.h> #include <stdint.h> #include <ctype.h> #include <string.h> #include <assert.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include "parse.h" typedef struct Typename Typename; struct Typename { Ty ty; char *name; }; Type *littypes[Nlit] = {NULL,}; Type **tytab = NULL; int ntypes; Cstr **cstrtab; int ncstrs; static Typename typenames[] = { {Tyvoid, "void"}, {Tychar, "char"}, {Tybyte, "byte"}, {Tyint8, "int8"}, {Tyint16, "int16"}, {Tyint32, "int32"}, {Tyint64, "int64"}, {Tyuint8, "uint8"}, {Tyuint16, "uint16"}, {Tyuint32, "uint32"}, {Tyuint64, "uint64"}, {Tyfloat32, "float32"}, {Tyfloat64, "float64"}, {Tybad, NULL} }; static Cstr *tycstrs[Ntypes][4]; Type *mkty(int line, Ty ty) { Type *t; int i; t = zalloc(sizeof(Type)); t->type = ty; t->tid = ntypes++; tytab = xrealloc(tytab, ntypes*sizeof(Type*)); for(i = 0; tycstrs[ty][i]; i++) constrain(t, tycstrs[ty][i]); return t; } Type *tylike(Type *t, Ty like) { int i; for (i = 0; tycstrs[like][i]; i++) constrain(t, tycstrs[like][i]); return t; } /* steals memb, funcs */ Cstr *mkcstr(int line, char *name, Node **memb, size_t nmemb, Node **funcs, size_t nfuncs) { Cstr *c; c = zalloc(sizeof(Cstr)); c->name = strdup(name); c->memb = memb; c->nmemb = nmemb; c->funcs = funcs; c->nfuncs = nfuncs; c->cid = ncstrs++; cstrtab = xrealloc(cstrtab, ncstrs*sizeof(Cstr*)); cstrtab[c->cid] = c; return c; } Type *mktyvar(int line) { Type *t; t = mkty(line, Tyvar); return t; } Type *mktyparam(int line, char *name) { Type *t; t = mkty(line, Tyvar); t->pname = strdup(name); return t; } Type *mktynamed(int line, Node *name) { int i; Type *t; /* is it a built in type? */ if (name->name.nparts == 1) for (i = 0; typenames[i].name; i++) if (!strcmp(typenames[i].name, name->name.parts[0])) return mkty(line, typenames[i].ty); /* if not, resolve it in the type inference stage */ t = mkty(line, Tyname); t->name = name; return t; } Type *mktyarray(int line, Type *base, Node *sz) { Type *t; t = mkty(line, Tyarray); t->sub = xalloc(sizeof(Type*)); t->sub[0] = base; t->asize = sz; return t; } Type *mktyslice(int line, Type *base) { Type *t; t = mkty(line, Tyslice); t->sub = xalloc(sizeof(Type*)); t->sub[0] = base; return t; } Type *mktyptr(int line, Type *base) { Type *t; t = mkty(line, Typtr); t->sub = xalloc(sizeof(Type*)); t->sub[0] = base; return t; } Type *mktyfunc(int line, Node **args, size_t nargs, Type *ret) { Type *t; int i; t = mkty(line, Tyfunc); t->nsub = nargs + 1; t->sub = xalloc((1 + nargs)*sizeof(Type)); t->sub[0] = ret; for (i = 0; i < nargs; i++) t->sub[i + 1] = decltype(args[i]); return t; } Type *mktystruct(int line, Node **decls, size_t ndecls) { Type *t; t = mkty(line, Tystruct); t->nsub = ndecls; t->sdecls = memdup(decls, ndecls*sizeof(Node *)); return t; } Type *mktyunion(int line, Node **decls, size_t ndecls) { Type *t; t = mkty(line, Tyunion); t->udecls = decls; return t; } Type *mktyenum(int line, Node **decls, size_t ndecls) { Type *t; t = mkty(line, Tyenum); t->edecls = decls; return t; } void tlappend(Type ***tl, int *len, Type *t) { *tl = xrealloc(tl, (*len + 1)*sizeof(Type*)); (*tl)[*len] = t; (*len)++; } static int namefmt(char *buf, size_t len, Node *name) { int i; char *p; char *end; char *sep; p = buf; end = p + len; sep = ""; for (i = 0; i < name->name.nparts; i++) { p += snprintf(p, end - p, "%s%s", sep, name->name.parts[i]); sep = "."; } return len - (end - p); } int constrain(Type *t, Cstr *c) { if (!t->cstrs) t->cstrs = mkbs(); if (t->type != Tyvar && t->type != Typaram) return 0; bsput(t->cstrs, c->cid); return 1; } int hascstr(Type *t, Cstr *c) { return t->cstrs && bshas(t->cstrs, c->cid); } static int cstrfmt(char *buf, size_t len, Type *t) { char *p; char *end; int first; int i; if (!t->cstrs || !bscount(t->cstrs)) return 0; p = buf; end = p + len; first = 1; p += snprintf(p, end - p, " :: "); for (i = 0; i < ncstrs; i++) { if (bshas(t->cstrs, i)) { if (!first) { first = 0; p += snprintf(p, end - p, ", "); } p += snprintf(p, end - p, "%s", cstrtab[i]->name); } } return end - p; } static int tybfmt(char *buf, size_t len, Type *t) { char *p; char *end; int i; char *sep; p = buf; end = p + len; sep = ""; if (!t) { p += snprintf(p, end - p, "tynil"); return len - (end - p); } switch (t->type) { case Tybad: p += snprintf(p, end - p, "BAD"); break; case Tyvoid: p += snprintf(p, end - p, "void"); break; case Tybool: p += snprintf(p, end - p, "bool"); break; case Tychar: p += snprintf(p, end - p, "char"); break; case Tyint8: p += snprintf(p, end - p, "int8"); break; case Tyint16: p += snprintf(p, end - p, "int16"); break; case Tyint: p += snprintf(p, end - p, "int"); break; case Tyint32: p += snprintf(p, end - p, "int32"); break; case Tyint64: p += snprintf(p, end - p, "int64"); break; case Tylong: p += snprintf(p, end - p, "long"); break; case Tybyte: p += snprintf(p, end - p, "byte"); break; case Tyuint8: p += snprintf(p, end - p, "uint8"); break; case Tyuint16: p += snprintf(p, end - p, "uint16"); break; case Tyuint: p += snprintf(p, end - p, "uint"); break; case Tyuint32: p += snprintf(p, end - p, "uint32"); break; case Tyuint64: p += snprintf(p, end - p, "uint64"); break; case Tyulong: p += snprintf(p, end - p, "ulong"); break; case Tyfloat32: p += snprintf(p, end - p, "float32"); break; case Tyfloat64: p += snprintf(p, end - p, "float64"); break; case Tyvalist: p += snprintf(p, end - p, "..."); break; case Typtr: p += tybfmt(p, end - p, t->sub[0]); p += snprintf(p, end - p, "*"); break; case Tyslice: p += tybfmt(p, end - p, t->sub[0]); p += snprintf(p, end - p, "[,]"); break; case Tyarray: p += tybfmt(p, end - p, t->sub[0]); p += snprintf(p, end - p, "[LEN]"); break; case Tyfunc: p += snprintf(p, end - p, "("); for (i = 1; i < t->nsub; i++) { p += snprintf(p, end - p, "%s", sep); p += tybfmt(p, end - p, t->sub[i]); sep = ", "; } p += snprintf(p, end - p, " -> "); p += tybfmt(p, end - p, t->sub[0]); p += snprintf(p, end - p, ")"); break; case Tytuple: p += snprintf(p, end - p, "["); for (i = 1; i < t->nsub; i++) { p += snprintf(p, end - p, "%s", sep); p += tybfmt(p, end - p, t->sub[i]); sep = ", "; } p += snprintf(p, end - p, "]"); break; case Tyvar: p += snprintf(p, end - p, "@$%d", t->tid); break; case Typaram: p += snprintf(p, end - p, "@%s", t->pname); break; case Tyname: p += snprintf(p, end - p, "?"); /* indicate unresolved name. should not be seen by user. */ p += namefmt(p, end - p, t->name); break; case Tystruct: case Tyunion: case Tyenum: snprintf(p, end - p, "TYPE ?"); break; case Ntypes: die("Ntypes is not a type"); break; } /* we only show constraints on non-builtin typarams */ if (t->type == Tyvar || t->type == Typaram) p += cstrfmt(p, end - p, t); return len - (end - p); } char *tyfmt(char *buf, size_t len, Type *t) { tybfmt(buf, len, t); return buf; } char *tystr(Type *t) { char buf[1024]; tyfmt(buf, 1024, t); return strdup(buf); } static struct { char enc; /* character to encode */ int special; /* 0 => atomic, 1 => unary, 2 => nary, -1 => special-cased */ } enctab[] = { [Tybad] = {'\0',0}, [Tyvoid] = {'z', 0}, [Tybool] = {'t', 0}, [Tychar] = {'c', 0}, [Tyint8] = {'h', 0}, [Tyint16] = {'s', 0}, [Tyint] = {'i', 0}, [Tyint32] = {'l', 0}, [Tyint64] = {'q', 0}, [Tylong] = {'v', 0}, [Tybyte] = {'b', 0}, [Tyuint8] = {'H', 0}, [Tyuint16] = {'S', 0}, [Tyuint] = {'I', 0}, [Tyuint32] = {'L', 0}, [Tyuint64] = {'Q', 0}, [Tyulong] = {'V', 0}, [Tyfloat32] = {'f', 0}, [Tyfloat64] = {'F', 0}, [Tyvalist] = {'.', 1}, [Typtr] = {'*', 1}, [Tyslice] = {':', 1}, [Tyarray] = {'$', 1}, [Tyfunc] = {'<', 2}, [Tytuple] = {',', 2}, [Tyvar] = {'#', -1}, [Typaram] = {'@', -1}, [Tyname] = {'%', -1}, [Tystruct] = {'^', -1}, [Tyunion] = {'!', -1}, [Tyenum] = {'/', -1}, [Ntypes] = {'\0', 0} }; static int encbuf(Type *t, char *buf, size_t len) { char *p; char *end; int i; p = buf; end = buf + len; if (len <= 0) return 0; *p++ = enctab[t->type].enc; if (enctab[t->type].special == 1) { encbuf(t->sub[0], p, end - p); } else if (enctab[t->type].special == 2) { p += snprintf(p, end - p, "%zd", t->nsub); for (i = 0; i < t->nsub; i++) encbuf(t->sub[i], p, end - p); } else if (enctab[t->type].special == -1) { switch (t->type) { case Tyname: p += namefmt(p, end - p, t->name); break; default: die("type %s should not be special", tystr(t)); } /* all special forms end with ';' */ snprintf(p, end - p, ";"); } else { die("Don't know how to encode %s", tystr(t)); } return p - buf; } char *tyenc(Type *t) { char buf[1024]; encbuf(t, buf, 1024); return strdup(buf); } static Type *decname(char *p) { char *name; char *parts[16]; char *startp; int i; Node *n; i = 0; name = p; startp = p; while (1) { if (*p == '.' || *p == ';') { if (i == 16) die("too many parts to name %s", name); parts[i++] = strdupn(startp, p - startp); startp = p; } if (!*p) die("bad decoded name %s", name); if (*p == ';') break; if (*p == '.') p++; p++; } n = mkname(-1, parts[i - 1]); i--; for (; i > 0; i--) setns(n, parts[i - 1]); return mktynamed(-1, n); } Type *tydec(char *p) { Ty i; Type *t; for (i = 0; i < Ntypes; i++) { if (enctab[i].enc == *p) break; } p++; if (enctab[i].special == 0) { t = mkty(-1, i); } else if (enctab[i].special == 1) { t = mkty(-1, i); t->nsub = 1; t->sub = xalloc(sizeof(Type*)); t->sub[0] = tydec(p); } else { switch (i) { case Tyname: t = decname(p); break; default: die("Unimplemented tydec for %s", p); break; } } return t; } void tyinit(void) { int i; #define Tc(c, n) \ mkcstr(-1, n, NULL, 0, NULL, 0); #include "cstr.def" #undef Tc #define Ty(t) \ mkty(-1, t); #include "types.def" #undef Ty /* bool :: tctest */ tycstrs[Tybool][0] = cstrtab[Tctest]; /* <integer types> :: tcnum, tcint, tctest */ for (i = Tyint8; i < Tyfloat32; i++) { tycstrs[i][0] = cstrtab[Tcnum]; tycstrs[i][1] = cstrtab[Tcint]; tycstrs[i][2] = cstrtab[Tctest]; } /* <floats> :: tcnum */ tycstrs[Tyfloat32][0] = cstrtab[Tcnum]; tycstrs[Tyfloat64][1] = cstrtab[Tcnum]; /* @a* :: tctest[0] = tcslice */ tycstrs[Typtr][0] = cstrtab[Tctest]; tycstrs[Typtr][1] = cstrtab[Tcslice]; /* @a[,] :: tctest[0] = tcslice[0] = tcidx */ tycstrs[Tyslice][0] = cstrtab[Tctest]; tycstrs[Tyslice][1] = cstrtab[Tcslice]; tycstrs[Tyslice][2] = cstrtab[Tcidx]; /* enum :: tcint, tcnum */ tycstrs[Tyenum][0] = cstrtab[Tcint]; tycstrs[Tyenum][1] = cstrtab[Tcnum]; /* array :: tcidx, tcslice */ tycstrs[Tyarray][0] = cstrtab[Tcidx]; tycstrs[Tyarray][1] = cstrtab[Tcslice]; /* ptr :: tcslice, tctest */ tycstrs[Typtr][0] = cstrtab[Tcidx]; tycstrs[Typtr][1] = cstrtab[Tctest]; /* slice :: tcidx, tcslice, tctest */ tycstrs[Tyslice][0] = cstrtab[Tcidx]; tycstrs[Tyslice][1] = cstrtab[Tcslice]; tycstrs[Tyslice][1] = cstrtab[Tctest]; }