shithub: mc

Download patch

ref: e79cc81b134141763a5e0b92a5f4bb8743ac990b
parent: 8f5b85cb3a6efba94b59abfb7a40c56892e18df1
parent: 789d36d2bbe0b625a8cf37ccb1e4c04b2a8531dd
author: Ori Bernstein <[email protected]>
date: Tue May 15 21:03:27 EDT 2012

Merge branch 'master' of git+ssh://mimir.eigenstate.org/git/ori/mc2

Conflicts:
	8/isel.c

--- a/8/reduce.c
+++ b/8/reduce.c
@@ -263,11 +263,8 @@
     if (!one)
         one = mkexpr(-1, Olit, mkint(-1, 1), NULL);
     switch (exprop(n)) {
-        case Ovar:
-            r = n;
-        case Omemb:
-            r = membaddr(s, n);
-            break;
+        case Ovar: r = n; break;
+        case Omemb: r = membaddr(s, n); break;
         default:
             die("%s cannot be an lval", opstr(exprop(n)));
             break;
--- /dev/null
+++ b/a.s
@@ -1,0 +1,24 @@
+.globl _main
+_main:
+	pushl %ebp
+	movl %esp,%ebp
+	subl $12,%esp
+	jmp .L2
+.L1:
+	movl 4(%esp),%eax
+	addl (%esp),%eax
+	movl %eax,4(%esp)
+.L2:
+	movl (%esp),%eax
+	cmpl $10,%eax
+	jl .L1
+	jmp .L3
+.L3:
+	movl 4(%esp),%eax
+	movl %eax,(%esp)
+	jmp .L0
+.L0:
+	movl (%esp),%eax
+	movl %ebp,%esp
+	popl %ebp
+	ret
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -21,96 +21,100 @@
 //int n = 0;
 %}
 
-%token<tok> TError
-%token<tok> TPlus    /* + */
-%token<tok> TMinus   /* - */
-%token<tok> TStar    /* * */
-%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> Terror
+%token<tok> Tplus    /* + */
+%token<tok> Tminus   /* - */
+%token<tok> Tstar    /* * */
+%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> 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> 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> 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> TAt      /* @ */
+%token<tok> Tobrace  /* { */
+%token<tok> Tcbrace  /* } */
+%token<tok> Toparen  /* ( */
+%token<tok> Tcparen  /* ) */
+%token<tok> Tosqbrac /* [ */
+%token<tok> Tcsqbrac /* ] */
+%token<tok> Tat      /* @ */
 
-%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> TDefault /* default */
-%token<tok> TGoto            /* goto */
+%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> Tdefault /* default */
+%token<tok> Tgoto            /* goto */
 
-%token<tok> TIntlit
-%token<tok> TStrlit
-%token<tok> TFloatlit
-%token<tok> TChrlit
-%token<tok> TBoollit
+%token<tok> Tintlit
+%token<tok> Tstrlit
+%token<tok> Tfloatlit
+%token<tok> Tchrlit
+%token<tok> Tboollit
 
-%token<tok> TEnum    /* enum */
-%token<tok> TStruct  /* struct */
-%token<tok> TUnion   /* union */
+%token<tok> Tenum    /* enum */
+%token<tok> Tstruct  /* struct */
+%token<tok> Tunion   /* union */
+%token<tok> Ttyparam /* @typename */
 
-%token<tok> TConst   /* const */
-%token<tok> TVar             /* var */
-%token<tok> TExtern  /* extern */
+%token<tok> Tconst   /* const */
+%token<tok> Tvar     /* var */
+%token<tok> Tgeneric /* var */
+%token<tok> Textern  /* extern */
 
-%token<tok> TExport  /* export */
-%token<tok> TProtect /* protect */
+%token<tok> Texport  /* export */
+%token<tok> Tprotect /* protect */
 
-%token<tok> TEllipsis        /* ... */
-%token<tok> TEndln           /* ; or \n */
-%token<tok> TEndblk  /* ;; */
-%token<tok> TColon   /* : */
-%token<tok> TDot             /* . */
-%token<tok> TComma   /* , */
-%token<tok> TRet             /* -> */
-%token<tok> TUse             /* use */
-%token<tok> TPkg             /* pkg */
-%token<tok> TSizeof  /* sizeof */
 
