#pragma once #include #include #define iota(x) 1 << (x) /* core types */ typedef struct Io Io; typedef struct Pos Pos; typedef struct Token Token; typedef struct Sym Sym; typedef struct Type Type; typedef struct Spec Spec; typedef struct Decl Decl; typedef struct Stmt Stmt; typedef struct Expr Expr; /* maps */ typedef struct SymTab SymTab; typedef struct StrTab StrTab; // ----------------------------------------------------------------------- // lexing: byte stream -> tokens // pre-processor built in struct Pos { int col; int line; string path; }; #define DIRECTIVES \ DIRECTIVE(Dpragma,"pragma") \ DIRECTIVE(Dinclude,"include") \ DIRECTIVE(Dif,"if") \ DIRECTIVE(Ddefine,"define") \ DIRECTIVE(Difdef,"ifdef") \ DIRECTIVE(Difndef,"ifndef") #define DIRECTIVE(a, b) a, enum { DIRECTIVES }; #undef DIRECTIVE #define DIRECTIVE(a, b) b, static byte *directives[] = { DIRECTIVES }; #undef DIRECTIVE #define KEYWORDS \ KEYWORD(Kauto,"auto") \ KEYWORD(Kregister,"register") \ KEYWORD(Kstatic,"static") \ KEYWORD(Kextern,"extern") \ KEYWORD(Ktypedef,"typedef") \ KEYWORD(Kconst,"const") \ KEYWORD(Kvolatile,"volatile") \ KEYWORD(Krestrict,"restrict") \ KEYWORD(Kinline,"inline") \ KEYWORD(Kvoid,"void") \ KEYWORD(Kchar,"char") \ KEYWORD(Kint,"int") \ KEYWORD(Kfloat,"float") \ KEYWORD(Kdouble,"double") \ KEYWORD(Ksigned,"signed") \ KEYWORD(Kunsigned,"unsigned") \ KEYWORD(Kshort,"short") \ KEYWORD(Klong,"long") \ KEYWORD(Kvlong,"vlong") \ KEYWORD(Kstruct,"struct") \ KEYWORD(Kunion,"union") \ KEYWORD(Kenum,"enum") \ KEYWORD(Kfor,"for") \ KEYWORD(Kdo,"do") \ KEYWORD(Kwhile,"while") \ KEYWORD(Kcontinue,"continue") \ KEYWORD(Kif,"if") \ KEYWORD(Kelse,"else") \ KEYWORD(Kswitch,"switch") \ KEYWORD(Kcase,"case") \ KEYWORD(Kdefault,"default") \ KEYWORD(Kbreak,"break") \ KEYWORD(Kgoto,"goto") \ KEYWORD(Kreturn,"return") \ KEYWORD(Ksizeof,"sizeof") \ KEYWORD(Kalignof,"alignof") #define KEYWORD(a, b) a, enum { KEYWORDS }; #undef KEYWORD #define KEYWORD(a, b) b, static byte *keywords[] = { KEYWORDS }; #undef KEYWORD #undef KEYWORDS #define TOKENS \ TOK(Anil,"nil") \ TOK(Aeof,"eof") \ TOK(Aeq, "==") \ TOK(Aneq, "!=") \ TOK(Anot, "!") \ TOK(Aneg, "~") \ TOK(Axor, "^") \ TOK(Aor, "|") \ TOK(Aand, "&") \ TOK(Aoror, "||") \ TOK(Aandand, "&&") \ TOK(Aadd,"+") \ TOK(Asub,"-") \ TOK(Astar,"*") \ TOK(Adiv,"/") \ TOK(Amod,"%") \ TOK(Agt,">") \ TOK(Alt,"<") \ TOK(Agteq,">=") \ TOK(Alteq,"<=") \ TOK(Alsft,"<<") \ TOK(Arsft,">>") \ TOK(Ainc,"++") \ TOK(Adec,"--") \ TOK(Aasn,"=") \ TOK(Aorasn,"|=") \ TOK(Axorasn,"^=") \ TOK(Aandasn,"&=") \ TOK(Aaddasn,"+=") \ TOK(Asubasn,"-=") \ TOK(Amulasn,"*=") \ TOK(Adivasn,"/=") \ TOK(Amodasn,"%=") \ TOK(Alsftasn,"<<=") \ TOK(Arsftasn,">>=") \ TOK(Acomma,",") \ TOK(Acolon,":") \ TOK(Asemi,";") \ TOK(Alparen,"(") \ TOK(Arparen,")") \ TOK(Albrace,"{") \ TOK(Arbrace,"}") \ TOK(Albrkt,"[") \ TOK(Arbrkt,"]") \ TOK(Adot,".") \ TOK(Aarrow,"->") \ TOK(Aqmark,"?") \ TOK(Aellip,"...") \ TOK(Alit,"") \ TOK(Aident,"") \ TOK(Akeywd,"") \ #define TOK(a, b) a, enum { TOKENS }; #undef TOK #define TOK(a, b) b, static byte *tokens[] = { TOKENS }; #undef TOK #undef TOKENS /* TODO: store literals in a big val */ struct Token { uint32 kind; struct Pos pos; union { string str; double f; vlong i; }; }; enum { Svar, Sfunc, Smacro, }; struct Sym { uint32 kind; string name; }; struct Lexer { Token tok; Io *io; SymTab *sym; byte buf[1024]; }; // ----------------------------------------------------------------------- // parsing & type resolution // tokens -> ast /* statements */ enum { Sbad, Slabel, Sblock, Sexpr, Sselect, Sloop, Sjump, }; struct Stmt { union { }; }; /* expressions */ enum { Xbad, Xparen, Xident, Xlit, Xassign, Xcomma, Xternary, Xbinary, Xprefix, Xunary, Xpostfix, Xcast, }; struct Expr { union { }; }; /* declarations */ // specifiers enum { Mauto = iota(0), // Corresponds to auto int Mtype = iota(1), Mstatic = iota(2), Mreg = iota(3), Qconst = iota(4), Qrestr = iota(5), Qvoltl = iota(6), Finlne = iota(7), Tlong = iota(8), Tvlong = iota(9), Tsign = iota(10), Tunsign = iota(11), Tvoid = iota(12), Tchar = iota(13), Tshort = iota(14), Tfloat = iota(15), Tdouble = iota(16), Tcmplx = iota(17), Timag = iota(18), Taggr = iota(19), Tenum = iota(20), Tname = iota(21), }; enum { Dnil, Dbad, Dfunc, Dvar, }; struct Decl { Pos pos; uint kind; }; // ----------------------------------------------------------------------- // compiler struct Io { io·Buffer b; string path; uint32 flag; struct Io *link; }; struct StrTab { int32 n_buckets, size, n_occupied, upper_bound; int32 *flags; string *keys; int32 *vals; }; static struct { mem·Arena *heap; StrTab strs; string *include; Io *io; Io iostk[100]; } C; void init(); int32 intern(byte **str); string internview(byte* beg, byte *end); #undef iota