compiler.c (174123B)
1 #include <assert.h> 2 #include <ctype.h> 3 #include <stdarg.h> 4 #include <stdio.h> 5 #include <stdint.h> 6 #include <stdlib.h> 7 #include <stdbool.h> 8 #include <string.h> 9 10 /* @note redeinition of assert() for ease of debugging. */ 11 12 #if 0 13 #ifdef assert 14 #undef assert 15 #endif 16 static void 17 myassert(const char *expr, const char *file, int line) 18 { 19 _assert(expr, file, line); 20 } 21 22 #define assert(_Expression) (void) ( \ 23 (!!(_Expression)) || (myassert(#_Expression,__FILE__,__LINE__),0) \ 24 ) 25 #endif 26 27 // @section forward declarations {{{ 28 29 typedef unsigned char uchar; 30 typedef unsigned int uint; 31 32 typedef 33 struct Node Node; 34 35 typedef 36 struct Type Type; 37 38 typedef 39 struct Decl Decl; 40 41 typedef 42 struct Env Env; 43 44 typedef 45 struct AnnotParam AnnotParam; 46 47 typedef 48 struct Annot Annot; 49 50 typedef 51 struct Docket Docket; 52 53 typedef 54 struct Gist Gist; 55 56 typedef 57 struct Conduct Conduct; 58 59 typedef 60 struct Block Block; 61 62 63 64 // }}} 65 66 // @section node kind table {{{ 67 68 #define SENDOFFILE "end-of-file" 69 #define SINVALID "invalide token" 70 #define SLINEDELIM "line-delimiter" 71 72 #define SCHAR "character-literal" 73 #define SIDENT "identifier" 74 #define SNUMBER "number-literal" 75 #define SSTRING "string-literal" 76 77 #define SASTMT "statement" 78 #define SALOOPUNTIL "loop-until-clause" 79 #define SADECL "declaration" 80 #define SADECLREF "symbol-reference" 81 #define SASWITCH "case-clause" 82 #define SACASE "of-clause" 83 #define SACONV "conversion" 84 85 #define NODETAB \ 86 /* tag , string , childs , flags , prec */ \ 87 /* Basic */ \ 88 entry(ENDOFFILE , SENDOFFILE , 0 , 0 , 0) \ 89 entry(INVALID , SINVALID , 0 , 0 , 0) \ 90 entry(LINEDELIM , SLINEDELIM , 0 , 0 , 0) \ 91 entry(SEMIDELIM , ";" , 0 , 0 , 0) \ 92 entry(COMMADELIM , "," , 0 , 0 , 0) \ 93 entry(COLONDELIM , ":" , 0 , 0 , 0) \ 94 entry(LCURLDELIM , "{" , 0 , 0 , 0) \ 95 entry(LSQRDELIM , "[" , 0 , 0 , 0) \ 96 entry(LPARDELIM , "(" , 0 , 0 , 0) \ 97 entry(RCURLDELIM , "}" , 0 , 0 , 0) \ 98 entry(RSQRDELIM , "]" , 0 , 0 , 0) \ 99 entry(RPARDELIM , ")" , 0 , 0 , 0) \ 100 entry(ANNOT , "@" , 0 , 0 , 0) \ 101 entry(CHAR , SCHAR , 0 , 0 , 0) \ 102 entry(IDENT , SIDENT , 0 , 0 , 0) \ 103 entry(NUMBER , SNUMBER , 0 , 0 , 0) \ 104 entry(STRING , SSTRING , 0 , 0 , 0) \ 105 entry(TYPE , "type" , 0 , 0 , 0) \ 106 /* Keywords */ \ 107 entry(KVOID , "void" , 0 , 0 , 0) \ 108 entry(KBOOL , "bool" , 0 , 0 , 0) \ 109 entry(KU8 , "u8" , 0 , 0 , 0) \ 110 entry(KS8 , "s8" , 0 , 0 , 0) \ 111 entry(KU16 , "u16" , 0 , 0 , 0) \ 112 entry(KS16 , "s16" , 0 , 0 , 0) \ 113 entry(KU32 , "u32" , 0 , 0 , 0) \ 114 entry(KS32 , "s32" , 0 , 0 , 0) \ 115 entry(KU64 , "u64" , 0 , 0 , 0) \ 116 entry(KS64 , "s64" , 0 , 0 , 0) \ 117 entry(KF32 , "f32" , 0 , 0 , 0) \ 118 entry(KF64 , "f64" , 0 , 0 , 0) \ 119 entry(KUCHAR , "uchar" , 0 , 0 , 0) \ 120 entry(KCHAR , "char" , 0 , 0 , 0) \ 121 entry(KUSHORT , "ushort" , 0 , 0 , 0) \ 122 entry(KSHORT , "short" , 0 , 0 , 0) \ 123 entry(KUINT , "uint" , 0 , 0 , 0) \ 124 entry(KINT , "int" , 0 , 0 , 0) \ 125 entry(KULONG , "ulong" , 0 , 0 , 0) \ 126 entry(KLONG , "long" , 0 , 0 , 0) \ 127 entry(KULLONG , "ullong" , 0 , 0 , 0) \ 128 entry(KLLONG , "llong" , 0 , 0 , 0) \ 129 entry(KFLOAT , "float" , 0 , 0 , 0) \ 130 entry(KDOUBLE , "double" , 0 , 0 , 0) \ 131 entry(KLDOUBLE , "ldouble" , 0 , 0 , 0) \ 132 entry(KUSIZE , "usize" , 0 , 0 , 0) \ 133 entry(KSSIZE , "ssize" , 0 , 0 , 0) \ 134 entry(KFALSE , "false" , 0 , 0 , 0) \ 135 entry(KTRUE , "true" , 0 , 0 , 0) \ 136 entry(KNULL , "null" , 0 , 0 , 0) \ 137 entry(KUSE , "use" , 0 , 0 , 0) \ 138 entry(KBUNDLE , "bundle" , 0 , 0 , 0) \ 139 entry(KNOT , "not" , 0 , 0 , 0) \ 140 entry(KAND , "and" , 0 , 0 , 0) \ 141 entry(KOR , "or" , 0 , 0 , 0) \ 142 entry(KIS , "is" , 0 , 0 , 0) \ 143 entry(KSIZEOF , "sizeof" , 0 , 0 , 0) \ 144 entry(KALIGNOF , "alignof" , 0 , 0 , 0) \ 145 entry(KLENGTHOF , "lengthof" , 0 , 0 , 0) \ 146 entry(KBITCAST , "bitcast" , 0 , 0 , 0) \ 147 entry(KEXTERN , "extern" , 0 , 0 , 0) \ 148 entry(KINTERN , "intern" , 0 , 0 , 0) \ 149 entry(KSTATIC , "static" , 0 , 0 , 0) \ 150 entry(KCONST , "const" , 0 , 0 , 0) \ 151 entry(KVAR , "var" , 0 , 0 , 0) \ 152 entry(KBREAK , "break" , 0 , 0 , 0) \ 153 entry(KCONTINUE , "continue" , 0 , 0 , 0) \ 154 entry(KGOTO , "goto" , 0 , 0 , 0) \ 155 entry(KRETURN , "return" , 0 , 0 , 0) \ 156 entry(KIF , "if" , 0 , 0 , 0) \ 157 entry(KELSE , "else" , 0 , 0 , 0) \ 158 entry(KCASE , "case" , 0 , 0 , 0) \ 159 entry(KOF , "of" , 0 , 0 , 0) \ 160 entry(KDO , "do" , 0 , 0 , 0) \ 161 entry(KFOR , "for" , 0 , 0 , 0) \ 162 entry(KLOOP , "loop" , 0 , 0 , 0) \ 163 entry(KWHILE , "while" , 0 , 0 , 0) \ 164 entry(KUNTIL , "until" , 0 , 0 , 0) \ 165 entry(KSTRUCT , "struct" , 0 , 0 , 0) \ 166 entry(KUNION , "union" , 0 , 0 , 0) \ 167 /* Operators */ \ 168 entry(OSUFINC , "++" , 1 , FRASSOC , PUNSUF ) \ 169 entry(OSUFDEC , "--" , 1 , FRASSOC , PUNSUF ) \ 170 entry(OARRAY , "[]" , 1 , FRASSOC , PUNSUF ) \ 171 entry(OCALL , "()" , 1 , FRASSOC , PUNSUF ) \ 172 entry(ODISP , "." , 1 , FRASSOC , PUNSUF ) \ 173 entry(ODEREF , "*" , 1 , 0 , PUNARY ) \ 174 entry(OINC , "++" , 1 , 0 , PUNARY ) \ 175 entry(ODEC , "--" , 1 , 0 , PUNARY ) \ 176 entry(OBNOT , "~" , 1 , 0 , PUNARY ) \ 177 entry(OLNOT , "!" , 1 , 0 , PUNARY ) \ 178 entry(OFLIP , "!>" , 1 , 0 , PUNARY ) \ 179 entry(OADDR , "&" , 1 , 0 , PUNARY ) \ 180 entry(OPLUS , "+" , 1 , 0 , PUNARY ) \ 181 entry(OMINUS , "-" , 1 , 0 , PUNARY ) \ 182 entry(OCAST , "(type)" , 1 , 0 , PUNARY ) \ 183 entry(OMUL , "*" , 2 , 0 , PMUL ) \ 184 entry(ODIV , "/" , 2 , 0 , PMUL ) \ 185 entry(OMOD , "%" , 2 , 0 , PMUL ) \ 186 entry(OLSH , "<<" , 2 , 0 , PMUL ) \ 187 entry(OARSH , ">>>" , 2 , 0 , PMUL ) \ 188 entry(ORSH , ">>" , 2 , 0 , PMUL ) \ 189 entry(OBAND , "&" , 2 , 0 , PMUL ) \ 190 entry(OADD , "+" , 2 , 0 , PADD ) \ 191 entry(OSUB , "-" , 2 , 0 , PADD ) \ 192 entry(OBOR , "|" , 2 , 0 , PADD ) \ 193 entry(OXOR , "^" , 2 , 0 , PADD ) \ 194 entry(ORANGE , ".." , 2 , 0 , PRANGE ) \ 195 entry(OLEQ , "<=" , 2 , 0 , PRELAT ) \ 196 entry(OLET , "<" , 2 , 0 , PRELAT ) \ 197 entry(OGEQ , ">=" , 2 , 0 , PRELAT ) \ 198 entry(OGRT , ">" , 2 , 0 , PRELAT ) \ 199 entry(ONEQ , "!=" , 2 , 0 , PRELAT ) \ 200 entry(OEQU , "==" , 2 , 0 , PRELAT ) \ 201 entry(OIDENT , "===" , 2 , 0 , PRELAT ) \ 202 entry(OLAND , "&&" , 2 , 0 , PAND ) \ 203 entry(OLOR , "||" , 2 , 0 , POR ) \ 204 entry(OASS , "=" , 2 , FRASSOC , PASSIGN ) \ 205 entry(OMULA , "*=" , 2 , FRASSOC , PASSIGN ) \ 206 entry(ODIVA , "/=" , 2 , FRASSOC , PASSIGN ) \ 207 entry(OMODA , "%=" , 2 , FRASSOC , PASSIGN ) \ 208 entry(OLSHA , "<<=" , 2 , FRASSOC , PASSIGN ) \ 209 entry(OARSHA , ">>>=" , 2 , FRASSOC , PASSIGN ) \ 210 entry(ORSHA , ">>=" , 2 , FRASSOC , PASSIGN ) \ 211 entry(OANDA , "&=" , 2 , FRASSOC , PASSIGN ) \ 212 entry(OADDA , "+=" , 2 , FRASSOC , PASSIGN ) \ 213 entry(OSUBA , "-=" , 2 , FRASSOC , PASSIGN ) \ 214 entry(OORA , "|=" , 2 , FRASSOC , PASSIGN ) \ 215 entry(OXORA , "^=" , 2 , FRASSOC , PASSIGN ) \ 216 /* Ast */ \ 217 entry(ACOMMA , "," , 0 , 0 , 0) \ 218 entry(ASTMT , SASTMT , 0 , 0 , 0) \ 219 entry(ADECL , SADECL , 0 , 0 , 0) \ 220 entry(ADECLREF , SADECLREF , 0 , 0 , 0) \ 221 entry(AENV , "env" , 0 , 0 , 0) \ 222 entry(ALOOPUNTIL , SALOOPUNTIL , 0 , 0 , 0) \ 223 entry(AFOREACH , "for-each" , 0 , 0 , 0) \ 224 entry(AFORSTEP , "for-step" , 0 , 0 , 0) \ 225 entry(ASCOPE , "scope" , 0 , 0 , 0) \ 226 entry(ALABEL , "label" , 0 , 0 , 0) \ 227 entry(ASWITCH , SASWITCH , 0 , 0 , 0) \ 228 entry(ACASE , SACASE , 0 , 0 , 0) \ 229 entry(ACONV , SACONV , 0 , 0 , 0) \ 230 entry(ADEREF , "*" , 0 , 0 , 0) \ 231 entry(AADDR , "&" , 0 , 0 , 0) \ 232 entry(ACOMPOUND , "{...}" , 0 , 0 , 0) \ 233 entry(AFIELDINIT , ":" , 0 , 0 , 0) \ 234 entry(ASELFDISP , ":" , 0 , 0 , 0) \ 235 /* endof NODETAB */ 236 237 #define isbinaryop(kind) ((kind) >= OMUL && (kind) < ACOMMA) 238 239 240 241 // }}} 242 243 // @section type kind table {{{ 244 245 #define TYPETAB \ 246 /* tag , size , align*/ \ 247 entry(TNONE , 0 , 0) \ 248 entry(TERRTYPE , 0 , 0) \ 249 entry(TUNDEFINED , 0 , 0) \ 250 entry(TVOID , 0 , 0) \ 251 entry(TBOOL , 1 , 1) \ 252 entry(TINFER , 4 , 4) \ 253 entry(TUINFER , 4 , 4) \ 254 entry(TS8 , 1 , 1) \ 255 entry(TU8 , 1 , 1) \ 256 entry(TS16 , 2 , 2) \ 257 entry(TU16 , 2 , 2) \ 258 entry(TS32 , 4 , 4) \ 259 entry(TU32 , 4 , 4) \ 260 entry(TS64 , 8 , 8) \ 261 entry(TU64 , 8 , 8) \ 262 entry(TF32 , 4 , 4) \ 263 entry(TF64 , 8 , 8) \ 264 entry(TPTR , 8 , 8) \ 265 entry(TARRAY , 0 , 0) \ 266 entry(TTUPLE , 0 , 0) \ 267 entry(TFUNCTION , 0 , 0) \ 268 entry(TSTRUCT , 0 , 0) \ 269 entry(TUNION , 0 , 0) \ 270 /* endof TYPETAB */ 271 272 #define TCHAR TS8 273 #define TUCHAR TU8 274 #define TSHORT TS16 275 #define TUSHORT TU16 276 #define TINT TS32 277 #define TUINT TU32 278 #define TLONG TS64 279 #define TULONG TU64 280 #define TLLONG TS64 281 #define TULLONG TU64 282 283 #define TFLOAT TF32 284 #define TDOUBLE TF64 285 #define TLDOUBLE TF64 286 287 #define TSSIZE TS64 288 #define TUSIZE TU64 289 /* @todo maybe add long double type ? */ 290 291 #define TYPEKEWORDYTAB \ 292 entry(VOID) entry(BOOL) \ 293 entry(S8) entry(U8) \ 294 entry(S16) entry(U16) \ 295 entry(S32) entry(U32) \ 296 entry(S64) entry(U64) \ 297 entry(F32) entry(F64) \ 298 entry(CHAR) entry(UCHAR) \ 299 entry(SHORT) entry(USHORT) \ 300 entry(INT) entry(UINT) \ 301 entry(LONG) entry(ULONG) \ 302 entry(LLONG) entry(ULLONG) \ 303 entry(FLOAT) entry(DOUBLE) entry(LDOUBLE) \ 304 entry(SSIZE) entry(USIZE) \ 305 /* endof TYPEKEYWORDTAB */ 306 307 308 309 // }}} 310 311 // @section enumerations & constants {{{ 312 313 typedef 314 enum Flags { 315 FRASSOC = 1 316 } Flads; 317 318 typedef 319 enum Precedence { 320 PUNSUF = 10, 321 PUNARY = 9, 322 PMUL = 8, 323 PADD = 7, 324 PRANGE = 6, 325 PRELAT = 5, 326 PAND = 4, 327 POR = 3, 328 PASSIGN = 2, 329 330 PSTART = 1 331 } Precedence; 332 333 typedef 334 enum Kind { 335 #define entry(tag, string, childs, flags, prec) \ 336 tag, 337 NODETAB 338 #undef entry 339 340 MAXKINDS 341 } Kind; 342 343 #define KSTART KVOID 344 #define OSTART OSUFINC 345 #define ASTART ASTMT 346 347 #define iskeyword(kind) ((kind) >= KSTART && (kind) < OSTART) 348 #define isoperator(kind) ((kind) >= OSTART && (kind) < ASTART) 349 #define isastnode(kind) ((kind) >= ASTART && (kind) < MAXKINDS) 350 351 static bool 352 isatomnode(Kind kind) 353 { 354 return kind == IDENT || kind == ADECLREF || kind == NUMBER || 355 kind == STRING || kind == CHAR; 356 } 357 358 359 typedef 360 enum TypeKind { 361 #define entry(tag, size, align) \ 362 tag, 363 TYPETAB 364 #undef entry 365 366 TMAX 367 } TypeKind; 368 369 370 typedef 371 enum DeclKind { 372 DMODULE = 0, 373 DTYPE, /* @note maybe be the same as void-module ? */ 374 DVAR, 375 DPARAM, 376 DFUNCTION, 377 DFIELDALIAS, 378 DBUNDLE, 379 /* 380 DMACRO, 381 DENFOLD 382 */ 383 } DeclKind; 384 385 typedef 386 enum DeclFlags { 387 MSPECIAL = 0x0001, 388 /* MINPORT = 0x0002, ... */ 389 } DeclFlags; 390 391 typedef 392 enum EnvKind { 393 STOPLEVEL = 0, 394 SPARAMLIST, 395 SFUNCTION, 396 SSCOPE, 397 SIFHEADER, 398 SLOOPHEADER, 399 SDO, 400 SLOOP, 401 SWHILE, 402 SIF, 403 SELSE, 404 SSTRUCT, 405 SUNION 406 /* 407 SUNION, 408 SSTRUCT, 409 SENUM, 410 */ 411 } EnvKind; 412 413 typedef 414 enum Qualifier { 415 QINTERN = 0x0001, 416 QEXTERN = 0x0002, 417 418 QSTATIC = 0x0010, 419 420 QCONST = 0x0200, 421 422 QVAR = 0x1000, 423 424 /* masks */ 425 QALL = QINTERN | QEXTERN | QSTATIC | QCONST | QVAR, 426 QVISIB = QEXTERN | QINTERN, 427 QSTORAGE = QSTATIC, 428 QTYPE = QCONST, 429 QINFER = QVAR 430 } Qualifier; 431 432 typedef 433 enum AnnotParamKind { 434 NSTATEEXPR, 435 NPARAM, 436 NEXPR 437 } AnnotParamKind; 438 439 typedef 440 enum BlockKind { 441 BTOPLEVEL = 0, 442 BFUNCTION = 1, 443 BSCOPE = 2, 444 BIF = 3, 445 BLOOP = 4, 446 BWHILELOOP = 5, 447 BLOOPUNTIL = 6, 448 BFORLOOP = 7, 449 BELSE = 8 450 } BlockKind; 451 452 typedef 453 enum ConductKind { 454 CUNREACH = 0, /* alway after a break, continue, goto or return */ 455 CSCOPE = 1, /* only the first conduct of a block and conducts after 456 * cunducts containing blocks are of this kind */ 457 CBLOCK = 2, /* always containing one or more blocks and nothing 458 else */ 459 CLABEL = 3 /* always after a label */ 460 } ConductKind; 461 462 463 464 // }}} 465 466 // @section type definitions {{{ 467 468 typedef 469 struct SrcLoc { 470 uint line, column; 471 const char *filename; 472 } SrcLoc; 473 474 /** 475 * @brief A node in the abstract syntax tree. 476 * @details The location is used to report errors. The type is used to store the 477 * type of the node. The union u is used to store the value of the node 478 * for its given kind. The lhs pointer points to the left hand side of 479 * its child node and the rhs pointer points to the right hand side of 480 * its child node (if any). Or the lhs and rhs pointer are used to 481 * point to the previous and next statement in a linked list (in case 482 * of ASTMT). Additionally, the payload pointer is used to store the 483 * condition of an if-statement and other statements. 484 */ 485 struct Node { 486 Kind kind; 487 SrcLoc loc; 488 489 Type *type; 490 491 union { 492 int key; 493 494 double d; 495 uintmax_t u; 496 intmax_t s; 497 498 Node *payload; 499 Decl *declref; 500 Env *env; 501 } u; 502 503 Node *lhs, *rhs; 504 /* ASTMT: rhs points to next stmt (linked list) */ 505 }; 506 507 struct Type { 508 TypeKind kind; 509 SrcLoc loc; 510 511 Type *target; /* pointer, array, tuple-lht, function param-list, ... */ 512 513 size_t size, align; 514 515 union { 516 struct { 517 int offset, size; /* in bits */ 518 } bit; 519 520 struct { 521 size_t length; 522 size_t elemsize; 523 } array; 524 525 Node *val; 526 Type *rtarget; /* for tuples (rht) and function return-type */ 527 } u; 528 529 Decl *module; /* module and record info */ 530 }; 531 532 typedef struct Field Field; 533 534 typedef struct Record { 535 Field *head, *tail; 536 537 bool isunion; 538 } Record; 539 540 struct Field { 541 Decl *decl; 542 543 size_t offset, size; /* in bytes */ 544 545 bool use; 546 547 Field *prev, *next; 548 }; 549 550 struct Decl { 551 DeclKind kind; 552 SrcLoc loc; 553 554 Type *type; 555 Decl *module; /* module or bundle */ 556 Record *record; 557 558 int key; 559 DeclFlags flags; 560 561 Env *parentenv, *contentenv; 562 union { 563 Node *content; /* init or function body */ 564 565 bool usefield; 566 } u; 567 568 Decl *prev, *next; 569 }; 570 571 struct Env { 572 EnvKind kind; 573 SrcLoc loc; 574 575 uint8_t keycache[64]; 576 577 Decl *head, *tail; 578 579 Node *stmts; 580 Decl *envdecl; /* for SFUNCTION, SSTRUCT, SUNION */ 581 582 /* for toplevel declarations. it will be assigned to decl->module 583 * if decl->module is null (in declaration()). */ 584 Decl *bundle; 585 586 Env *below; 587 588 bool pending; 589 Env *pendingnext, *pendingprev; 590 }; 591 592 typedef 593 struct Source { 594 SrcLoc currloc; 595 596 /* pre-lexer state */ 597 598 char line[4096]; 599 long linepos; 600 601 bool handlereplprompt; 602 603 /* error-reporting and lexer state */ 604 605 FILE *filein; 606 int tabwidth; 607 char stringbuf[1024]; 608 609 int lastindent, lastkind; 610 Node tok, savedtok; 611 612 /* environment */ 613 614 Env *headenv, *currenv; 615 Env *pendingenvhead, *pendingenvtail; 616 617 Env *implicitenv; 618 619 bool haspendingenv; 620 621 /* pending nodes */ 622 Node *pendingnodes[512]; 623 int pendingcount; 624 625 /* parser state */ 626 Node *lastis; 627 628 /* stack-alloc save state */ 629 } Source; 630 631 struct AnnotParam { 632 AnnotParamKind kind; 633 634 int key; 635 636 Node *node; 637 638 AnnotParam *prev, *next; 639 }; 640 641 struct Annot { 642 int key; 643 SrcLoc loc; 644 645 AnnotParam *head, *tail; 646 647 Annot *prev, *next; 648 }; 649 650 struct Docket { 651 Node *node; 652 Decl *decl; 653 654 Annot *head, *tail; 655 }; 656 657 struct Gist { 658 Decl *decl; 659 Conduct *parent; 660 661 bool init; 662 Node *where; 663 664 /* for other declarations */ 665 Gist *prev, *next; 666 }; 667 668 struct Block { 669 BlockKind kind; 670 671 Env *env; 672 673 /* Conduct-Sequence list*/ 674 Conduct *head, *tail, *parent; 675 676 /* Neighbooring Blocks */ 677 Block *prev, *next; 678 }; 679 680 struct Conduct { 681 ConductKind kind; 682 uint id; 683 684 Node *label, *branch; 685 Node *first, *last; 686 687 bool doesbreak; 688 bool doescontinue; 689 bool doesreturn; 690 bool doesjump; 691 692 struct ConductGists { 693 Gist *head, *tail; 694 } gists; 695 696 struct ConductBranches { 697 /* Branch-relation from child to parents */ 698 Conduct *head, *tail; 699 700 /* Branch-parent list */ 701 Conduct *next, *prev; 702 } branches; 703 704 /* Block-stack */ 705 Block *head, *tail, *parent; 706 707 /* Conduct-sequence list */ 708 Conduct *next, *prev; 709 }; 710 711 typedef struct Section Section; 712 typedef struct Edge Edge; 713 typedef struct EdgeEntry EdgeEntry; 714 typedef struct Analysis Analysis; 715 716 typedef enum EdgeKind { 717 JBRANCH = 0, /* unconditional branch */ 718 JIFBRANCH = 1, /* conditional branch */ 719 JNEXT = 2, /* unconditional next section (without branch) */ 720 JIFNEXT = 3 /* conditional next section (without branch) */ 721 } EdgeKind; 722 723 struct Edge { 724 EdgeKind kind; 725 Section *section; 726 727 Conduct *gistlist; /* @note maybe remove this, since the gistlist 728 * is always the last of a section */ 729 730 /* @todo add information about the branch/edge condition */ 731 732 /* for memory-management, since an edge is used in mult. edge-entries */ 733 int refcount; 734 }; 735 736 typedef enum EdgeEntryKind { 737 JINGOING = 0, /* added as reachedfrom to section */ 738 JOUTGOING = 1, /* added as branchto to section */ 739 JSTART = 2, /* added as reachedfrom edge entry to first section */ 740 JEND = 3 /* added as branchto edge entry to last section */ 741 } EdgeEntryKind; 742 743 /* @note since an edge is used in multiple lists, edge-entry is used 744 * as linked-list entry */ 745 struct EdgeEntry { 746 EdgeEntryKind kind; 747 Section *belongsto; 748 749 Edge *edge; /* is NULL on JSTART or JEND */ 750 EdgeEntry *prev, *next; 751 }; 752 753 /* a section is single level. there is no hierarchy, like in the case of 754 * scopes/environments. a function has simply a list of section from top to 755 * bottom. */ 756 struct Section { 757 uint id; /* incremental number */ 758 759 /* a section begins after baranch/label/start and ends 760 * containing a terminating branch/label/end. this way it contains at 761 * least one instructin/statement (terminating branch/label), if the 762 * (terminating branch/label/end) is not augment at the end of the 763 * function-scope/clause. */ 764 Node *first, *last; 765 766 struct { 767 Conduct *head, *tail; 768 } gistlists; 769 770 struct { 771 EdgeEntry *head, *tail; 772 } reachedfrom; 773 774 struct { 775 EdgeEntry *head, *tail; 776 } branchto; 777 778 /* prev/next section in code (no branch-info) from top to bottom 779 * in function */ 780 Section *prev, *next; 781 }; 782 783 struct Analysis { 784 Section *head, *tail; 785 }; 786 787 788 789 // }}} 790 791 // @section global-vars {{{ 792 793 Source testsource; 794 795 796 797 // }}} 798 799 // @section look-up tables {{{ 800 801 #define defaultloc {0, 1, "<builtin>"} 802 803 #define entry(tag, size, align) \ 804 {(tag), defaultloc, NULL, (size), (align), {{0}}, NULL}, 805 Type prim[] = { 806 TYPETAB 807 }; 808 #undef entry 809 810 #define primitive(typetag) (prim + typetag) 811 812 int keywordlengths[OSTART - KSTART]; 813 814 const int keywordtypeids[] = { 815 #define entry(tag) \ 816 [K##tag] = T##tag, 817 TYPEKEWORDYTAB 818 #undef entry 819 820 [OSTART] = 0 821 }; 822 823 const char *const nodestrings[MAXKINDS] = { 824 #define entry(tag, string, childs, flags, prec) \ 825 string, 826 NODETAB 827 #undef entry 828 }; 829 830 /* 831 Node kinds: 832 '@' - Annotation 833 ';' ',' ':' '{' '}' ']' ')' - Delimiters 834 'A' - Statement 835 'I' - Identifier 836 'K' - Keyword 837 'N' - Number-literal 838 'O' - Operator 839 'S' - String-literal 840 */ 841 842 #define opentry(numops, rassoc, prec) \ 843 ((uint8_t) ( ((numops) << 6) | ((rassoc) << 5) | (prec) )) 844 845 const uint8_t opinfo[] = { 846 #define entry(tag, string, childs, flags, prec) ((uint8_t) ( \ 847 ((childs) << 6) | \ 848 (!!(flags & FRASSOC) << 5) | \ 849 (prec) \ 850 )), 851 NODETAB 852 #undef entry 853 }; 854 855 #define getnumops(kind) (opinfo[kind] >> 6) 856 #define israssoc(kind) ((opinfo[kind] >> 5) & 0x01) 857 #define getprec(kind) ((opinfo[kind] & 0x1f)) 858 859 860 861 // }}} 862 863 // @section utility functions {{{ 864 865 #define listappendex(parent, child, head, tail, prev, next) do { \ 866 if ((parent)->head) { \ 867 assert((parent)->tail); \ 868 (child)->prev = (parent)->tail; \ 869 (child)->next = NULL; \ 870 (parent)->tail->next = (child); \ 871 } else { \ 872 assert(!(parent)->tail); \ 873 (child)->prev = NULL; \ 874 (child)->next = NULL; \ 875 (parent)->head = (child); \ 876 } \ 877 (parent)->tail = (child); \ 878 } while (0) 879 880 #define listappend(parent, child) \ 881 listappendex(parent, child, head, tail, prev, next) 882 883 #ifndef lengthof 884 #define lengthof(array) ((int) sizeof(array) / (int) sizeof(*(array))) 885 #endif 886 887 #define unpool(pool, top) \ 888 (assert((top) < lengthof(pool)), \ 889 memset((pool) + (top), 0, sizeof*(pool)), \ 890 (pool) + (top)++) 891 892 static int 893 mystrncasecmp(const char *str1, const char *str2, size_t max_len) 894 { 895 char tmp1[] = {'\0', '\0'}; 896 char tmp2[] = {'\0', '\0'}; 897 char c1, c2; 898 int result; 899 900 size_t i; 901 902 if (max_len == 0) { 903 size_t len1 = strlen(str1); 904 size_t len2 = strlen(str2); 905 max_len = len1 > len2 ? len1 : len2; 906 } 907 908 for (i = 0; i < max_len; ++i) { 909 c1 = tolower(str1[i]); 910 c2 = tolower(str2[i]); 911 if (c1 == '\0' && c2 == '\0') return 0; 912 tmp1[0] = c1; 913 tmp2[0] = c2; 914 result = strcmp(tmp1, tmp2); 915 if (result != 0) return result; 916 } 917 918 return 0; 919 } 920 921 static int 922 mystrcasecmp(const char *str1, const char *str2) 923 { 924 char tmp1[] = {'\0', '\0'}; 925 char tmp2[] = {'\0', '\0'}; 926 char c1, c2; 927 int result; 928 929 size_t i; 930 931 for (i = 0;; ++i) { 932 c1 = tolower(str1[i]); 933 c2 = tolower(str2[i]); 934 if (c1 == '\0' && c2 == '\0') return 0; 935 tmp1[0] = c1; 936 tmp2[0] = c2; 937 result = strcmp(tmp1, tmp2); 938 if (result != 0) return result; 939 } 940 941 return 0; 942 } 943 944 945 946 // }}} 947 948 // @section pre-lexer {{{ 949 950 static void 951 tryprompt(Source *source, const char ch); 952 953 static bool 954 processcommand(Source *source); 955 956 static bool 957 mygetline(Source *source) 958 { 959 int i, l, c; 960 FILE *in = source->filein; 961 962 tryprompt(source, '.'); 963 c = getc(in); 964 965 source->linepos = ftell(in); 966 967 advance: 968 ++source->currloc.line; 969 970 i = 0, l = 0; 971 while (c == '\r' || c == '\n') { 972 tryprompt(source, '.'); 973 l = c, c = getc(in); 974 975 if (l == '\r' && c == '\n') 976 c = getc(in); 977 978 ++source->currloc.line; 979 } 980 981 source->tok.loc.line = source->currloc.line; 982 983 while (c != EOF && c != '\n' && c != '\r') { 984 source->line[i++] = c; 985 c = getc(in); 986 987 if (c == '\\') { 988 int x = getc(in); 989 if (x == '\n') { 990 tryprompt(source, '\\'); 991 c = getc(in); 992 993 ++source->currloc.line; 994 } else if (x == '\r') { 995 int y; 996 997 tryprompt(source, '\\'); 998 y = getc(in); 999 1000 c = (y == '\n') ? getc(in) : y; 1001 ++source->currloc.line; 1002 } else if (x == EOF) { 1003 c = x; 1004 } else { 1005 ungetc(x, in); 1006 } 1007 } 1008 } 1009 1010 if (c == '\r') { 1011 int x; 1012 1013 tryprompt(source, '.'); 1014 x = getc(in); 1015 if (x != '\n') 1016 ungetc(x, in); 1017 } 1018 1019 if (c != EOF && i == 0) 1020 goto advance; 1021 1022 source->line[i] = 0; 1023 1024 if (in == stdin && source->line[0] == ':') 1025 return processcommand(source); 1026 1027 return c != EOF || i; 1028 } 1029 1030 1031 1032 // }}} 1033 1034 // @section keyword map {{{ 1035 1036 #define KEYWORD_MAP_SIZE 128 1037 const char *keywordkeys[KEYWORD_MAP_SIZE]; 1038 int keywordvals[KEYWORD_MAP_SIZE]; 1039 1040 static int 1041 strnhash(const char *str, int n) 1042 { 1043 int hash = 5381, i; 1044 for (i = 0; i < n && str[i]; ++i) 1045 hash = (hash << 5) + hash + str[i]; 1046 return hash; 1047 } 1048 1049 static void 1050 initkeywords(void) 1051 { 1052 int i, j, h; 1053 for (i = 0; i < lengthof(keywordlengths); ++i) { 1054 int n = keywordlengths[i] = strlen(nodestrings[i + KSTART]); 1055 h = strnhash(nodestrings[i + KSTART], n) & 1056 (lengthof(keywordkeys) - 8); 1057 for (j = 0; j < 8; ++j, ++h) { 1058 if (!keywordkeys[h]) { 1059 keywordkeys[h] = nodestrings[i + KSTART]; 1060 keywordvals[h] = i; 1061 goto nextkeyword; 1062 } 1063 } 1064 1065 fprintf(stderr, "bug: keyword hash-map is too small\n"); 1066 abort(); 1067 nextkeyword: 1068 (void) 0; 1069 } 1070 1071 /* 1072 for (i = 0; i < lengthof(keywordkeys); ++i) { 1073 printf("%-12s%c", keywordkeys[i] ? keywordkeys[i] : ".", (i+1) % 8 ? ' ' : '\n'); 1074 } 1075 */ 1076 } 1077 1078 static int 1079 getkeyword(const char *str, int n) 1080 { 1081 int i, h = strnhash(str, n) & (lengthof(keywordkeys) - 8); 1082 for (i = 0; i < 8; ++i, ++h) { 1083 int len; 1084 if (!keywordkeys[h]) 1085 return -1; 1086 len = keywordlengths[keywordvals[h]]; 1087 if (n == len && memcmp(keywordkeys[h], str, n) == 0) 1088 return keywordvals[h]; 1089 } 1090 return -1; 1091 } 1092 1093 1094 1095 // }}} 1096 1097 // @section string map {{{ 1098 1099 typedef 1100 struct StringEntry { 1101 int len; 1102 const char *str; 1103 } StringEntry; 1104 1105 typedef 1106 struct StringMap { 1107 int *keys; 1108 int keyscap; 1109 1110 StringEntry *vals; 1111 int valscap, valslen; 1112 } StringMap; 1113 1114 StringMap idents; 1115 StringMap strings; 1116 1117 static void 1118 initstrmap(StringMap *map) 1119 { 1120 map->keys = calloc(32, sizeof(int)); 1121 map->keyscap = 32; 1122 assert(map->keys); 1123 1124 map->vals = calloc(32, sizeof(StringEntry)); 1125 map->valslen = 0; 1126 map->valscap = 32; 1127 assert(map->vals); 1128 } 1129 1130 #if 0 1131 static void 1132 disposestrmap(StringMap *map) 1133 { 1134 int i; 1135 for (i = map->valslen - 1; i >= 0; --i) { 1136 free((char *) map->vals[i].str); 1137 } 1138 1139 free(map->vals); 1140 free(map->keys); 1141 } 1142 #endif 1143 1144 static void 1145 putstringkey(StringMap *map, int key, int hash) 1146 { 1147 int *keys = map->keys; 1148 StringEntry *vals = map->vals; 1149 1150 int i, j; 1151 1152 redo: 1153 j = (hash << 3) & (map->keyscap - 1); 1154 for (i = 0; i < 8; ++i, ++j) { 1155 if (!keys[j]) { 1156 keys[j] = key; 1157 return; 1158 } 1159 } 1160 1161 free(keys); 1162 map->keyscap *= 2; 1163 keys = map->keys = calloc(map->keyscap, sizeof(int)); 1164 for (i = 0; i < map->valslen; ++i) { 1165 j = strnhash(vals[i].str, vals[i].len); 1166 putstringkey(map, i + 1, j); 1167 } 1168 1169 goto redo; 1170 } 1171 1172 int auxthen, auxin, auxto, auxstep; 1173 int auxself; 1174 1175 static int 1176 getstringkey(StringMap *map, const char *str, int n) 1177 { 1178 int *keys = map->keys; 1179 StringEntry *vals = map->vals; 1180 1181 int key, hash = strnhash(str, n); 1182 int i, j = (hash << 3) & (map->keyscap - 1); 1183 1184 char *newstr; 1185 1186 for (i = 0; i < 8; ++i, ++j) { 1187 key = keys[j]; 1188 if (!key) 1189 break; 1190 1191 assert(key > 0); 1192 if (n == vals[key - 1].len && 1193 memcmp(str, vals[key - 1].str, n) == 0) 1194 { 1195 return key; 1196 } 1197 } 1198 1199 key = map->valslen + 1; 1200 putstringkey(map, key, hash); 1201 1202 if (key > map->valscap) { 1203 int cap = map->valscap * 3 / 2 + 1; 1204 vals = map->vals = realloc(vals, cap * sizeof(StringEntry)); 1205 assert(vals); 1206 map->valscap = cap; 1207 } 1208 1209 newstr = calloc(n + 1, sizeof(char*)); /* @todo sizeof(char*) --> sizeof(char) ? */ 1210 assert(newstr); 1211 memcpy(newstr, str, n); 1212 1213 vals[key - 1].len = n; 1214 vals[key - 1].str = newstr; 1215 ++map->valslen; 1216 1217 return key; 1218 } 1219 1220 #define getstring(map, key) ((map).vals[(key) - 1].str) 1221 #define getlength(map, key) ((map).vals[(key) - 1].len) 1222 1223 1224 1225 // }}} 1226 1227 // @section error reporting {{{ 1228 1229 int warningcount = 0; 1230 int errorcount = 0; 1231 1232 static int 1233 warn(SrcLoc *loc, const char *fmt, ...) 1234 { 1235 va_list ap; 1236 int n; 1237 1238 const char *filename = loc ? loc->filename : "<unknown-source>"; 1239 uint line = loc ? loc->line : 1; 1240 uint column = loc ? loc->column : 0; 1241 1242 va_start(ap, fmt); 1243 n = fprintf(stderr, "%s:%u:%u: warning: ", 1244 filename, line, column + 1); 1245 n += vfprintf(stderr, fmt, ap); 1246 n += fprintf(stderr, "\n"); 1247 va_end(ap); 1248 1249 ++warningcount; 1250 return n; 1251 } 1252 1253 #define error(loc, ...) error_(loc, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__) 1254 1255 static int 1256 error_(SrcLoc *loc, const char *func, const char *file, int line_, 1257 const char *fmt, ...) 1258 { 1259 va_list ap; 1260 int n; 1261 1262 const char *filename = loc ? loc->filename : "<unknown-source>"; 1263 uint line = loc ? loc->line : 1; 1264 uint column = loc ? loc->column : 0; 1265 1266 va_start(ap, fmt); 1267 n = fprintf(stderr, "%s:%u:%u: error: ", 1268 filename, line, column + 1); 1269 n += vfprintf(stderr, fmt, ap); 1270 n += fprintf(stderr, " \x1b[30m[in %s() at %s:%u]\x1b[0m\n", func, file, line_); 1271 va_end(ap); 1272 1273 ++errorcount; 1274 return n; 1275 } 1276 1277 1278 1279 // }}} 1280 1281 // @section lexer {{{ 1282 1283 #define nextindent(source, indent) \ 1284 ((indent) + (source)->tabwidth - ((indent) % (source)->tabwidth)) 1285 1286 #define peekchar(source) \ 1287 ((source)->line[(source)->currloc.column]) 1288 1289 #define peeknextchar(source) \ 1290 ((source)->line[(source)->currloc.column + 1]) 1291 1292 #define nextchar(source) \ 1293 ((source)->line[++(source)->currloc.column]) 1294 1295 // @sub-section tokenize keyword / identifier {{{ 1296 1297 static int 1298 tokenizealphanumeric(Source *source, register int ch) 1299 { 1300 int keyword; 1301 1302 while (isalnum(ch) || ch == '_') 1303 ch = nextchar(source); 1304 1305 keyword = getkeyword( 1306 source->line + source->tok.loc.column, 1307 source->currloc.column - source->tok.loc.column 1308 ); 1309 1310 if (source->tok.kind != ANNOT && keyword >= 0 && 1311 source->tok.kind != ODISP) 1312 { 1313 if (keyword == KOR - KSTART || keyword == KAND - KSTART) { 1314 return source->tok.kind = 1315 keyword == KOR - KSTART ? OLOR : OLAND; 1316 } else if (keywordtypeids[keyword + KSTART]) { 1317 1318 source->tok.u.key = 1319 keywordtypeids[keyword + KSTART]; 1320 1321 source->tok.type = prim + source->tok.u.key; 1322 1323 return source->tok.kind = TYPE; 1324 } 1325 1326 return source->tok.kind = keyword + KSTART; 1327 } 1328 1329 source->tok.u.key = getstringkey( 1330 &idents, 1331 source->line + source->tok.loc.column, 1332 source->currloc.column - source->tok.loc.column 1333 ); 1334 1335 return source->tok.kind = IDENT; 1336 } 1337 1338 // }}} 1339 1340 // @sub-section tokenize number {{{ 1341 1342 static Type * 1343 suffixfloattype(Source *source, const char *end) 1344 { 1345 Type *ty = primitive(TDOUBLE); 1346 1347 if (*end == 0) 1348 return ty; 1349 1350 /* FIXME(m21c): r-suffix might conflict with radix */ 1351 if ((*end == 'f' || *end == 'F') && !end[1]) { 1352 ty = primitive(TFLOAT); 1353 1354 } else if (*end == 'l' || *end == 'L') { 1355 ty = primitive(TDOUBLE); 1356 1357 if (end[1]) 1358 goto errorfloat; 1359 1360 } else if (!mystrcasecmp(end, "f32") || !mystrcasecmp(end, "r32")) { 1361 ty = primitive(TF32); 1362 1363 } else if (!mystrcasecmp(end, "f64") || !mystrcasecmp(end, "r64")) { 1364 ty = primitive(TF64); 1365 1366 } else { 1367 errorfloat: 1368 error(&source->currloc, "invalid floating-point format"); 1369 } 1370 1371 return ty; 1372 } 1373 1374 static Type * 1375 suffixinttype(Source *source, const char *end) 1376 { 1377 int typeid = TUINT - TINT; 1378 1379 switch (*end) { 1380 case 0: 1381 return primitive(TINFER); 1382 1383 case 's': case 'S': case 'i': case 'I': 1384 typeid = 0; 1385 1386 /* fallthrough */ 1387 case 'u': case 'U': 1388 ++end; 1389 if (*end == 0) { 1390 return prim + (typeid + TINFER); 1391 1392 } else if (*end == '8') { 1393 typeid += TS8; 1394 1395 if (end[1]) 1396 goto errorint; 1397 1398 return prim + typeid; 1399 1400 } else if (!strcmp(end, "16")) { 1401 return prim + (typeid + TS16); 1402 1403 } else if (!strcmp(end, "32")) { 1404 return prim + (typeid + TS32); 1405 1406 } else if (!strcmp(end, "64")) { 1407 return prim + (typeid + TS64); 1408 1409 } else if (!mystrcasecmp(end, "sz")) { 1410 return prim + (typeid + TSSIZE); 1411 } 1412 1413 /* fallthrough */ 1414 default: 1415 if (!mystrcasecmp(end, "ll")) { 1416 return prim + (typeid + TLLONG); 1417 1418 } else if (*end == 'l' || *end == 'L') { 1419 typeid += TLONG; 1420 1421 if (end[1]) 1422 goto errorint; 1423 1424 return prim + typeid; 1425 } 1426 } 1427 1428 errorint: 1429 error(&source->currloc, "invalid integer format"); 1430 return primitive(TINT); 1431 } 1432 1433 static int 1434 tokenizenumber(Source *source, register int ch) 1435 { 1436 int l = ch, t = peeknextchar(source), i, j; 1437 bool hasdec = false, hasexp = false; 1438 char *end; 1439 1440 advancenum: 1441 while (isalnum(ch) || ch == '_' || 1442 (ch == '.' && peeknextchar(source) != '.' && !hasdec)) 1443 { 1444 if (ch != '_') 1445 l = ch; 1446 if (ch == '.') 1447 hasdec = true; 1448 1449 ch = nextchar(source); 1450 } 1451 1452 if (hasdec && !hasexp && (ch == '+' || ch == '-')) { 1453 t = tolower(t); 1454 l = tolower(l); 1455 1456 if ((l == 'e' && t != 'x') || (l == 'p' && t == 'x')) { 1457 ch = nextchar(source); 1458 hasexp = true; 1459 1460 goto advancenum; 1461 } 1462 } 1463 1464 /* remove underscores */ 1465 for (j = 0, i = source->tok.loc.column; 1466 i < (int) source->currloc.column; 1467 ++i) 1468 { 1469 if (source->line[i] != '_') { 1470 if (j >= lengthof(source->stringbuf) - 1) { 1471 error( 1472 &source->currloc, 1473 "number-literal is too long" 1474 ); 1475 1476 source->tok.u.u = 0; 1477 source->tok.type = primitive(TINT); 1478 1479 return source->tok.kind = NUMBER; 1480 } 1481 1482 source->stringbuf[j++] = source->line[i]; 1483 } 1484 } 1485 source->stringbuf[j] = 0; 1486 1487 if (strpbrk(source->stringbuf, ".pPrR") || 1488 (!strpbrk(source->stringbuf, "xX") && 1489 strpbrk(source->stringbuf, "eEfF"))) 1490 { 1491 source->tok.u.d = strtod(source->stringbuf, &end); 1492 source->tok.type = suffixfloattype(source, end); 1493 1494 } else { 1495 if (mystrncasecmp(source->stringbuf, "0b", 2) == 0) { 1496 source->tok.u.u = strtoull( 1497 source->stringbuf + 2, 1498 &end, 2 1499 ); 1500 1501 } else { 1502 source->tok.u.u = strtoull( 1503 source->stringbuf, 1504 &end, 0 1505 ); 1506 1507 } 1508 1509 source->tok.type = suffixinttype(source, end); 1510 } 1511 1512 return source->tok.kind = NUMBER; 1513 } 1514 1515 // }}} 1516 1517 // @sub-section tokenize string {{{ 1518 1519 static int 1520 tokenizestring(Source *source, register int ch) 1521 { 1522 int delim = ch, j; 1523 1524 ch = nextchar(source); 1525 source->tok.loc.column = source->currloc.column; 1526 1527 j = source->currloc.column; 1528 while (ch != delim && ch != 0) { 1529 if (ch == '\\') { 1530 ch = nextchar(source); 1531 1532 switch (ch) { 1533 case '\\': 1534 ch = '\\'; 1535 break; 1536 1537 case 'n': 1538 ch = '\n'; 1539 break; 1540 1541 case 'r': 1542 ch = '\r'; 1543 break; 1544 1545 case 't': 1546 ch = '\t'; 1547 break; 1548 1549 case '\'': 1550 ch = '\''; 1551 break; 1552 1553 case '"': 1554 ch = '"'; 1555 break; 1556 1557 /* @todo read more escape sequences */ 1558 case 0: 1559 goto stringeol; 1560 1561 default: 1562 error(&source->currloc, 1563 "invalid escape sequence '\\%c'", ch); 1564 } 1565 } 1566 1567 source->line[j++] = ch; 1568 ch = nextchar(source); 1569 } 1570 1571 ++source->currloc.column; 1572 source->line[j++] = 0; 1573 1574 if (ch == 0) { 1575 stringeol: 1576 error(&source->currloc, "unexpected end-of-line"); 1577 1578 return source->tok.kind = LINEDELIM; 1579 } 1580 1581 if (ch == '"') { 1582 source->tok.u.key = getstringkey( 1583 &strings, 1584 source->line + source->tok.loc.column, 1585 j - source->tok.loc.column 1586 ); 1587 1588 return source->tok.kind = STRING; 1589 } 1590 1591 /* @todo read numerical value of character properly 1592 * (escape sequences, etc.) */ 1593 source->tok.type = prim + TUCHAR; 1594 source->tok.u.u = source->line[source->tok.loc.column]; 1595 return source->tok.kind = CHAR; 1596 } 1597 1598 // }}} 1599 1600 // @sub-section tokenizer {{{ 1601 1602 static int 1603 gettok(Source *source) 1604 { 1605 register int ch = (uchar) peekchar(source); 1606 static bool hasnewline = false; 1607 1608 source->lastkind = source->tok.kind; 1609 1610 if (source->savedtok.kind) { 1611 source->tok = source->savedtok; 1612 source->savedtok.kind = 0; 1613 return source->tok.kind; 1614 } 1615 1616 skipwhite: 1617 if (hasnewline) { 1618 if (!mygetline(source)) { 1619 source->lastindent = 0; 1620 return source->tok.kind = 0; 1621 } 1622 1623 source->currloc.column = 0; 1624 ch = peekchar(source); 1625 } 1626 1627 if (source->currloc.column) { 1628 /* just skip whitespace */ 1629 while (isspace(ch)) 1630 ch = nextchar(source); 1631 1632 } else { 1633 /* skip whitespace and calculate indentation */ 1634 source->lastindent = 0; 1635 while (isspace(ch)) { 1636 if (ch == '\t') { 1637 source->lastindent = nextindent( 1638 source, 1639 source->lastindent 1640 ); 1641 } else { 1642 ++source->lastindent; 1643 } 1644 1645 ch = nextchar(source); 1646 } 1647 } 1648 1649 source->tok.type = primitive(TUNDEFINED); 1650 source->tok.u.u = 0; 1651 source->tok.lhs = NULL; 1652 source->tok.rhs = NULL; 1653 source->tok.loc.column = source->currloc.column; 1654 1655 /* get line */ 1656 if (!ch || ch == '#') { 1657 if (hasnewline) { 1658 goto skipwhite; 1659 } else { 1660 /* defer reading new line to next call of gettok() 1661 * and return LINEDELIM */ 1662 hasnewline = true; 1663 return source->tok.kind = LINEDELIM; 1664 } 1665 } 1666 1667 /* c-syle block comment with nesting allowed */ 1668 if (ch == '/' && peeknextchar(source) == '*') { 1669 int nest = 1; 1670 1671 nextchar(source); 1672 ch = nextchar(source); 1673 1674 for (;nest; ch = nextchar(source)) { 1675 if (!ch) { 1676 if (!mygetline(source)) 1677 return source->tok.kind = 0; 1678 1679 source->currloc.column = 0; /* is this needed? */ 1680 ch = peekchar(source); 1681 } 1682 1683 if (ch == '*' && peeknextchar(source) == '/') { 1684 nextchar(source); 1685 --nest; 1686 } else if (ch == '/' && peeknextchar(source) == '*') { 1687 nextchar(source); 1688 ++nest; 1689 } 1690 } 1691 1692 goto skipwhite; 1693 } 1694 1695 hasnewline = false; 1696 1697 /* identifier or keyword */ 1698 if (isalpha(ch) || ch == '_') 1699 return tokenizealphanumeric(source, ch); 1700 1701 /* number literal */ 1702 if (isdigit(ch) || (ch == '.' && isdigit(peeknextchar(source)))) 1703 return tokenizenumber(source, ch); 1704 1705 /* string & character-literal */ 1706 if (ch == '"' || ch == '\'') 1707 return tokenizestring(source, ch); 1708 1709 /* operators */ 1710 #define select(ch, then, otherwise) ( \ 1711 peekchar(source) == (ch) ? \ 1712 ++source->currloc.column, (then) : \ 1713 (otherwise) \ 1714 ) 1715 1716 ++source->currloc.column; 1717 switch (ch) { 1718 case '.': 1719 /* tok.kind = select('.', ORANGE, ODISP); */ 1720 ch = ODISP; 1721 break; 1722 1723 case '*': 1724 ch = select('=', OMULA, OMUL); 1725 break; 1726 1727 case '/': 1728 ch = select('=', ODIVA, ODIV); 1729 break; 1730 1731 case '%': 1732 ch = select('=', OMODA, OMOD); 1733 break; 1734 1735 case '<': 1736 ch = select('=', OLEQ, 1737 select('<', 1738 select('=', OLSHA, OLSH), 1739 OLET)); 1740 break; 1741 1742 case '>': 1743 ch = select('=', OGEQ, 1744 select('>', 1745 select('>', 1746 select('=', OARSHA, OARSH), 1747 select('=', ORSHA, ORSH)), 1748 OGRT)); 1749 break; 1750 1751 case '&': 1752 ch = select('=', OANDA, select('&', OLAND, OBAND)); 1753 break; 1754 1755 case '+': 1756 ch = select('=', OADDA, select('+', OSUFINC, OADD)); 1757 break; 1758 1759 case '-': 1760 ch = select('=', OSUBA, select('-', OSUFDEC, OSUB)); 1761 break; 1762 1763 case '|': 1764 ch = select('=', OORA, select('|', OLOR, OBOR)); 1765 break; 1766 1767 case '^': 1768 ch = select('=', OXORA, OXOR); 1769 break; 1770 1771 case '!': 1772 ch = select('=', ONEQ, OLNOT); 1773 break; 1774 1775 case '~': 1776 ch = select('=', OFLIP, OBNOT); 1777 break; 1778 1779 case '=': 1780 ch = select('=', select('=', OIDENT, OEQU), OASS); 1781 break; 1782 1783 /* delimiters */ 1784 case ',': ch = COMMADELIM; break; 1785 case ';': ch = SEMIDELIM; break; 1786 case '@': ch = ANNOT; break; 1787 case ':': ch = COLONDELIM; break; 1788 case '{': ch = LCURLDELIM; break; 1789 case '}': ch = RCURLDELIM; break; 1790 case '[': ch = LSQRDELIM; break; 1791 case ']': ch = RSQRDELIM; break; 1792 case '(': ch = LPARDELIM; break; 1793 case ')': ch = RPARDELIM; break; 1794 1795 default: 1796 error(&source->currloc, "invalid input character '%c'", ch); 1797 return INVALID; 1798 } 1799 1800 return source->tok.kind = ch; 1801 #undef select 1802 } 1803 1804 // }}} 1805 1806 // @sub-section tokenizer utilities {{{ 1807 1808 static void 1809 pushbacktok(Source *source, Node *tok) 1810 { 1811 assert(source->savedtok.kind == 0); 1812 1813 source->savedtok = source->tok; 1814 source->tok = *tok; 1815 } 1816 1817 #define skipnewline(source) \ 1818 ((source)->tok.kind == LINEDELIM ? (void) gettok(source) : (void) 0) 1819 1820 static bool 1821 isbasicdelimiter(Kind kind) 1822 { 1823 switch ((int) kind) { 1824 case 0: 1825 case LINEDELIM: case COMMADELIM: case SEMIDELIM: 1826 case COLONDELIM: 1827 case RPARDELIM: case RSQRDELIM: case RCURLDELIM: 1828 case KELSE: 1829 case KUNTIL: 1830 return true; 1831 } 1832 1833 return false; 1834 } 1835 1836 static Kind 1837 getunary(Kind kind) 1838 { 1839 if (getprec(kind) == PUNARY) 1840 return kind; 1841 1842 switch (kind) { 1843 case OMUL: return ODEREF; 1844 case OBAND: return OADDR; 1845 case OADD: return OPLUS; 1846 case OSUB: return OMINUS; 1847 case OSUFINC: return OINC; 1848 case OSUFDEC: return ODEC; 1849 default: 1850 return 0; 1851 } 1852 } 1853 1854 static bool 1855 isdelimiter(Kind kind) 1856 { 1857 if (isbasicdelimiter(kind)) 1858 return true; 1859 1860 if (getunary(kind)) 1861 return false; 1862 1863 if (getnumops(kind)) 1864 return true; 1865 1866 return false; 1867 } 1868 1869 static Kind 1870 getunarysuffix(Source *source) 1871 { 1872 Kind kind = source->tok.kind; 1873 1874 if (getprec(kind) == PUNSUF) 1875 return kind; 1876 1877 /* @note fixes parsing unary suffix across multiple lines. 1878 * (which shouldn't happen) */ 1879 if (isbasicdelimiter(source->lastkind)) 1880 return 0; 1881 1882 switch (kind) { 1883 case COLONDELIM: return ASELFDISP; 1884 case LPARDELIM: return OCALL; 1885 case LSQRDELIM: return OARRAY; 1886 default: 1887 return 0; 1888 } 1889 } 1890 1891 // }}} 1892 1893 1894 1895 // }}} 1896 1897 // @section ast-node {{{ 1898 1899 Node *poolednodes; 1900 Node nodebuf[4096]; 1901 int nodetop, poolednodecount, totalnodecount; 1902 1903 #define tokennode(source, lhs) makenode(&(source)->tok, (lhs)) 1904 1905 static Node * 1906 makenode(Node *orig, Node *lhs) 1907 { 1908 Node *node; 1909 1910 if (poolednodes) { 1911 node = poolednodes; 1912 poolednodes = poolednodes->rhs; 1913 node->rhs = NULL; 1914 node->lhs = NULL; 1915 --poolednodecount; 1916 } else { 1917 node = nodebuf + nodetop++; 1918 } 1919 1920 ++totalnodecount; 1921 *node = *orig; 1922 node->lhs = lhs; 1923 node->rhs = NULL; 1924 1925 return node; 1926 } 1927 1928 static void 1929 deleteenv(Env *env); 1930 1931 static void 1932 deletenode(Node *node) 1933 { 1934 if (node->kind == 0) 1935 return; 1936 1937 if (node->kind == ASCOPE) { 1938 Node *curr, *next; 1939 1940 if (node->u.env) { 1941 assert(node->u.env->stmts == node); 1942 node->u.env->stmts = NULL; 1943 deleteenv(node->u.env); 1944 } 1945 1946 for (curr = node->lhs; curr; curr = next) { 1947 assert(curr->kind == ASTMT); 1948 next = curr->rhs; 1949 deletenode(curr); 1950 } 1951 1952 } else if (node->kind == ASTMT) { 1953 if (node->lhs) 1954 deletenode(node->lhs); 1955 1956 } else { 1957 if (node->rhs) 1958 deletenode(node->rhs); 1959 1960 if (node->lhs) 1961 deletenode(node->lhs); 1962 1963 if (node->u.payload && (node->kind == KIF || 1964 node->kind == KWHILE || node->kind == ALOOPUNTIL)) 1965 { 1966 deletenode(node->u.payload); 1967 } 1968 } 1969 1970 ++poolednodecount; 1971 node->kind = 0; 1972 node->rhs = poolednodes; 1973 poolednodes = node; 1974 } 1975 1976 1977 1978 // }}} 1979 1980 // @section type-struct {{{ 1981 1982 Type typebuf[4096]; 1983 int typetop; 1984 1985 static Type * 1986 maketype(SrcLoc *loc, Type *orig, Type *target) 1987 { 1988 Type *ty = typebuf + typetop++; 1989 1990 *ty = *orig; 1991 ty->loc = *loc; 1992 ty->target = target; 1993 1994 return ty; 1995 } 1996 1997 1998 1999 // }}} 2000 2001 // @section annotation {{{ 2002 2003 Annot annotbuf[4096]; 2004 int annottop; 2005 2006 Docket docketbuf[4096]; 2007 int dockettop; 2008 2009 static Annot * 2010 makeannot(SrcLoc *loc, int key) 2011 { 2012 Annot *annot; 2013 2014 assert(annottop < lengthof(annotbuf)); 2015 2016 annot = annotbuf + annottop; 2017 2018 annot->key = key; 2019 annot->loc = *loc; 2020 2021 /* @todo implement initialization. */ 2022 2023 return annot; 2024 } 2025 2026 static Docket * 2027 makedocket(Node *node) 2028 { 2029 Docket *docket; 2030 2031 (void) node; /* @todo implement. */ 2032 2033 assert(dockettop < lengthof(docketbuf)); 2034 2035 docket = docketbuf + dockettop; 2036 2037 /* @todo implement initialization. */ 2038 2039 return docket; 2040 } 2041 2042 2043 2044 // }}} 2045 2046 // @section environment {{{ 2047 2048 Env envbuf[4096]; 2049 int envtop; 2050 2051 static Decl * 2052 finddeclinenv(int key, Env *env) 2053 { 2054 const int cacheindex = (key >> 3) & 0x3f; 2055 const int cachebit = 1 << (key & 0x03); 2056 2057 Decl *decl; 2058 2059 if ((env->keycache[cacheindex] & cachebit) == 0) 2060 return NULL; 2061 2062 for (decl = env->head; decl; decl = decl->next) { 2063 if (decl->key == key) 2064 return decl; 2065 } 2066 2067 return NULL; 2068 } 2069 2070 static Decl * 2071 finddeclaration(Source *source, Env *startenv, int key) 2072 { 2073 const int cacheindex = (key >> 3) & 0x3f; 2074 const int cachebit = 1 << (key & 0x03); 2075 2076 Env *env; 2077 Decl *decl; 2078 2079 for (env = startenv; env; env = env->below) { 2080 /* @note look-up exclusion list first. 2081 * If found: only lookup in found env */ 2082 /* FIXME(m21c): make a separate list, and not use excludehead, 2083 * excludenext ! */ 2084 /* 2085 for (decl = env->excludehead; decl; decl = decl->excludenext) { 2086 if (decl->key == key) 2087 return finddeclinenv(key, env); 2088 } 2089 */ 2090 2091 2092 if ((env->keycache[cacheindex] & cachebit) == 0) 2093 continue; 2094 2095 for (decl = env->head; decl; decl = decl->next) { 2096 if (decl->key == key) 2097 return decl; 2098 } 2099 } 2100 2101 if (!source) 2102 return NULL; 2103 2104 env = source->implicitenv; 2105 2106 if ((env->keycache[cacheindex] & cachebit) == 0) 2107 return NULL; 2108 2109 for (decl = env->head; decl; decl = decl->next) { 2110 if (decl->key == key) 2111 return decl; 2112 } 2113 2114 return NULL; 2115 } 2116 2117 #if 0 2118 static Env * 2119 setheadenv(Source *source, EnvKind kind) 2120 { 2121 /* @note this might only be useful for parameter => function env 2122 * translation */ 2123 Env *env = envbuf + envtop++; 2124 2125 env->kind = kind; 2126 2127 /* @todo make sure that source->tok.loc is the correct 2128 * source-location. */ 2129 /* @todo maybe use getloc(source) instead of 2130 * &source->tok.loc and move the declaration of 2131 * getloc() up in the source-code. */ 2132 env->loc = source->tok.loc; 2133 env->below = source->currenv; 2134 2135 assert(source->headenv == NULL); 2136 source->currenv = source->headenv = env; 2137 2138 return env; 2139 } 2140 #endif 2141 2142 static Env * 2143 pushenv(Source *source, EnvKind kind) 2144 { 2145 Env *env; 2146 2147 if (source->headenv) { 2148 source->headenv->kind = kind; 2149 2150 assert(source->headenv == source->currenv); 2151 source->headenv = NULL; 2152 2153 return source->currenv; 2154 } 2155 2156 env = envbuf + envtop++; 2157 env->kind = kind; 2158 /* @todo make sure that source->tok.loc is the correct 2159 * source-location. */ 2160 /* @todo maybe use getloc(source) instead of 2161 * &source->tok.loc and move the declaration of 2162 * getloc() up in the source-code. */ 2163 env->loc = source->tok.loc; 2164 env->below = source->currenv; 2165 2166 source->currenv = env; 2167 2168 return env; 2169 } 2170 2171 static Env * 2172 popenv(Source *source) 2173 { 2174 Env *currenv = source->currenv; 2175 Env *env = currenv; 2176 2177 if (currenv) 2178 source->currenv = currenv->below; 2179 2180 return env; 2181 } 2182 2183 static Env * 2184 getfuncenv(Env *currenv) 2185 { 2186 Env *env; 2187 2188 for (env = currenv; env; env = env->below) { 2189 if (env->kind == SFUNCTION) { 2190 return env; 2191 } 2192 } 2193 2194 return NULL; 2195 } 2196 2197 static bool 2198 deferfuncenv(Source *source, int keydeclinfunc) 2199 { 2200 Env *funcenv = getfuncenv(source->currenv); 2201 2202 if (funcenv) { 2203 if (!funcenv->pending) { 2204 funcenv->pending = true; 2205 /* @todo handle nested functions properly */ 2206 source->haspendingenv = true; 2207 2208 listappendex(source, funcenv, 2209 pendingenvhead, pendingenvtail, 2210 pendingprev, pendingnext); 2211 } 2212 } else { 2213 /* @todo maybe use getloc(source) instead of 2214 * &source->tok.loc and move the declaration of 2215 * getloc() up in the source-code. */ 2216 error( 2217 &source->tok.loc, 2218 "'%s' undeclared", 2219 getstring(idents, keydeclinfunc) 2220 ); 2221 2222 return false; 2223 } 2224 2225 return true; 2226 } 2227 2228 2229 static Node * 2230 wrapenv(Node *node, Env *env) 2231 { 2232 Node *aenv = makenode(node, node); 2233 2234 aenv->kind = AENV; 2235 aenv->u.env = env; 2236 2237 return aenv; 2238 } 2239 2240 static void 2241 deleteenv(Env *env) 2242 { 2243 if (env->stmts) 2244 deletenode(env->stmts); 2245 2246 /* @todo delete env */ 2247 } 2248 2249 2250 2251 // }}} 2252 2253 // @section declaration {{{ 2254 2255 Decl declbuf[4096]; 2256 int decltop; 2257 2258 static void 2259 appenddecltoenv(Decl *decl, Env *targetenv) 2260 { 2261 const int key = decl->key; 2262 const int cacheindex = (key >> 3) & 0x3f; 2263 const int cachebit = 1 << (key & 0x03); 2264 2265 targetenv->keycache[cacheindex] |= cachebit; 2266 2267 decl->parentenv = targetenv; 2268 2269 listappend(targetenv, decl); 2270 } 2271 2272 static void 2273 removedeclfromenv(Decl *decl) 2274 { 2275 Env *sourceenv = decl->parentenv; 2276 2277 if (decl->prev) 2278 decl->prev->next = decl->next; 2279 else 2280 sourceenv->head = decl->next; 2281 2282 if (decl->next) 2283 decl->next->prev = decl->prev; 2284 else 2285 sourceenv->tail = decl->prev; 2286 2287 decl->parentenv = NULL; 2288 decl->next = decl->prev = NULL; 2289 } 2290 2291 static Decl * 2292 makedecl(Source *source, int key, DeclKind kind) 2293 { 2294 Env *currenv = source->currenv; 2295 Decl *decl; 2296 2297 assert(currenv); 2298 2299 /* @todo maybe remove check if already declared, 2300 * since many functions that call makedecl 2301 * already try to obtain a declaration for 2302 * other reasons. So the check if it is 2303 * already declared can be done by those 2304 * functions */ 2305 2306 decl = finddeclinenv(key, currenv); 2307 2308 if (decl) { 2309 if (decl->parentenv == source->implicitenv) { 2310 removedeclfromenv(decl); 2311 appenddecltoenv(decl, currenv); 2312 2313 return decl; 2314 } 2315 2316 /* @todo make sure that source->tok.loc is the correct 2317 * source-location. */ 2318 /* @todo maybe use getloc(source) instead of 2319 * &source->tok.loc and move the declaration of 2320 * getloc() up in the source-code. */ 2321 error( 2322 &source->tok.loc, 2323 "'%s' already declared", 2324 getstring(idents, key) 2325 ); 2326 } 2327 2328 decl = declbuf + decltop++; 2329 2330 decl->kind = kind; 2331 /* @todo make sure that source->tok.loc is the correct 2332 * source-location. */ 2333 /* @todo maybe use getloc(source) instead of 2334 * &source->tok.loc and move the declaration of 2335 * getloc() up in the source-code. */ 2336 decl->loc = source->tok.loc; 2337 decl->key = key; 2338 decl->type = primitive(TVOID); 2339 decl->contentenv = NULL; 2340 decl->module = NULL; 2341 2342 appenddecltoenv(decl, currenv); 2343 2344 return decl; 2345 } 2346 2347 static Decl * 2348 makebundle(Source *source, int key, Decl *parentbundle) 2349 { 2350 /* Env *currenv = source->currenv; */ 2351 Decl *decl; 2352 2353 /* assert(currenv); */ 2354 2355 decl = declbuf + decltop++; 2356 2357 decl->kind = DBUNDLE; 2358 /* @todo make sure that source->tok.loc is the correct 2359 * source-location. */ 2360 /* @todo maybe use getloc(source) instead of 2361 * &source->tok.loc and move the declaration of 2362 * getloc() up in the source-code. */ 2363 decl->loc = source->tok.loc; 2364 decl->key = key; 2365 decl->type = primitive(TVOID); 2366 decl->contentenv = NULL; 2367 decl->module = parentbundle; 2368 2369 return decl; 2370 } 2371 2372 static Decl * 2373 makedecl2(SrcLoc *loc, Env *env, int key, DeclKind kind) 2374 { 2375 Decl *decl; 2376 2377 assert(env); 2378 2379 /* @todo maybe remove check if already declared, 2380 * since many functions that call makedecl 2381 * already try to obtain a declaration for 2382 * other reasons. So the check if it is 2383 * already declared can be done by those 2384 * functions */ 2385 2386 decl = finddeclinenv(key, env); 2387 if (decl) { 2388 /* @todo maybe check also for implicit declarations */ 2389 error(loc, "'%s' already declared", getstring(idents, key)); 2390 } 2391 2392 decl = declbuf + decltop++; 2393 2394 decl->kind = kind; 2395 /* @todo make sure that source->tok.loc is the correct 2396 * source-location. */ 2397 /* @todo maybe use getloc(source) instead of 2398 * &source->tok.loc and move the declaration of 2399 * getloc() up in the source-code. */ 2400 decl->loc = *loc; 2401 decl->key = key; 2402 decl->type = primitive(TVOID); 2403 decl->contentenv = NULL; 2404 2405 appenddecltoenv(decl, env); 2406 2407 return decl; 2408 } 2409 2410 static Decl * 2411 defertypedeclaration(Source *source, int key) 2412 { 2413 Env *savedcurrenv = source->currenv; 2414 Decl *decl; 2415 2416 source->currenv = source->implicitenv; 2417 decl = makedecl(source, key, DTYPE); 2418 2419 /* FIXME(m21c): type may be overwritten, when the declaration 2420 * is completed */ 2421 decl->type = maketype(&source->tok.loc, primitive(TVOID), NULL); 2422 decl->type->module = decl; 2423 source->currenv = savedcurrenv; 2424 2425 return decl; 2426 } 2427 2428 2429 2430 // }}} 2431 2432 // @section record {{{ 2433 2434 Record recordbuf[4096]; 2435 int recordtop; 2436 2437 static Record * 2438 makerecord(Decl *recorddecl) 2439 { 2440 Record *record; 2441 2442 assert(recordtop < lengthof(recordbuf)); 2443 record = recordbuf + recordtop++; 2444 record->head = record->tail = NULL; 2445 2446 recorddecl->record = record; 2447 2448 assert(recorddecl->type); 2449 record->isunion = recorddecl->type->kind == TUNION; 2450 2451 return record; 2452 } 2453 2454 Field fieldbuf[4096 * 16]; 2455 int fieldtop; 2456 2457 static Field * 2458 makefield(Record *record, Decl *decl) 2459 { 2460 Field *field; 2461 2462 assert(fieldtop < lengthof(fieldbuf)); 2463 field = fieldbuf + fieldtop++; 2464 field->decl = decl; 2465 field->offset = field->size = 0; 2466 field->use = false; 2467 field->prev = field->next = NULL; 2468 2469 assert(record); 2470 listappend(record, field); 2471 2472 return field; 2473 } 2474 2475 2476 2477 // }}} 2478 2479 // @section parser {{{ 2480 2481 #define getkind(source) \ 2482 ((source)->tok.kind) 2483 2484 #define getloc(source) \ 2485 (&(source)->tok.loc) 2486 2487 static bool 2488 expect(Source *source, int kind, const char *fmt, ...) 2489 { 2490 va_list ap; 2491 2492 int line = source->tok.loc.line; 2493 int column = source->tok.loc.column; 2494 const char *filename = source->tok.loc.filename; 2495 2496 if (getkind(source) != (Kind) kind) { 2497 va_start(ap, fmt); 2498 fprintf(stderr, "%s:%i:%i: error: ", 2499 filename, line, column + 1); 2500 vfprintf(stderr, fmt, ap); 2501 fprintf(stderr, "\n"); 2502 va_end(ap); 2503 2504 return false; 2505 } 2506 2507 gettok(source); 2508 return true; 2509 } 2510 2511 // @sub-section read annotations {{{ 2512 2513 static AnnotParam * 2514 readannotparam(Source *source) 2515 { 2516 bool hasident = false; 2517 2518 while (getkind(source)) { 2519 int count = 1; 2520 2521 switch (getkind(source)) { 2522 case IDENT: 2523 if (!hasident) { 2524 int key = source->tok.u.key; 2525 const char *ident = getstring(idents, key); 2526 printf("Annotation Parameter: %s\n", ident); 2527 2528 hasident = true; 2529 } 2530 2531 gettok(source); 2532 break; 2533 2534 case COMMADELIM: case RPARDELIM: 2535 goto finish; 2536 2537 case LPARDELIM: 2538 gettok(source); 2539 while (getkind(source) && count > 0) { 2540 switch (getkind(source)) { 2541 case LPARDELIM: 2542 ++count; 2543 break; 2544 case RPARDELIM: 2545 --count; 2546 break; 2547 default: 2548 break; 2549 } 2550 gettok(source); 2551 } 2552 2553 if(!getkind(source)) 2554 goto finish; 2555 2556 /* FALLTHROUGH */ 2557 default: 2558 gettok(source); 2559 } 2560 } 2561 2562 finish: 2563 return NULL; 2564 } 2565 2566 static void 2567 readannots(Source *source) 2568 { 2569 Docket *docket = NULL; 2570 2571 while (getkind(source) == ANNOT) { 2572 SrcLoc loc = source->tok.loc; 2573 int key = 0; 2574 2575 Annot *annot = NULL; 2576 2577 gettok(source); 2578 2579 key = source->tok.u.key; 2580 if (!expect(source, IDENT, "expected annotation-identifier.")) 2581 return; 2582 2583 annot = makeannot(&loc, key); 2584 2585 if (getkind(source) == LPARDELIM) { 2586 int count; 2587 2588 gettok(source); 2589 for (count = 0; getkind(source); ++count) { 2590 AnnotParam *param = readannotparam(source); 2591 2592 if (param) 2593 listappend(annot, param); 2594 2595 if (getkind(source) == COMMADELIM) { 2596 gettok(source); 2597 continue; 2598 } 2599 2600 if (getkind(source) != RPARDELIM) { 2601 error(getloc(source), 2602 "expected ',' or ')'."); 2603 } else { 2604 gettok(source); 2605 } 2606 2607 break; 2608 } 2609 } 2610 2611 if (docket == NULL) { 2612 docket = makedocket(NULL); 2613 /* @todo add docket to source */ 2614 } 2615 2616 listappend(docket, annot); 2617 2618 skipnewline(source); 2619 2620 printf("Annotation: '%s'\n", getstring(idents, key)); 2621 } 2622 } 2623 2624 // }}} 2625 2626 // @sub-section read statement list {{{ 2627 2628 static bool 2629 checkend(Source *source, bool hastail, int needindent, 2630 const char *expecterrmsg) 2631 { 2632 Node savedtok = {0}; 2633 2634 if (getkind(source) == LINEDELIM) { 2635 savedtok = source->tok; 2636 2637 gettok(source); 2638 2639 if (getkind(source) == SEMIDELIM) { 2640 error(getloc(source), expecterrmsg); 2641 gettok(source); 2642 2643 pushbacktok(source, &savedtok); 2644 return true; 2645 } 2646 } 2647 2648 if (source->lastkind == LINEDELIM && source->lastindent < needindent) { 2649 /* @note Is that correct? Maybe we should always pushback 2650 * a made-up new-line, instead of asserting that we 2651 * have saved one. Since it might be the case, that 2652 * we already have read a new-line prior the call 2653 * to this function. But I'll leave it this way, 2654 * for now. */ 2655 /* assert(savedtok.kind == LINEDELIM); */ 2656 2657 if (savedtok.kind == LINEDELIM) 2658 pushbacktok(source, &savedtok); 2659 return true; 2660 } 2661 2662 if (getkind(source) == SEMIDELIM) { 2663 savedtok = source->tok; 2664 gettok(source); 2665 2666 /* @note used for REPL. it allows having 2667 * semicolons on line-endings and nultiple 2668 * adjacent semecolons in REPL-mode. */ 2669 if ((getkind(source) == SEMIDELIM || 2670 getkind(source) == LINEDELIM) && 2671 source->filein != stdin) 2672 /* @note output an error-message if not in REPL-mode */ 2673 error(&savedtok.loc, "trailing semicolon."); 2674 } 2675 2676 if (isdelimiter(source->tok.kind)) 2677 return true; 2678 2679 if (hastail && 2680 source->lastkind != LINEDELIM && 2681 source->lastkind != SEMIDELIM) 2682 error(getloc(source), "expected line delimiter"); 2683 2684 return false; 2685 } 2686 2687 static Node * 2688 exprlist(Source *source, bool isparam, Type *paramtype); 2689 2690 static Node * 2691 stmtlist(Source *source, int indent, EnvKind envkind, 2692 Decl *envdecl, bool reuseenv) 2693 { 2694 Node *head = NULL, *tail = NULL; 2695 int needindent = nextindent(source, indent); 2696 2697 Env *env = NULL; 2698 2699 if (reuseenv) { 2700 source->currenv->kind = envkind; 2701 } else { 2702 env = pushenv(source, envkind); 2703 env->envdecl = envdecl; 2704 } 2705 2706 for (;;) { 2707 Node *stmt; 2708 2709 if (checkend(source, !!tail, needindent, "expected expression")) 2710 break; 2711 2712 if (getkind(source) == LINEDELIM) 2713 gettok(source); 2714 2715 readannots(source); 2716 stmt = exprlist(source, false, NULL); 2717 stmt = tokennode(source, stmt); 2718 stmt->kind = ASTMT; 2719 2720 if (!tail) { 2721 head = tail = stmt; 2722 } else { 2723 tail->rhs = stmt; 2724 tail = stmt; 2725 } 2726 } 2727 2728 if (reuseenv) { 2729 assert(env == NULL); 2730 env = source->currenv; 2731 } 2732 2733 if (head) { 2734 head = tokennode(source, head); 2735 head->kind = ASCOPE; 2736 head->u.env = env; 2737 env->stmts = head; 2738 2739 popenv(source); 2740 } else { 2741 popenv(source); 2742 /* if (!reuseenv) deleteenv(env); */ 2743 } 2744 2745 return head; 2746 } 2747 2748 // }}} 2749 2750 // @sub-section read declaration {{{ 2751 2752 static int 2753 qualifiers(Source *source, int allowmask) 2754 { 2755 int flags = 0, mask = allowmask; 2756 2757 while (iskeyword(getkind(source))) { 2758 int f, m; 2759 2760 switch (getkind(source)) { 2761 case KEXTERN: 2762 f = QEXTERN, m = ~QVISIB; 2763 break; 2764 2765 case KINTERN: 2766 f = QINTERN, m = ~QVISIB; 2767 break; 2768 2769 case KSTATIC: 2770 f = QSTATIC, m = ~QSTORAGE; 2771 break; 2772 2773 case KCONST: 2774 f = QCONST, m = 0; 2775 break; 2776 2777 /* @todo remove this */ 2778 case KVAR: 2779 f = QVAR, m = ~(QTYPE | QINFER); 2780 break; 2781 2782 default: 2783 goto finish; 2784 } 2785 2786 if (f & ~allowmask) { 2787 const char *str = nodestrings[getkind(source)]; 2788 2789 error(getloc(source), "invalid qualifier '%s'", str); 2790 } else if (f & flags & QTYPE) { 2791 const char *str = nodestrings[getkind(source)]; 2792 2793 warn(getloc(source), "redundant qualifier '%s'", str); 2794 } else if (f & ~mask) { 2795 const char *str = nodestrings[getkind(source)]; 2796 2797 error(getloc(source), "redundant qualifier '%s'", str); 2798 } 2799 2800 flags |= f & allowmask & mask; 2801 mask &= m; 2802 gettok(source); 2803 } 2804 2805 finish: 2806 return flags; 2807 } 2808 2809 static Node * 2810 readexpr(Source *source, int minprec); 2811 2812 static Type * 2813 gettype(Source *source, Type *basetype) 2814 { 2815 int flags; 2816 2817 if (!basetype) 2818 return NULL; 2819 2820 advance: 2821 flags = qualifiers(source, QTYPE); 2822 (void) flags; 2823 2824 if (getkind(source) == LSQRDELIM) { 2825 Type *tmp = maketype(getloc(source), primitive(TARRAY), basetype); 2826 basetype = tmp; 2827 2828 gettok(source); 2829 if (source->tok.kind != RSQRDELIM) 2830 basetype->u.val = readexpr(source, PASSIGN); 2831 2832 expect(source, RSQRDELIM, "expect ']'"); 2833 goto advance; 2834 } 2835 2836 if (getkind(source) == OMUL) { 2837 Type *tmp = maketype(getloc(source), primitive(TPTR), basetype); 2838 basetype = tmp; 2839 2840 gettok(source); 2841 goto advance; 2842 } 2843 2844 return basetype; 2845 } 2846 2847 static Node * 2848 typecheck(Env *env, Node *expr); 2849 2850 static Node * 2851 declaration(Source *source, Type *ty, bool tryreadtype) 2852 { 2853 bool selfparam = false; 2854 Type *module = NULL; 2855 Decl *decl = NULL; 2856 Node *result = NULL; 2857 2858 /* 2859 EnvKind context; 2860 */ 2861 2862 if (tryreadtype) { 2863 decl = finddeclaration(source, source->currenv, source->tok.u.key); 2864 2865 if (decl && decl->kind == DTYPE) { 2866 gettok(source); 2867 ty = gettype(source, decl->type); 2868 tryreadtype = false; 2869 } 2870 } 2871 2872 if (!ty) 2873 return NULL; 2874 2875 /* @todo use the currenv->kind as context, whether or how 2876 * certain declarations (like function-declarations) 2877 * are processed */ 2878 2879 /* 2880 context = source->currenv->kind; 2881 */ 2882 2883 redodeclaration: 2884 skipnewline(source); 2885 2886 /* variable name */ 2887 if (getkind(source) == IDENT) { 2888 int key = source->tok.u.key; 2889 SrcLoc loc = source->tok.loc; 2890 EnvKind envkind = source->currenv->kind; 2891 2892 gettok(source); 2893 2894 if (tryreadtype && (envkind == SSTRUCT || envkind == SUNION)) { 2895 2896 if (!isbasicdelimiter(getkind(source)) && 2897 getkind(source) != LPARDELIM) 2898 { 2899 decl = defertypedeclaration(source, key); 2900 decl->loc = loc; 2901 ty = gettype(source, decl->type); 2902 tryreadtype = false; 2903 goto redodeclaration; 2904 } 2905 } 2906 2907 decl = finddeclaration(source, source->currenv, key); 2908 2909 if (decl && decl->kind != DFUNCTION && decl->kind != DPARAM && 2910 decl->kind != DVAR) 2911 { 2912 module = decl->type; 2913 decl = NULL; 2914 goto readvarmodule; 2915 } 2916 2917 if ((getkind(source) == ODISP || getkind(source) == COLONDELIM) && 2918 getkind(source) != LPARDELIM && getkind(source) != OASS) 2919 { 2920 error(&loc, "expected type or module"); 2921 } 2922 2923 decl = makedecl(source, key, DVAR); 2924 decl->loc = loc; 2925 decl->type = ty; 2926 2927 /* module for variable */ 2928 } else if (getkind(source) == TYPE) { 2929 module = source->tok.type; 2930 gettok(source); 2931 2932 readvarmodule: 2933 module = gettype(source, module); 2934 2935 if (getkind(source) == ODISP || getkind(source) == COLONDELIM) { 2936 selfparam = getkind(source) == COLONDELIM; 2937 (void) selfparam; 2938 gettok(source); 2939 } else { 2940 error(getloc(source), "expected '.' or ':'"); 2941 } 2942 2943 /* @todo obtain Decl* for 2944 * Type Module:my_decl 2945 * or Type Module.my_decl - declarations */ 2946 2947 /* variable name */ 2948 if (getkind(source) == IDENT) { 2949 Env *moduleenv = NULL; 2950 assert(module->module); 2951 assert(module->module->contentenv); 2952 moduleenv = module->module->contentenv; 2953 2954 decl = makedecl2(&source->tok.loc, 2955 moduleenv, source->tok.u.key, DVAR); 2956 decl->type = ty; 2957 decl->module = module->module; 2958 gettok(source); 2959 } else { 2960 error(getloc(source), "expected identifier"); 2961 } 2962 /* just return a node for the type */ 2963 } else { 2964 result = tokennode(source, NULL); 2965 result->kind = TYPE; 2966 result->type = ty; 2967 2968 return result; 2969 } 2970 2971 if (!decl->module) 2972 decl->module = source->currenv->bundle; 2973 2974 /* function declaration */ 2975 if (getkind(source) == LPARDELIM) { 2976 Type *paramtype = NULL; 2977 Env *functionenv = NULL; 2978 Node *body = NULL; 2979 2980 /* function params */ 2981 gettok(source); 2982 if (getkind(source) != RPARDELIM) { 2983 Decl *param; 2984 Node *paramlist; 2985 Type *paramtype = NULL; 2986 2987 functionenv = pushenv(source, SPARAMLIST); 2988 functionenv->envdecl = decl; 2989 2990 if (selfparam) { 2991 param = makedecl(source, auxself, DVAR); 2992 param->type = maketype(¶m->loc, 2993 prim + TPTR, module); 2994 param->flags |= MSPECIAL; 2995 /* @note param doesn't need to be added to 2996 * paramlist. since paramlist will be 2997 * deleted anyway and param is already 2998 * present in env. */ 2999 paramtype = param->type; 3000 } 3001 3002 paramlist = exprlist(source, true, paramtype); 3003 paramlist = typecheck(functionenv, paramlist); 3004 paramtype = paramlist->type; 3005 deletenode(paramlist); 3006 3007 for (param = functionenv->head; param; 3008 param = param->next) 3009 { 3010 assert(param->kind == DVAR); 3011 param->kind = DPARAM; 3012 } 3013 } else if (selfparam) { 3014 Type *selftype = maketype(&decl->loc, 3015 primitive(TPTR), module); 3016 Decl *selfdecl; 3017 3018 functionenv = pushenv(source, SPARAMLIST); 3019 functionenv->envdecl = decl; 3020 3021 selfdecl = makedecl(source, auxself, DPARAM); 3022 selfdecl->type = selftype; 3023 selfdecl->flags |= MSPECIAL; 3024 } 3025 expect(source, RPARDELIM, "expected ')'"); 3026 3027 if (module && ty->kind == TINFER) { 3028 ty = module; 3029 } else if (ty->kind == TINFER) { 3030 error(&decl->loc, 3031 "cannot infer return type of function"); 3032 } 3033 3034 decl->type = maketype(&decl->loc, primitive(TFUNCTION), paramtype); 3035 decl->kind = DFUNCTION; 3036 decl->type->u.rtarget = ty; 3037 ty = decl->type; 3038 3039 /* function body */ 3040 if (getkind(source) != OASS) { 3041 body = stmtlist(source, source->lastindent, 3042 SFUNCTION, decl, !!functionenv); 3043 3044 assert(body && body->kind == ASCOPE); 3045 functionenv = body->u.env; 3046 3047 /* function init (body defined by assigment) */ 3048 } else if (getkind(source) == OASS) { 3049 gettok(source); 3050 3051 functionenv->kind = SFUNCTION; 3052 body = readexpr(source, PASSIGN); 3053 3054 popenv(source); 3055 3056 /* no function body */ 3057 } else { 3058 popenv(source); 3059 } 3060 3061 assert(decl->contentenv == NULL); 3062 decl->contentenv = functionenv; 3063 3064 assert(decl->u.content == NULL); 3065 decl->u.content = body; 3066 3067 3068 /* @todo maybe add function-declaration to its type and 3069 * add the paramlist to the type-info */ 3070 3071 /* @todo store the params-node (its initializations) 3072 * somewhere */ 3073 3074 goto finish; 3075 } 3076 3077 /* variable init */ 3078 if (getkind(source) == OASS) { 3079 gettok(source); 3080 assert(decl); 3081 decl->u.content = readexpr(source, PASSIGN); 3082 3083 /* no init */ 3084 } else { 3085 assert(decl); 3086 decl->u.content = NULL; 3087 3088 if (ty->kind == TINFER) { 3089 error(&decl->loc, 3090 "cannot infer type, expected initialization"); 3091 } 3092 } 3093 3094 finish: 3095 result = tokennode(source, decl->u.content); 3096 result->type = ty; 3097 result->u.declref = decl; 3098 result->loc = decl->loc; 3099 result->kind = ADECL; 3100 3101 return result; 3102 } 3103 3104 // }}} 3105 3106 // @sub-section read atom {{{ 3107 3108 static Node * 3109 readident(Source *source, int flags) 3110 { 3111 Node *lhs = NULL; 3112 Decl *decl = NULL; 3113 SrcLoc loc = source->tok.loc; 3114 int key = source->tok.u.key; 3115 3116 EnvKind envkind = source->currenv 3117 ? source->currenv->kind 3118 : STOPLEVEL; 3119 3120 decl = finddeclaration(source, source->currenv, source->tok.u.key); 3121 gettok(source); 3122 3123 if (!decl && (envkind == SSTRUCT || envkind == SUNION)) { 3124 if (!isbasicdelimiter(getkind(source))) { 3125 decl = defertypedeclaration(source, key); 3126 decl->loc = loc; 3127 } 3128 } 3129 3130 if (decl && decl->kind == DTYPE) { 3131 lhs = declaration(source, gettype(source, decl->type), false); 3132 return lhs; 3133 } 3134 3135 lhs = tokennode(source, NULL); 3136 lhs->loc = loc; 3137 3138 if (decl) { 3139 lhs->kind = ADECLREF; 3140 lhs->type = decl->type; 3141 lhs->u.declref = decl; 3142 } else { 3143 if (deferfuncenv(source, key)) { 3144 lhs->kind = IDENT; 3145 lhs->u.key = key; 3146 } else { 3147 lhs->kind = NUMBER; 3148 lhs->u.u = 0; 3149 } 3150 3151 lhs->type = primitive(TVOID); 3152 } 3153 3154 if (flags & QCONST) { 3155 /* @todo const - conversion */ 3156 } 3157 3158 return lhs; 3159 } 3160 3161 static void 3162 extractfields(Record *record, Node *recordscope) 3163 { 3164 Node *stmt; 3165 3166 for (stmt = recordscope->lhs; stmt; stmt = stmt->rhs) { 3167 Node *expr; 3168 3169 assert(stmt->kind == ASTMT); 3170 3171 expr = stmt->lhs; 3172 3173 /* @fixme expr might be validly NULL */ 3174 assert(expr); 3175 3176 if (expr->kind == ACOMMA) { 3177 for (; expr; expr = expr->lhs) { 3178 Node *nested; 3179 3180 if (expr->kind == ADECL) 3181 makefield(record, expr->u.declref); 3182 3183 if (expr->kind != ACOMMA) 3184 break; 3185 3186 nested = expr->rhs; 3187 3188 if (nested->kind != ADECL) 3189 continue; 3190 3191 makefield(record, nested->u.declref); 3192 } 3193 continue; 3194 } 3195 if (expr->kind != ADECL) 3196 continue; 3197 3198 makefield(record, expr->u.declref); 3199 } 3200 } 3201 3202 static void 3203 calculatefields(Record *record, Type *recordtype) 3204 { 3205 const bool isunion = record->isunion; 3206 Field *field; 3207 3208 /* @todo calculate size/align for unions */ 3209 for (field = record->head; field; field = field->next) { 3210 size_t mod = 0, padding; 3211 Type *type; 3212 3213 type = field->decl->type; 3214 3215 if (recordtype->align < type->align) 3216 recordtype->align = type->align; 3217 3218 if (isunion) { 3219 if (recordtype->size < type->size) 3220 recordtype->size = type->size; 3221 continue; 3222 } 3223 3224 if (recordtype->align) 3225 mod = recordtype->size % recordtype->align; 3226 3227 padding = mod ? recordtype->align - mod : 0; 3228 field->offset = padding + recordtype->size; 3229 recordtype->size += padding + type->size; 3230 } 3231 } 3232 3233 static Node * 3234 readrecord(Source *source, bool isunion) 3235 { 3236 Node *recordnode; 3237 Decl *module; 3238 Record *record; 3239 int indent = source->lastindent; 3240 3241 EnvKind envkind = SSTRUCT; 3242 TypeKind typekind = TSTRUCT; 3243 3244 if (isunion) { 3245 envkind = SUNION; 3246 typekind = TUNION; 3247 } 3248 3249 recordnode = tokennode(source, NULL); 3250 recordnode->kind = getkind(source); 3251 gettok(source); 3252 3253 /* read record tag-name */ 3254 if (getkind(source) == IDENT) { 3255 recordnode->lhs = tokennode(source, NULL); 3256 gettok(source); 3257 } else { 3258 error(getloc(source), "expected identifier"); 3259 } 3260 3261 module = makedecl(source, recordnode->lhs->u.key, DTYPE); 3262 3263 if (module->type->module == module) { 3264 *module->type = prim[TSTRUCT]; 3265 } else { 3266 module->type = maketype(&recordnode->loc, prim + typekind, NULL); 3267 } 3268 3269 module->type->module = module; 3270 recordnode->type = module->type; 3271 3272 if (!module->module) /* @note currently module->module == NULL always */ 3273 module->module = source->currenv->bundle; 3274 3275 /* read record body */ 3276 3277 /* @note maybe we will use stmtlist() for parsing the record body, 3278 since we have to parse statements or expressions beside 3279 field declarations */ 3280 3281 /* @todo check for new-line and only then read body */ 3282 recordnode->rhs = stmtlist(source, indent, envkind, module, false); 3283 if (recordnode->rhs) { 3284 module->contentenv = recordnode->rhs->u.env; 3285 } 3286 3287 record = makerecord(module); 3288 3289 /* @todo validate record body, extract declarations, 3290 * compute size and align, resolve aliases */ 3291 3292 if (recordnode->rhs) { 3293 assert(recordnode->rhs->kind == ASCOPE); 3294 extractfields(record, recordnode->rhs); 3295 } 3296 3297 calculatefields(record, recordnode->type); 3298 return recordnode; 3299 } 3300 3301 static bool 3302 skipnewlineontok(Source *source, Kind kind, int neededindent) 3303 { 3304 Node savedtok; 3305 3306 if (getkind(source) == kind) 3307 return source->lastindent >= neededindent; 3308 3309 if (getkind(source) == LINEDELIM) { 3310 savedtok = source->tok; 3311 3312 if (gettok(source) == (int) kind && 3313 source->lastindent >= neededindent) 3314 return true; 3315 3316 pushbacktok(source, &savedtok); 3317 } 3318 3319 return false; 3320 } 3321 3322 static Node * 3323 readrecordinitfield(Source *source, Type *recordtype) 3324 { 3325 Node *fieldinit = NULL; 3326 Node savedtok = {0}; 3327 3328 /* @todo add init-env */ 3329 3330 skipnewline(source); 3331 3332 fieldinit = tokennode(source, NULL); 3333 fieldinit->kind = AFIELDINIT; 3334 if (getkind(source) == IDENT) { 3335 savedtok = source->tok; 3336 gettok(source); 3337 if (getkind(source) == COLONDELIM) { 3338 gettok(source); 3339 /* @todo associate field name with field in record type */ 3340 fieldinit->lhs = makenode(&savedtok, NULL); 3341 } else { 3342 pushbacktok(source, &savedtok); 3343 } 3344 } 3345 3346 fieldinit->rhs = readexpr(source, PASSIGN); 3347 return fieldinit; 3348 } 3349 3350 static Node * 3351 readrecordinitfieldlist(Source *source, Type *recordtype) 3352 { 3353 /* @todo add init-env */ 3354 /* @todo check for missing field-initializers */ 3355 Node *init = readrecordinitfield(source, recordtype); 3356 3357 while (skipnewline(source), getkind(source) == COMMADELIM) { 3358 init = tokennode(source, init); 3359 init->kind = ACOMMA; 3360 gettok(source); 3361 init->rhs = readrecordinitfield(source, recordtype); 3362 } 3363 3364 return init; 3365 } 3366 3367 static Node * 3368 finishcontrolflow(Source *source, Node *lhs, int indent) 3369 { 3370 if (skipnewlineontok(source, KELSE, indent)) { 3371 gettok(source); 3372 lhs->rhs = stmtlist(source, indent, SELSE, NULL, false); 3373 } 3374 3375 return wrapenv(lhs, popenv(source)); 3376 } 3377 3378 static Node * 3379 readatom(Source *source, int flags) 3380 { 3381 Node *lhs = NULL, *savedis = source->lastis; 3382 int indent; 3383 3384 /* unary 'is'-operator */ 3385 if (getkind(source) == KIS) { 3386 if (!source->lastis) { 3387 error( 3388 getloc(source), 3389 "there is no left-hand-side for 'is'" 3390 ); 3391 3392 lhs = tokennode(source, NULL); 3393 } else { 3394 lhs = tokennode(source, source->lastis->lhs); 3395 } 3396 3397 gettok(source); 3398 3399 if (getkind(source) == KNOT) 3400 gettok(source), lhs->kind = ONEQ; 3401 else 3402 lhs->kind = OEQU; 3403 3404 lhs->rhs = readexpr(source, PRELAT); 3405 return lhs; 3406 } 3407 3408 /* unary prefix operators */ 3409 if (getunary(source->tok.kind)) { 3410 lhs = tokennode(source, NULL); 3411 3412 /* @todo remove redundant function-call */ 3413 lhs->kind = getunary(source->tok.kind); 3414 3415 gettok(source); 3416 lhs->lhs = readatom(source, 0); 3417 return lhs; 3418 } 3419 3420 if (flags & ~(QINFER | QCONST)) { 3421 error(getloc(source), "invalid use of qualifiers"); 3422 flags = flags & (QINFER | QCONST); 3423 } 3424 3425 if (flags) { 3426 lhs = readatom(source, flags); 3427 return lhs; 3428 } 3429 3430 /* actual atom */ 3431 switch (getkind(source)) { 3432 case LPARDELIM: 3433 gettok(source); 3434 3435 if (getkind(source) == LINEDELIM) { 3436 /* FIXME(m21c): stmtlist should ignore indentation in 3437 * this case! */ 3438 lhs = stmtlist(source, source->lastindent, 3439 SSCOPE, NULL, false); 3440 source->lastis = savedis; 3441 } else { 3442 lhs = exprlist(source, false, NULL); 3443 source->lastis = savedis; 3444 3445 if (lhs->kind == TYPE) { 3446 /* @note expecting that the type is also set in lhs->type */ 3447 lhs->kind = OCAST; 3448 skipnewline(source); 3449 expect(source, RPARDELIM, "expected ')'"); 3450 3451 lhs->lhs = readatom(source, 0); 3452 break; 3453 } 3454 3455 if (lhs->kind == ACOMMA && 3456 lhs->lhs->kind == TYPE && 3457 lhs->rhs->kind == TYPE) 3458 { 3459 Type *ty = maketype(&lhs->loc, primitive(TTUPLE), NULL); 3460 ty->target = lhs->lhs->type; 3461 ty->u.rtarget = lhs->rhs->type; 3462 deletenode(lhs); 3463 3464 skipnewline(source); 3465 expect(source, RPARDELIM, "expected ')'"); 3466 3467 lhs = declaration(source, gettype(source, ty), false); 3468 3469 assert(lhs); 3470 return lhs; 3471 } 3472 3473 skipnewline(source); 3474 } 3475 3476 expect(source, RPARDELIM, "expected ')'"); 3477 break; 3478 3479 case IDENT: 3480 lhs = readident(source, flags); 3481 break; 3482 3483 case TYPE: 3484 do { 3485 Type *type = source->tok.type; 3486 gettok(source); 3487 lhs = declaration(source, gettype(source, type), false); 3488 } while (0); 3489 3490 break; 3491 3492 case NUMBER: 3493 case STRING: 3494 case CHAR: 3495 lhs = tokennode(source, NULL); 3496 gettok(source); 3497 3498 if (flags & QCONST) { 3499 /* @todo const - conversion */ 3500 } 3501 3502 break; 3503 3504 case KVAR: 3505 gettok(source); 3506 lhs = declaration(source, primitive(TINFER), false); 3507 /* skip postfix-operators */ 3508 return lhs; 3509 3510 case KFALSE: 3511 case KTRUE: 3512 lhs = tokennode(source, NULL); 3513 lhs->kind = NUMBER; 3514 lhs->type = primitive(TBOOL); 3515 lhs->u.u = (uintmax_t) (getkind(source) == KTRUE); 3516 gettok(source); 3517 break; 3518 3519 case KNULL: 3520 lhs = tokennode(source, NULL); 3521 lhs->kind = NUMBER; 3522 lhs->type = maketype(&source->tok.loc, primitive(TPTR), primitive(TVOID)); 3523 lhs->u.u = (uintmax_t) (getkind(source) == KTRUE); 3524 gettok(source); 3525 break; 3526 3527 case KSTRUCT: 3528 case KUNION: 3529 lhs = readrecord(source, source->tok.kind == KUNION); 3530 /* skip postfix-operators */ 3531 return lhs; 3532 3533 case KNOT: 3534 lhs = tokennode(source, NULL); 3535 gettok(source); 3536 lhs->kind = OLNOT; 3537 lhs->lhs = readexpr(source, PRELAT); 3538 break; 3539 3540 case KALIGNOF: 3541 case KSIZEOF: 3542 case KLENGTHOF: 3543 lhs = tokennode(source, NULL); 3544 gettok(source); 3545 if (getkind(source) == LPARDELIM) { 3546 gettok(source); 3547 lhs->lhs = exprlist(source, false, NULL); 3548 expect(source, RPARDELIM, "expected ')'"); 3549 } else { 3550 lhs->lhs = readatom(source, 0); 3551 } 3552 3553 break; 3554 3555 case KBITCAST: 3556 lhs = tokennode(source, NULL); 3557 gettok(source); 3558 expect(source, LPARDELIM, "expected '('"); 3559 lhs->rhs = exprlist(source, false, NULL); 3560 expect(source, RPARDELIM, "expected ')'"); 3561 lhs->lhs = readatom(source, 0); 3562 break; 3563 3564 case KBREAK: 3565 case KCONTINUE: 3566 lhs = tokennode(source, NULL); 3567 lhs->kind = getkind(source); 3568 gettok(source); 3569 3570 if (getkind(source) == COLONDELIM) { 3571 gettok(source); 3572 skipnewline(source); 3573 if (getkind(source) == IDENT) { 3574 lhs->lhs = tokennode(source, NULL); 3575 gettok(source); 3576 } else { 3577 error(getloc(source), "expected identifier"); 3578 } 3579 } 3580 3581 break; 3582 3583 case KRETURN: 3584 lhs = tokennode(source, NULL); 3585 gettok(source); 3586 3587 if (getkind(source) == COLONDELIM) { 3588 gettok(source); 3589 skipnewline(source); 3590 if (getkind(source) == IDENT) { 3591 lhs->lhs = tokennode(source, NULL); 3592 gettok(source); 3593 } else { 3594 error(getloc(source), "expected identifier"); 3595 } 3596 } 3597 3598 /* if is atom */ 3599 if (!isdelimiter(source->tok.kind)) 3600 lhs->rhs = exprlist(source, false, NULL); 3601 3602 break; 3603 3604 case KDO: 3605 indent = source->lastindent; 3606 lhs = tokennode(source, NULL); 3607 gettok(source); 3608 lhs->lhs = stmtlist(source, indent, SDO, NULL, false); 3609 /* skip postfix-operators */ 3610 return lhs; 3611 3612 case KLOOP: 3613 indent = source->lastindent; 3614 lhs = tokennode(source, NULL); 3615 gettok(source); 3616 pushenv(source, SLOOPHEADER); 3617 lhs->lhs = stmtlist(source, indent, SLOOP, NULL, false); 3618 3619 if (skipnewlineontok(source, KUNTIL, indent)) { 3620 lhs->kind = ALOOPUNTIL; 3621 gettok(source); 3622 lhs->u.payload = readexpr(source, POR); 3623 } 3624 3625 if (lhs->kind != KLOOP) 3626 goto joinelse; 3627 3628 /* skip postfix-operators */ 3629 // return finishcontrolflow(source, lhs, indent); 3630 3631 return wrapenv(lhs, popenv(source)); 3632 3633 case KFOR: 3634 indent = source->lastindent; 3635 lhs = tokennode(source, NULL); 3636 gettok(source); 3637 3638 pushenv(source, SLOOPHEADER); 3639 lhs->u.payload = readexpr(source, POR); 3640 if (getkind(source) == IDENT) { 3641 if (source->tok.u.key == auxin) { 3642 Node *aux = tokennode(source, NULL); 3643 aux->lhs = lhs->u.payload; 3644 aux->kind = AFOREACH; 3645 lhs->u.payload = aux; 3646 gettok(source); 3647 aux->rhs = readexpr(source, POR); 3648 } else if (source->tok.u.key == auxto) { 3649 Node *aux = tokennode(source, NULL); 3650 aux->lhs = lhs->u.payload; 3651 aux->kind = AFORSTEP; 3652 lhs->u.payload = aux; 3653 gettok(source); 3654 aux->rhs = readexpr(source, POR); 3655 if (getkind(source) == IDENT 3656 && source->tok.u.key == auxstep) { 3657 gettok(source); 3658 aux->u.payload = readexpr(source, POR); 3659 } else { 3660 aux->u.payload = tokennode(source, NULL); 3661 aux->u.payload->kind = NUMBER; 3662 aux->u.payload->type = primitive(TINFER); 3663 aux->u.payload->u.s = 1; 3664 } 3665 } else if (source->tok.u.key == auxstep) { 3666 Node *aux = tokennode(source, NULL); 3667 aux->lhs = lhs->u.payload; 3668 aux->kind = AFORSTEP; 3669 lhs->u.payload = aux; 3670 gettok(source); 3671 aux->u.payload = readexpr(source, POR); 3672 3673 /* @note is this even correct? */ 3674 aux->rhs = tokennode(source, NULL); 3675 aux->rhs->kind = NUMBER; 3676 aux->rhs->type = primitive(TINFER); 3677 aux->rhs->u.s = INTMAX_MAX; 3678 } 3679 } 3680 3681 /* @todo maybe use SFOR instead of SLOOP */ 3682 lhs->lhs = stmtlist(source, indent, SLOOP, NULL, false); 3683 goto joinelse; 3684 return finishcontrolflow(source, lhs, indent); 3685 3686 case KWHILE: 3687 indent = source->lastindent; 3688 lhs = tokennode(source, NULL); 3689 gettok(source); 3690 pushenv(source, SLOOPHEADER); 3691 lhs->u.payload = readexpr(source, POR); 3692 lhs->lhs = stmtlist(source, indent, SWHILE, NULL, false); 3693 goto joinelse; 3694 return finishcontrolflow(source, lhs, indent); 3695 3696 case KIF: 3697 indent = source->lastindent; 3698 lhs = tokennode(source, NULL); 3699 gettok(source); 3700 pushenv(source, SIFHEADER); 3701 lhs->u.payload = readexpr(source, POR); 3702 /* skipnewline(source); */ 3703 3704 if (getkind(source) == IDENT && source->tok.u.key == auxthen) 3705 gettok(source); 3706 3707 lhs->lhs = stmtlist(source, indent, SIF, NULL, false); 3708 joinelse: 3709 if (skipnewlineontok(source, KELSE, indent)) { 3710 gettok(source); 3711 lhs->rhs = stmtlist(source, indent, SELSE, NULL, false); 3712 } 3713 return finishcontrolflow(source, lhs, indent); 3714 3715 /* skip postfix-operators */ 3716 return wrapenv(lhs, popenv(source)); 3717 3718 default: 3719 /* joinerror: */ 3720 error(getloc(source), "expected expression"); 3721 lhs = tokennode(source, NULL); 3722 lhs->kind = NUMBER; 3723 lhs->type = primitive(TERRTYPE); 3724 lhs->u.u = 0; 3725 gettok(source); 3726 } 3727 3728 /* compound-literal */ 3729 if (getkind(source) == LCURLDELIM && lhs->kind == TYPE) { 3730 lhs = tokennode(source, lhs); 3731 lhs->kind = ACOMPOUND; 3732 lhs->type = lhs->lhs->type; 3733 3734 gettok(source); 3735 // source->lastindent = nextindent(source, source->lastindent); 3736 lhs->rhs = readrecordinitfieldlist(source, lhs->type); 3737 expect(source, RCURLDELIM, "expected '}'"); 3738 } 3739 3740 /* unary postfix operators */ 3741 while (getunarysuffix(source)) { 3742 lhs = tokennode(source, lhs); 3743 3744 /* @todo remove redundant function-call */ 3745 lhs->kind = getunarysuffix(source); 3746 3747 if (getkind(source) == ODISP) { 3748 gettok(source); 3749 skipnewline(source); 3750 3751 if (getkind(source) != IDENT) 3752 error(getloc(source), "expected identifier"); 3753 3754 lhs->rhs = tokennode(source, NULL); 3755 3756 } else if (getkind(source) == COLONDELIM) { 3757 gettok(source); 3758 skipnewline(source); 3759 3760 if (getkind(source) != IDENT) 3761 error(getloc(source), "expected identifier"); 3762 3763 lhs->rhs = tokennode(source, NULL); 3764 3765 } else if (getkind(source) == LPARDELIM) { 3766 gettok(source); 3767 3768 if (getkind(source) != RPARDELIM) { 3769 lhs->rhs = exprlist(source, false, NULL); 3770 source->lastis = savedis; 3771 } 3772 3773 expect(source, RPARDELIM, "expected ')'"); 3774 continue; 3775 3776 } else if (getkind(source) == LSQRDELIM) { 3777 gettok(source); 3778 3779 lhs->rhs = exprlist(source, false, NULL); 3780 source->lastis = savedis; 3781 3782 expect(source, RSQRDELIM, "expected ']'"); 3783 continue; 3784 } 3785 3786 gettok(source); 3787 } 3788 3789 /* 'not'-suffix for the binary 'is'-operator (i.e. 'is not') */ 3790 while (getkind(source) == KIS) { 3791 lhs = tokennode(source, lhs); 3792 gettok(source); 3793 3794 lhs->kind = 'O'; 3795 if (getkind(source) == KNOT) 3796 gettok(source), lhs->kind = ONEQ; 3797 else 3798 lhs->kind = OEQU; 3799 3800 source->lastis = lhs; 3801 lhs->rhs = readexpr(source, PRELAT); 3802 } 3803 3804 /* skip funtion-call without parentheses when next token is an 3805 * auxiliary keyword */ 3806 if (getkind(source) == IDENT) { 3807 if (source->tok.u.key == auxthen 3808 || source->tok.u.key == auxin 3809 || source->tok.u.key == auxto 3810 || source->tok.u.key == auxstep) { 3811 return lhs; 3812 } 3813 } 3814 3815 /* function call without parentheses */ 3816 if (lhs->kind == ADECLREF 3817 && lhs->u.declref->kind == DFUNCTION 3818 && isatomnode(getkind(source))) { 3819 lhs = tokennode(source, lhs); 3820 lhs->kind = OCALL; 3821 3822 lhs->rhs = exprlist(source, false, NULL); 3823 source->lastis = savedis; /* @note is this correct? */ 3824 } 3825 3826 return lhs; 3827 } 3828 3829 // }}} 3830 3831 // @sub-section read expression {{{ 3832 3833 static Node * 3834 readexpr(Source *source, int minprec) 3835 { 3836 Node *lhs = readatom(source, 0), *last = NULL; 3837 3838 /* only binary expr */ 3839 while (getprec(getkind(source)) >= minprec) { 3840 lhs = tokennode(source, lhs); 3841 gettok(source); 3842 skipnewline(source); 3843 3844 lhs->rhs = readexpr( 3845 source, 3846 getprec(lhs->kind) + !israssoc(lhs->kind) 3847 ); 3848 3849 switch (getprec(lhs->kind)) { 3850 case PRELAT: 3851 if (last) { 3852 lhs = tokennode(source, lhs); 3853 3854 lhs->rhs = lhs->lhs; 3855 lhs->kind = OLAND; 3856 3857 lhs->lhs = lhs->rhs->lhs; 3858 lhs->rhs->lhs = last->rhs; /* copy */ 3859 last = lhs->rhs; 3860 } else { 3861 last = lhs; 3862 } 3863 3864 break; 3865 3866 default: 3867 last = NULL; 3868 break; 3869 } 3870 } 3871 3872 return lhs; 3873 } 3874 3875 #if 0 3876 static Node * 3877 todeclaration(Node *curr, Node **ty) 3878 { 3879 if (*ty) { 3880 if (curr->kind == IDENT) { 3881 Node *decl = makenode(curr, *ty); 3882 curr->kind = ADECL; 3883 decl->rhs = curr; 3884 curr = decl; 3885 } else if (curr->kind == OASS && 3886 curr->lhs && curr->lhs->kind == IDENT) 3887 { 3888 curr->kind = ADECL; 3889 curr->u.payload = curr->rhs; 3890 curr->rhs = curr->lhs; 3891 curr->lhs = *ty; 3892 } 3893 } 3894 3895 if (curr->kind == ADECL) 3896 *ty = curr->lhs; 3897 3898 return curr; 3899 } 3900 #endif 3901 3902 /* @todo this is stupid! There should be a simpler way to parse the 3903 * comma-expressions (comma-operator, param-list, declaration-list, 3904 * type-tuples and expression-tuples) */ 3905 static Node * 3906 exprlist(Source *source, bool isparam, Type *paramtype) 3907 { 3908 Node *lhs; 3909 bool isdeclaration, typetuple; 3910 3911 /* tail = todeclaration(tail, ¶mtype); */ 3912 3913 if (paramtype && getkind(source) == IDENT) { 3914 lhs = declaration(source, paramtype, false); 3915 } else { 3916 lhs = readexpr(source, PASSIGN); 3917 } 3918 3919 isdeclaration = lhs->kind == ADECL; 3920 3921 if (isdeclaration) 3922 paramtype = lhs->type; 3923 else if (isparam) 3924 error(getloc(source), "expected declaration"); 3925 3926 typetuple = lhs->kind == TYPE; 3927 3928 while (getkind(source) == COMMADELIM) { 3929 Node *rhs = NULL; 3930 3931 if (lhs->kind == ACOMMA && 3932 lhs->lhs->kind == TYPE && 3933 lhs->rhs->kind == TYPE) 3934 { 3935 lhs->type = maketype(&lhs->loc, primitive(TTUPLE), 3936 lhs->lhs->type); 3937 lhs->type->u.rtarget = lhs->rhs->type; 3938 3939 lhs->lhs->type = NULL; 3940 lhs->rhs->type = NULL; 3941 deletenode(lhs->lhs); 3942 deletenode(lhs->rhs); 3943 3944 lhs->lhs = NULL; 3945 lhs->rhs = NULL; 3946 lhs->kind = TYPE; 3947 } 3948 3949 lhs = tokennode(source, lhs); 3950 lhs->kind = ACOMMA; 3951 gettok(source); 3952 3953 if (getkind(source) == IDENT && isdeclaration) { 3954 rhs = declaration(source, paramtype, true); 3955 typetuple = false; 3956 } else { 3957 rhs = readexpr(source, PASSIGN); 3958 typetuple &= rhs->kind == TYPE; 3959 /* rhs = todeclaration(curr, ¶mtype); */ 3960 } 3961 3962 if ((paramtype || isparam) && rhs->kind != ADECL) 3963 error(getloc(source), "expected declaration"); 3964 3965 if (rhs->kind == ADECL) { 3966 paramtype = rhs->type; 3967 isdeclaration = true; 3968 } 3969 3970 lhs->rhs = rhs; 3971 } 3972 3973 source->lastis = NULL; 3974 return lhs; 3975 } 3976 3977 // }}} 3978 3979 3980 3981 // }}} 3982 3983 // @section type-checking & folding {{{ 3984 3985 static bool 3986 isinttype(Type *ty) 3987 { 3988 switch (ty->kind) { 3989 case TINFER: case TUINFER: 3990 case TS8: case TU8: 3991 case TS16: case TU16: 3992 case TS32: case TU32: 3993 case TS64: case TU64: 3994 case TERRTYPE: /* avoiding error-reporting on error-type */ 3995 return true; 3996 3997 /* FIXME(m21c): This *just* tests wether a tuple only contains types of 3998 * certain kinds. In order to check wether two tuple-types 3999 * are compatible (for casting), another function has to 4000 * be implemented. */ 4001 case TTUPLE: 4002 return isinttype(ty->target) 4003 && isinttype(ty->u.rtarget); 4004 4005 default: 4006 return false; 4007 } 4008 } 4009 4010 static bool 4011 isintorbooltype(Type *ty) 4012 { 4013 switch (ty->kind) { 4014 case TBOOL: 4015 case TINFER: case TUINFER: 4016 case TS8: case TU8: 4017 case TS16: case TU16: 4018 case TS32: case TU32: 4019 case TS64: case TU64: 4020 case TERRTYPE: /* avoiding error-reporting on error-type */ 4021 return true; 4022 4023 /* FIXME(m21c): This *just* tests wether a tuple only contains types of 4024 * certain kinds. In order to check wether two tuple-types 4025 * are compatible (for casting), another function has to 4026 * be implemented. */ 4027 case TTUPLE: 4028 return isintorbooltype(ty->target) 4029 && isintorbooltype(ty->u.rtarget); 4030 4031 default: 4032 return false; 4033 } 4034 } 4035 4036 static bool 4037 isfloattype(Type *ty) 4038 { 4039 switch (ty->kind) { 4040 case TF32: case TF64: 4041 case TERRTYPE: /* avoiding error-reporting on error-type */ 4042 return true; 4043 4044 /* FIXME(m21c): This *just* tests wether a tuple only contains types of 4045 * certain kinds. In order to check wether two tuple-types 4046 * are compatible (for casting), another function has to 4047 * be implemented. */ 4048 case TTUPLE: 4049 return isfloattype(ty->target) 4050 && isfloattype(ty->u.rtarget); 4051 4052 default: 4053 return false; 4054 } 4055 } 4056 4057 static bool 4058 isarithtype(Type *ty) 4059 { 4060 switch (ty->kind) { 4061 case TBOOL: 4062 case TINFER: case TUINFER: 4063 case TS8: case TU8: 4064 case TS16: case TU16: 4065 case TS32: case TU32: 4066 case TS64: case TU64: 4067 case TF32: case TF64: 4068 case TERRTYPE: /* avoiding error-reporting on error-type */ 4069 return true; 4070 4071 /* FIXME(m21c): This *just* tests wether a tuple only contains types of 4072 * certain kinds. In order to check wether two tuple-types 4073 * are compatible (for casting), another function has to 4074 * be implemented. */ 4075 case TTUPLE: 4076 return isarithtype(ty->target) 4077 && isarithtype(ty->u.rtarget); 4078 4079 default: 4080 return false; 4081 } 4082 } 4083 4084 static bool 4085 isunsignedtype(Type *ty) 4086 { 4087 switch (ty->kind) { 4088 case TBOOL: 4089 case TUINFER: 4090 case TU8: case TU16: 4091 case TU32: case TU64: 4092 case TERRTYPE: /* avoiding error-reporting on error-type */ 4093 return true; 4094 4095 /* FIXME(m21c): This *just* tests wether a tuple only contains types of 4096 * certain kinds. In order to check wether two tuple-types 4097 * are compatible (for casting), another function has to 4098 * be implemented. */ 4099 case TTUPLE: 4100 return isunsignedtype(ty->target) 4101 && isunsignedtype(ty->u.rtarget); 4102 4103 default: 4104 return false; 4105 } 4106 } 4107 4108 static bool 4109 islvalue(Node *node) 4110 { 4111 assert(node); 4112 4113 switch (node->kind) { 4114 case ADECLREF: 4115 case ADEREF: 4116 case ADECL: 4117 case ODISP: /* only for member fields. @todo evaluate for properties. */ 4118 case TERRTYPE: /* avoiding error-reporting on error-type */ 4119 return true; 4120 4121 case ACOMMA: 4122 return islvalue(node->lhs) && islvalue(node->rhs); 4123 4124 default: 4125 return false; 4126 } 4127 } 4128 4129 /* @todo also mask int/float values in the tokenizer */ 4130 static uintmax_t 4131 maskint(int size, uintmax_t value) 4132 { 4133 if (size == 1) return value & 0xfful; 4134 if (size == 2) return value & 0xfffful; 4135 if (size == 4) return value & 0xfffffffful; 4136 4137 return value; 4138 } 4139 4140 static double 4141 maskfloat(int size, double value) 4142 { 4143 if (size == 4) return (double) (float) value; 4144 4145 return value; 4146 } 4147 4148 static uintmax_t 4149 convint(int srcsize, bool srcsigned, uintmax_t value) 4150 { 4151 if (!srcsigned) return value; 4152 if (srcsize == 1) return (uintmax_t) (int8_t ) value; 4153 if (srcsize == 2) return (uintmax_t) (int16_t) value; 4154 if (srcsize == 4) return (uintmax_t) (int32_t) value; 4155 4156 return value; 4157 } 4158 4159 static Node * 4160 conv(Node *node); 4161 4162 static Node * 4163 wrap(Type *type, Node *node) 4164 { 4165 Type *nodetype = node->type; 4166 4167 assert(type); 4168 4169 // @todo add error-reporting | refactor 4170 if (!nodetype) { 4171 printf("node has no type\n"); 4172 } 4173 4174 assert(nodetype); 4175 4176 /* @todo do proper type-check */ 4177 if (type->kind == nodetype->kind) 4178 return node; 4179 4180 if (node->kind == NUMBER) { 4181 /* @todo layout correct type-conversions ? */ 4182 if (isfloattype(nodetype)) { 4183 if (isfloattype(type)) { 4184 node->u.d = maskfloat( 4185 type->size, 4186 node->u.d 4187 ); 4188 4189 } else if (isintorbooltype(type)) { 4190 node->u.u = maskint( 4191 type->size, 4192 (intmax_t) node->u.d 4193 ); 4194 } 4195 } else if (isintorbooltype(nodetype)) { 4196 if (isfloattype(type)) { 4197 node->u.d = maskfloat( 4198 type->size, (double) 4199 (intmax_t) convint(node->type->size, 4200 !isunsignedtype(node->type), 4201 node->u.u 4202 ) 4203 ); 4204 4205 } else if (isintorbooltype(type)) { 4206 node->u.u = maskint( 4207 type->size, 4208 convint( 4209 nodetype->size, 4210 !isunsignedtype(nodetype), 4211 node->u.u 4212 ) 4213 ); 4214 } 4215 } 4216 4217 node->type = type; 4218 return node; 4219 } 4220 4221 /* @note no implicit (de-)referencing if the wrap-type is bool */ 4222 if (type->kind == TBOOL) 4223 goto doconversion; 4224 4225 /* @todo skip implicit (de-)referencing on arithmetic 4226 * conversion, also skip if called from conv() */ 4227 4228 /* implicit referencing: */ 4229 if (type->kind == TPTR && type->target->kind == nodetype->kind) { 4230 node = makenode(node, node); 4231 node->kind = OADDR; 4232 node->type = type->target; 4233 4234 /* @todo check for lvalue & maybe do further 4235 * type-checks*/ 4236 return node; 4237 } 4238 4239 /* implicit de-referencing: */ 4240 if (nodetype->kind == TPTR && nodetype->target->kind == type->kind) { 4241 node = makenode(node, node); 4242 node->kind = ODEREF; 4243 node->type = type; 4244 4245 /* @todo maybe do further type-checks*/ 4246 return node; 4247 } 4248 4249 doconversion: 4250 node = makenode(node, node); 4251 node->kind = ACONV; 4252 node->type = type; 4253 4254 return node; 4255 } 4256 4257 static Node * 4258 conv(Node *node) 4259 { 4260 Type *ty = node->type; 4261 4262 assert(ty); 4263 4264 if (ty->kind == TINFER) 4265 return wrap(primitive(TINT), node); 4266 4267 if (ty->kind == TUINFER) 4268 return wrap(primitive(TUINT), node); 4269 4270 return node; 4271 } 4272 4273 4274 static bool 4275 arithtuplereorder(Env *env, Node *expr, int numops) 4276 { 4277 Node *tmp; 4278 4279 (void) env; 4280 4281 if (numops == 2) { 4282 if (expr->lhs->kind != ACOMMA) 4283 return false; 4284 4285 if (expr->rhs->kind != ACOMMA) 4286 return false; 4287 4288 /* (a, b) OP (x, y) ==> (a OP x, b OP y) */ 4289 expr->lhs->kind = expr->kind; 4290 expr->rhs->kind = expr->kind; 4291 expr->kind = ACOMMA; 4292 4293 tmp = expr->lhs->rhs; 4294 expr->lhs->rhs = expr->rhs->lhs; 4295 expr->rhs->lhs = tmp; 4296 4297 return true; 4298 } 4299 4300 if (numops == 1) { 4301 if (expr->lhs->kind != ACOMMA) 4302 return false; 4303 4304 /* OP (a, b) ==> (OP a, OP b) */ 4305 expr->lhs->kind = expr->kind; 4306 4307 tmp = expr->rhs; 4308 expr->rhs = makenode(expr, expr->lhs->rhs); 4309 expr->lhs->rhs = tmp; /* @note some unary nodes may have a rhs? */ 4310 expr->rhs->rhs = tmp; /* @todo make a copy */ 4311 expr->kind = ACOMMA; 4312 4313 return true; 4314 } 4315 4316 return false; 4317 } 4318 4319 static Type * 4320 typecheckdecl(Env *env, Decl *decl) 4321 { 4322 if (decl->kind == DPARAM || decl->kind == DVAR) { 4323 if (!decl->u.content) 4324 return decl->type; 4325 4326 decl->u.content = typecheck(env, decl->u.content); 4327 4328 if (decl->type->kind == TINFER) { 4329 decl->u.content = conv(decl->u.content); 4330 decl->type = decl->u.content->type; 4331 } else { 4332 decl->u.content = wrap(decl->type, decl->u.content); 4333 } 4334 } else if (decl->kind == DFUNCTION) { 4335 if (!decl->u.content) 4336 return decl->type; 4337 4338 assert(decl->contentenv); 4339 if (decl->contentenv->pending) 4340 return decl->type; 4341 4342 decl->u.content = typecheck(env, decl->u.content); 4343 } 4344 4345 return decl->type; 4346 } 4347 4348 static Node * 4349 substitutedispatch(Env *env, Node *expr) 4350 { 4351 #if 0 4352 /* This is wrong (tuple != comma-operator)*/ 4353 assert(expr->u.declref); 4354 assert(expr->type == expr->u.declref->type); 4355 4356 expr->kind = ACOMMA; 4357 expr->type = maketype(&expr->loc, primitive(TTUPLE), expr->lhs->type); 4358 4359 expr->rhs->kind = ADECLREF; 4360 expr->rhs->u.declref = expr->u.declref; 4361 expr->rhs->type = expr->type; 4362 4363 expr->type->u.rtarget = expr->lhs->type; 4364 return expr; 4365 #else 4366 Node *result = makenode(expr, NULL); 4367 result->kind = ADECLREF; 4368 result->u.declref = expr->u.declref; 4369 result->type = expr->type; 4370 4371 /* @fixme delete doesnt work (self is used multiple times) */ 4372 /* deletenode(expr); */ 4373 return result; 4374 #endif 4375 } 4376 4377 static Node * 4378 substitutedispatchcall(Env *env, Node *expr) 4379 { 4380 expr->lhs = substitutedispatch(env, expr->lhs); 4381 4382 return expr; 4383 } 4384 4385 static Node * 4386 selfdispatchcall(Env *env, Node *expr) 4387 { 4388 Node *self, *probe, *insert; 4389 4390 assert(expr && expr->kind == OCALL); 4391 4392 if (expr->lhs->kind != ASELFDISP) 4393 return expr; 4394 4395 self = expr->lhs->lhs; 4396 assert(self); 4397 assert(self->type); 4398 4399 if (self->type->kind == TSTRUCT || self->type->kind == TUNION) { 4400 self = makenode(self, self); 4401 self->kind = OADDR; 4402 self->type = maketype(&self->loc, primitive(TINT), self->type); 4403 } else if (self->type->kind != TPTR) { 4404 error(&self->loc, "expected struct or union or pointer type"); 4405 } else if (self->type->target->kind != TSTRUCT && 4406 self->type->target->kind != TUNION) { 4407 error(&self->loc, "expected pointer to struct or union type"); 4408 } 4409 4410 if (!expr->rhs) { 4411 expr->rhs = self; 4412 return substitutedispatchcall(env, expr); 4413 } 4414 4415 if (expr->rhs->kind != ACOMMA) { 4416 insert = makenode(expr->rhs, self); 4417 insert->kind = ACOMMA; 4418 insert->rhs = expr->rhs; 4419 expr->rhs = insert; 4420 4421 return substitutedispatchcall(env, expr); 4422 } 4423 4424 probe = expr->rhs; 4425 while (probe->lhs && probe->lhs->kind == ACOMMA) 4426 probe = probe->lhs; 4427 4428 insert = makenode(probe, self); 4429 insert->rhs = probe->lhs; 4430 probe->lhs = insert; 4431 4432 return substitutedispatchcall(env, expr); 4433 } 4434 4435 static Node * 4436 resolvepending(Env *env, Node *expr) 4437 { 4438 Decl *decl; 4439 4440 assert(expr->kind == IDENT); 4441 4442 decl = finddeclaration(NULL, env, expr->u.key); 4443 4444 if (!decl) { 4445 error(&expr->loc, "'%s' undeclared", 4446 getstring(idents, expr->u.key)); 4447 4448 return expr; 4449 } 4450 4451 if (decl->kind != DVAR && decl->kind != DFUNCTION) { 4452 error(&expr->loc, "'%s' is not a variable nor a function", 4453 getstring(idents, expr->u.key)); 4454 4455 return expr; 4456 } 4457 4458 expr->kind = ADECLREF; 4459 expr->u.declref = decl; 4460 expr->type = decl->type; 4461 4462 return typecheck(env, expr); 4463 } 4464 4465 static Node * 4466 dispatch(Node *expr, Node *parent) 4467 { 4468 Type *type; 4469 Decl *field; 4470 4471 /* @note might change in future */ 4472 assert(expr->lhs); 4473 type = expr->lhs->type; 4474 assert(type); 4475 4476 /* @todo maybe do implicit dereference */ 4477 if (type->kind == TPTR) { 4478 Node *lhs = makenode(expr->lhs, expr->lhs); 4479 lhs->kind = ADEREF; 4480 lhs->type = type->target; 4481 4482 type = type->target; 4483 expr->lhs = lhs; 4484 } 4485 4486 if (type->kind != TSTRUCT && type->kind != TUNION) { 4487 error(&expr->lhs->loc, "expected struct or union type"); 4488 return expr; 4489 } 4490 4491 /* @note might change in future */ 4492 assert(expr->rhs); 4493 assert(expr->rhs->kind == IDENT); 4494 4495 /* @note improvised for now */ 4496 assert(type->module->contentenv); 4497 field = finddeclinenv(expr->rhs->u.key, type->module->contentenv); 4498 4499 if (!field) { 4500 const char *typekind = type->kind == TSTRUCT ? "struct" : "union"; 4501 const char *modulename = getstring(idents, type->module->key); 4502 const char *fieldname = getstring(idents, expr->rhs->u.key); 4503 error(&expr->rhs->loc, "%s '%s' has no field '%s'", 4504 typekind, modulename, fieldname); 4505 expr->type = primitive(TERRTYPE); 4506 return expr; 4507 } 4508 4509 expr->type = field->type; 4510 expr->u.declref = field; 4511 4512 return expr; 4513 } 4514 4515 static void 4516 forloop(Env *env, Node *expr, Node *header) 4517 { 4518 if (header->kind == AFORSTEP) { 4519 Node *init = header->lhs; 4520 if (init->kind == ADECL) { 4521 Decl *it = init->u.declref; 4522 if (!it->u.content) { 4523 if (!isarithtype(it->type)) { 4524 error(&it->loc, "for loop variable must be initialized"); 4525 return; 4526 } 4527 it->u.content = makenode(header, NULL); 4528 it->u.content->kind = NUMBER; 4529 it->u.content->type = it->type; 4530 it->u.content->u.u = 0; 4531 } 4532 4533 header->lhs = conv(typecheck(env, header->lhs)); 4534 } 4535 4536 /* @todo do proper typechecking */ 4537 header->rhs = wrap(header->lhs->type, typecheck(env, header->rhs)); 4538 header->u.payload = wrap(header->lhs->type, typecheck(env, header->u.payload)); 4539 return; 4540 } 4541 4542 if (header->kind == AFOREACH) { 4543 4544 return; 4545 } 4546 4547 header = expr->u.payload = conv(typecheck(env, header)); 4548 4549 if (isarithtype(header->type)) { 4550 Decl *it; 4551 Node *forstep; 4552 4553 4554 it = makedecl2(&header->loc, env, 4555 getstringkey(&idents, "it", 2), DVAR); 4556 it->type = header->type; 4557 it->u.content = makenode(header, NULL); 4558 it->u.content->kind = NUMBER; 4559 it->u.content->type = header->type; 4560 it->u.content->u.u = 0; 4561 4562 forstep = makenode(header, NULL); 4563 forstep->kind = AFORSTEP; 4564 forstep->type = header->type; 4565 4566 forstep->lhs = makenode(header, NULL); 4567 forstep->lhs->kind = ADECL; 4568 forstep->lhs->u.declref = it; 4569 4570 forstep->rhs = header; 4571 4572 forstep->u.payload = makenode(header, NULL); 4573 forstep->u.payload->kind = NUMBER; 4574 forstep->u.payload->type = header->type; 4575 /* @todo handle negative step when possible 4576 * (i.e. when header is signed and constant) */ 4577 if (isfloattype(header->type)) 4578 forstep->u.payload->u.d = 1.0; 4579 else 4580 forstep->u.payload->u.u = 1; 4581 4582 expr->u.payload = forstep; 4583 return; 4584 } 4585 4586 /* @todo handle other cases (e.g. arrays/strings/lists/iterators) */ 4587 error(&expr->loc, "invalid loop header"); 4588 } 4589 4590 Node *parentnodes[1024]; 4591 int parenttop = 0; 4592 4593 static Node * 4594 typecheck(Env *env, Node *expr) 4595 { 4596 #define return return --parenttop, 4597 4598 Node *lhs = expr->lhs, *rhs = expr->rhs; 4599 4600 parentnodes[parenttop++] = expr; 4601 4602 #define errortype(condition) do { \ 4603 if (condition) { \ 4604 expr->type = primitive(TERRTYPE); \ 4605 return expr; \ 4606 } \ 4607 } while (0) 4608 4609 #define reporton(condition, loc, errormsg) do { \ 4610 if (condition) { \ 4611 error((loc), (errormsg)); \ 4612 expr->type = primitive(TERRTYPE); \ 4613 return expr; \ 4614 } \ 4615 } while (0) 4616 4617 switch (getnumops(expr->kind)) { 4618 case 2: 4619 assert(rhs); 4620 errortype(rhs->type->kind == TERRTYPE); 4621 rhs = typecheck(env, rhs); 4622 /* FALLTHROUGH */ 4623 case 1: 4624 assert(lhs); 4625 errortype(lhs->type->kind == TERRTYPE); 4626 lhs = typecheck(env, lhs); 4627 4628 if (arithtuplereorder(env, expr, getnumops(expr->kind))) 4629 goto joincomma; 4630 } 4631 4632 if (expr->type && expr->type->kind == TERRTYPE) 4633 return expr; 4634 4635 switch (expr->kind) { 4636 case ODISP: 4637 case ASELFDISP: 4638 lhs = typecheck(env, lhs); 4639 expr->lhs = conv(lhs); 4640 4641 if (parenttop > 1) 4642 return dispatch(expr, parentnodes[parenttop - 2]); 4643 4644 return dispatch(expr, NULL); 4645 4646 case OCALL: 4647 reporton(lhs->type->kind == TPTR && lhs->type->target->kind != TFUNCTION, 4648 &expr->loc, "operand is not a pointer to function"); 4649 4650 reporton(lhs->type->kind != TPTR && lhs->type->kind != TFUNCTION, 4651 &expr->loc, "operand is not a function"); 4652 4653 if (lhs->type->kind == TFUNCTION) 4654 expr->type = lhs->type->u.rtarget; 4655 else 4656 expr->type = lhs->type->target->u.rtarget; 4657 4658 expr = selfdispatchcall(env, expr); 4659 expr->rhs = typecheck(env, expr->rhs); 4660 return expr; 4661 4662 case OARRAY: 4663 expr->lhs = conv(lhs); 4664 reporton(lhs->type->kind != TARRAY && lhs->type->kind != TPTR, 4665 &expr->loc, "operand is not an array or pointer"); 4666 4667 expr->rhs = typecheck(env, rhs); 4668 4669 /* @todo handle negative indices when possible (use unsigned) */ 4670 reporton(!isinttype(rhs->type), 4671 &rhs->loc, "array index is not an integer"); 4672 4673 expr->rhs = wrap(primitive(TUSIZE), expr->rhs); 4674 4675 expr->type = lhs->type->target; 4676 return expr; 4677 4678 case OINC: case ODEC: case OSUFINC: case OSUFDEC: 4679 reporton(!islvalue(lhs), 4680 &expr->loc, "operand is not an lvalue"); 4681 4682 expr->lhs = conv(lhs); 4683 expr->type = lhs->type; 4684 return expr; 4685 4686 case ODEREF: 4687 expr->type = lhs->type; 4688 4689 reporton(expr->type->kind != TPTR, 4690 &expr->loc, "operand is not a pointer"); 4691 4692 expr->type = expr->type->target; 4693 return expr; 4694 4695 case OADDR: 4696 reporton(!islvalue(lhs), 4697 &expr->loc, "operand is not an lvalue"); 4698 4699 expr->type = maketype(&expr->loc, primitive(TPTR), lhs->type); 4700 return expr; 4701 4702 case OPLUS: case OMINUS: 4703 /* 4704 reporton(!isarithtype(lhs->type), 4705 &lhs->loc, "expression is not of arithmetic type"); 4706 */ 4707 4708 expr->lhs = conv(lhs); 4709 expr->type = lhs->type; 4710 return expr; 4711 4712 case OBNOT: 4713 reporton(!isintorbooltype(lhs->type), 4714 &lhs->loc, "expression is not of integer type"); 4715 4716 expr->lhs = conv(lhs); 4717 expr->type = lhs->type; 4718 return expr; 4719 4720 case OLNOT: 4721 reporton(!isarithtype(lhs->type), 4722 &lhs->loc, "expression is not of arithmetic type"); 4723 4724 expr->type = primitive(TBOOL); 4725 expr->lhs = conv(lhs); /* cannot be wrap(expr->type, lhs) */ 4726 return expr; 4727 4728 case OCAST: 4729 /* 4730 assert(rhs); 4731 assert(lhs->kind == TYPE); 4732 */ 4733 4734 if (arithtuplereorder(env, expr, 1)) 4735 goto joincomma; 4736 4737 /* expr->type = expr->lhs->type; */ 4738 return expr; 4739 4740 case OMUL: case ODIV: case OMOD: 4741 case OADD: case OSUB: 4742 reporton(!isarithtype(lhs->type) || !isarithtype(rhs->type), 4743 &expr->loc, "expression is not of arithmetic type"); 4744 4745 /* usual arithmetic conversion */ 4746 if (lhs->type->kind < rhs->type->kind) 4747 expr->type = rhs->type; 4748 else 4749 expr->type = lhs->type; 4750 4751 expr->lhs = wrap(expr->type, lhs); 4752 expr->rhs = wrap(expr->type, rhs); 4753 return expr; 4754 4755 case OBAND: case OBOR: case OXOR: 4756 reporton(!isintorbooltype(lhs->type) || !isintorbooltype(rhs->type), 4757 &expr->loc, "expression is not of integer type"); 4758 4759 /* usual arithmetic conversion */ 4760 if (lhs->type->kind < rhs->type->kind) 4761 expr->type = rhs->type; 4762 else 4763 expr->type = lhs->type; 4764 4765 expr->lhs = wrap(expr->type, lhs); 4766 expr->rhs = wrap(expr->type, rhs); 4767 return expr; 4768 4769 case OLSH: case ORSH: case OARSH: 4770 reporton(!isinttype(lhs->type) || !isinttype(rhs->type), 4771 &expr->loc, "expression is not of integer type"); 4772 4773 expr->lhs = conv(lhs); 4774 expr->rhs = wrap(primitive(TINT), rhs); 4775 expr->type = lhs->type; 4776 return expr; 4777 4778 case OEQU: case ONEQ: 4779 case OLET: case OLEQ: 4780 case OGRT: case OGEQ: 4781 reporton(!isarithtype(lhs->type) || !isarithtype(rhs->type), 4782 &expr->loc, "expression is not of arithmetic type"); 4783 4784 expr->lhs = conv(lhs); 4785 expr->rhs = conv(rhs); 4786 expr->type = primitive(TBOOL); 4787 return expr; 4788 4789 case OLAND: case OLOR: 4790 reporton(!isarithtype(lhs->type) || !isarithtype(rhs->type), 4791 &expr->loc, "expression is not of arithmetic type"); 4792 4793 expr->type = primitive(TBOOL); 4794 expr->lhs = wrap(expr->type, lhs); 4795 expr->rhs = wrap(expr->type, rhs); 4796 return expr; 4797 4798 case OMULA: case ODIVA: case OMODA: 4799 case OADDA: case OSUBA: 4800 reporton(!isarithtype(lhs->type) || !isarithtype(rhs->type), 4801 &expr->loc, "expression is not of arithmetic type"); 4802 goto joinassign; 4803 4804 case OLSHA: case ORSHA: case OARSHA: 4805 case OANDA: 4806 case OORA: case OXORA: 4807 reporton(!isinttype(lhs->type) || !isinttype(rhs->type), 4808 &expr->loc, "expression is not of integer type"); 4809 /* FALLTHROUGH */ 4810 4811 case OASS: 4812 joinassign: 4813 reporton(!islvalue(lhs), 4814 &expr->loc, "left-hand-side is not an lvalue"); 4815 4816 expr->lhs = conv(lhs); 4817 expr->type = lhs->type; 4818 expr->rhs = wrap(expr->type, rhs); 4819 return expr; 4820 4821 case KIF: 4822 case KWHILE: 4823 case KUNTIL: 4824 assert(expr->u.payload); 4825 expr->u.payload = typecheck(env, expr->u.payload); 4826 expr->u.payload = wrap(primitive(TBOOL), expr->u.payload); 4827 4828 if (lhs) 4829 expr->lhs = typecheck(env, lhs); 4830 4831 if (rhs) 4832 expr->rhs = typecheck(env, rhs); 4833 4834 /* @todo find a way how we do type-checking for the 4835 * last expression in a statement-list, which 4836 * might be needed by the enclosed statement-list 4837 */ 4838 4839 expr->type = primitive(TVOID); 4840 return expr; 4841 4842 case KFOR: 4843 assert(expr->u.payload); 4844 forloop(env, expr, expr->u.payload); 4845 4846 if (lhs) 4847 expr->lhs = typecheck(env, lhs); 4848 4849 if (rhs) 4850 expr->rhs = typecheck(env, rhs); 4851 4852 /* @todo infer type of the for-loop like in the case above. */ 4853 4854 expr->type = primitive(TVOID); 4855 return expr; 4856 4857 case AENV: 4858 case ASCOPE: 4859 assert(lhs); 4860 assert(expr->u.env); 4861 4862 expr->lhs = typecheck(expr->u.env, lhs); 4863 return expr; 4864 4865 case ASTMT: 4866 rhs = expr; 4867 advancestmt: 4868 lhs = typecheck(env, lhs); 4869 rhs->lhs = lhs; 4870 4871 if (rhs->rhs) { 4872 assert(rhs->rhs->kind == ASTMT); 4873 rhs = rhs->rhs, lhs = rhs->lhs; 4874 goto advancestmt; 4875 } 4876 return expr; 4877 4878 case ADECL: 4879 expr->type = typecheckdecl(env, expr->u.declref); 4880 return expr; 4881 4882 case ADECLREF: 4883 /* @note propagate type changes from ADECL to ADECLREF */ 4884 expr->type = expr->u.declref->type; 4885 return expr; 4886 4887 case AADDR: 4888 case ADEREF: 4889 assert(lhs); 4890 lhs = typecheck(env, lhs); 4891 4892 expr->lhs = conv(lhs); 4893 return expr; 4894 4895 case ACOMPOUND: 4896 assert(lhs); 4897 assert(rhs); 4898 4899 expr->lhs = typecheck(env, lhs); 4900 expr->type = lhs->type; 4901 expr->rhs = typecheck(env, rhs); 4902 return expr; 4903 4904 case AFIELDINIT: 4905 assert(expr->rhs); 4906 expr->rhs = typecheck(env, rhs); 4907 return expr; 4908 4909 case IDENT: 4910 return resolvepending(env, expr); 4911 4912 joincomma: 4913 lhs = expr->lhs; 4914 rhs = expr->rhs; 4915 /* FALLTHROUGH */ 4916 case ACOMMA: 4917 assert(lhs); 4918 assert(rhs); 4919 4920 /* @todo make sure that typechecking is done 4921 * correctly, since comma might be re- 4922 * ordered: 4923 * - check that maketype is NOT called 4924 * multiple times and/or discarded on 4925 * the same node. 4926 * - check wether the resulting type 4927 * does account for nesting on rhs */ 4928 errortype(lhs->type->kind == TERRTYPE); 4929 errortype(rhs->type->kind == TERRTYPE); 4930 4931 lhs = typecheck(env, lhs); 4932 rhs = typecheck(env, rhs); 4933 4934 /* @note converting nodes may be uneccessary */ 4935 expr->lhs = conv(lhs); 4936 expr->rhs = conv(rhs); 4937 4938 expr->type = maketype(&expr->loc, primitive(TTUPLE), lhs->type); 4939 expr->type->u.rtarget = rhs->type; 4940 return expr; 4941 4942 case KBITCAST: 4943 assert(lhs); 4944 assert(rhs); 4945 4946 expr->lhs = lhs = typecheck(env, lhs); 4947 4948 errortype(lhs->type->kind == TERRTYPE); 4949 errortype(rhs->type->kind == TERRTYPE); 4950 reporton(rhs->kind != TYPE, &rhs->loc, "expected type"); 4951 4952 expr->type = rhs->type; 4953 return expr; 4954 4955 case KSIZEOF: 4956 case KALIGNOF: 4957 case KLENGTHOF: 4958 assert(lhs); 4959 4960 expr->lhs = lhs = typecheck(env, lhs); 4961 errortype(lhs->type->kind == TERRTYPE); 4962 4963 expr->type = primitive(TUSIZE); 4964 return expr; 4965 4966 case KRETURN: 4967 rhs = expr->rhs; 4968 4969 if (rhs) { 4970 expr->rhs = rhs = typecheck(env, rhs); 4971 errortype(rhs->type->kind == TERRTYPE); 4972 } 4973 4974 do { 4975 Env *funcenv = getfuncenv(env); 4976 Type *functype; 4977 4978 reporton(!funcenv, 4979 &expr->loc, "return statement is not inside a function"); 4980 4981 assert(funcenv->envdecl); 4982 assert(funcenv->envdecl->type); 4983 4984 functype = funcenv->envdecl->type; 4985 4986 assert(functype->kind == TFUNCTION); 4987 assert(functype->u.rtarget); 4988 4989 expr->type = functype->u.rtarget; 4990 } while (0); 4991 4992 reporton(expr->type->kind == TVOID && 4993 rhs && rhs->type->kind != TVOID, 4994 &expr->loc, "expected no return value"); 4995 4996 reporton(expr->type->kind != TVOID && 4997 (!rhs || rhs->type->kind == TVOID), 4998 &expr->loc, "expected return value"); 4999 5000 if (rhs) 5001 expr->lhs = wrap(expr->type, rhs); 5002 5003 return expr; 5004 5005 default: 5006 return expr; 5007 } 5008 5009 #undef errortype 5010 #undef reporton 5011 #undef return 5012 } 5013 5014 static Node * 5015 foldexpr(Env *env, Node *expr); 5016 5017 static Node * 5018 folddeclaration(Env *env, Node *expr) 5019 { 5020 Decl *decl = expr->u.declref; 5021 5022 assert(decl); 5023 5024 if (decl->kind == DFUNCTION) { 5025 if (decl->u.content) 5026 /* @todo make sure the correct env is used */ 5027 decl->u.content = foldexpr(env, decl->u.content); 5028 5029 } else if (decl->kind == DPARAM || decl->kind == DVAR) { 5030 5031 /* @todo remove condition. it is only for testing structs. 5032 * content may not be NULL otherwise (needs validation) */ 5033 if (decl->u.content) 5034 decl->u.content = foldexpr(env, decl->u.content); 5035 } 5036 5037 return expr; 5038 } 5039 5040 static Node * 5041 foldexpr(Env *env, Node *expr) 5042 { 5043 Node *lhs = expr->lhs, *rhs = expr->rhs; 5044 Type *ty = expr->type; 5045 5046 5047 #define evalbinary(op) do { \ 5048 expr->kind = NUMBER; \ 5049 if (isfloattype(ty)) \ 5050 expr->u.d = maskfloat(ty->size, \ 5051 maskfloat(ty->size, lhs->u.d) op \ 5052 maskfloat(ty->size, rhs->u.d) \ 5053 ); \ 5054 else if (isintorbooltype(ty)) \ 5055 expr->u.u = maskint(ty->size, \ 5056 maskint(ty->size, lhs->u.u) op \ 5057 maskint(ty->size, rhs->u.u) \ 5058 ); \ 5059 deletenode(lhs); \ 5060 deletenode(rhs); \ 5061 } while (0) 5062 5063 #define isvalue(expr, value) (expr->kind == NUMBER && \ 5064 ((expr->u.u == value && isintorbooltype(ty)) || \ 5065 (expr->u.d == value && isarithtype(ty)))) 5066 5067 /* @todo maybe modify getnumops() in such a way, that it 5068 * will behave properly for non-operator nodes too */ 5069 switch (getnumops(expr->kind)) { 5070 case 2: 5071 rhs = foldexpr(env, rhs); 5072 /* FALLTHROUGH */ 5073 case 1: 5074 lhs = foldexpr(env, lhs); 5075 } 5076 5077 switch ((int) expr->kind) { 5078 case OADD: case OSUB: 5079 if (lhs->kind == NUMBER && rhs->kind == NUMBER) { 5080 if (expr->kind == OADD) evalbinary(+); 5081 else evalbinary(-); 5082 } else if (isvalue(lhs, 0)) { 5083 if (expr->kind == OADD) { 5084 *expr = *rhs; 5085 deletenode(lhs); 5086 deletenode(rhs); 5087 } else { 5088 expr->kind = OMINUS; 5089 expr->lhs = rhs; 5090 deletenode(lhs); 5091 } 5092 } else if (isvalue(rhs, 0)) { 5093 *expr = *lhs; 5094 deletenode(lhs); deletenode(rhs); 5095 } 5096 5097 return expr; 5098 5099 case OMUL: case ODIV: case OMOD: 5100 if (lhs->kind == NUMBER && rhs->kind == NUMBER) { 5101 if (expr->kind == OMUL) { 5102 evalbinary(*); 5103 } else { 5104 if (rhs->u.u == 0 && isintorbooltype(ty)) { 5105 error( 5106 &expr->loc, 5107 "division by zero" 5108 ); 5109 } else if (expr->kind == ODIV) { 5110 evalbinary(/); 5111 } else { 5112 evalbinary(/); /* @todo implement modulus for float-types */ 5113 } 5114 } 5115 } else if (isvalue(lhs, 0)) { 5116 *expr = *lhs; 5117 deletenode(lhs); 5118 deletenode(rhs); 5119 } else if (expr->kind == OMUL && isvalue(rhs, 0)) { 5120 *expr = *rhs; 5121 deletenode(lhs); 5122 deletenode(rhs); 5123 } else if (isvalue(rhs, 0)) { 5124 if (rhs->u.u == 0 && isintorbooltype(ty)) 5125 error(&expr->loc, "division by zero"); 5126 *expr = *rhs; 5127 deletenode(lhs); 5128 deletenode(rhs); 5129 } else if (isvalue(lhs, 1)) { 5130 *expr = *rhs; 5131 deletenode(lhs); 5132 deletenode(rhs); 5133 } else if (expr->kind == OMUL && isvalue(rhs, 1)) { 5134 *expr = *lhs; 5135 deletenode(lhs); 5136 deletenode(rhs); 5137 } 5138 5139 return expr; 5140 5141 case OPLUS: 5142 *expr = *lhs; 5143 5144 deletenode(lhs); 5145 return expr; 5146 5147 case OMINUS: 5148 if (lhs->kind == NUMBER) { 5149 if (isfloattype(ty)) { 5150 expr->kind = NUMBER; 5151 expr->u.d = maskfloat(ty->size, -lhs->u.d); 5152 deletenode(lhs); 5153 } else if (isintorbooltype(ty)) { 5154 expr->kind = NUMBER; 5155 expr->u.u = maskint(ty->size, -lhs->u.u); 5156 deletenode(lhs); 5157 } 5158 } else if (lhs->kind == OMINUS && lhs->lhs) { 5159 *expr = *lhs->lhs; 5160 deletenode(lhs); 5161 } 5162 5163 return expr; 5164 5165 case OBAND: case OBOR: case OXOR: 5166 if (lhs->kind == NUMBER && rhs->kind == NUMBER) { 5167 assert(isintorbooltype(lhs->type)); 5168 assert(isintorbooltype(rhs->type)); 5169 lhs->u.u = maskint(ty->size, lhs->u.u); 5170 rhs->u.u = maskint(ty->size, rhs->u.u); 5171 if (expr->kind == OBAND) 5172 expr->u.u = lhs->u.u & rhs->u.u; 5173 else if (expr->kind == OBOR) 5174 expr->u.u = lhs->u.u | rhs->u.u; 5175 else 5176 expr->u.u = lhs->u.u ^ rhs->u.u; 5177 expr->kind = NUMBER; 5178 expr->u.u = maskint(ty->size, expr->u.u); 5179 } 5180 5181 return expr; 5182 5183 case ASCOPE: 5184 assert(expr->lhs); 5185 assert(expr->u.env); 5186 5187 expr->lhs = foldexpr(expr->u.env, expr->lhs); 5188 return expr; 5189 5190 case ASTMT: 5191 rhs = expr; 5192 advancestmt: 5193 lhs = foldexpr(env, lhs); 5194 rhs->lhs = lhs; 5195 5196 if (rhs->rhs) { 5197 assert(rhs->rhs->kind == ASTMT); 5198 rhs = rhs->rhs, lhs = rhs->lhs; 5199 goto advancestmt; 5200 } 5201 5202 return expr; 5203 5204 case ACOMMA: 5205 expr->lhs = foldexpr(env, lhs); 5206 expr->rhs = foldexpr(env, rhs); 5207 return expr; 5208 5209 case KSIZEOF: 5210 case KALIGNOF: 5211 case KLENGTHOF: 5212 assert(lhs); 5213 5214 expr->lhs = NULL; 5215 if (expr->kind == KSIZEOF) { 5216 expr->u.u = lhs->type->size; 5217 5218 } else if (expr->kind == KALIGNOF) { 5219 expr->u.u = lhs->type->align; 5220 5221 } else /* if (expr->kind == KLENGTHOF) */ { 5222 5223 /* @todo add case for slice */ 5224 if (lhs->type->kind == TARRAY) 5225 expr->u.u = lhs->type->u.array.length; 5226 else if (lhs->type->kind == TPTR) { 5227 expr->u.u = 1; 5228 } else { 5229 expr->u.u = 0; 5230 } 5231 } 5232 5233 deletenode(lhs); 5234 /* @todo delete type */ 5235 expr->type = prim + TUSIZE; 5236 expr->kind = NUMBER; 5237 return expr; 5238 5239 case ACONV: 5240 /* @todo implement this properly! */ 5241 lhs = foldexpr(env, lhs); 5242 if (lhs->type->kind == expr->type->kind) 5243 *expr = *lhs, deletenode(lhs); 5244 5245 return expr; 5246 5247 case ADECL: 5248 return folddeclaration(env, expr); 5249 5250 case TYPE: 5251 error(&expr->loc, "exptected expression, not type"); 5252 /* FALLTHROUGH */ 5253 5254 default: 5255 return expr; 5256 } 5257 } 5258 5259 5260 5261 // }}} 5262 5263 // @section data-flow analysis {{{ 5264 5265 /* 5266 In order to do DFA, we divide the code of a scope into sections. 5267 For each section there will be a DF-Conduct associated with it. 5268 5269 */ 5270 5271 Block blockbuf[1024*8]; 5272 int blocktop; 5273 5274 Conduct conductbuf[1024*8]; 5275 int conducttop; 5276 5277 Gist gistbuf[1024*8]; 5278 int gisttop; 5279 5280 static Block * 5281 makeblock(BlockKind kind, Env *env) 5282 { 5283 Block *block = unpool(blockbuf, blocktop); 5284 5285 block->kind = kind; 5286 block->env = env; 5287 5288 return block; 5289 } 5290 5291 static Conduct * 5292 makeconduct(ConductKind kind, Node *label) 5293 { 5294 Conduct *conduct = unpool(conductbuf, conducttop); 5295 5296 conduct->kind = kind; 5297 conduct->label = label; 5298 5299 return conduct; 5300 } 5301 5302 static void 5303 transfergists(Conduct *source, Conduct *dest); 5304 5305 static void 5306 appendconduct(Block *parent, ConductKind kind, Node *label) 5307 { 5308 Conduct *conduct = makeconduct(kind, label); 5309 5310 if (!parent) 5311 return; 5312 5313 conduct->parent = parent; 5314 5315 listappend(parent, conduct); 5316 5317 if (conduct->prev) 5318 transfergists(conduct->prev, conduct); 5319 } 5320 5321 static void 5322 appendblock(Conduct *parent, BlockKind kind, Env *env) 5323 { 5324 Block *block = makeblock(kind, env); 5325 5326 appendconduct(block, CSCOPE, NULL); 5327 5328 if (!parent) 5329 return; 5330 5331 block->parent = parent; 5332 5333 listappend(parent, block); 5334 5335 transfergists(parent, block->tail); 5336 } 5337 5338 static Gist * 5339 makegist(Decl *decl, Node *where, bool init) 5340 { 5341 Gist *gist = unpool(gistbuf, gisttop); 5342 5343 gist->decl = decl; 5344 gist->where = where; 5345 gist->init = init; 5346 5347 return gist; 5348 } 5349 5350 static void 5351 appendgist(Conduct *conduct, Gist *info) 5352 { 5353 info->parent = conduct; 5354 5355 listappendex(conduct, info, gists.head, gists.tail, prev, next); 5356 } 5357 5358 static void 5359 transfergists(Conduct *source, Conduct *dest) 5360 { 5361 Gist *info; 5362 5363 for (info = source->gists.head; info; info = info->next) { 5364 Gist *copy = makegist(NULL, NULL, false); 5365 5366 *copy = *info; 5367 5368 appendgist(dest, copy); 5369 } 5370 } 5371 5372 static Gist * 5373 getgist(Conduct *conduct, Decl *decl) 5374 { 5375 Gist *probe; 5376 assert(conduct); 5377 5378 for (probe = conduct->gists.head; probe; probe = probe->next) { 5379 if (probe->decl == decl) 5380 return probe; 5381 } 5382 5383 return NULL; 5384 } 5385 5386 static void 5387 gistread(Conduct *conduct, Node *node) 5388 { 5389 const char *name; 5390 Decl *decl; 5391 Gist *info; 5392 5393 if (!node || (node->kind != ADECLREF && node->kind != ADECL)) 5394 return; 5395 5396 decl = node->u.declref; 5397 5398 /* @note additional checks require that this moves 5399 * somewhere else. */ 5400 if ( decl->kind == DPARAM || 5401 (decl->kind == DVAR && 5402 decl->parentenv && 5403 decl->parentenv->kind == STOPLEVEL)) 5404 return; 5405 5406 name = getstring(idents, decl->key); 5407 info = getgist(conduct, decl); 5408 5409 if (info) { 5410 Node *where = info->where; 5411 5412 if (info->init) 5413 return; 5414 5415 assert(where); 5416 error(&node->loc, "use of un-initialized '%s'.", name); 5417 /* @todo change to notice or similiar, 5418 * instead of warn */ 5419 warn(&where->loc, "last use of '%s' was here.", name); 5420 } else { 5421 error(&node->loc, "use of un-initialized '%s'.", name); 5422 } 5423 } 5424 5425 static void 5426 gistwrite(Conduct *conduct, Node *node, bool init) 5427 { 5428 Decl *decl; 5429 Gist *info; 5430 5431 if (!node || (node->kind != ADECLREF && node->kind != ADECL)) 5432 return; 5433 5434 decl = node->u.declref; 5435 5436 info = getgist(conduct, decl); 5437 if (!info) { 5438 info = makegist(decl, node, init); 5439 appendgist(conduct, info); 5440 return; 5441 } 5442 5443 info->init = init; 5444 info->where = node; 5445 } 5446 5447 static void 5448 fetchblocks(Block *block, Node *expr); 5449 5450 static void 5451 fetchscoped(Conduct *conduct, Node *expr, BlockKind kind) 5452 { 5453 if (expr && expr->kind == ASCOPE) { 5454 appendblock(conduct, kind, expr->u.env); 5455 fetchblocks(conduct->tail, expr->lhs); 5456 5457 } else if (expr) { 5458 assert(conduct->parent); 5459 assert(conduct->parent->env); 5460 5461 appendblock(conduct, kind, conduct->parent->env); 5462 fetchblocks(conduct->tail, expr); 5463 } 5464 } 5465 5466 static void 5467 fetchblocks(Block *block, Node *expr) 5468 { 5469 Node *lhs, *rhs; 5470 5471 assert(expr); 5472 assert(block); 5473 assert(block->tail); 5474 5475 lhs = expr->lhs; 5476 rhs = expr->rhs; 5477 5478 switch (expr->kind) { 5479 /* unary read */ 5480 case ODEREF: 5481 case OPLUS: case OMINUS: 5482 case OBNOT: 5483 case OLNOT: 5484 case OCAST: 5485 fetchblocks(block, lhs); 5486 gistread(block->tail, lhs); 5487 return; 5488 5489 /* unary read/write */ 5490 case OINC: case ODEC: 5491 case OSUFINC: case OSUFDEC: 5492 fetchblocks(block, lhs); 5493 gistread(block->tail, lhs); 5494 gistwrite(block->tail, lhs, true); 5495 return; 5496 5497 /* binary read */ 5498 case OMUL: case ODIV: case OMOD: 5499 case OADD: case OSUB: 5500 case OBAND: case OBOR: case OXOR: 5501 case OLSH: case ORSH: case OARSH: 5502 case OEQU: case ONEQ: 5503 case OLET: case OLEQ: 5504 case OGRT: case OGEQ: 5505 case OLAND: case OLOR: 5506 fetchblocks(block, lhs); 5507 gistread(block->tail, lhs); 5508 5509 fetchblocks(block, rhs); 5510 gistread(block->tail, rhs); 5511 return; 5512 5513 5514 /* binary write */ 5515 case OASS: 5516 fetchblocks(block, rhs); 5517 gistread(block->tail, rhs); 5518 5519 fetchblocks(block, lhs); 5520 gistwrite(block->tail, lhs, true); 5521 return; 5522 5523 /* binary read/write */ 5524 case OMULA: case ODIVA: case OMODA: 5525 case OADDA: case OSUBA: 5526 case OLSHA: case ORSHA: case OARSHA: 5527 case OANDA: 5528 case OORA: case OXORA: 5529 fetchblocks(block, rhs); 5530 gistread(block->tail, rhs); 5531 5532 fetchblocks(block, lhs); 5533 gistread(block->tail, lhs); 5534 gistwrite(block->tail, lhs, true); 5535 return; 5536 5537 case ASTMT: 5538 advancestmt: 5539 assert(lhs); 5540 5541 fetchblocks(block, lhs); 5542 5543 if (expr->rhs) { 5544 assert(expr->rhs->kind == ASTMT); 5545 expr = expr->rhs, lhs = expr->lhs; 5546 goto advancestmt; 5547 } 5548 return; 5549 5550 case ADECL: 5551 assert(expr->u.declref); 5552 lhs = expr->u.declref->u.content; 5553 5554 if (expr->u.declref->kind == DFUNCTION) { 5555 fetchscoped(block->tail, lhs, BFUNCTION); 5556 appendconduct(block, CSCOPE, NULL); 5557 } else if (lhs) { 5558 appendblock(block->tail, BSCOPE, expr->u.env); 5559 fetchblocks(block->tail->tail, lhs); 5560 appendconduct(block, CSCOPE, NULL); 5561 } 5562 5563 gistwrite(block->tail, expr, !!lhs); 5564 return; 5565 5566 case ASCOPE: 5567 assert(lhs); 5568 5569 appendblock(block->tail, BSCOPE, expr->u.env); 5570 fetchblocks(block->tail->tail, lhs); 5571 appendconduct(block, CSCOPE, NULL); 5572 return; 5573 5574 case ACOMMA: 5575 assert(lhs); 5576 assert(rhs); 5577 5578 /* @note is this correct? */ 5579 fetchblocks(block, lhs); 5580 fetchblocks(block, rhs); 5581 return; 5582 5583 case KIF: 5584 assert(lhs); 5585 assert(expr->u.payload); 5586 5587 fetchscoped(block->tail, lhs, BIF); 5588 if (rhs) 5589 fetchscoped(block->tail, rhs, BELSE); 5590 5591 appendconduct(block, CSCOPE, NULL); 5592 return; 5593 5594 case KDO: 5595 return; 5596 5597 case KLOOP: 5598 return; 5599 5600 case ALOOPUNTIL: 5601 return; 5602 5603 case KBREAK: 5604 block->tail->doesbreak = true; 5605 goto joinctrltransfer; 5606 5607 case KCONTINUE: 5608 block->tail->doescontinue = true; 5609 goto joinctrltransfer; 5610 5611 case KRETURN: 5612 block->tail->doesreturn = true; 5613 goto joinctrltransfer; 5614 5615 case KGOTO: 5616 block->tail->doesjump = true; 5617 joinctrltransfer: 5618 appendconduct(block, CUNREACH, NULL); 5619 return; 5620 5621 default: 5622 case OADDR: 5623 return; 5624 } 5625 } 5626 5627 #if 0 5628 static void 5629 debugprintconduct(Conduct *conduct, int indent); 5630 5631 static void 5632 debugprintblock(Block *block, int indent) 5633 { 5634 Block *curr; 5635 assert(block); 5636 5637 for (curr = block; curr; curr = curr->next) { 5638 int i; 5639 5640 for (i = 0; i < indent; ++i) { 5641 printf("\t"); 5642 } 5643 5644 switch (curr->kind) { 5645 case BTOPLEVEL: printf("\x1b[31mblock<toplevel>\x1b[0m\n"); break; 5646 case BFUNCTION: printf("\x1b[31mblock<function>\x1b[0m\n"); break; 5647 case BSCOPE: printf("\x1b[31mblock<scope>\x1b[0m\n"); break; 5648 case BIF: printf("\x1b[31mblock<if>\x1b[0m\n"); break; 5649 case BLOOP: printf("\x1b[31mblock<loop>\x1b[0m\n"); break; 5650 case BWHILELOOP: printf("\x1b[31mblock<while-loop>\x1b[0m\n"); break; 5651 case BLOOPUNTIL: printf("\x1b[31mblock<loop-until>\x1b[0m\n"); break; 5652 case BFORLOOP: printf("\x1b[31mblock<for-loop>\x1b[0m\n"); break; 5653 case BELSE: printf("\x1b[31mblock<else>\x1b[0m\n"); break; 5654 } 5655 5656 if (curr->head) 5657 debugprintconduct(curr->head, indent); 5658 } 5659 } 5660 5661 static void 5662 debugprintconduct(Conduct *conduct, int indent) 5663 { 5664 Conduct *curr; 5665 assert(conduct); 5666 5667 for (curr = conduct; curr; curr = curr->next) { 5668 int i; 5669 5670 for (i = 0; i < indent; ++i) { 5671 printf("\t"); 5672 } 5673 5674 switch (curr->kind) { 5675 case CUNREACH: printf("\x1b[34mconduct<unreach>\x1b[0m\n"); break; 5676 case CSCOPE: printf("\x1b[34mconduct<scope>\x1b[0m\n"); break; 5677 case CLABEL: printf("\x1b[34mconduct<label>\x1b[0m\n"); break; 5678 case CBLOCK: 5679 break; 5680 } 5681 5682 if (curr->head) 5683 debugprintblock(curr->head, indent + 1); 5684 } 5685 } 5686 #else 5687 static void 5688 debugprintblock(Block *block, int indent) 5689 { 5690 (void) block; 5691 (void) indent; 5692 } 5693 #endif 5694 5695 static void 5696 dataflow(Block *block, Node *expr) 5697 { 5698 assert(expr); 5699 5700 fetchblocks(block, expr); 5701 5702 debugprintblock(block, 0); 5703 } 5704 5705 5706 5707 /* @section data-flow analysis version 2 */ 5708 5709 #if 0 5710 5711 static void 5712 fetchsections(Analysis *analysis, Node *expr) 5713 { 5714 Node *lhs, *rhs; 5715 5716 nextnode: 5717 switch (expr->kind) { 5718 default: 5719 break; 5720 } 5721 } 5722 5723 static void 5724 dataflow2(Analysis *analysis, Node *expr) 5725 { 5726 assert(expr); 5727 5728 fetchsections(analysis, expr); 5729 } 5730 5731 #endif 5732 5733 5734 5735 // }}} 5736 5737 5738 // @section extract nested functions {{{ 5739 5740 Node *extracted[1024 * 4]; 5741 int extractedtop = 0; 5742 5743 static bool 5744 isnestedfunction(Env *startenv) 5745 { 5746 Env *env; 5747 int n = 0; 5748 5749 for (env = startenv; env; env = env->below) { 5750 if (env->kind == SFUNCTION) 5751 ++n; 5752 } 5753 5754 return n > 1; 5755 } 5756 5757 static void 5758 extractnfs(Env *env, Node *expr); 5759 5760 static void 5761 substituenfs(Env *env, Node *expr) 5762 { 5763 Decl *decl = expr->u.declref; 5764 Node *enlist = NULL; 5765 5766 assert(decl); 5767 5768 if (decl->u.content) { 5769 env = decl->contentenv ? decl->contentenv : env; 5770 extractnfs(env, decl->u.content); 5771 } 5772 5773 if (decl->kind == DFUNCTION && isnestedfunction(decl->contentenv)) { 5774 enlist = makenode(expr, NULL); 5775 expr->kind = ADECLREF; 5776 5777 assert(extractedtop < lengthof(extracted)); 5778 extracted[extractedtop++] = enlist; 5779 } 5780 } 5781 5782 static void 5783 extractnfs(Env *env, Node *expr) 5784 { 5785 advance: 5786 assert(expr); 5787 5788 if (isoperator(expr->kind)) { 5789 switch (getnumops(expr->kind)) { 5790 case 3: 5791 assert(expr->u.payload); 5792 extractnfs(env, expr->u.payload); 5793 /* FALLTHROUGH */ 5794 case 2: 5795 assert(expr->rhs); 5796 extractnfs(env, expr->rhs); 5797 /* FALLTHROUGH */ 5798 case 1: 5799 assert(expr->lhs); 5800 extractnfs(env, expr->lhs); 5801 } 5802 return; 5803 } 5804 5805 switch (expr->kind) { 5806 case KRETURN: 5807 case KIF: 5808 case KCASE: 5809 case KOF: 5810 case KDO: 5811 case KFOR: 5812 case KLOOP: 5813 case KWHILE: 5814 case KUNTIL: 5815 case AFORSTEP: 5816 case AFOREACH: 5817 case ALOOPUNTIL: 5818 if (expr->u.payload) 5819 extractnfs(env, expr->u.payload); 5820 if (expr->lhs) 5821 extractnfs(env, expr->lhs); 5822 if (expr->rhs) 5823 extractnfs(env, expr->rhs); 5824 break; 5825 case ADEREF: 5826 case ACONV: 5827 case ASELFDISP: 5828 assert(expr->lhs); 5829 extractnfs(env, expr->lhs); 5830 break; 5831 case ACOMMA: 5832 assert(expr->lhs); 5833 assert(expr->rhs); 5834 extractnfs(env, expr->lhs); 5835 extractnfs(env, expr->rhs); 5836 break; 5837 case ASTMT: 5838 assert(expr->lhs); 5839 extractnfs(env, expr->lhs); 5840 if (expr->rhs) { 5841 expr = expr->rhs; 5842 goto advance; 5843 } 5844 break; 5845 case ADECL: 5846 substituenfs(env, expr); 5847 break; 5848 case AENV: 5849 case ASCOPE: 5850 assert(expr->lhs); 5851 assert(expr->u.env); 5852 extractnfs(expr->u.env, expr->lhs); 5853 break; 5854 case TYPE: /* @note is this correct? */ 5855 case CHAR: 5856 case NUMBER: 5857 case STRING: 5858 case ADECLREF: 5859 case IDENT: /* @note is this correct? */ 5860 break; 5861 5862 case ACOMPOUND: 5863 /* @todo extract within type (lhs)? */ 5864 assert(expr->rhs); 5865 extractnfs(env, expr->lhs); 5866 break; 5867 5868 case AFIELDINIT: 5869 assert(expr->rhs); 5870 extractnfs(env, expr->rhs); 5871 break; 5872 5873 case KSTRUCT: 5874 case KUNION: 5875 assert(expr->rhs); 5876 extractnfs(env, expr->rhs); 5877 break; 5878 5879 case KBREAK: 5880 case KCONTINUE: 5881 case KGOTO: 5882 break; 5883 5884 case KSIZEOF: 5885 case KALIGNOF: 5886 /* @todo check for nested functions and report error */ 5887 break; 5888 5889 default: 5890 error(&expr->loc, "internal error: unknown expression kind" 5891 " (%s).", nodestrings[expr->kind]); 5892 break; 5893 } 5894 } 5895 5896 static Node * 5897 extractnestedfunctions(Env *env, Node *expr) 5898 { 5899 extractedtop = 0; 5900 5901 extractnfs(env, expr); 5902 5903 assert(extractedtop < lengthof(extracted)); 5904 extracted[extractedtop++] = expr; 5905 return expr; 5906 } 5907 5908 // }}} 5909 5910 // @section c code generation {{{ 5911 5912 typedef struct CodeGen CodeGen; 5913 5914 struct CodeGen { 5915 FILE *out; 5916 5917 Env *env; 5918 int indent, commacount; 5919 bool needsvalue, hasclause; 5920 const char *valuename; 5921 }; 5922 5923 static void 5924 codegen(CodeGen *cg, Node *expr); 5925 5926 static void 5927 cgindent(CodeGen *cg) 5928 { 5929 int i; 5930 5931 for (i = 0; i < cg->indent; ++i) { 5932 fprintf(cg->out, "\t"); 5933 } 5934 } 5935 5936 static void 5937 cgprintf(CodeGen *cg, const char *fmt, ...) 5938 { 5939 va_list ap; 5940 5941 (void) cg; 5942 va_start(ap, fmt); 5943 vfprintf(cg->out, fmt, ap); 5944 va_end(ap); 5945 } 5946 5947 static void 5948 cginit(CodeGen *cg, Env *toplevel, FILE *out) 5949 { 5950 cg->out = out; 5951 cg->env = toplevel; 5952 cg->indent = 0; 5953 cg->commacount = 0; 5954 cg->needsvalue = false; 5955 cg->hasclause = false; 5956 cg->valuename = NULL; 5957 5958 assert(cg->out); 5959 assert(cg->env); 5960 5961 cgprintf(cg, "#include <assert.h>\n"); 5962 cgprintf(cg, "#include <stdarg.h>\n"); 5963 cgprintf(cg, "#include <stdbool.h>\n"); 5964 cgprintf(cg, "#include <stdint.h>\n"); 5965 cgprintf(cg, "#include <stdio.h>\n"); 5966 cgprintf(cg, "#include <stdlib.h>\n"); 5967 cgprintf(cg, "#include <string.h>\n"); 5968 5969 cgprintf(cg, "typedef int16_t s16;\n"); 5970 cgprintf(cg, "typedef uint16_t u16;\n"); 5971 cgprintf(cg, "typedef unsigned int uint;\n"); 5972 cgprintf(cg, "typedef int64_t s64;\n"); 5973 cgprintf(cg, "typedef uint64_t u64;\n"); 5974 5975 cgprintf(cg, "\n"); 5976 } 5977 5978 static void 5979 cgtoplevel(Source *source, Node *ast, CodeGen *cg) 5980 { 5981 if (source->haspendingenv) { 5982 assert(source->pendingcount < 512); 5983 source->pendingnodes[source->pendingcount++] = ast; 5984 source->haspendingenv = false; 5985 } else { 5986 codegen(cg, ast); 5987 if (ast->kind != ADECL || ast->u.declref->kind != DFUNCTION) 5988 cgprintf(cg, ";\n"); 5989 else 5990 cgprintf(cg, "\n"); 5991 /* deletenode(ast); */ 5992 } 5993 } 5994 5995 static void 5996 cgtoplevelfinish(Source *source, CodeGen *cg) 5997 { 5998 int i; 5999 6000 for (i = 0; i < source->pendingcount; ++i) { 6001 Node *ast = source->pendingnodes[i]; 6002 6003 codegen(cg, ast); 6004 if (ast->kind != ADECL || ast->u.declref->kind != DFUNCTION) 6005 cgprintf(cg, ";\n"); 6006 else 6007 cgprintf(cg, "\n"); 6008 /* deletenode(ast); */ 6009 } 6010 } 6011 6012 #if 0 6013 static void 6014 cgtypetail(CodeGen *cg, Type *type) 6015 { 6016 if (!type) 6017 return; 6018 6019 if (type->kind == TFUNCTION) { 6020 cgtypetail(cg, type->u.rtarget); 6021 cgprintf(cg, " function("); 6022 if (type->target) 6023 cgtypetail(cg, type->target); 6024 cgprintf(cg, ")"); 6025 return; 6026 } 6027 6028 if (type->kind != TTUPLE && type->target && 6029 type->target->kind == TTUPLE) 6030 { 6031 cgprintf(cg, "("); 6032 cgtypetail(cg, type->target); 6033 cgprintf(cg, ")"); 6034 } else { 6035 cgtypetail(cg, type->target); 6036 } 6037 6038 if (type->module) { 6039 cgprintf(cg, "%s", getstring(idents, type->module->key)); 6040 return; 6041 } 6042 6043 switch (type->kind) { 6044 case TARRAY: 6045 cgprintf(cg, "["); 6046 6047 /* @note the value may be always set in the future */ 6048 if (type->u.val) 6049 codegen(cg, type->u.val); 6050 6051 cgprintf(cg, "]"); 6052 break; 6053 6054 case TTUPLE: 6055 cgprintf(cg, ", "); 6056 if (type->u.rtarget && type->u.rtarget->kind == TTUPLE) { 6057 cgprintf(cg, "("); 6058 cgtypetail(cg, type->u.rtarget); 6059 cgprintf(cg, ")"); 6060 } else { 6061 cgtypetail(cg, type->u.rtarget); 6062 } 6063 6064 break; 6065 6066 default:; 6067 } 6068 6069 return; 6070 } 6071 6072 static void 6073 cgbasetype(CodeGen *cg, Type *type) 6074 { 6075 while (type->target) 6076 type = type->target; 6077 6078 switch (type->kind) { 6079 #define typecase(type, str) \ 6080 case type: cgprintf(cg, str); break 6081 typecase(TERRTYPE, "<error-type>"); 6082 typecase(TUNDEFINED, "<undefined-type>"); 6083 typecase(TPTR, "*"); 6084 typecase(TVOID, "void" ); typecase(TBOOL, "bool" ); 6085 typecase(TINFER, "infer"); typecase(TUINFER, "uinfer"); 6086 typecase(TS8, "char" ); typecase(TU8, "uchar" ); 6087 typecase(TS16, "s16" ); typecase(TU16, "u16" ); 6088 typecase(TS32, "int" ); typecase(TU32, "uint" ); 6089 typecase(TS64, "s64" ); typecase(TU64, "u64" ); 6090 typecase(TF32, "float"); typecase(TF64, "double"); 6091 #undef typecase 6092 default: 6093 cgprintf(cg, "<unknown-type-%d>", type->kind); 6094 } 6095 } 6096 #endif 6097 6098 static void 6099 cgtype(CodeGen *cg, Type *type, Decl *decl); 6100 6101 static void 6102 cgnamedparams(CodeGen *cg, Decl *decl) 6103 { 6104 Decl *param, *head = NULL; 6105 6106 cgprintf(cg, "("); 6107 6108 if (decl->contentenv) { 6109 head = decl->contentenv->head; 6110 } 6111 6112 for (param = head; param; param = param->next) { 6113 if (param->kind != DPARAM) 6114 break; 6115 6116 if (param != head) { 6117 cgprintf(cg, ", "); 6118 } 6119 6120 ++cg->indent; 6121 cgtype(cg, param->type, param); 6122 --cg->indent; 6123 } 6124 6125 cgprintf(cg, ")"); 6126 } 6127 6128 static void 6129 cgdeclmodule(CodeGen *cg, Decl *module) 6130 { 6131 if (module->module) 6132 cgdeclmodule(cg, module->module); 6133 6134 cgprintf(cg, "%s_", getstring(idents, module->key)); 6135 } 6136 6137 static void 6138 cgdeclname(CodeGen *cg, Decl *decl) 6139 { 6140 if (decl->module) 6141 cgdeclmodule(cg, decl->module); 6142 6143 cgprintf(cg, "%s", getstring(idents, decl->key)); 6144 } 6145 6146 static void 6147 cgbasetype(CodeGen *cg, Type *type) 6148 { 6149 switch (type->kind) { 6150 #define typecase(type, str) \ 6151 case type: cgprintf(cg, str); break 6152 typecase(TERRTYPE, "<error-type>"); 6153 typecase(TUNDEFINED, "<undefined-type>"); 6154 typecase(TPTR, "*"); 6155 typecase(TVOID, "void" ); typecase(TBOOL, "bool" ); 6156 typecase(TINFER, "infer"); typecase(TUINFER, "uinfer"); 6157 typecase(TS8, "char" ); typecase(TU8, "uchar" ); 6158 typecase(TS16, "s16" ); typecase(TU16, "u16" ); 6159 typecase(TS32, "int" ); typecase(TU32, "uint" ); 6160 typecase(TS64, "s64" ); typecase(TU64, "u64" ); 6161 typecase(TF32, "float"); typecase(TF64, "double"); 6162 #undef typecase 6163 6164 case TUNION: 6165 cgprintf(cg, "union "); 6166 goto joinstruct; 6167 6168 case TSTRUCT: 6169 cgprintf(cg, "struct "); 6170 joinstruct: 6171 assert(type->module); 6172 cgdeclname(cg, type->module); 6173 break; 6174 6175 default: 6176 cgprintf(cg, "<unknown-type-%d>", type->kind); 6177 } 6178 } 6179 6180 static void 6181 cgtype(CodeGen *cg, Type *type, Decl *decl) 6182 { 6183 Type *stack[64]; 6184 Type *post[64]; 6185 int top = 0, pcount = 0; 6186 6187 while (type->target || type->kind == TFUNCTION) { 6188 assert(top < lengthof(stack)); 6189 stack[top++] = type; 6190 if (type->kind == TFUNCTION) { 6191 assert(type->u.rtarget); 6192 type = type->u.rtarget; 6193 } else { 6194 type = type->target; 6195 } 6196 } 6197 6198 if (cg->commacount) 6199 goto decorate; 6200 6201 cgbasetype(cg, type); 6202 cgprintf(cg, " "); 6203 6204 decorate: 6205 while (top > 0) { 6206 Type *curr = stack[--top]; 6207 if (curr->kind == TPTR) { 6208 Type *target = curr->target; 6209 if (target->kind != TPTR && target->target) { 6210 cgprintf(cg, "(*"); 6211 assert(pcount < lengthof(post)); 6212 post[pcount++] = curr; 6213 } else { 6214 cgprintf(cg, "*"); 6215 } 6216 #if 0 6217 if (target->isconst) 6218 cgprintf(cg, "const "); 6219 #endif 6220 } else { 6221 assert(pcount < lengthof(post)); 6222 post[pcount++] = curr; 6223 } 6224 } 6225 6226 if (decl) 6227 cgdeclname(cg, decl); 6228 6229 6230 while (pcount > 0) { 6231 Type *curr = post[--pcount]; 6232 switch (curr->kind) { 6233 case TPTR: 6234 cgprintf(cg, ")"); 6235 continue; 6236 case TARRAY: 6237 cgprintf(cg, "["); 6238 codegen(cg, curr->u.val); 6239 cgprintf(cg, "]"); 6240 continue; 6241 case TFUNCTION: 6242 if (decl && decl->kind == DFUNCTION) { 6243 /* print named or empty parameter list */ 6244 cgnamedparams(cg, decl); 6245 /* Only the innermost function is referred 6246 * by decl. So we can set decl to NULL. */ 6247 decl = NULL; 6248 } else if (curr->target 6249 && curr->target->kind == TTUPLE) { 6250 Type *tuple = curr->target; 6251 /* print anonymous parameter list */ 6252 cgprintf(cg, "("); 6253 for (;;) { 6254 assert(tuple->target); 6255 cgtype(cg, tuple->target, NULL); 6256 cgprintf(cg, ", "); 6257 6258 assert(tuple->u.rtarget); 6259 tuple = tuple->u.rtarget; 6260 if (tuple->kind != TTUPLE) { 6261 cgtype(cg, tuple, NULL); 6262 break; 6263 } 6264 } 6265 cgprintf(cg, ")"); 6266 } else { 6267 /* print empty parameter list */ 6268 cgprintf(cg, "()"); 6269 } 6270 default: 6271 continue; 6272 } 6273 } 6274 } 6275 6276 static void 6277 cgnumber(CodeGen *cg, Node *expr) 6278 { 6279 switch (expr->type->kind) { 6280 case TF32: case TF64: 6281 /* case TLDOUBLE: */ 6282 cgprintf(cg, "%f", expr->u.d); 6283 if (expr->type->kind == TF32) 6284 cgprintf(cg, "f"); 6285 break; 6286 6287 case TINFER: 6288 case TS8: case TS16: case TS32: case TS64: 6289 cgprintf(cg, "%lli", expr->u.s); 6290 break; 6291 6292 case TUINFER: 6293 case TU8: case TU16: case TU32: case TU64: 6294 cgprintf(cg, "%llu", expr->u.s); 6295 break; 6296 6297 case TBOOL: 6298 if (expr->u.u == 0) 6299 cgprintf(cg, "false"); 6300 else if (expr->u.u == 1) 6301 cgprintf(cg, "true"); 6302 else 6303 cgprintf(cg, "((bool) 0x%016llx)", expr->u.u); 6304 break; 6305 6306 case TPTR: 6307 if (expr->u.u == 0) 6308 cgprintf(cg, "NULL"); 6309 else 6310 cgprintf(cg, "((void *) 0x%016llx)", expr->u.u); 6311 break; 6312 6313 case TVOID: 6314 default: 6315 cgprintf(cg, "---"); 6316 break; 6317 6318 } 6319 6320 } 6321 6322 static void 6323 cgdeclaration(CodeGen *cg, Node *expr) 6324 { 6325 Decl *decl = expr->u.declref; 6326 6327 assert(decl); 6328 assert(expr->type); 6329 6330 cgtype(cg, expr->type, decl); 6331 6332 if (decl->kind == DFUNCTION) { 6333 if (!decl->u.content) 6334 return; 6335 6336 cgprintf(cg, "\n"); 6337 cgindent(cg); 6338 cgprintf(cg, "{\n"); 6339 6340 ++cg->indent; 6341 codegen(cg, decl->contentenv->stmts); 6342 --cg->indent; 6343 6344 cgindent(cg); 6345 cgprintf(cg, "}\n"); 6346 cg->hasclause = true; 6347 } else if (decl->kind == DPARAM || decl->kind == DVAR) { 6348 if (decl->parentenv->kind == SUNION 6349 || decl->parentenv->kind == SSTRUCT) 6350 return; 6351 cgprintf(cg, " = "); 6352 6353 /* @todo remove condition. it is only for testing structs. 6354 * content may not be NULL otherwise (needs validation) */ 6355 if (decl->u.content) 6356 codegen(cg, decl->u.content); 6357 } 6358 } 6359 6360 static void 6361 cgsubexpr(CodeGen *cg, Node *expr) 6362 { 6363 if (isatomnode(expr->kind)) { 6364 codegen(cg, expr); 6365 return; 6366 } 6367 6368 cgprintf(cg, "("); 6369 codegen(cg, expr); 6370 cgprintf(cg, ")"); 6371 } 6372 6373 static void 6374 cgunaryprefixop(CodeGen *cg, Node *expr, const char *op) 6375 { 6376 cgprintf(cg, "%s", op); 6377 cgsubexpr(cg, expr->lhs); 6378 } 6379 6380 static void 6381 cgbinaryop(CodeGen *cg, Node *expr, const char *op) 6382 { 6383 cgsubexpr(cg, expr->lhs); 6384 cgprintf(cg, " %s ", op); 6385 cgsubexpr(cg, expr->rhs); 6386 } 6387 6388 static void 6389 cgprintclause(CodeGen *cg, Node *clause) 6390 { 6391 cgprintf(cg, " {\n"); 6392 ++cg->indent; 6393 codegen(cg, clause); 6394 --cg->indent; 6395 cgindent(cg); 6396 cgprintf(cg, "}"); 6397 cg->hasclause = true; 6398 } 6399 6400 static void 6401 codegen(CodeGen *cg, Node *expr) 6402 { 6403 assert(expr); 6404 6405 switch (expr->kind) { 6406 case IDENT: 6407 cgprintf(cg, "%s", getstring(idents, expr->u.key)); 6408 break; 6409 case CHAR: 6410 /* @todo print char value properly */ 6411 cgprintf(cg, "'%c'", (uchar) expr->u.u); 6412 break; 6413 case TYPE: 6414 break; 6415 case NUMBER: 6416 cgnumber(cg, expr); 6417 break; 6418 case STRING: 6419 cgprintf(cg, "\""); 6420 do { 6421 const int length = getlength(strings, expr->u.key); 6422 const char *string = getstring(strings, expr->u.key); 6423 6424 int i; 6425 6426 /* @note string must have at least one char 6427 * (null-char at the end) which is not printed */ 6428 assert(length); 6429 for (i = 0; i < length - 1; ++i) { 6430 switch (string[i]) { 6431 case '\\': 6432 cgprintf(cg, "\\\\"); 6433 break; 6434 case '"': 6435 cgprintf(cg, "\\\""); 6436 break; 6437 case '\n': 6438 cgprintf(cg, "\\n"); 6439 break; 6440 case '\t': 6441 cgprintf(cg, "\\t"); 6442 break; 6443 case '\r': 6444 cgprintf(cg, "\\r"); 6445 break; 6446 case '\b': 6447 cgprintf(cg, "\\b"); 6448 break; 6449 case '\f': 6450 cgprintf(cg, "\\f"); 6451 break; 6452 case '\v': 6453 cgprintf(cg, "\\v"); 6454 break; 6455 case '\0': 6456 cgprintf(cg, "\\0"); 6457 break; 6458 default: 6459 cgprintf(cg, "%c", string[i]); 6460 break; 6461 } 6462 } 6463 } while (0); 6464 cgprintf(cg, "\""); 6465 break; 6466 case ACOMPOUND: 6467 cgprintf(cg, "(("); 6468 cgbasetype(cg, expr->type); 6469 cgprintf(cg, ") {"); 6470 ++cg->indent; 6471 codegen(cg, expr->rhs); 6472 --cg->indent; 6473 cgindent(cg); 6474 cgprintf(cg, "})"); 6475 break; 6476 case AFIELDINIT: 6477 codegen(cg, expr->rhs); 6478 break; 6479 case KTRUE: 6480 cgprintf(cg, "true"); 6481 break; 6482 case KFALSE: 6483 cgprintf(cg, "false"); 6484 break; 6485 case KNULL: 6486 cgprintf(cg, "NULL"); 6487 break; 6488 case KSIZEOF: 6489 break; 6490 case KALIGNOF: 6491 break; 6492 case KLENGTHOF: 6493 break; 6494 case ADECLREF: 6495 cgdeclname(cg, expr->u.declref); 6496 break; 6497 case ALABEL: 6498 case ASWITCH: 6499 case ACASE: 6500 break; 6501 case ACONV: 6502 codegen(cg, expr->lhs); 6503 break; 6504 case ASCOPE: 6505 do { 6506 Node *curr = expr->lhs; 6507 while (curr) { 6508 cgindent(cg); 6509 codegen(cg, curr); 6510 if (curr->kind == ASTMT) 6511 curr = curr->rhs; 6512 else 6513 break; 6514 } 6515 } while (0); 6516 break; 6517 case AENV: 6518 assert(expr->lhs); 6519 codegen(cg, expr->lhs); 6520 break; 6521 case ASTMT: 6522 cg->hasclause = false; 6523 codegen(cg, expr->lhs); 6524 if (!cg->hasclause) 6525 cgprintf(cg, "; /* statement */\n"); 6526 cg->hasclause = false; 6527 break; 6528 case ADECL: 6529 cgdeclaration(cg, expr); 6530 break; 6531 case OSUFINC: 6532 cgsubexpr(cg, expr->lhs); 6533 cgprintf(cg, "++"); 6534 break; 6535 case OSUFDEC: 6536 cgsubexpr(cg, expr->lhs); 6537 cgprintf(cg, "++"); 6538 break; 6539 case OARRAY: 6540 cgsubexpr(cg, expr->lhs); 6541 cgprintf(cg, "["); 6542 codegen(cg, expr->rhs); 6543 cgprintf(cg, "]"); 6544 break; 6545 case ODISP: 6546 cgsubexpr(cg, expr->lhs); 6547 cgprintf(cg, "."); 6548 codegen(cg, expr->rhs); 6549 break; 6550 case OCALL: 6551 cgsubexpr(cg, expr->lhs); 6552 cgprintf(cg, "("); 6553 if (expr->rhs) 6554 codegen(cg, expr->rhs); 6555 cgprintf(cg, ")"); 6556 break; 6557 case OADDR: 6558 case AADDR: 6559 cgunaryprefixop(cg, expr, "&"); 6560 break; 6561 case ODEREF: 6562 case ADEREF: 6563 cgunaryprefixop(cg, expr, "*"); 6564 break; 6565 case OINC: 6566 cgunaryprefixop(cg, expr, "++"); 6567 break; 6568 case ODEC: 6569 cgunaryprefixop(cg, expr, "--"); 6570 break; 6571 case OBNOT: 6572 cgunaryprefixop(cg, expr, "~"); 6573 break; 6574 case OLNOT: 6575 cgunaryprefixop(cg, expr, "!"); 6576 break; 6577 case OPLUS: 6578 cgunaryprefixop(cg, expr, "+"); 6579 break; 6580 case OMINUS: 6581 cgunaryprefixop(cg, expr, "-"); 6582 break; 6583 case OCAST: 6584 /* @todo implement c version correctly */ 6585 cgprintf(cg, "("); 6586 codegen(cg, expr->lhs); 6587 cgprintf(cg, ")"); 6588 break; 6589 case OMUL: 6590 cgbinaryop(cg, expr, "*"); 6591 break; 6592 case ODIV: 6593 cgbinaryop(cg, expr, "/"); 6594 break; 6595 case OMOD: 6596 cgbinaryop(cg, expr, "%"); 6597 break; 6598 case OBAND: 6599 cgbinaryop(cg, expr, "&"); 6600 break; 6601 case OLSH: 6602 cgbinaryop(cg, expr, "<<"); 6603 break; 6604 case OARSH: 6605 /* @todo implement c version correctly */ 6606 cgbinaryop(cg, expr, ">>>"); 6607 break; 6608 case ORSH: 6609 cgbinaryop(cg, expr, ">>"); 6610 break; 6611 case OADD: 6612 cgbinaryop(cg, expr, "+"); 6613 break; 6614 case OSUB: 6615 cgbinaryop(cg, expr, "-"); 6616 break; 6617 case OBOR: 6618 cgbinaryop(cg, expr, "|"); 6619 break; 6620 case OXOR: 6621 cgbinaryop(cg, expr, "^"); 6622 break; 6623 case OFLIP: 6624 case ORANGE: 6625 /* @todo implement c version correctly */ 6626 cgbinaryop(cg, expr, "~"); 6627 break; 6628 case OLEQ: 6629 cgbinaryop(cg, expr, "<="); 6630 break; 6631 case OLET: 6632 cgbinaryop(cg, expr, "<"); 6633 break; 6634 case OGEQ: 6635 cgbinaryop(cg, expr, ">="); 6636 break; 6637 case OGRT: 6638 cgbinaryop(cg, expr, ">"); 6639 break; 6640 case ONEQ: 6641 cgbinaryop(cg, expr, "!="); 6642 break; 6643 case OEQU: 6644 cgbinaryop(cg, expr, "=="); 6645 break; 6646 case OIDENT: 6647 /* @todo implement c version correctly */ 6648 cgbinaryop(cg, expr, "=="); 6649 break; 6650 case OLAND: 6651 cgbinaryop(cg, expr, "&&"); 6652 break; 6653 case OLOR: 6654 cgbinaryop(cg, expr, "||"); 6655 break; 6656 case OASS: 6657 cgbinaryop(cg, expr, "="); 6658 break; 6659 case OMULA: 6660 cgbinaryop(cg, expr, "*="); 6661 break; 6662 case ODIVA: 6663 cgbinaryop(cg, expr, "/="); 6664 break; 6665 case OMODA: 6666 cgbinaryop(cg, expr, "%="); 6667 break; 6668 case OLSHA: 6669 cgbinaryop(cg, expr, "<<="); 6670 break; 6671 case OARSHA: 6672 /* @todo implement c version correctly */ 6673 cgbinaryop(cg, expr, ">>>="); 6674 break; 6675 case ORSHA: 6676 cgbinaryop(cg, expr, ">>="); 6677 break; 6678 case OANDA: 6679 cgbinaryop(cg, expr, "&="); 6680 break; 6681 case OADDA: 6682 cgbinaryop(cg, expr, "+="); 6683 break; 6684 case OSUBA: 6685 cgbinaryop(cg, expr, "-="); 6686 break; 6687 case OXORA: 6688 cgbinaryop(cg, expr, "^="); 6689 break; 6690 case OORA: 6691 cgbinaryop(cg, expr, "|="); 6692 break; 6693 case KBREAK: 6694 cgprintf(cg, "break"); 6695 break; 6696 case KCONTINUE: 6697 cgprintf(cg, "continue"); 6698 break; 6699 case KGOTO: 6700 cgprintf(cg, "goto %s", getstring(idents, expr->u.key)); 6701 break; 6702 case KRETURN: 6703 cgprintf(cg, "return "); 6704 if (expr->rhs) 6705 codegen(cg, expr->rhs); 6706 break; 6707 case KWHILE: 6708 cgprintf(cg, "while ("); 6709 goto joinif; 6710 case KFOR: 6711 cgprintf(cg, "for ("); 6712 goto joinif; 6713 case KIF: 6714 cgprintf(cg, "if ("); 6715 joinif: 6716 if (expr->u.payload) 6717 codegen(cg, expr->u.payload); 6718 cgprintf(cg, ") "); 6719 if (expr->lhs) 6720 cgprintclause(cg, expr->lhs); 6721 if (expr->rhs) { 6722 cgprintf(cg, " else "); 6723 cgprintclause(cg, expr->rhs); 6724 } 6725 cgprintf(cg, "\n"); 6726 break; 6727 case AFORSTEP: 6728 assert(expr->lhs); 6729 assert(expr->rhs); 6730 assert(expr->u.payload); 6731 assert(expr->lhs->kind == ADECL || expr->lhs->kind == ADECLREF); 6732 codegen(cg, expr->lhs); 6733 cgprintf(cg, "; %s < (", getstring(idents, expr->lhs->u.declref->key)); 6734 codegen(cg, expr->rhs); 6735 cgprintf(cg, "); %s += (", getstring(idents, expr->lhs->u.declref->key)); 6736 codegen(cg, expr->u.payload); 6737 cgprintf(cg, ")"); 6738 break; 6739 case AFOREACH: 6740 break; 6741 case KLOOP: 6742 cgprintf(cg, "for (;;) "); 6743 if (expr->lhs) 6744 cgprintclause(cg, expr->lhs); 6745 /* @todo implement else-case properly? */ 6746 /* @note else-clause might be useless for an infinite loop */ 6747 /* 6748 if (expr->rhs) { 6749 cgprintf(cg, " else "); 6750 cgprintclause(cg, expr->rhs); 6751 } 6752 */ 6753 cgprintf(cg, "\n"); 6754 break; 6755 case ALOOPUNTIL: 6756 cgprintf(cg, "do "); 6757 if (expr->lhs) 6758 cgprintclause(cg, expr->lhs); 6759 cgprintf(cg, " while (!("); 6760 if (expr->u.payload) 6761 codegen(cg, expr->u.payload); 6762 cgprintf(cg, "));\n"); 6763 /* @todo implement else-case properly */ 6764 /* 6765 if (expr->rhs) { 6766 cgprintf(cg, " else "); 6767 cgprintclause(cg, expr->rhs); 6768 } 6769 */ 6770 break; 6771 case KCASE: 6772 case KOF: 6773 case KDO: 6774 case KUNTIL: 6775 /* @todo implement c version correctly */ 6776 break; 6777 case ACOMMA: 6778 codegen(cg, expr->lhs); 6779 cgprintf(cg, ", "); 6780 ++cg->commacount; 6781 codegen(cg, expr->rhs); 6782 --cg->commacount; 6783 break; 6784 case KUNION: 6785 cgprintf(cg, "union "); 6786 goto joinstruct; 6787 case KSTRUCT: 6788 cgprintf(cg, "struct "); 6789 6790 joinstruct: 6791 assert(expr->type); 6792 if (expr->type->module) 6793 cgdeclname(cg, expr->type->module); 6794 6795 cgprintf(cg, " {\n"); 6796 ++cg->indent; 6797 if (expr->rhs) 6798 codegen(cg, expr->rhs); 6799 --cg->indent; 6800 cgindent(cg); 6801 cgprintf(cg, "}"); 6802 break; 6803 case INVALID: 6804 case LINEDELIM: 6805 case SEMIDELIM: 6806 case COMMADELIM: 6807 case COLONDELIM: 6808 case LCURLDELIM: 6809 case LSQRDELIM: 6810 case LPARDELIM: 6811 case RCURLDELIM: 6812 case RSQRDELIM: 6813 case RPARDELIM: 6814 case ANNOT: 6815 case KVOID: 6816 case KBOOL: 6817 case KU8: 6818 case KS8: 6819 case KU16: 6820 case KS16: 6821 case KU32: 6822 case KS32: 6823 case KU64: 6824 case KS64: 6825 case KF32: 6826 case KF64: 6827 case KUCHAR: 6828 case KCHAR: 6829 case KUSHORT: 6830 case KSHORT: 6831 case KUINT: 6832 case KINT: 6833 case KULONG: 6834 case KLONG: 6835 case KULLONG: 6836 case KLLONG: 6837 case KFLOAT: 6838 case KDOUBLE: 6839 case KLDOUBLE: 6840 case KUSIZE: 6841 case KSSIZE: 6842 case KUSE: 6843 case KNOT: 6844 case KAND: 6845 case KOR: 6846 case KIS: 6847 case KBITCAST: 6848 case KEXTERN: 6849 case KINTERN: 6850 case KSTATIC: 6851 case KCONST: 6852 case KVAR: 6853 case KELSE: 6854 case MAXKINDS: 6855 case ENDOFFILE: 6856 cgprintf(cg, "<not implemented: '%s' ", nodestrings[expr->kind]); 6857 if (expr->lhs) 6858 codegen(cg, expr->lhs); 6859 cgprintf(cg, " "); 6860 if (expr->rhs) 6861 codegen(cg, expr->rhs); 6862 cgprintf(cg, ">"); 6863 break; 6864 } 6865 } 6866 6867 6868 6869 // }}} 6870 6871 // @section print ast {{{ 6872 6873 static void 6874 promptenvpath(Env* currenv) 6875 { 6876 const char *envstring = "environment"; 6877 6878 if (currenv && currenv->kind != STOPLEVEL) { 6879 promptenvpath(currenv->below); 6880 6881 switch (currenv->kind) { 6882 case SFUNCTION: 6883 case SPARAMLIST: 6884 envstring = "function"; 6885 break; 6886 case SSTRUCT: 6887 envstring = "struct"; 6888 break; 6889 case SUNION: 6890 envstring = "union"; 6891 break; 6892 case SSCOPE: 6893 envstring = "scope"; 6894 break; 6895 case SIF: 6896 envstring = "if"; 6897 break; 6898 case SELSE: 6899 envstring = "else"; 6900 break; 6901 case SDO: 6902 envstring = "do"; 6903 break; 6904 case SLOOP: 6905 envstring = "loop"; 6906 break; 6907 case SWHILE: 6908 envstring = "while"; 6909 break; 6910 default: 6911 break; 6912 } 6913 6914 if (currenv->envdecl) { 6915 int key = currenv->envdecl->key; 6916 envstring = getstring(idents, key); 6917 } 6918 6919 fprintf(stdout, "# scope: %s/", envstring); 6920 } 6921 } 6922 6923 static void 6924 tryprompt(Source *source, const char ch) 6925 { 6926 if (source->handlereplprompt) { 6927 Env *currenv = source->currenv; 6928 6929 if (ch == '.' && currenv && currenv->kind != STOPLEVEL) { 6930 fputs("\x1b[1;30m", stdout); 6931 promptenvpath(currenv); 6932 fprintf(stdout, "\n\x1b[35m%c \x1b[0m", ch); 6933 } else { 6934 fprintf(stdout, "\x1b[35m%c \x1b[0m", ch); 6935 } 6936 6937 } else if (source->filein == stdin) { 6938 source->handlereplprompt = true; 6939 } 6940 } 6941 6942 typedef 6943 enum Highlight { 6944 HLNONE = 0, 6945 HLDELIM = 1, 6946 HLUNKNOWN = 2, 6947 HLKEYWORD = 3, 6948 HLNUMBER = 4, 6949 HLSTRING = 5, 6950 HLTYPE = 6, 6951 HLFUNCTION = 7, 6952 HLPARAM = 8, 6953 #if 0 6954 HLFUNCTIONDECL = 9, 6955 HLPARAMDECL = 10, 6956 HLDECL = 11, 6957 #endif 6958 HLSPECIAL = 12, 6959 HLINFO = 13, 6960 HLPROMPT = 14 6961 } Highlight; 6962 6963 #define HLFUNCTIONDECL HLFUNCTION 6964 #define HLPARAMDECL HLPARAM 6965 #define HLDECL HLIDENT 6966 6967 #define HLOP HLDELIM 6968 #define HLCHAR HLSTRING 6969 #define HLIDENT HLNONE 6970 6971 Highlight lasthighlight; 6972 6973 static int 6974 highlight(FILE *out, Highlight kind) 6975 { 6976 int n = 0; 6977 6978 if (out != stdout) 6979 return 0; 6980 6981 if (lasthighlight == kind) 6982 return 0; 6983 6984 if (kind == HLNONE) 6985 return lasthighlight = kind, fprintf(out, "\x1b[0m"); 6986 6987 if (lasthighlight == HLDELIM || kind == HLDELIM || 6988 lasthighlight == HLFUNCTION || kind == HLFUNCTION || 6989 lasthighlight == HLPARAM || kind == HLPARAM || 6990 #if 0 6991 lasthighlight == HLFUNCTIONDECL || kind == HLFUNCTIONDECL || 6992 lasthighlight == HLPARAMDECL || kind == HLPARAMDECL || 6993 lasthighlight == HLDECL || kind == HLDECL || 6994 #endif 6995 lasthighlight == HLSPECIAL || 6996 lasthighlight == HLUNKNOWN || kind == HLUNKNOWN) 6997 n += fprintf(out, "\x1b[0m"); 6998 6999 switch (kind) { 7000 case HLDELIM: 7001 n += fprintf(out, "\x1b[2m"); 7002 break; 7003 7004 case HLUNKNOWN: 7005 n += fprintf(out, "\x1b[41;30m"); 7006 break; 7007 7008 case HLKEYWORD: 7009 n += fprintf(out, "\x1b[35m"); 7010 break; 7011 7012 case HLNUMBER: 7013 n += fprintf(out, "\x1b[36m"); 7014 break; 7015 7016 case HLSTRING: 7017 n += fprintf(out, "\x1b[31m"); 7018 break; 7019 7020 case HLTYPE: 7021 n += fprintf(out, "\x1b[34m"); 7022 break; 7023 7024 case HLFUNCTION: 7025 n += fprintf(out, "\x1b[1;3m"); 7026 break; 7027 7028 case HLPARAM: 7029 n += fprintf(out, "\x1b[3m"); 7030 break; 7031 7032 #if 0 7033 case HLFUNCTIONDECL: 7034 n += fprintf(out, "\x1b[1;4;3m"); 7035 break; 7036 7037 case HLPARAMDECL: 7038 n += fprintf(out, "\x1b[4;3m"); 7039 break; 7040 7041 case HLDECL: 7042 n += fprintf(out, "\x1b[4m"); 7043 break; 7044 #endif 7045 7046 case HLSPECIAL: 7047 n += fprintf(out, "\x1b[3;36m"); 7048 break; 7049 7050 case HLINFO: 7051 n += fprintf(out, "\x1b[33m"); 7052 break; 7053 7054 case HLPROMPT: 7055 n += fprintf(out, "\x1b[35m"); 7056 break; 7057 default: 7058 break; 7059 } 7060 7061 lasthighlight = kind; 7062 return n; 7063 } 7064 7065 static int 7066 printexpr(FILE *out, Node *expr, int indent); 7067 7068 static int 7069 printtypetail(FILE *out, Type *type, int indent) 7070 { 7071 int n = 0; 7072 7073 if (!type) 7074 return 0; 7075 7076 if (type->kind == TFUNCTION) { 7077 n += printtypetail(out, type->u.rtarget, indent); 7078 n += fprintf(out, " function("); 7079 if (type->target) 7080 n += printtypetail(out, type->target, indent); 7081 n += fprintf(out, ")"); 7082 return n; 7083 } 7084 7085 if (type->kind != TTUPLE && type->target && 7086 type->target->kind == TTUPLE) 7087 { 7088 n += fprintf(out, "("); 7089 n += printtypetail(out, type->target, indent); 7090 n += fprintf(out, ")"); 7091 } else { 7092 n += printtypetail(out, type->target, indent); 7093 } 7094 7095 if (type->module) { 7096 n += fprintf(out, "%s", getstring(idents, type->module->key)); 7097 return n; 7098 } 7099 7100 switch (type->kind) { 7101 case TARRAY: 7102 n += fprintf(out, "["); 7103 7104 /* @note the value may be always set in the future */ 7105 if (type->u.val) 7106 n += printexpr(out, type->u.val, indent); 7107 7108 n += fprintf(out, "]"); 7109 break; 7110 7111 case TTUPLE: 7112 n += fprintf(out, ", "); 7113 if (type->u.rtarget && type->u.rtarget->kind == TTUPLE) { 7114 n += fprintf(out, "("); 7115 n += printtypetail(out, type->u.rtarget, indent); 7116 n += fprintf(out, ")"); 7117 } else { 7118 n += printtypetail(out, type->u.rtarget, indent); 7119 } 7120 7121 break; 7122 7123 #define typecase(type, str) \ 7124 case type: n += fprintf(out, str); break 7125 7126 typecase(TERRTYPE, "<error-type>"); 7127 typecase(TUNDEFINED, "<undefined-type>"); 7128 typecase(TPTR, "*"); 7129 typecase(TVOID, "void" ); typecase(TBOOL, "bool" ); 7130 typecase(TINFER, "infer"); typecase(TUINFER, "uinfer"); 7131 typecase(TS8, "char" ); typecase(TU8, "uchar" ); 7132 typecase(TS16, "s16" ); typecase(TU16, "u16" ); 7133 typecase(TS32, "int" ); typecase(TU32, "uint" ); 7134 typecase(TS64, "s64" ); typecase(TU64, "u64" ); 7135 typecase(TF32, "float"); typecase(TF64, "double"); 7136 7137 #undef typecase 7138 default:; 7139 } 7140 7141 return n; 7142 } 7143 7144 static int 7145 printtype(FILE *out, Type *type, int indent) 7146 { 7147 if (type && type->kind == TTUPLE) { 7148 int n = 0; 7149 7150 n += fprintf(out, "("); 7151 n += printtypetail(out, type, indent); 7152 7153 return n + fprintf(out, ")"); 7154 } 7155 7156 return printtypetail(out, type, indent); 7157 } 7158 7159 static int 7160 printtypesuffix(FILE *out, Type *type) 7161 { 7162 int n = 0; 7163 7164 if (!type) 7165 return 0; 7166 7167 switch (type->kind) { 7168 #define typecase(type, str) \ 7169 case type: n += fprintf(out, str); break 7170 7171 typecase(TINFER, "i" ); typecase(TUINFER, "u" ); 7172 typecase(TS8, "s8" ); typecase(TU8, "u8" ); 7173 typecase(TS16, "s16" ); typecase(TU16, "u16" ); 7174 typecase(TS32, "s32" ); typecase(TU32, "u32" ); 7175 typecase(TS64, "s64" ); typecase(TU64, "u64" ); 7176 typecase(TF32, "f32" ); typecase(TF64, "f64" ); 7177 7178 #undef typecase 7179 default:; 7180 } 7181 7182 return n; 7183 } 7184 7185 static bool 7186 isclauseorempty(Node *expr) 7187 { 7188 Kind kind; 7189 7190 while (expr && (expr->kind == ASCOPE || expr->kind == ASTMT)) 7191 expr = expr->lhs; 7192 7193 if (!expr) 7194 return true; 7195 7196 kind = expr->kind; 7197 return kind == KDO || kind == KIF || kind == KFOR || 7198 kind == KGOTO || kind == KRETURN || kind == KBREAK || 7199 kind == KCONTINUE; 7200 } 7201 7202 static int 7203 printclause(FILE *out, Node *expr, int indent) 7204 { 7205 int n = 0; 7206 7207 if (!expr) 7208 return 0; 7209 7210 if (isclauseorempty(expr)) { 7211 n += fprintf(out, " "); 7212 n += printexpr(out, expr, indent); 7213 } else { 7214 n += fprintf(out, "\n"); 7215 n += printexpr(out, expr, indent + 1); 7216 } 7217 7218 return n; 7219 } 7220 7221 static int 7222 printstring(FILE *out, Node *string) 7223 { 7224 const char *str = getstring(strings, string->u.key); 7225 int len = getlength(strings, string->u.key); 7226 int i, n = fprintf(out, "\""); 7227 7228 for (i = 0; i < len; ++i) { 7229 switch (str[i]) { 7230 case '\\': 7231 n += fprintf(out, "\\\\"); 7232 break; 7233 7234 case '\n': 7235 n += fprintf(out, "\\n"); 7236 break; 7237 7238 case '\r': 7239 n += fprintf(out, "\\r"); 7240 break; 7241 7242 case '\t': 7243 n += fprintf(out, "\\t"); 7244 break; 7245 7246 case '\"': 7247 n += fprintf(out, "\\\""); 7248 break; 7249 7250 case '\'': 7251 n += fprintf(out, "\\\'"); 7252 break; 7253 7254 case 0: 7255 n += fprintf(out, "\\0"); 7256 break; 7257 7258 default: 7259 putc(str[i], out); 7260 ++n; 7261 } 7262 } 7263 7264 return n + fprintf(out, "\""); 7265 } 7266 7267 static int 7268 printoperant(FILE *out, Node *expr, int opprec, bool braceequalprec, int indent) 7269 { 7270 int prec, n = 0; 7271 7272 if (!expr) 7273 return 0; 7274 7275 prec = getprec(expr->kind); 7276 if (!isatomnode(expr->kind) && (!getnumops(expr->kind) || 7277 prec < opprec || 7278 (braceequalprec && prec == opprec))) { 7279 n += highlight(out, HLDELIM); 7280 7281 n += fprintf(out, "("); 7282 n += highlight(out, HLNONE); 7283 n += printexpr(out, expr, indent); 7284 n += highlight(out, HLDELIM); 7285 n += fprintf(out, ")"); 7286 7287 n += highlight(out, HLNONE); 7288 } else { 7289 n += printexpr(out, expr, indent); 7290 } 7291 7292 return n; 7293 } 7294 7295 static int 7296 printsubexpr(FILE *out, Node *expr, bool islhs, int indent) 7297 { 7298 int n = 0; 7299 7300 if (!expr) 7301 return 0; 7302 7303 if ((islhs && expr->kind == ACOMMA) || expr->kind == ADECL) 7304 n += printexpr(out, expr, indent); 7305 else 7306 n += printoperant(out, expr, PSTART, !islhs, indent); 7307 7308 return n; 7309 } 7310 7311 static int 7312 printdeclmodule(FILE *out, Decl *module) 7313 { 7314 int n = 0; 7315 7316 if (module->module) 7317 printdeclmodule(out, module->module); 7318 7319 if (module->kind == DTYPE) { 7320 n += highlight(out, HLTYPE); 7321 fprintf(out, "%s", getstring(idents, module->key)); 7322 n += highlight(out, HLDELIM); 7323 } else { 7324 n += highlight(out, HLDELIM); 7325 fprintf(out, "%s", getstring(idents, module->key)); 7326 } 7327 n += fprintf(out, "."); 7328 7329 return n; 7330 } 7331 7332 static int 7333 printdeclname(FILE *out, Decl *decl, bool isdecl) 7334 { 7335 int n = 0; 7336 7337 if (decl->module) 7338 printdeclmodule(out, decl->module); 7339 7340 if (isdecl) { 7341 n += highlight(out, 7342 decl->kind == DFUNCTION ? HLFUNCTIONDECL : 7343 decl->kind == DPARAM ? ( 7344 decl->flags & MSPECIAL ? HLSPECIAL : HLPARAMDECL 7345 ) : HLDECL); 7346 } else { 7347 n += highlight(out, decl->kind == DFUNCTION ? 7348 HLFUNCTION : decl->kind == DPARAM ? ( 7349 decl->flags & MSPECIAL ? HLSPECIAL : HLPARAM 7350 ) : HLIDENT); 7351 } 7352 n += fprintf(out, "%s", getstring(idents, decl->key)); 7353 7354 return n; 7355 } 7356 7357 static int 7358 printdeclaration(FILE *out, Decl *decl, int indent) 7359 { 7360 int n = 0; 7361 7362 assert(decl); 7363 7364 n += highlight(out, HLTYPE); 7365 if (decl->kind == DFUNCTION) { 7366 n += printtype(out, decl->type->u.rtarget, indent); 7367 } else { 7368 n += printtype(out, decl->type, indent); 7369 } 7370 7371 n += fprintf(out, " "); 7372 printdeclname(out, decl, true); 7373 7374 if (decl->kind == DFUNCTION) { 7375 Decl *param, *head = NULL; 7376 7377 n += highlight(out, HLDELIM); 7378 n += fprintf(out, "("); 7379 7380 if (decl->contentenv) { 7381 head = decl->contentenv->head; 7382 } 7383 7384 for (param = head; param; param = param->next) { 7385 if (param->kind != DPARAM) 7386 break; 7387 7388 if (param != head) { 7389 n += highlight(out, HLDELIM); 7390 n += fprintf(out, ", "); 7391 } 7392 7393 n += printdeclaration(out, param, indent + 1); 7394 } 7395 7396 n += highlight(out, HLDELIM); 7397 n += fprintf(out, ")"); 7398 7399 if (decl->u.content) { 7400 n += fprintf(out, "\n"); 7401 n += printexpr(out, decl->u.content, indent + 1); 7402 } 7403 } else if (decl->u.content) { 7404 n += highlight(out, HLDELIM); 7405 n += fprintf(out, " = "); 7406 n += printoperant(out, decl->u.content, PASSIGN, false, indent); 7407 } 7408 7409 return n; 7410 } 7411 7412 static int 7413 printexpr(FILE *out, Node *expr, int indent) 7414 { 7415 int n = 0; 7416 7417 if (expr->kind == 0) { 7418 n += highlight(out, HLKEYWORD); 7419 n += fprintf(out, "_"); 7420 return 0; 7421 } 7422 7423 if (getnumops(expr->kind) == 2) { 7424 n += printoperant(out, expr->lhs, 7425 getprec(expr->kind), 7426 israssoc(expr->kind), 7427 indent); 7428 7429 n += highlight(out, HLDELIM); 7430 n += fprintf(out, " %s ", nodestrings[expr->kind]); 7431 7432 n += printoperant(out, expr->rhs, 7433 getprec(expr->kind), 7434 !israssoc(expr->kind), 7435 indent); 7436 goto finish; 7437 } 7438 7439 if (getnumops(expr->kind) == 1) { 7440 if (getprec(expr->kind) == PUNSUF) { 7441 printoperant(out, expr->lhs, PUNSUF, false, indent); 7442 7443 switch (expr->kind) { 7444 case OARRAY: 7445 case OCALL: 7446 n += highlight(out, HLDELIM); 7447 n += fprintf(out, "%c", nodestrings[expr->kind][0]); 7448 7449 if (expr->rhs) 7450 n += printexpr(out, expr->rhs, indent); 7451 7452 n += highlight(out, HLDELIM); 7453 n += fprintf(out, "%c", nodestrings[expr->kind][1]); 7454 break; 7455 7456 case ODISP: 7457 n += highlight(out, HLDELIM); 7458 n += fprintf(out, "."); 7459 if (expr->rhs && expr->rhs->kind == IDENT) { 7460 n += highlight(out, HLIDENT); 7461 n += fprintf(out, "%s", 7462 getstring(idents, expr->rhs->u.key)); 7463 } else { 7464 /* @note this might be unnecessary */ 7465 n += printexpr(out, expr->rhs, indent); 7466 } 7467 break; 7468 7469 default: 7470 n += highlight(out, HLDELIM); 7471 n += fprintf(out, "%s", nodestrings[expr->kind]); 7472 } 7473 7474 } else { 7475 switch (expr->kind) { 7476 case OCAST: 7477 n += highlight(out, HLDELIM); 7478 putc('(', out), ++n; 7479 n += highlight(out, HLTYPE); 7480 n += printtype(out, expr->type, indent); 7481 n += highlight(out, HLDELIM); 7482 putc(')', out), ++n; 7483 break; 7484 7485 default: 7486 n += highlight(out, HLDELIM); 7487 n += fprintf(out, "%s", nodestrings[expr->kind]); 7488 7489 if (getprec(expr->lhs->kind) == PUNARY && 7490 expr->kind != ODEREF && 7491 expr->kind != OADDR) 7492 { 7493 putc(' ', out), ++n; 7494 } 7495 } 7496 7497 n += printoperant(out, expr->lhs, PUNARY, false, indent); 7498 } 7499 7500 goto finish; 7501 } 7502 7503 switch (expr->kind) { 7504 case IDENT: 7505 n += highlight(out, HLUNKNOWN); 7506 n += fprintf(out, "%s?", getstring(idents, expr->u.key)); 7507 n += highlight(out, HLNONE); 7508 break; 7509 7510 case NUMBER: 7511 n += highlight(out, HLNUMBER); 7512 7513 switch (expr->type->kind) { 7514 case TF32: case TF64: 7515 /* case TLDOUBLE: */ 7516 n += fprintf(out, "%f", expr->u.d); 7517 n += printtypesuffix(out, expr->type); 7518 break; 7519 7520 case TINFER: 7521 case TS8: case TS16: case TS32: case TS64: 7522 n += fprintf(out, "%lli", expr->u.s); 7523 n += printtypesuffix(out, expr->type); 7524 break; 7525 7526 case TUINFER: 7527 case TU8: case TU16: case TU32: case TU64: 7528 n += fprintf(out, "%llu", expr->u.s); 7529 n += printtypesuffix(out, expr->type); 7530 break; 7531 7532 case TBOOL: 7533 if (expr->u.u == 0) 7534 n += fprintf(out, "false"); 7535 else if (expr->u.u == 1) 7536 n += fprintf(out, "true"); 7537 else 7538 n += fprintf(out, "0x%016llx", expr->u.u); 7539 7540 break; 7541 7542 case TPTR: 7543 if (expr->u.u == 0) 7544 n += fprintf(out, "null"); 7545 else 7546 n += fprintf(out, "0x%016llx", expr->u.u); 7547 break; 7548 7549 case TVOID: 7550 default: 7551 n += fprintf(out, "---"); 7552 break; 7553 7554 } 7555 7556 break; 7557 7558 case CHAR: 7559 /* @todo print chars correctly */ 7560 n += highlight(out, HLCHAR); 7561 n += fprintf(out, "'%c'", (uchar) expr->u.u); 7562 break; 7563 7564 case STRING: 7565 n += highlight(out, HLSTRING); 7566 n += printstring(out, expr); 7567 break; 7568 7569 case TYPE: 7570 /* @note might be unnecessary (only used for ACOMPOUND) */ 7571 n += highlight(out, HLTYPE); 7572 n += printtype(out, expr->type, indent); 7573 break; 7574 7575 case ADECLREF: 7576 printdeclname(out, expr->u.declref, false); 7577 break; 7578 7579 case ADECL: 7580 n += printdeclaration(out, expr->u.declref, indent); 7581 break; 7582 7583 case ACOMMA: 7584 n += printsubexpr(out, expr->lhs, true, indent); 7585 n += highlight(out, HLDELIM); 7586 n += printf(", "); 7587 n += printsubexpr(out, expr->rhs, false, indent); 7588 break; 7589 7590 case KSIZEOF: 7591 case KALIGNOF: 7592 case KLENGTHOF: 7593 n += highlight(out, HLKEYWORD); 7594 n += fprintf(out, "%s", nodestrings[expr->kind]); 7595 n += highlight(out, HLDELIM); 7596 7597 n += fprintf(out, "("); 7598 n += printexpr(out, expr->lhs, indent); 7599 n += highlight(out, HLDELIM); 7600 n += fprintf(out, ")"); 7601 break; 7602 7603 case KBITCAST: 7604 n += highlight(out, HLKEYWORD); 7605 n += fprintf(out, "bitcast"); 7606 n += highlight(out, HLDELIM); 7607 n += fprintf(out, "("); 7608 7609 n += highlight(out, HLTYPE); 7610 n += printtype(out, expr->rhs->type, indent); 7611 n += highlight(out, HLDELIM); 7612 7613 n += fprintf(out, ") ("); 7614 n += printexpr(out, expr->lhs, indent); 7615 n += highlight(out, HLDELIM); 7616 n += fprintf(out, ")"); 7617 break; 7618 7619 case KRETURN: 7620 n += highlight(out, HLKEYWORD); 7621 if (expr->rhs) { 7622 n += fprintf(out, "return "); 7623 n += printexpr(out, expr->rhs, indent); 7624 } else { 7625 n += fprintf(out, "return"); 7626 } 7627 break; 7628 7629 case KBREAK: 7630 n += highlight(out, HLKEYWORD); 7631 n += fprintf(out, "break"); 7632 break; 7633 7634 case KCONTINUE: 7635 n += highlight(out, HLKEYWORD); 7636 n += fprintf(out, "continue"); 7637 break; 7638 case KWHILE: 7639 n += highlight(out, HLKEYWORD); 7640 n += fprintf(out, "while "); 7641 goto joinifbody; 7642 7643 case KFOR: 7644 n += highlight(out, HLKEYWORD); 7645 n += fprintf(out, "for "); 7646 goto joinifbody; 7647 7648 case AFORSTEP: 7649 n += printexpr(out, expr->lhs, indent); 7650 n += highlight(out, HLKEYWORD); 7651 n += fprintf(out, " to "); 7652 n += printexpr(out, expr->rhs, indent); 7653 7654 assert(expr->u.payload); 7655 if (expr->u.payload->kind == NUMBER && false) { 7656 if (isfloattype(expr->u.payload->type) 7657 && expr->u.payload->u.d == 1.0) 7658 break; 7659 if (isinttype(expr->u.payload->type) 7660 && expr->u.payload->u.u == 1) 7661 break; 7662 } 7663 n += highlight(out, HLKEYWORD); 7664 n += fprintf(out, " step "); 7665 n += printexpr(out, expr->u.payload, indent); 7666 break; 7667 7668 case KIF: 7669 n += highlight(out, HLKEYWORD); 7670 n += fprintf(out, "if "); 7671 /* FALLTHROUGH */ 7672 joinifbody: 7673 n += printexpr(out, expr->u.payload, indent); 7674 n += printclause(out, expr->lhs, indent); 7675 7676 if (expr->rhs) { 7677 int i; 7678 7679 n += fprintf(out, "\n"); 7680 7681 for (i = 0; i < indent; ++i) 7682 n += fprintf(out, "\t"); 7683 7684 n += highlight(out, HLKEYWORD); 7685 n += fprintf(out, "else"); 7686 n += printclause(out, expr->rhs, indent); 7687 } 7688 break; 7689 7690 case KLOOP: 7691 case ALOOPUNTIL: 7692 n += highlight(out, HLKEYWORD); 7693 n += fprintf(out, "loop"); 7694 n += printclause(out, expr->lhs, indent); 7695 if (expr->kind == KLOOP) 7696 break; 7697 7698 do { 7699 int i; 7700 n += fprintf(out, "\n"); 7701 7702 for (i = 0; i < indent; ++i) 7703 n += fprintf(out, "\t"); 7704 7705 } while (0); 7706 7707 n += highlight(out, HLKEYWORD); 7708 n += fprintf(out, "until "); 7709 n += printexpr(out, expr->u.payload, indent); 7710 7711 if (expr->rhs) { 7712 n += highlight(out, HLKEYWORD); 7713 n += fprintf(out, " else"); 7714 n += printclause(out, expr->rhs, indent); 7715 } 7716 break; 7717 7718 7719 case KDO: 7720 n += highlight(out, HLKEYWORD); 7721 n += fprintf(out, "do"); 7722 n += printclause(out, expr->lhs, indent); 7723 break; 7724 7725 case KUNION: 7726 case KSTRUCT: 7727 n += highlight(out, HLKEYWORD); 7728 7729 n += fprintf(out, 7730 expr->kind == KSTRUCT ? "struct" : "union"); 7731 7732 if (expr->lhs && expr->lhs->kind == IDENT) { 7733 n += highlight(out, HLTYPE); 7734 n += fprintf(out, " %s", 7735 getstring(idents, expr->lhs->u.key)); 7736 } 7737 7738 if (expr->rhs) 7739 n += printclause(out, expr->rhs, indent); 7740 7741 break; 7742 7743 case ASTMT: 7744 advancestmt: 7745 do { 7746 int i; 7747 7748 for (i = 0; i < indent; ++i) 7749 n += fprintf(out, "\t"); 7750 } while (0); 7751 7752 n += printexpr(out, expr->lhs, indent); 7753 7754 if (expr->rhs) { 7755 assert(expr->rhs->kind == ASTMT); 7756 n += fprintf(out, "\n"); 7757 expr = expr->rhs; 7758 goto advancestmt; 7759 } 7760 7761 break; 7762 7763 case ASCOPE: 7764 /* @todo improve this piece of code */ 7765 if (expr->lhs && 7766 expr->lhs->kind == ASTMT && 7767 expr->u.env && 7768 expr->u.env->kind != SFUNCTION && 7769 expr->u.env->kind != SSTRUCT) 7770 { 7771 Node *stmt = expr->lhs; 7772 7773 if (!stmt->rhs && isclauseorempty(stmt)) { 7774 n += printexpr(out, stmt->lhs, indent); 7775 break; 7776 } 7777 } 7778 n += printexpr(out, expr->lhs, indent); 7779 // n += fprintf(out, "\n"); /* blank line */ 7780 break; 7781 7782 case AENV: 7783 n += printexpr(out, expr->lhs, indent); 7784 break; 7785 7786 case ACONV: 7787 n += highlight(out, HLNUMBER); 7788 n += fprintf(out, "conv("); 7789 7790 n += highlight(out, HLTYPE); 7791 n += printtype(out, expr->type, indent); 7792 n += highlight(out, HLDELIM); 7793 7794 n += fprintf(out, ") "); 7795 n += printoperant(out, expr->lhs, PUNARY, false, indent); 7796 break; 7797 7798 case AADDR: 7799 n += highlight(out, HLDELIM); 7800 n += fputs("&{", out); 7801 n += printoperant(out, expr->lhs, PUNARY, false, indent); 7802 n += highlight(out, HLDELIM); 7803 n += fputs("}", out); 7804 break; 7805 7806 case ADEREF: 7807 n += highlight(out, HLDELIM); 7808 n += fputs("*{", out); 7809 n += printoperant(out, expr->lhs, PUNARY, false, indent); 7810 n += highlight(out, HLDELIM); 7811 n += fputs("}", out); 7812 break; 7813 7814 case ACOMPOUND: 7815 n += highlight(out, HLTYPE); 7816 n += printtype(out, expr->type, indent); 7817 n += highlight(out, HLDELIM); 7818 n += fputs("{", out); 7819 n += printexpr(out, expr->rhs, indent); 7820 n += highlight(out, HLDELIM); 7821 n += fputs("}", out); 7822 break; 7823 7824 case AFIELDINIT: 7825 if (expr->lhs) { 7826 n += highlight(out, HLDELIM); 7827 n += fprintf(out, "%s: ", getstring(idents, expr->u.key)); 7828 } 7829 n += printexpr(out, expr->rhs, indent); 7830 break; 7831 7832 case ASELFDISP: 7833 n += printexpr(out, expr->lhs, indent); 7834 n += highlight(out, HLNONE); 7835 /* @todo use printexpr when typechecked */ 7836 n += fprintf(out, ":%s", getstring(idents, expr->rhs->u.key)); 7837 break; 7838 7839 default: 7840 n += highlight(out, HLINFO); 7841 n += fprintf(out, "node(%u)", expr->kind); 7842 7843 if (expr->lhs) { 7844 n += fprintf(out, " -> "); 7845 n += printsubexpr(out, expr->lhs, true, indent); 7846 } 7847 if (expr->rhs) { 7848 n += highlight(out, HLINFO); 7849 n += fprintf(out, " => "); 7850 n += printsubexpr(out, expr->rhs, false, indent); 7851 } 7852 7853 break; 7854 } 7855 7856 finish: 7857 #if 0 7858 if (expr->kind == ASTMT && expr->next) { 7859 n += fprintf(out, "\n"); 7860 } else if (expr->next) { 7861 n += highlight(out, HLDELIM); 7862 n += fprintf(out, ", "); 7863 } 7864 #endif 7865 7866 return n; 7867 } 7868 7869 7870 7871 // }}} 7872 7873 // @section toplevel bundle & use {{{ 7874 7875 #if 0 7876 typedef struct String String; 7877 struct String { 7878 char *string; 7879 int length; 7880 }; 7881 7882 static String 7883 makestring(char *string) 7884 { 7885 String result; 7886 7887 result.string = string; 7888 result.length = strlen(string); 7889 7890 return result; 7891 } 7892 7893 static bool 7894 endswithcase(String name, String ending) 7895 { 7896 const int delta = name.length - ending.length; 7897 int i; 7898 7899 if (name.length < ending.length) 7900 return false; 7901 7902 for (i = 0; i < ending.length; ++i) { 7903 const int j = i + delta; 7904 if (tolower(name.string[j]) != ending.string[i]) 7905 return false; 7906 } 7907 7908 return true; 7909 } 7910 7911 static bool 7912 beginswith(String name, String beginning) 7913 { 7914 int i; 7915 7916 if (name.length < beginning.length) 7917 return false; 7918 7919 for (i = 0; i < beginning.length; ++i) { 7920 if (name.string[i] != beginning.string[i]) 7921 return false; 7922 } 7923 7924 return true; 7925 } 7926 7927 static String 7928 duplicatestring(String s) 7929 { 7930 String copy; 7931 7932 copy.string = (char *) calloc(s.length + 1, sizeof*(s.string)); 7933 copy.length = s.length; 7934 7935 assert(copy.string); 7936 strncpy(copy.string, s.string, s.length); 7937 7938 return copy; 7939 } 7940 #endif 7941 7942 // }}} 7943 7944 // @section init source {{{ 7945 7946 static void 7947 initsource(Source *source, const char *filename, FILE *file) 7948 { 7949 source->filein = file; 7950 source->currloc.filename = filename; 7951 source->tok.loc.filename = filename; 7952 source->tabwidth = 8; 7953 source->haspendingenv = false; 7954 source->handlereplprompt = false; 7955 7956 source->pendingcount = 0; 7957 7958 source->implicitenv = envbuf + envtop++; 7959 7960 gettok(source); 7961 if (getkind(source) == LINEDELIM) 7962 gettok(source); 7963 } 7964 7965 7966 7967 // }}} 7968 7969 // @section main-routine {{{ 7970 7971 const char * 7972 isolatecommand(char **string) 7973 { 7974 char *commandline = *string; 7975 const char *command; 7976 7977 while (isspace(*commandline)) 7978 ++commandline; 7979 7980 command = commandline; 7981 7982 while (!isspace(*commandline) && *commandline) 7983 ++commandline; 7984 7985 if (*commandline) 7986 *commandline = 0, ++commandline; 7987 7988 *string = commandline; 7989 7990 return command; 7991 } 7992 7993 static bool 7994 processcommand(Source *source) 7995 { 7996 char *commandline = source->line + 1; 7997 7998 const char *command = isolatecommand(&commandline); 7999 8000 if (!strcmp(command, "exit")) { 8001 source->line[0] = 0; 8002 return false; 8003 } 8004 8005 if (!strcmp(command, "memory")) { 8006 int i; 8007 8008 printf("ast-nodes: %5u, deletes: %5u, total: %5u\n", 8009 nodetop, poolednodecount, totalnodecount); 8010 8011 printf("type-nodes: %5u\n", typetop); 8012 printf("declarations: %5u\n", decltop); 8013 printf("environments: %5u\n", envtop); 8014 8015 for (i = 0; i < nodetop; ++i) { 8016 if (nodebuf[i].kind == 0) 8017 continue; 8018 8019 highlight(stdout, HLINFO); 8020 printf("node[%u]:\n", i); 8021 printexpr(stdout, nodebuf + i, 0); 8022 printf("\n"); 8023 } 8024 8025 goto finish; 8026 } 8027 8028 if (!strcmp(command, "delete")) { 8029 command = isolatecommand(&commandline); 8030 8031 if (!strcmp(command, "node") || 8032 !strcmp(command, "ast-node") || 8033 isdigit(*command)) 8034 { 8035 int i; 8036 8037 if (!isdigit(*command)) 8038 command = isolatecommand(&commandline); 8039 8040 i = atoi(command); 8041 8042 if (i < 4096 && i >= 0) { 8043 Node *node = nodebuf + i; 8044 8045 if (node->kind != 0) 8046 deletenode(node); 8047 else 8048 printf("already deleted.\n"); 8049 } else { 8050 fprintf(stderr, "error: invalid number.\n"); 8051 } 8052 } else { 8053 fprintf(stderr, "error: unknown argument '%s'.\n", 8054 command); 8055 } 8056 8057 goto finish; 8058 } 8059 8060 fprintf(stderr, "error: unknown command '%s'.\n", command); 8061 finish: 8062 return mygetline(source); 8063 } 8064 8065 static void 8066 handlelineending(Source *source); 8067 8068 char bundlenamebuffer[1024 * 4]; 8069 int bundlenamelength = 0; 8070 8071 static bool 8072 processtopleveluse(Source *source, SrcLoc *loc, const int bundlepath[], int count) 8073 { 8074 static const char prefix[] = "arialib/"; 8075 static const char suffix[] = ".co"; 8076 8077 FILE *importfile = NULL; 8078 const char *filename = NULL; 8079 8080 int i; 8081 8082 if (sizeof(prefix) - 1 > sizeof(bundlenamebuffer) - 1) 8083 goto errorlength; 8084 8085 bundlenamelength = sizeof(prefix) - 1; 8086 memcpy(bundlenamebuffer, prefix, sizeof(prefix) - 1); 8087 8088 for (i = 0; i < count; ++i) { 8089 const int key = bundlepath[i]; 8090 const char *string = getstring(idents, key); 8091 const int length = getlength(idents, key); 8092 8093 if (length + bundlenamelength > sizeof(bundlenamebuffer) - 1) 8094 goto errorlength; 8095 8096 memcpy(bundlenamebuffer + bundlenamelength, string, length); 8097 bundlenamelength += length; 8098 8099 if (i >= count - 1) 8100 continue; 8101 8102 if (bundlenamelength + 1 > sizeof(bundlenamebuffer) - 1) 8103 goto errorlength; 8104 8105 bundlenamebuffer[bundlenamelength++] = '/'; 8106 } 8107 8108 if (bundlenamelength + sizeof(suffix) - 1 > sizeof(bundlenamebuffer) - 1) 8109 goto errorlength; 8110 8111 memcpy(bundlenamebuffer + bundlenamelength, suffix, sizeof(suffix) - 1); 8112 bundlenamelength += sizeof(suffix) - 1; 8113 bundlenamebuffer[bundlenamelength] = '\0'; 8114 8115 filename = calloc(bundlenamelength + 1, sizeof*(bundlenamebuffer)); 8116 8117 if (!filename) { 8118 error(loc, "out of memory"); 8119 return false; 8120 } 8121 8122 memcpy(filename, bundlenamebuffer, bundlenamelength); 8123 8124 importfile = fopen(filename, "r"); 8125 8126 if (!importfile) { 8127 error(loc, "could not open bundle file '%s'", filename); 8128 return false; 8129 } 8130 8131 warn(loc, "using bundle '%s'", filename); 8132 8133 fclose(importfile); 8134 free(filename); 8135 8136 return true; 8137 8138 errorlength: 8139 error(loc, "bundle path is too long"); 8140 return false; 8141 } 8142 8143 static Node * 8144 toplevel(Source *source, Block *block) 8145 { 8146 Node *ast; 8147 8148 redo: 8149 readannots(source); 8150 if (getkind(source) == KBUNDLE) { 8151 SrcLoc loc = *getloc(source); 8152 #if 0 8153 int bundlekey = 0; 8154 gettok(source); 8155 while (getkind(source) == IDENT) { 8156 char *name = getstring(idents, source->tok.u.key); 8157 int length = getlength(idents, source->tok.u.key); 8158 8159 /* @fixme check name length */ 8160 memcpy(bundlenamebuffer + bundlenamelength, name, length); 8161 bundlenamelength += length; 8162 gettok(source); 8163 bundlenamebuffer[bundlenamelength] = '\0'; 8164 8165 if (getkind(source) != ODISP) 8166 break; 8167 8168 gettok(source); 8169 bundlenamebuffer[bundlenamelength++] = '_'; 8170 bundlenamebuffer[bundlenamelength] = '\0'; 8171 } 8172 8173 if (bundlenamelength) { 8174 bundlekey = getstringkey(&idents, bundlenamebuffer, 8175 bundlenamelength); 8176 assert(source->currenv); 8177 source->currenv->bundle = makedecl(source, bundlekey, 8178 DBUNDLE); 8179 source->currenv->loc = loc; 8180 } 8181 #else 8182 Decl *bundle = NULL; 8183 gettok(source); 8184 while (getkind(source) == IDENT) { 8185 const int bundlekey = source->tok.u.key; 8186 8187 assert(source->currenv); 8188 bundle = makebundle(source, bundlekey, bundle); 8189 8190 gettok(source); 8191 8192 if (getkind(source) != ODISP) 8193 break; 8194 8195 gettok(source); 8196 } 8197 8198 if (bundle) { 8199 source->currenv->bundle = bundle; 8200 source->currenv->loc = loc; 8201 } else { 8202 /* @note is this correct? */ 8203 source->currenv->bundle = NULL; 8204 } 8205 #endif 8206 8207 handlelineending(source); 8208 goto redo; 8209 } 8210 8211 if (getkind(source) == KUSE) { 8212 int bundlepath[64]; 8213 int bundlepathtop = 0; 8214 8215 SrcLoc loc = *getloc(source); 8216 8217 gettok(source); 8218 while (getkind(source) == IDENT) { 8219 const int bundlekey = source->tok.u.key; 8220 8221 bundlepath[bundlepathtop++] = bundlekey; 8222 8223 gettok(source); 8224 8225 if (getkind(source) != ODISP) 8226 break; 8227 8228 gettok(source); 8229 } 8230 8231 handlelineending(source); 8232 8233 processtopleveluse(source, &loc, bundlepath, bundlepathtop); 8234 goto redo; 8235 } 8236 ast = exprlist(source, false, NULL); 8237 /* ast = readexpr(source, PSTART); */ 8238 /* 8239 printast(ast, 0); 8240 printf("\n"); 8241 */ 8242 if (ast->kind != ADECL || 8243 !ast->u.payload || 8244 ast->u.payload->kind != ASCOPE) 8245 { 8246 ast = typecheck(source->currenv, ast); 8247 ast = foldexpr(source->currenv, ast); 8248 dataflow(block, ast); 8249 } 8250 ast = extractnestedfunctions(source->currenv, ast); 8251 8252 return ast; 8253 } 8254 8255 static void 8256 processpendingenvs(Source *source, Block *block) 8257 { 8258 Env *p; 8259 8260 for (p = source->pendingenvhead; p; p = p->pendingnext) { 8261 if (p->stmts) { 8262 p->stmts = typecheck(source->currenv, p->stmts); 8263 p->stmts = foldexpr(source->currenv, p->stmts); 8264 dataflow(block, p->stmts); 8265 8266 /* debug prints: */ 8267 highlight(stdout, HLINFO); 8268 printf("statements:\n"); 8269 highlight(stdout, HLNONE); 8270 printexpr(stdout, p->stmts, 1); 8271 8272 highlight(stdout, HLINFO); 8273 fputs(" : ", stdout); 8274 printtype(stdout, p->stmts->type, 0); 8275 highlight(stdout, HLNONE); 8276 8277 printf("\n"); 8278 } 8279 } 8280 8281 } 8282 8283 static void 8284 handlelineending(Source *source) 8285 { 8286 if (getkind(source) == LINEDELIM) { 8287 if (source->filein == stdin) { 8288 highlight(stdout, HLPROMPT); 8289 printf("> "); 8290 highlight(stdout, HLNONE); 8291 source->handlereplprompt = false; 8292 } 8293 gettok(source); 8294 } else if (getkind(source) == SEMIDELIM) { 8295 gettok(source); 8296 } 8297 8298 if (source->lastkind != SEMIDELIM && source->lastkind != LINEDELIM){ 8299 error(getloc(source), "expected new line"); 8300 while (getkind(source) != SEMIDELIM && 8301 getkind(source) != LINEDELIM && 8302 getkind(source) != 0) 8303 { 8304 gettok(source); 8305 } 8306 8307 if (source->filein == stdin) { 8308 highlight(stdout, HLPROMPT); 8309 printf("> "); 8310 highlight(stdout, HLNONE); 8311 source->handlereplprompt = false; 8312 } 8313 8314 if (getkind(source) != 0) 8315 gettok(source); 8316 } 8317 } 8318 8319 static void 8320 processfile(Source *source) 8321 { 8322 Block *block; 8323 Decl *intrinsic; 8324 8325 CodeGen cg = {0}; 8326 8327 pushenv(source, STOPLEVEL); 8328 block = makeblock(BTOPLEVEL, source->currenv); 8329 appendconduct(block, CSCOPE, NULL); 8330 8331 intrinsic = makedecl(source, getstringkey(&idents, "printf", 6), DFUNCTION); 8332 intrinsic->type = maketype(&source->tok.loc, primitive(TFUNCTION), NULL); 8333 intrinsic->type->u.rtarget = primitive(TINT); 8334 8335 cginit(&cg, source->currenv, fopen("out.c", "wb")); 8336 while (getkind(source) != 0) { 8337 /* printf("token:%i:%i: %c '%.*s'\n", lastline, lastcol + 1, 8338 tok.u.id, currcol - lastcol, line + lastcol);*/ 8339 Node *ast = toplevel(source, block); 8340 8341 highlight(stdout, HLINFO); 8342 printf("number of nested functions: %u\n", extractedtop - 1); 8343 highlight(stdout, HLNONE); 8344 8345 if (source->filein == stdin) { 8346 highlight(stdout, HLINFO); 8347 fputs("= ", stdout); 8348 highlight(stdout, HLNONE); 8349 } 8350 8351 printexpr(stdout, ast, 0); 8352 highlight(stdout, HLNONE); 8353 8354 if (source->filein == stdin) { 8355 highlight(stdout, HLINFO); 8356 fputs(" : ", stdout); 8357 printtype(stdout, ast->type, 0); 8358 highlight(stdout, HLNONE); 8359 } 8360 printf("\n"); 8361 8362 cgtoplevel(source, ast, &cg); 8363 handlelineending(source); 8364 } 8365 8366 highlight(stdout, HLINFO); 8367 puts("dump pending environments ..."); 8368 highlight(stdout, HLNONE); 8369 8370 processpendingenvs(source, block); 8371 cgtoplevelfinish(source, &cg); 8372 /* dfpopconduct(); */ 8373 popenv(source); 8374 8375 highlight(stdout, HLINFO); 8376 printf("exiting with %u errors and %u warnings ...\x1b[0m\n", 8377 errorcount, warningcount); 8378 8379 fclose(cg.out); 8380 } 8381 8382 int 8383 main(int argc, char **argv) 8384 { 8385 Source *source = &testsource; 8386 8387 initkeywords(); 8388 initstrmap(&idents); 8389 initstrmap(&strings); 8390 8391 auxthen = getstringkey(&idents, "then", 4); 8392 auxin = getstringkey(&idents, "in", 2); 8393 auxto = getstringkey(&idents, "to", 2); 8394 auxstep = getstringkey(&idents, "step", 4); 8395 8396 auxself = getstringkey(&idents, "self", 4); 8397 8398 if (argc >= 2) { 8399 initsource(source, argv[1], fopen(argv[1], "rb")); 8400 assert(source->filein); 8401 } else { 8402 highlight(stdout, HLPROMPT); 8403 printf("> "); 8404 highlight(stdout, HLNONE); 8405 initsource(source, "<stdin>", stdin); 8406 } 8407 8408 processfile(source); 8409 8410 /* fclose(source->filein); */ 8411 /* disposestrmap(&strings); */ 8412 /* disposestrmap(&idents); */ 8413 8414 return !!errorcount; 8415 } 8416 8417 // }}}