-%token<tok> TIdent
-%token<tok> TEof
+%token<tok> Tellipsis        /* ... */
+%token<tok> Tendln           /* ; or \n */
+%token<tok> Tendblk  /* ;; */
+%token<tok> Tcolon   /* : */
+%token<tok> Tdot             /* . */
+%token<tok> Tcomma   /* , */
+%token<tok> Tret             /* -> */
+%token<tok> Tuse             /* use */
+%token<tok> Tpkg             /* pkg */
+%token<tok> Tsizeof  /* sizeof */
 
+%token<tok> Tident
+%token<tok> Teof
+
 %start module
 
 %type <ty> type structdef uniondef enumdef compoundtype functype funcsig
+%type <ty> generictype
 
 %type <tok> asnop cmpop addop mulop shiftop
 
@@ -165,31 +169,35 @@
         | package
         | tydef
             {puttype(file->file.globls, mkname($1.line, $1.name), $1.type);}
-        | TEndln
+        | Tendln
         ;
 
-decl    : TVar declbody TEndln
+decl    : Tvar declbody Tendln
             {$2->decl.flags = 0;
              $$ = $2;}
-        | TConst declbody TEndln
+        | Tconst declbody Tendln
             {$2->decl.sym->isconst = 1;
              $2->decl.flags = 0;
              $$ = $2;}
-        | TExtern TVar declbody TEndln
+        | Tgeneric declbody Tendln
+            {$2->decl.sym->isconst = 1;
+             $2->decl.flags = 0;
+             $$ = $2;}
+        | Textern Tvar declbody Tendln
             {$3->decl.flags = Dclextern;
              $$ = $3;}
-        | TExtern TConst declbody TEndln
+        | Textern Tconst declbody Tendln
             {$3->decl.flags = Dclconst | Dclextern;
              $$ = $3;}
         ;
 
-use     : TUse TIdent TEndln
+use     : Tuse Tident Tendln
             {$$ = mkuse($1->line, $2->str, 0);}
-        | TUse TStrlit TEndln
+        | Tuse Tstrlit Tendln
             {$$ = mkuse($1->line, $2->str, 1);}
         ;
 
-package : TPkg TIdent TAsn pkgbody TEndblk
+package : Tpkg Tident Tasn pkgbody Tendblk
         ;
 
 
@@ -202,15 +210,15 @@
                          mkname($1.line, $1.name),
                          $1.type);}
         | visdef {die("Unimplemented visdef");}
-        | TEndln
+        | Tendln
         ;
 
-visdef  : TExport TColon
-        | TProtect TColon
+visdef  : Texport Tcolon
+        | Tprotect Tcolon
         ;
 
 
-declbody: declcore TAsn expr
+declbody: declcore Tasn expr
             {$$ = $1; $1->decl.init = $3;}
         | declcore
         ;
@@ -217,21 +225,21 @@
 
 declcore: name
             {$$ = mkdecl($1->line, mksym($1->line, $1, mktyvar($1->line)));}
-        | name TColon type
+        | name Tcolon type
             {$$ = mkdecl($1->line, mksym($1->line, $1, $3));}
         ;
 
-name    : TIdent
+name    : Tident
             {$$ = mkname($1->line, $1->str);}
-        | TIdent TDot name
+        | Tident Tdot name
             {$$ = $3; setns($3, $1->str);}
         ;
 
-tydef   : TType TIdent TAsn type TEndln
+tydef   : Ttype Tident Tasn type Tendln
             {$$.line = $1->line;
              $$.name = $2->str;
              $$.type = $4;}
-        | TType TIdent TEndln
+        | Ttype Tident Tendln
             {$$.line = $1->line;
              $$.name = $2->str;
              $$.type = NULL;}
@@ -241,23 +249,29 @@
         | uniondef
         | enumdef
         | compoundtype
+        | generictype
         ;
 
+generictype
+        : Ttyparam {$$ = mktyparam($1->line, $1->str);}
+        /* FIXME: allow constrained typarmas */
+        ;
+
 compoundtype
         : functype   {$$ = $1;}
-        | type TOsqbrac TComma TCsqbrac {$$ = mktyslice($2->line, $1);}
-        | type TOsqbrac expr TCsqbrac {$$ = mktyarray($2->line, $1, $3);}
-        | type TStar {$$ = mktyptr($2->line, $1);}
+        | type Tosqbrac Tcomma Tcsqbrac {$$ = mktyslice($2->line, $1);}
+        | type Tosqbrac expr Tcsqbrac {$$ = mktyarray($2->line, $1, $3);}
+        | type Tstar {$$ = mktyptr($2->line, $1);}
         | name       {$$ = mktynamed($1->line, $1);}
