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