%{#define YYERROR_VERBOSE#define YYDEBUG 1 #include <stdlib.h>#include <stdio.h>#include <stdarg.h>#include <inttypes.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 "util.h"#include "parse.h" #define LBLSTKSZ 64static Node **lbls[LBLSTKSZ];static size_t nlbls[LBLSTKSZ];Stab *curscope; /* the first time we see a label, we increment to 0 */static int lbldepth = -1; void yyerror(const char *s);int yylex(void); static Op binop(int);static Node *mkpseudodecl(Srcloc, Type *);static void installucons(Stab *, Type *);static void setattrs(Node *, char **attrs, size_t);static void setwith(Type *, Traitspec **, size_t);static void mergeenv(Node *, Node *);static void mangleautocall(Node *, char *);static void addinit(Node *, Node *);static void setuname(Type *); %} %token<tok> Tplus /* + */%token<tok> Tminus /* - */%token<tok> Tmul /* * */%token<tok> Tdiv /* / */%token<tok> Tinc /* ++ */%token<tok> Tdec /* -- */%token<tok> Tmod /* % */%token<tok> Tasn /* = */%token<tok> Taddeq /* += */%token<tok> Tsubeq /* -= */%token<tok> Tmuleq /* *= */%token<tok> Tdiveq /* /= */%token<tok> Tmodeq /* %= */%token<tok> Tboreq /* |= */%token<tok> Tbxoreq /* ^= */%token<tok> Tbandeq /* &= */%token<tok> Tbsleq /* <<= */%token<tok> Tbsreq /* >>= */ %token<tok> Tbor /* | */%token<tok> Tbxor /* ^ */%token<tok> Tband /* & */%token<tok> Tbsl /* << */%token<tok> Tbsr /* >> */%token<tok> Tbnot /* ~ */ %token<tok> Teq /* == */%token<tok> Tgt /* > */%token<tok> Tlt /* < */%token<tok> Tge /* >= */%token<tok> Tle /* <= */%token<tok> Tne /* != */ %token<tok> Tlor /* || */%token<tok> Tland /* && */%token<tok> Tlnot /* ! */ %token<tok> Tobrace /* { */%token<tok> Tcbrace /* } */%token<tok> Toparen /* ( */%token<tok> Tcparen /* ) */%token<tok> Tosqbrac /* [ */%token<tok> Tcsqbrac /* ] */%token<tok> Ttick /* ` */%token<tok> Tderef /* # */%token<tok> Tqmark /* ? */ %token<tok> Ttype /* type */%token<tok> Tfor /* for */%token<tok> Twhile /* while */%token<tok> Tif /* if */%token<tok> Telse /* else */%token<tok> Telif /* else */%token<tok> Tmatch /* match */%token<tok> Tgoto /* goto */%token<tok> Tbreak /* break */%token<tok> Tcontinue /* continue */%token<tok> Tauto /* auto */ %token<tok> Tintlit%token<tok> Tstrlit%token<tok> Tfloatlit%token<tok> Tchrlit%token<tok> Tboollit%token<tok> Tvoidlit %token<tok> Ttrait /* trait */%token<tok> Timpl /* trait */%token<tok> Tstruct /* struct */%token<tok> Tunion /* union */%token<tok> Ttyparam /* @typename */ %token<tok> Tconst /* const */%token<tok> Tvar /* var */%token<tok> Tgeneric /* generic */ %token<tok> Tgap /* _ */%token<tok> Tellipsis /* ... */%token<tok> Tendln /* ; or \n */%token<tok> Tendblk /* ;; */%token<tok> Tcolon /* : */%token<tok> Twith /* :: */%token<tok> Tdot /* . */%token<tok> Tcomma /* , */%token<tok> Tret /* -> */%token<tok> Tuse /* use */%token<tok> Tpkg /* pkg */%token<tok> Tattr /* $attr */%token<tok> Tsizeof /* sizeof */ %token<tok> Tident %start file %type <ty> type structdef uniondef tupledef compoundtype functype funcsig%type <ty> generictype%type <tylist> typelist typarams optauxtypes%type <traitspecs> traitspec traits%type <traitspec> traitvar%type <nodelist> traitlist %type <tok> asnop cmpop addop mulop shiftop optident obrace %type <tydef> tydef pkgtydef typeid%type <trait> traitdef %type<node> exprln retexpr goto continue break expr atomicexpr%type<node> littok literal lorexpr landexpr borexpr strlit bandexpr%type<node> cmpexpr addexpr mulexpr shiftexpr prefixexpr ternexpr%type<node> postfixexpr funclit seqlit tuplit name block stmt label%type<node> use fnparam declbody declcore typedeclcore structent%type<node> arrayelt structelt tuphead ifstmt forstmt whilestmt%type<node> matchstmt elifs optexprln loopcond optexpr match %type <ucon> unionelt%type <node> blkbody%type <node> implstmt %type <nodelist> arglist argdefs params matches%type <nodelist> structbody structelts arrayelts%type <nodelist> tupbody tuprest%type <nodelist> decl decllist%type <nodelist> traitbody implbody%type <strlist> attrs %type <uconlist> unionbody /*We want to bind more tightly to `Foo unaryexprthan to binary operators around it. Eg: `Foo +bar should be interpreted as (`Foo (+bar)) and not (`Foo) + (bar) The default action of shifting does the right thing,but warnings suck.*/%left Ttick%left Tplus Tminus Tband %union { struct { Srcloc loc; Node **nl; size_t nn; } nodelist; struct { char **str; size_t nstr; } strlist; struct { Srcloc loc; Ucon **ucl; size_t nucl; } uconlist; struct { Srcloc loc; Type **types; size_t ntypes; } tylist; struct { /* FIXME: unused */ Srcloc loc; char *name; Type *type; Type **params; size_t nparams; } tydef; struct { Traitspec **spec; size_t nspec; } traitspecs; Traitspec *traitspec; Trait *trait; Node *node; Tok *tok; Type *ty; Ucon *ucon;} %% file : toplev | file Tendln toplev ; toplev : package | use {lappend(&file.uses, &file.nuses, $1);} | implstmt { lappend(&file.stmts, &file.nstmts, $1); } | traitdef { size_t i; puttrait(file.globls, $1->name, $1); for (i = 0; i < $1->nproto; i++) putdcl(file.globls, $1->proto[i]); } | tydef { puttype(file.globls, mkname($1.loc, $1.name), $1.type); installucons(file.globls, $1.type); } | decl { size_t i; Node *n, *d; for (i = 0; i < $1.nn; i++) { d = $1.nl[i]; /* putdcl can merge, so we need to getdcl after */ mangleautocall(d, declname(d)); putdcl(file.globls, d); n = getdcl(file.globls, d->decl.name); lappend(&file.stmts, &file.nstmts, n); d->decl.isglobl = 1; if (d->decl.isinit) file.localinit = d; if (d->decl.isfini) file.localfini = d; } } | /* empty */ ; decl : attrs Tvar decllist traitspec { size_t i; for (i = 0; i < $3.nn; i++) setattrs($3.nl[i], $1.str, $1.nstr); $$ = $3; } | attrs Tconst decllist traitspec { size_t i; for (i = 0; i < $3.nn; i++) { setattrs($3.nl[i], $1.str, $1.nstr); $3.nl[i]->decl.isconst = 1; } $$ = $3; } | attrs Tgeneric decllist traitspec { size_t i; for (i = 0; i < $3.nn; i++) { setattrs($3.nl[i], $1.str, $1.nstr); setwith($3.nl[i]->decl.type, $4.spec, $4.nspec); $3.nl[i]->decl.isconst = 1; $3.nl[i]->decl.isgeneric = 1; } $$ = $3; } ; attrs : /* empty */ {$$.nstr = 0; $$.str = NULL;} | Tattr attrs { $$ = $2; lappend(&$$.str, &$$.nstr, strdup($1->id)); } ; traitspec : Twith traits {$$ = $2;} | /* nothing */ {$$.nspec = 0;} ; traits : traitvar { $$.spec = NULL; $$.nspec = 0; lappend(&$$.spec, &$$.nspec, $1); } | traits listsep traitvar { $$ = $1; lappend(&$$.spec, &$$.nspec, $3); } ; traitvar : traitlist generictype { $$ = calloc(sizeof(Traitspec), 1); $$->trait = $1.nl; $$->ntrait = $1.nn; $$->param = $2; $$->aux = NULL; } | traitlist generictype Tret type { $$ = calloc(sizeof(Traitspec), 1); $$->trait = $1.nl; $$->ntrait = $1.nn; $$->param = $2; $$->aux = $4; } ; traitlist : name { $$.nl = 0; $$.nn = 0; lappend(&$$.nl, &$$.nn, $1); } | traitlist listsep name { lappend(&$$.nl, &$$.nn, $3); } ; decllist: declbody { $$.loc = $1->loc; $$.nl = NULL; $$.nn = 0; lappend(&$$.nl, &$$.nn, $1); } | declbody listsep decllist { linsert(&$3.nl, &$3.nn, 0, $1); $$=$3; } ; use : Tuse Tident {$$ = mkuse($1->loc, $2->id, 0);} | Tuse Tstrlit {$$ = mkuse($1->loc, $2->strval.buf, 1);} ; optident: Tident {$$ = $1;} | /* empty */ {$$ = NULL;} ; package : Tpkg optident Tasn pkgbody Tendblk { if (file.globls->name) lfatal($1->loc, "Package already declared\n"); if ($2) { updatens(file.globls, $2->id); } } ; pkgbody : pkgitem | pkgbody Tendln pkgitem ; pkgitem : decl { size_t i; for (i = 0; i < $1.nn; i++) { $1.nl[i]->decl.vis = Visexport; $1.nl[i]->decl.isglobl = 1; putdcl(file.globls, $1.nl[i]); if ($1.nl[i]->decl.init) lappend(&file.stmts, &file.nstmts, $1.nl[i]); } } | pkgtydef { /* the type may only be null in a package context, so we can set the type when merging in this case. FIXME: clean up the fucking special cases. */ if ($1.type) $1.type->vis = Visexport; puttype(file.globls, mkname($1.loc, $1.name), $1.type); installucons(file.globls, $1.type); } | traitdef { size_t i; $1->vis = Visexport; puttrait(file.globls, $1->name, $1); for (i = 0; i < $1->nproto; i++) putdcl(file.globls, $1->proto[i]); } | implstmt { $1->impl.vis = Visexport; lappend(&file.stmts, &file.nstmts, $1); } | /* empty */ ; pkgtydef: attrs tydef { size_t i; $$ = $2; for (i = 0; i < $1.nstr; i++) { if (!strcmp($1.str[i], "pkglocal")) $$.type->ispkglocal = 1; else lfatal($$.loc, "invalid type attribute '%s'", $1.str[i]); } } ; declbody: declcore | declcore Tasn expr { $$ = $1; $1->decl.init = $3; mergeenv($1, $3); } ; declcore: name {$$ = mkdecl($1->loc, $1, mktyvar($1->loc));} | typedeclcore {$$ = $1;} ; typedeclcore : name Tcolon type {$$ = mkdecl($1->loc, $1, $3);} ; name : Tident {$$ = mkname($1->loc, $1->id);} | Tident Tdot Tident { $$ = mknsname($3->loc, $1->id, $3->id); } ; implstmt : Timpl name type optauxtypes traitspec { size_t i; $$ = mkimplstmt($1->loc, $2, $3, $4.types, $4.ntypes, NULL, 0); $$->impl.isproto = 1; setwith($3, $5.spec, $5.nspec); for (i = 0; i < $4.ntypes; i++) setwith($4.types[i], $5.spec, $5.nspec); } | Timpl name type optauxtypes traitspec Tasn Tendln implbody Tendblk { size_t i; $$ = mkimplstmt($1->loc, $2, $3, $4.types, $4.ntypes, $8.nl, $8.nn); setwith($3, $5.spec, $5.nspec); for (i = 0; i < $4.ntypes; i++) setwith($4.types[i], $5.spec, $5.nspec); } ; implbody : optendlns {$$.nl = NULL; $$.nn = 0;} | implbody Tident Tasn exprln optendlns { Node *d; $$ = $1; d = mkdecl($2->loc, mkname($2->loc, $2->id), mktyvar($2->loc)); d->decl.init = $4; d->decl.isconst = 1; d->decl.isglobl = 1; mergeenv(d, $4); lappend(&$$.nl, &$$.nn, d); } ; traitdef : Ttrait Tident generictype optauxtypes traitspec { /* trait prototype */ size_t i; $$ = mktrait($1->loc, mkname($2->loc, $2->id), $3, $4.types, $4.ntypes, NULL, 0, 1); setwith($3, $5.spec, $5.nspec); for (i = 0; i < $4.ntypes; i++) setwith($4.types[i], $5.spec, $5.nspec); } | Ttrait Tident generictype optauxtypes traitspec Tasn traitbody Tendblk /* trait definition */ { size_t i; $$ = mktrait($1->loc, mkname($2->loc, $2->id), $3, $4.types, $4.ntypes,Lines 1–500 of 1331. Load more
%{ #define YYERROR_VERBOSE #define YYDEBUG 1 #include <stdlib.h> #include <stdio.h> #include <stdarg.h> #include <inttypes.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 "util.h" #include "parse.h" #define LBLSTKSZ 64 static Node **lbls[LBLSTKSZ]; static size_t nlbls[LBLSTKSZ]; Stab *curscope; /* the first time we see a label, we increment to 0 */ static int lbldepth = -1; void yyerror(const char *s); int yylex(void); static Op binop(int); static Node *mkpseudodecl(Srcloc, Type *); static void installucons(Stab *, Type *); static void setattrs(Node *, char **attrs, size_t); static void setwith(Type *, Traitspec **, size_t); static void mergeenv(Node *, Node *); static void mangleautocall(Node *, char *); static void addinit(Node *, Node *); static void setuname(Type *); %} %token<tok> Tplus /* + */ %token<tok> Tminus /* - */ %token<tok> Tmul /* * */ %token<tok> Tdiv /* / */ %token<tok> Tinc /* ++ */ %token<tok> Tdec /* -- */ %token<tok> Tmod /* % */ %token<tok> Tasn /* = */ %token<tok> Taddeq /* += */ %token<tok> Tsubeq /* -= */ %token<tok> Tmuleq /* *= */ %token<tok> Tdiveq /* /= */ %token<tok> Tmodeq /* %= */ %token<tok> Tboreq /* |= */ %token<tok> Tbxoreq /* ^= */ %token<tok> Tbandeq /* &= */ %token<tok> Tbsleq /* <<= */ %token<tok> Tbsreq /* >>= */ %token<tok> Tbor /* | */ %token<tok> Tbxor /* ^ */ %token<tok> Tband /* & */ %token<tok> Tbsl /* << */ %token<tok> Tbsr /* >> */ %token<tok> Tbnot /* ~ */ %token<tok> Teq /* == */ %token<tok> Tgt /* > */ %token<tok> Tlt /* < */ %token<tok> Tge /* >= */ %token<tok> Tle /* <= */ %token<tok> Tne /* != */ %token<tok> Tlor /* || */ %token<tok> Tland /* && */ %token<tok> Tlnot /* ! */ %token<tok> Tobrace /* { */ %token<tok> Tcbrace /* } */ %token<tok> Toparen /* ( */ %token<tok> Tcparen /* ) */ %token<tok> Tosqbrac /* [ */ %token<tok> Tcsqbrac /* ] */ %token<tok> Ttick /* ` */ %token<tok> Tderef /* # */ %token<tok> Tqmark /* ? */ %token<tok> Ttype /* type */ %token<tok> Tfor /* for */ %token<tok> Twhile /* while */ %token<tok> Tif /* if */ %token<tok> Telse /* else */ %token<tok> Telif /* else */ %token<tok> Tmatch /* match */ %token<tok> Tgoto /* goto */ %token<tok> Tbreak /* break */ %token<tok> Tcontinue /* continue */ %token<tok> Tauto /* auto */ %token<tok> Tintlit %token<tok> Tstrlit %token<tok> Tfloatlit %token<tok> Tchrlit %token<tok> Tboollit %token<tok> Tvoidlit %token<tok> Ttrait /* trait */ %token<tok> Timpl /* trait */ %token<tok> Tstruct /* struct */ %token<tok> Tunion /* union */ %token<tok> Ttyparam /* @typename */ %token<tok> Tconst /* const */ %token<tok> Tvar /* var */ %token<tok> Tgeneric /* generic */ %token<tok> Tgap /* _ */ %token<tok> Tellipsis /* ... */ %token<tok> Tendln /* ; or \n */ %token<tok> Tendblk /* ;; */ %token<tok> Tcolon /* : */ %token<tok> Twith /* :: */ %token<tok> Tdot /* . */ %token<tok> Tcomma /* , */ %token<tok> Tret /* -> */ %token<tok> Tuse /* use */ %token<tok> Tpkg /* pkg */ %token<tok> Tattr /* $attr */ %token<tok> Tsizeof /* sizeof */ %token<tok> Tident %start file %type <ty> type structdef uniondef tupledef compoundtype functype funcsig %type <ty> generictype %type <tylist> typelist typarams optauxtypes %type <traitspecs> traitspec traits %type <traitspec> traitvar %type <nodelist> traitlist %type <tok> asnop cmpop addop mulop shiftop optident obrace %type <tydef> tydef pkgtydef typeid %type <trait> traitdef %type<node> exprln retexpr goto continue break expr atomicexpr %type<node> littok literal lorexpr landexpr borexpr strlit bandexpr %type<node> cmpexpr addexpr mulexpr shiftexpr prefixexpr ternexpr %type<node> postfixexpr funclit seqlit tuplit name block stmt label %type<node> use fnparam declbody declcore typedeclcore structent %type<node> arrayelt structelt tuphead ifstmt forstmt whilestmt %type<node> matchstmt elifs optexprln loopcond optexpr match %type <ucon> unionelt %type <node> blkbody %type <node> implstmt %type <nodelist> arglist argdefs params matches %type <nodelist> structbody structelts arrayelts %type <nodelist> tupbody tuprest %type <nodelist> decl decllist %type <nodelist> traitbody implbody %type <strlist> attrs %type <uconlist> unionbody /* We want to bind more tightly to `Foo unaryexpr than to binary operators around it. Eg: `Foo +bar should be interpreted as (`Foo (+bar)) and not (`Foo) + (bar) The default action of shifting does the right thing, but warnings suck. */ %left Ttick %left Tplus Tminus Tband %union { struct { Srcloc loc; Node **nl; size_t nn; } nodelist; struct { char **str; size_t nstr; } strlist; struct { Srcloc loc; Ucon **ucl; size_t nucl; } uconlist; struct { Srcloc loc; Type **types; size_t ntypes; } tylist; struct { /* FIXME: unused */ Srcloc loc; char *name; Type *type; Type **params; size_t nparams; } tydef; struct { Traitspec **spec; size_t nspec; } traitspecs; Traitspec *traitspec; Trait *trait; Node *node; Tok *tok; Type *ty; Ucon *ucon; } %% file : toplev | file Tendln toplev ; toplev : package | use {lappend(&file.uses, &file.nuses, $1);} | implstmt { lappend(&file.stmts, &file.nstmts, $1); } | traitdef { size_t i; puttrait(file.globls, $1->name, $1); for (i = 0; i < $1->nproto; i++) putdcl(file.globls, $1->proto[i]); } | tydef { puttype(file.globls, mkname($1.loc, $1.name), $1.type); installucons(file.globls, $1.type); } | decl { size_t i; Node *n, *d; for (i = 0; i < $1.nn; i++) { d = $1.nl[i]; /* putdcl can merge, so we need to getdcl after */ mangleautocall(d, declname(d)); putdcl(file.globls, d); n = getdcl(file.globls, d->decl.name); lappend(&file.stmts, &file.nstmts, n); d->decl.isglobl = 1; if (d->decl.isinit) file.localinit = d; if (d->decl.isfini) file.localfini = d; } } | /* empty */ ; decl : attrs Tvar decllist traitspec { size_t i; for (i = 0; i < $3.nn; i++) setattrs($3.nl[i], $1.str, $1.nstr); $$ = $3; } | attrs Tconst decllist traitspec { size_t i; for (i = 0; i < $3.nn; i++) { setattrs($3.nl[i], $1.str, $1.nstr); $3.nl[i]->decl.isconst = 1; } $$ = $3; } | attrs Tgeneric decllist traitspec { size_t i; for (i = 0; i < $3.nn; i++) { setattrs($3.nl[i], $1.str, $1.nstr); setwith($3.nl[i]->decl.type, $4.spec, $4.nspec); $3.nl[i]->decl.isconst = 1; $3.nl[i]->decl.isgeneric = 1; } $$ = $3; } ; attrs : /* empty */ {$$.nstr = 0; $$.str = NULL;} | Tattr attrs { $$ = $2; lappend(&$$.str, &$$.nstr, strdup($1->id)); } ; traitspec : Twith traits {$$ = $2;} | /* nothing */ {$$.nspec = 0;} ; traits : traitvar { $$.spec = NULL; $$.nspec = 0; lappend(&$$.spec, &$$.nspec, $1); } | traits listsep traitvar { $$ = $1; lappend(&$$.spec, &$$.nspec, $3); } ; traitvar : traitlist generictype { $$ = calloc(sizeof(Traitspec), 1); $$->trait = $1.nl; $$->ntrait = $1.nn; $$->param = $2; $$->aux = NULL; } | traitlist generictype Tret type { $$ = calloc(sizeof(Traitspec), 1); $$->trait = $1.nl; $$->ntrait = $1.nn; $$->param = $2; $$->aux = $4; } ; traitlist : name { $$.nl = 0; $$.nn = 0; lappend(&$$.nl, &$$.nn, $1); } | traitlist listsep name { lappend(&$$.nl, &$$.nn, $3); } ; decllist: declbody { $$.loc = $1->loc; $$.nl = NULL; $$.nn = 0; lappend(&$$.nl, &$$.nn, $1); } | declbody listsep decllist { linsert(&$3.nl, &$3.nn, 0, $1); $$=$3; } ; use : Tuse Tident {$$ = mkuse($1->loc, $2->id, 0);} | Tuse Tstrlit {$$ = mkuse($1->loc, $2->strval.buf, 1);} ; optident: Tident {$$ = $1;} | /* empty */ {$$ = NULL;} ; package : Tpkg optident Tasn pkgbody Tendblk { if (file.globls->name) lfatal($1->loc, "Package already declared\n"); if ($2) { updatens(file.globls, $2->id); } } ; pkgbody : pkgitem | pkgbody Tendln pkgitem ; pkgitem : decl { size_t i; for (i = 0; i < $1.nn; i++) { $1.nl[i]->decl.vis = Visexport; $1.nl[i]->decl.isglobl = 1; putdcl(file.globls, $1.nl[i]); if ($1.nl[i]->decl.init) lappend(&file.stmts, &file.nstmts, $1.nl[i]); } } | pkgtydef { /* the type may only be null in a package context, so we can set the type when merging in this case. FIXME: clean up the fucking special cases. */ if ($1.type) $1.type->vis = Visexport; puttype(file.globls, mkname($1.loc, $1.name), $1.type); installucons(file.globls, $1.type); } | traitdef { size_t i; $1->vis = Visexport; puttrait(file.globls, $1->name, $1); for (i = 0; i < $1->nproto; i++) putdcl(file.globls, $1->proto[i]); } | implstmt { $1->impl.vis = Visexport; lappend(&file.stmts, &file.nstmts, $1); } | /* empty */ ; pkgtydef: attrs tydef { size_t i; $$ = $2; for (i = 0; i < $1.nstr; i++) { if (!strcmp($1.str[i], "pkglocal")) $$.type->ispkglocal = 1; else lfatal($$.loc, "invalid type attribute '%s'", $1.str[i]); } } ; declbody: declcore | declcore Tasn expr { $$ = $1; $1->decl.init = $3; mergeenv($1, $3); } ; declcore: name {$$ = mkdecl($1->loc, $1, mktyvar($1->loc));} | typedeclcore {$$ = $1;} ; typedeclcore : name Tcolon type {$$ = mkdecl($1->loc, $1, $3);} ; name : Tident {$$ = mkname($1->loc, $1->id);} | Tident Tdot Tident { $$ = mknsname($3->loc, $1->id, $3->id); } ; implstmt : Timpl name type optauxtypes traitspec { size_t i; $$ = mkimplstmt($1->loc, $2, $3, $4.types, $4.ntypes, NULL, 0); $$->impl.isproto = 1; setwith($3, $5.spec, $5.nspec); for (i = 0; i < $4.ntypes; i++) setwith($4.types[i], $5.spec, $5.nspec); } | Timpl name type optauxtypes traitspec Tasn Tendln implbody Tendblk { size_t i; $$ = mkimplstmt($1->loc, $2, $3, $4.types, $4.ntypes, $8.nl, $8.nn); setwith($3, $5.spec, $5.nspec); for (i = 0; i < $4.ntypes; i++) setwith($4.types[i], $5.spec, $5.nspec); } ; implbody : optendlns {$$.nl = NULL; $$.nn = 0;} | implbody Tident Tasn exprln optendlns { Node *d; $$ = $1; d = mkdecl($2->loc, mkname($2->loc, $2->id), mktyvar($2->loc)); d->decl.init = $4; d->decl.isconst = 1; d->decl.isglobl = 1; mergeenv(d, $4); lappend(&$$.nl, &$$.nn, d); } ; traitdef : Ttrait Tident generictype optauxtypes traitspec { /* trait prototype */ size_t i; $$ = mktrait($1->loc, mkname($2->loc, $2->id), $3, $4.types, $4.ntypes, NULL, 0, 1); setwith($3, $5.spec, $5.nspec); for (i = 0; i < $4.ntypes; i++) setwith($4.types[i], $5.spec, $5.nspec); } | Ttrait Tident generictype optauxtypes traitspec Tasn traitbody Tendblk /* trait definition */ { size_t i; $$ = mktrait($1->loc, mkname($2->loc, $2->id), $3, $4.types, $4.ntypes,