-        | TAt TIdent {$$ = mktyparam($1->line, $2->str);}
+        | Tat Tident {$$ = mktyparam($1->line, $2->str);}
         ;
 
-functype: TOparen funcsig TCparen {$$ = $2;}
+functype: Toparen funcsig Tcparen {$$ = $2;}
         ;
 
 funcsig : argdefs
             {$$ = mktyfunc($1.line, $1.nl, $1.nn, mktyvar($1.line));}
-        | argdefs TRet type
+        | argdefs Tret type
             {$$ = mktyfunc($1.line, $1.nl, $1.nn, $3);}
         ;
 
@@ -265,12 +279,12 @@
             {$$.line = $1->line;
              $$.nl = NULL;
              $$.nn = 0; lappend(&$$.nl, &$$.nn, $1);}
-        | argdefs TComma declcore
+        | argdefs Tcomma declcore
             {lappend(&$$.nl, &$$.nn, $3);}
         ;
 
 structdef
-        : TStruct structbody TEndblk
+        : Tstruct structbody Tendblk
             {$$ = mktystruct($1->line, $2.nl, $2.nn);}
         ;
 
@@ -282,16 +296,16 @@
         ;
 
 structelt
-        : declcore TEndln
+        : declcore Tendln
             {$$ = $1;}
-        | visdef TEndln
+        | visdef Tendln
             {$$ = NULL;}
-        | TEndln
+        | Tendln
             {$$ = NULL;}
         ;
 
 uniondef
-        : TUnion unionbody TEndblk
+        : Tunion unionbody Tendblk
             {$$ = mktyunion($1->line, $2.nl, $2.nn);}
         ;
 
@@ -303,15 +317,15 @@
         ;
 
 unionelt
-        : TIdent type TEndln
+        : Tident type Tendln
             {$$ = NULL; die("unionelt impl");}
-        | visdef TEndln
+        | visdef Tendln
             {$$ = NULL;}
-        | TEndln
+        | Tendln
             {$$ = NULL;}
         ;
 
-enumdef : TEnum enumbody TEndblk
+enumdef : Tenum enumbody Tendblk
             {$$ = mktyenum($1->line, $2.nl, $2.nn);}
         ;
 
@@ -321,20 +335,20 @@
             {if ($2) {lappend(&$$.nl, &$$.nn, $2);}}
         ;
 
-enumelt : TIdent TEndln
+enumelt : Tident Tendln
             {$$ = NULL; die("enumelt impl");}
-        | TIdent TAsn exprln
+        | Tident Tasn exprln
             {$$ = NULL; die("enumelt impl");}
-        | TEndln
+        | Tendln
             {$$ = NULL;}
         ;
 
-retexpr : TRet exprln
+retexpr : Tret exprln
             {$$ = mkexpr($1->line, Oret, $2, NULL);}
         | exprln
         ;
 
-exprln  : expr TEndln
+exprln  : expr Tendln
         ;
 
 expr    : asnexpr
@@ -345,35 +359,35 @@
         | lorexpr
         ;
 
-asnop   : TAsn
-        | TAddeq        /* += */
-        | TSubeq        /* -= */
-        | TMuleq        /* *= */
-        | TDiveq        /* /= */
-        | TModeq        /* %= */
-        | TBoreq        /* |= */
-        | TBxoreq       /* ^= */
-        | TBandeq       /* &= */
-        | TBsleq        /* <<= */
-        | TBsreq        /* >>= */
+asnop   : Tasn
+        | Taddeq        /* += */
+        | Tsubeq        /* -= */
+        | Tmuleq        /* *= */
+        | Tdiveq        /* /= */
+        | Tmodeq        /* %= */
+        | Tboreq        /* |= */
+        | Tbxoreq       /* ^= */
+        | Tbandeq       /* &= */
+        | Tbsleq        /* <<= */
+        | Tbsreq        /* >>= */
         ;
 
-lorexpr : lorexpr TLor landexpr
+lorexpr : lorexpr Tlor landexpr
             {$$ = mkexpr($1->line, binop($2->type), $1, $3, NULL);}
         | landexpr
         ;
 
-landexpr: landexpr TLand borexpr
+landexpr: landexpr Tland borexpr
             {$$ = mkexpr($1->line, binop($2->type), $1, $3, NULL);}
         | borexpr
         ;
 
-borexpr : borexpr TBor bandexpr
+borexpr : borexpr Tbor bandexpr
             {$$ = mkexpr($1->line, binop($2->type), $1, $3, NULL);}
         | bandexpr
         ;
 
-bandexpr: bandexpr TBand cmpexpr
+bandexpr: bandexpr Tband cmpexpr
             {$$ = mkexpr($1->line, binop($2->type), $1, $3, NULL);}
         | cmpexpr
         ;
@@ -383,7 +397,7 @@
         | addexpr
         ;
 
-cmpop   : TEq | TGt | TLt | TGe | TLe | TNe ;
+cmpop   : Teq | Tgt | Tlt | Tge | Tle | Tne ;
 
 addexpr : addexpr addop mulexpr
             {$$ = mkexpr($1->line, binop($2->type), $1, $3, NULL);}
@@ -390,7 +404,7 @@
         | mulexpr
         ;
 
-addop   : TPlus | TMinus ;
+addop   : Tplus | Tminus ;
 
 mulexpr : mulexpr mulop shiftexpr
             {$$ = mkexpr($1->line, binop($2->type), $1, $3, NULL);}
@@ -397,7 +411,7 @@
         | shiftexpr
         ;
 
-mulop   : TStar | TDiv | TMod
+mulop   : Tstar | Tdiv | Tmod
         ;
 
 shiftexpr
@@ -406,32 +420,32 @@
         | prefixexpr
         ;
 
-shiftop : TBsl | TBsr;
+shiftop : Tbsl | Tbsr;
 
 prefixexpr
-        : TInc postfixexpr      {$$ = mkexpr($1->line, Opreinc, $2, NULL);}
-        | TDec postfixexpr      {$$ = mkexpr($1->line, Opredec, $2, NULL);}
-        | TStar postfixexpr     {$$ = mkexpr($1->line, Oderef, $2, NULL);}
-        | TBand postfixexpr     {$$ = mkexpr($1->line, Oaddr, $2, NULL);}
-        | TLnot postfixexpr     {$$ = mkexpr($1->line, Olnot, $2, NULL);}
-        | TBnot postfixexpr     {$$ = mkexpr($1->line, Obnot, $2, NULL);}
-        | TMinus postfixexpr    {$$ = mkexpr($1->line, Oneg, $2, NULL);}
-        | TPlus postfixexpr     {$$ = $2;} /* positive is a nop */
+        : Tinc postfixexpr      {$$ = mkexpr($1->line, Opreinc, $2, NULL);}
+        | Tdec postfixexpr      {$$ = mkexpr($1->line, Opredec, $2, NULL);}
+        | Tstar postfixexpr     {$$ = mkexpr($1->line, Oderef, $2, NULL);}
+        | Tband postfixexpr     {$$ = mkexpr($1->line, Oaddr, $2, NULL);}
+        | Tlnot postfixexpr     {$$ = mkexpr($1->line, Olnot, $2, NULL);}
+        | Tbnot postfixexpr     {$$ = mkexpr($1->line, Obnot, $2, NULL);}
+        | Tminus postfixexpr    {$$ = mkexpr($1->line, Oneg, $2, NULL);}
+        | Tplus postfixexpr     {$$ = $2;} /* positive is a nop */
         | postfixexpr
         ;
 
 postfixexpr
-        : postfixexpr TDot TIdent
+        : postfixexpr Tdot Tident
             {$$ = mkexpr($1->line, Omemb, $1, mkname($3->line, $3->str), NULL);}
-        | postfixexpr TInc
+        | postfixexpr Tinc
             {$$ = mkexpr($1->line, Opostinc, $1, NULL);}
-        | postfixexpr TDec
+        | postfixexpr Tdec
             {$$ = mkexpr($1->line, Opostdec, $1, NULL);}
-        | postfixexpr TOsqbrac expr TCsqbrac
-            {$$ = mkexpr($1->line, Oidx, $1, $3);}
-        | postfixexpr TOsqbrac expr TComma expr TCsqbrac
+        | postfixexpr Tosqbrac expr Tcsqbrac
+            {$$ = mkexpr($1->line, Oidx, $1, $3, NULL);}
+        | postfixexpr Tosqbrac expr Tcomma expr Tcsqbrac
             {$$ = mkexpr($1->line, Oslice, $1, $3, $5, NULL);}
-        | postfixexpr TOparen arglist TCparen
+        | postfixexpr Toparen arglist Tcparen
             {$$ = mkcall($1->line, $1, $3.nl, $3.nn);}
         | atomicexpr
         ;
@@ -438,7 +452,7 @@
 
 arglist : asnexpr
             {$$.nl = NULL; $$.nn = 0; lappend(&$$.nl, &$$.nn, $1);}
-        | arglist TComma asnexpr
+        | arglist Tcomma asnexpr
             {lappend(&$$.nl, &$$.nn, $3);}
         | /* empty */
             {$$.nl = NULL; $$.nn = 0;}
@@ -445,45 +459,45 @@
         ;
 
 atomicexpr
-        : TIdent
+        : Tident
             {$$ = mkexpr($1->line, Ovar, mkname($1->line, $1->str), NULL);}
         | literal {$$ = mkexpr($1->line, Olit, $1, NULL);}
-        | TOparen expr TCparen
+        | Toparen expr Tcparen
             {$$ = $2;}
-        | TSizeof atomicexpr
+        | Tsizeof atomicexpr
             {$$ = mkexpr($1->line, Osize, $2, NULL);}
         ;
 
 literal : funclit       {$$ = $1;}
         | arraylit      {$$ = $1;}
-        | TStrlit       {$$ = mkstr($1->line, $1->str);}
-        | TIntlit       {$$ = mkint($1->line, strtol($1->str, NULL, 0));}
-        | TChrlit       {$$ = mkchar($1->line, *$1->str);} /* FIXME: expand escapes, unicode  */
-        | TFloatlit     {$$ = mkfloat($1->line, strtod($1->str, NULL));}
-        | TBoollit      {$$ = mkbool($1->line, !strcmp($1->str, "true"));}
+        | Tstrlit       {$$ = mkstr($1->line, $1->str);}
+        | Tintlit       {$$ = mkint($1->line, strtol($1->str, NULL, 0));}
+        | Tchrlit       {$$ = mkchar($1->line, *$1->str);} /* FIXME: expand escapes, unicode  */
+        | Tfloatlit     {$$ = mkfloat($1->line, strtod($1->str, NULL));}
+        | Tboollit      {$$ = mkbool($1->line, !strcmp($1->str, "true"));}
         ;
 
-funclit : TObrace params TEndln blockbody TCbrace
+funclit : Tobrace params Tendln blockbody Tcbrace
             {$$ = mkfunc($1->line, $2.nl, $2.nn, mktyvar($3->line), $4);}
-        | TObrace params TRet type TEndln blockbody TCbrace
+        | Tobrace params Tret type Tendln blockbody Tcbrace
             {$$ = mkfunc($1->line, $2.nl, $2.nn, $4, $6);}
         ;
 
 params  : declcore
             {$$.nl = NULL; $$.nn = 0; lappend(&$$.nl, &$$.nn, $1);}
-        | params TComma declcore
+        | params Tcomma declcore
             {lappend(&$$.nl, &$$.nn, $3);}
         | /* empty */
             {$$.nl = NULL; $$.nn = 0;}
         ;
 
-arraylit : TOsqbrac arraybody TCsqbrac
+arraylit : Tosqbrac arraybody Tcsqbrac
             {$$ = NULL; die("Unimpl arraylit");}
          ;
 
 arraybody
         : expr
-        | arraybody TComma expr
+        | arraybody Tcomma expr
         ;
 
 stmt    : decl
@@ -492,38 +506,38 @@
         | ifstmt
         | forstmt
         | whilestmt
-        | TEndln {$$ = NULL;}
+        | Tendln {$$ = NULL;}
         ;
 
-forstmt : TFor optexprln optexprln optexprln block
+forstmt : Tfor optexprln optexprln optexprln block
             {$$ = mkloop($1->line, $2, $3, $4, $5);}
-        | TFor decl optexprln optexprln block
+        | Tfor decl optexprln optexprln block
             {$$ = mkloop($1->line, $2, $3, $4, $5);}
         ;
 
 optexprln: exprln {$$ = $1;}
-         | TEndln {$$ = NULL;}
+         | Tendln {$$ = NULL;}
          ;
 
 whilestmt
-        : TWhile exprln block
+        : Twhile exprln block
             {$$ = mkloop($1->line, NULL, $2, NULL, $3);}
         ;
 
-ifstmt  : TIf exprln blockbody elifs
+ifstmt  : Tif exprln blockbody elifs
             {$$ = mkif($1->line, $2, $3, $4);}
         ;
 
-elifs   : TElif exprln blockbody elifs
+elifs   : Telif exprln blockbody elifs
             {$$ = mkif($1->line, $2, $3, $4);}
-        | TElse blockbody TEndblk
+        | Telse blockbody Tendblk
             {$$ = $2;}
-        | TEndblk
+        | Tendblk
             {$$ = NULL;}
         ;
 
-block   : blockbody TEndblk
-        | TEndblk {$$ = NULL;}
+block   : blockbody Tendblk
+        | Tendblk {$$ = NULL;}
         ;
 
 blockbody
@@ -541,7 +555,7 @@
              $$ = $1;}
         ;
 
-label   : TColon TIdent
+label   : Tcolon Tident
             {$$ = mklbl($1->line, $1->str);}
         ;
 
@@ -561,35 +575,35 @@
 
     o = Obad;
     switch (tt) {
-        case TPlus:     o = Oadd;       break;
-        case TMinus:    o = Osub;       break;
-        case TStar:     o = Omul;       break;
-        case TDiv:      o = Odiv;       break;
-        case TMod:      o = Omod;       break;
-        case TAsn:      o = Oasn;       break;
-        case TAddeq:    o = Oaddeq;     break;
-        case TSubeq:    o = Osubeq;     break;
-        case TMuleq:    o = Omuleq;     break;
-        case TDiveq:    o = Odiveq;     break;
-        case TModeq:    o = Omodeq;     break;
-        case TBoreq:    o = Oboreq;     break;
-        case TBxoreq:   o = Obxoreq;    break;
-        case TBandeq:   o = Obandeq;    break;
-        case TBsleq:    o = Obsleq;     break;
-        case TBsreq:    o = Obsreq;     break;
-        case TBor:      o = Obor;       break;
-        case TBxor:     o = Obxor;      break;
-        case TBand:     o = Oband;      break;
-        case TBsl:      o = Obsl;       break;
-        case TBsr:      o = Obsr;       break;
-        case TEq:       o = Oeq;        break;
-        case TGt:       o = Ogt;        break;
-        case TLt:       o = Olt;        break;
-        case TGe:       o = Oge;        break;
-        case TLe:       o = Ole;        break;
-        case TNe:       o = One;        break;
-        case TLor:      o = Olor;       break;
-        case TLand:     o = Oland;      break;
+        case Tplus:     o = Oadd;       break;
+        case Tminus:    o = Osub;       break;
+        case Tstar:     o = Omul;       break;
+        case Tdiv:      o = Odiv;       break;
+        case Tmod:      o = Omod;       break;
+        case Tasn:      o = Oasn;       break;
+        case Taddeq:    o = Oaddeq;     break;
+        case Tsubeq:    o = Osubeq;     break;
+        case Tmuleq:    o = Omuleq;     break;
+        case Tdiveq:    o = Odiveq;     break;
+        case Tmodeq:    o = Omodeq;     break;
+        case Tboreq:    o = Oboreq;     break;
+        case Tbxoreq:   o = Obxoreq;    break;
+        case Tbandeq:   o = Obandeq;    break;
+        case Tbsleq:    o = Obsleq;     break;
+        case Tbsreq:    o = Obsreq;     break;
+        case Tbor:      o = Obor;       break;
+        case Tbxor:     o = Obxor;      break;
+        case Tband:     o = Oband;      break;
+        case Tbsl:      o = Obsl;       break;
+        case Tbsr:      o = Obsr;       break;
+        case Teq:       o = Oeq;        break;
+        case Tgt:       o = Ogt;        break;
+        case Tlt:       o = Olt;        break;
+        case Tge:       o = Oge;        break;
+        case Tle:       o = Ole;        break;
+        case Tne:       o = One;        break;
+        case Tlor:      o = Olor;       break;
+        case Tland:     o = Oland;      break;
         default:
             die("Unimplemented binop\n");
             break;
--- a/parse/tok.c
+++ b/parse/tok.c
@@ -132,28 +132,29 @@
 {
     int i;
     struct {char* kw; int tt;} kwmap[] = {
-        {"type",        TType},
-        {"for",         TFor},
-        {"while",       TWhile},
-        {"if",          TIf},
-        {"else",        TElse},
-        {"elif",        TElif},
-        {"match",       TMatch},
-        {"default",     TDefault},
-        {"goto",        TGoto},
-        {"enum",        TEnum},
-        {"struct",      TStruct},
-        {"union",       TUnion},
-        {"const",       TConst},
-        {"var",         TVar},
-        {"extern",      TExtern},
-        {"export",      TExport},
-        {"protect",     TProtect},
-        {"use",         TUse},
-        {"pkg",         TPkg},
-        {"sizeof",      TSizeof},
-        {"true",        TBoollit},
-        {"false",       TBoollit},
+        {"type",        Ttype},
+        {"for",         Tfor},
+        {"while",       Twhile},
+        {"if",          Tif},
+        {"else",        Telse},
+        {"elif",        Telif},
+        {"match",       Tmatch},
+        {"default",     Tdefault},
+        {"goto",        Tgoto},
+        {"enum",        Tenum},
+        {"struct",      Tstruct},
+        {"union",       Tunion},
+        {"const",       Tconst},
+        {"var",         Tvar},
+        {"generic",     Tgeneric},
+        {"extern",      Textern},
+        {"export",      Texport},
+        {"protect",     Tprotect},
+        {"use",         Tuse},
+        {"pkg",         Tpkg},
+        {"sizeof",      Tsizeof},
+        {"true",        Tboollit},
+        {"false",       Tboollit},
         {NULL, 0}
     };
 
@@ -161,16 +162,14 @@
         if (!strcmp(kwmap[i].kw, s))
             return kwmap[i].tt;
 
-    return TIdent;
+    return Tident;
 }
 
-static Tok *kwident(void)
+static int identstr(char *buf, size_t sz)
 {
-    char buf[1024];
-    char c;
     int i;
-    Tok *t;
-
+    char c;
+    
     i = 0;
     for (c = peek(); i < 1023 && identchar(c); c = peek()) {
         next();
@@ -177,6 +176,16 @@
         buf[i++] = c;
     }
     buf[i] = '\0';
+    return i;
+}
+
+static Tok *kwident(void)
+{
+    char buf[1024];
+    Tok *t;
+
+    if (!identstr(buf, sizeof buf))
+        return NULL;
     t = mktok(kwd(buf));
     t->str = strdup(buf);
     return t;
@@ -204,7 +213,7 @@
         else if (c == '\n')
             fatal(line, "Newlines not allowed in strings");
     };
-    t = mktok(TStrlit);
+    t = mktok(Tstrlit);
     t->str = strdupn(&fbuf[sstart], fidx - sstart);
     return t;
 }
@@ -231,7 +240,7 @@
         else if (c == '\n')
             fatal(line, "Newlines not allowed in char lit");
     };
-    t = mktok(TStrlit);
+    t = mktok(Tstrlit);
     t->str = strdupn(&fbuf[sstart], fidx - sstart);
     return t;
 }
@@ -243,130 +252,130 @@
 
     c = next();
     switch (c) {
-        case '{': tt = TObrace; break;
-        case '}': tt = TCbrace; break;
-        case '(': tt = TOparen; break;
-        case ')': tt = TCparen; break;
-        case '[': tt = TOsqbrac; break;
-        case ']': tt = TCsqbrac; break;
-        case ',': tt = TComma; break;
-        case ':': tt = TColon; break;
-        case '~': tt = TBnot; break;
+        case '{': tt = Tobrace; break;
+        case '}': tt = Tcbrace; break;
+        case '(': tt = Toparen; break;
+        case ')': tt = Tcparen; break;
+        case '[': tt = Tosqbrac; break;
+        case ']': tt = Tcsqbrac; break;
+        case ',': tt = Tcomma; break;
+        case ':': tt = Tcolon; break;
+        case '~': tt = Tbnot; break;
         case ';':
                   if (match(';'))
-                      tt = TEndblk;
+                      tt = Tendblk;
                   else
-                      tt = TEndln;
+                      tt = Tendln;
                   break;
         case '.':
                   if (match('.')) {
                       if (match('.')) {
-                          tt = TEllipsis;
+                          tt = Tellipsis;
                       } else { 
                           unget();
-                          tt = TDot;
+                          tt = Tdot;
                       }
                   } else {
-                      tt = TDot;
+                      tt = Tdot;
                   }
                   break;
         case '+':
                   if (match('='))
-                      tt = TAddeq;
+                      tt = Taddeq;
                   else if (match('+'))
-                      tt = TInc;
+                      tt = Tinc;
                   else
-                      tt = TPlus;
+                      tt = Tplus;
                   break;
         case '-':
                   if (match('='))
-                      tt = TSubeq;
+                      tt = Tsubeq;
                   else if (match('-'))
-                      tt = TDec;
+                      tt = Tdec;
                   else if (match('>'))
-                      tt = TRet;
+                      tt = Tret;
                   else
-                      tt = TMinus;
+                      tt = Tminus;
                   break;
         case '*':
                   if (match('='))
-                      tt = TMuleq;
+                      tt = Tmuleq;
                   else
-                      tt = TStar;
+                      tt = Tstar;
                   break;
         case '/':
                   if (match('='))
-                      tt = TDiveq;
+                      tt = Tdiveq;
                   else
-                      tt = TDiv;
+                      tt = Tdiv;
                   break;
         case '%':
                   if (match('='))
-                      tt = TModeq;
+                      tt = Tmodeq;
                   else
-                      tt = TMod;
+                      tt = Tmod;
                   break;
         case '=':
                   if (match('='))
-                      tt = TEq;
+                      tt = Teq;
                   else
-                      tt = TAsn;
+                      tt = Tasn;
                   break;
         case '|':
                   if (match('='))
-                      tt = TBoreq;
+                      tt = Tboreq;
                   else if (match('|'))
-                      tt = TLor;
+                      tt = Tlor;
                   else
-                      tt = TBor;
+                      tt = Tbor;
                   break;
         case '&':
                   if (match('='))
-                      tt = TBandeq;
+                      tt = Tbandeq;
                   else if (match('|'))
-                      tt = TLand;
+                      tt = Tland;
                   else
-                      tt = TBand;
+                      tt = Tband;
                   break;
         case '^':
                   if (match('='))
-                      tt = TBxoreq;
+                      tt = Tbxoreq;
                   else
-                      tt = TBxor;
+                      tt = Tbxor;
                   break;
         case '<':
                   if (match('=')) {
-                      tt = TLe;
+                      tt = Tle;
                   } else if (match('<')) {
                       if (match('='))
-                          tt = TBsleq;
+                          tt = Tbsleq;
                       else
-                          tt = TBsl;
+                          tt = Tbsl;
                   } else {
-                      tt = TLt;
+                      tt = Tlt;
                   }
                   break;
         case '>':
                   if (match('=')) {
-                      tt = TGe;
+                      tt = Tge;
                   } else if (match('<')) {
                       if (match('='))
-                          tt = TBsreq;
+                          tt = Tbsreq;
                       else
-                          tt = TBsr;
+                          tt = Tbsr;
                   } else {
-                      tt = TGt;
+                      tt = Tgt;
                   }
                   break;
 
         case '!':
                   if (match('='))
-                      tt = TNe;
+                      tt = Tne;
                   else
-                      tt = TLnot;
+                      tt = Tlnot;
                   break;
         default:
-                  tt = TError;
+                  tt = Terror;
                   fatal(line, "Junk character %c", c);
                   break;
     }
@@ -394,13 +403,13 @@
     if (isfloat && base == 10) {
         strtod(&fbuf[start], &endp);
         if (endp == &fbuf[fidx]) {
-            t = mktok(TFloatlit);
+            t = mktok(Tfloatlit);
             t->str = strdupn(&fbuf[start], fidx - start);
         }
     } else {
         strtol(&fbuf[start], &endp, base);
         if (endp == &fbuf[fidx]) {
-            t = mktok(TIntlit);
+            t = mktok(Tintlit);
             t->str = strdupn(&fbuf[start], fidx - start);
         }
     }
@@ -427,6 +436,21 @@
     return t;
 }
 
+static Tok *typaram()
+{
+    Tok *t;
+    char buf[1024];
+
+    t = NULL;
+    if (!match('@'))
+        return NULL;
+    if (!identstr(buf, 1024))
+        return NULL;
+    t = mktok(Ttyparam);
+    t->str = strdup(buf);
+    return t;
+}
+
 static Tok *toknext()
 {
     Tok *t;
@@ -439,7 +463,7 @@
     } else if (c == '\n') {
         line++;
         next();
-        t =  mktok(TEndln);
+        t =  mktok(Tendln);
     } else if (isalpha(c) || c == '_') {
         t =  kwident();
     } else if (c == '"') {
@@ -448,11 +472,13 @@
         t = charlit();
     } else if (isdigit(c)) {
         t =  numlit();
+    } else if (c == '@') {
+        t = typaram();
     } else {
         t = oper();
     }
 
-    if (!t || t->type == TError)
+    if (!t || t->type == Terror)
         fatal(line, "Unable to parse token starting with %c", c);
     return t;
 }
--- a/parse/type.c
+++ b/parse/type.c
@@ -99,7 +99,7 @@
 {
     Type *t;
 
-    t = mkty(line, Tyvar);
+    t = mkty(line, Typaram);
     t->pname = strdup(name);
     return t;
 }