1 /* Copyright (c) 1982 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)symbols.c 1.2 12/15/82"; 4 5 /* 6 * Symbol management. 7 */ 8 9 #include "defs.h" 10 #include "symbols.h" 11 #include "languages.h" 12 #include "printsym.h" 13 #include "tree.h" 14 #include "operators.h" 15 #include "eval.h" 16 #include "mappings.h" 17 #include "events.h" 18 #include "process.h" 19 #include "runtime.h" 20 #include "machine.h" 21 #include "names.h" 22 23 #ifndef public 24 typedef struct Symbol *Symbol; 25 26 #include "machine.h" 27 #include "names.h" 28 #include "languages.h" 29 30 /* 31 * Symbol classes 32 */ 33 34 typedef enum { 35 BADUSE, CONST, TYPE, VAR, ARRAY, PTRFILE, RECORD, FIELD, 36 PROC, FUNC, FVAR, REF, PTR, FILET, SET, RANGE, 37 LABEL, WITHPTR, SCAL, STR, PROG, IMPROPER, VARNT, 38 FPROC, FFUNC, MODULE, TYPEREF, TAG 39 } Symclass; 40 41 struct Symbol { 42 Name name; 43 Language language; 44 Symclass class : 8; 45 Integer level : 8; 46 Symbol type; 47 Symbol chain; 48 union { 49 int offset; /* variable address */ 50 long iconval; /* integer constant value */ 51 double fconval; /* floating constant value */ 52 struct { /* field offset and size (both in bits) */ 53 int offset; 54 int length; 55 } field; 56 struct { /* range bounds */ 57 long lower; 58 long upper; 59 } rangev; 60 struct { /* address of function value, code */ 61 int offset; 62 Address beginaddr; 63 } funcv; 64 struct { /* variant record info */ 65 int size; 66 Symbol vtorec; 67 Symbol vtag; 68 } varnt; 69 } symvalue; 70 Symbol block; /* symbol containing this symbol */ 71 Symbol next_sym; /* hash chain */ 72 }; 73 74 /* 75 * Basic types. 76 */ 77 78 Symbol t_boolean; 79 Symbol t_char; 80 Symbol t_int; 81 Symbol t_real; 82 Symbol t_nil; 83 84 Symbol program; 85 Symbol curfunc; 86 87 #define symname(s) ident(s->name) 88 #define codeloc(f) ((f)->symvalue.funcv.beginaddr) 89 #define isblock(s) (Boolean) ( \ 90 s->class == FUNC or s->class == PROC or \ 91 s->class == MODULE or s->class == PROG \ 92 ) 93 94 #include "tree.h" 95 96 /* 97 * Some macros to make finding a symbol with certain attributes. 98 */ 99 100 #define find(s, withname) \ 101 { \ 102 s = lookup(withname); \ 103 while (s != nil and not (s->name == (withname) and 104 105 #define where /* qualification */ 106 107 #define endfind(s) )) { \ 108 s = s->next_sym; \ 109 } \ 110 } 111 112 #endif 113 114 /* 115 * Symbol table structure currently does not support deletions. 116 */ 117 118 #define HASHTABLESIZE 2003 119 120 private Symbol hashtab[HASHTABLESIZE]; 121 122 #define hash(name) ((((unsigned) name) >> 2) mod HASHTABLESIZE) 123 124 /* 125 * Allocate a new symbol. 126 */ 127 128 #define SYMBLOCKSIZE 1000 129 130 typedef struct Sympool { 131 struct Symbol sym[SYMBLOCKSIZE]; 132 struct Sympool *prevpool; 133 } *Sympool; 134 135 private Sympool sympool = nil; 136 private Integer nleft = 0; 137 private struct Sympool zeropool; 138 139 public Symbol symbol_alloc() 140 { 141 register Sympool newpool; 142 143 if (nleft <= 0) { 144 newpool = new(Sympool); 145 *newpool = zeropool; 146 newpool->prevpool = sympool; 147 sympool = newpool; 148 nleft = SYMBLOCKSIZE; 149 } 150 --nleft; 151 return &(sympool->sym[nleft]); 152 } 153 154 /* 155 * Free all the symbols currently allocated. 156 */ 157 158 public symbol_free() 159 { 160 Sympool s, t; 161 register Integer i; 162 163 s = sympool; 164 while (s != nil) { 165 t = s->prevpool; 166 dispose(s); 167 s = t; 168 } 169 for (i = 0; i < HASHTABLESIZE; i++) { 170 hashtab[i] = nil; 171 } 172 sympool = nil; 173 nleft = 0; 174 } 175 176 /* 177 * Create a new symbol with the given attributes. 178 */ 179 180 public Symbol newSymbol(name, blevel, class, type, chain) 181 Name name; 182 Integer blevel; 183 Symclass class; 184 Symbol type; 185 Symbol chain; 186 { 187 register Symbol s; 188 189 s = symbol_alloc(); 190 s->name = name; 191 s->level = blevel; 192 s->class = class; 193 s->type = type; 194 s->chain = chain; 195 return s; 196 } 197 198 /* 199 * Insert a symbol into the hash table. 200 */ 201 202 public Symbol insert(name) 203 Name name; 204 { 205 register Symbol s; 206 register unsigned int h; 207 208 h = hash(name); 209 s = symbol_alloc(); 210 s->name = name; 211 s->next_sym = hashtab[h]; 212 hashtab[h] = s; 213 return s; 214 } 215 216 /* 217 * Symbol lookup. 218 */ 219 220 public Symbol lookup(name) 221 Name name; 222 { 223 register Symbol s; 224 register unsigned int h; 225 226 h = hash(name); 227 s = hashtab[h]; 228 while (s != nil and s->name != name) { 229 s = s->next_sym; 230 } 231 return s; 232 } 233 234 /* 235 * Dump out all the variables associated with the given 236 * procedure, function, or program at the given recursive level. 237 * 238 * This is quite inefficient. We traverse the entire symbol table 239 * each time we're called. The assumption is that this routine 240 * won't be called frequently enough to merit improved performance. 241 */ 242 243 public dumpvars(f, frame) 244 Symbol f; 245 Frame frame; 246 { 247 register Integer i; 248 register Symbol s; 249 250 for (i = 0; i < HASHTABLESIZE; i++) { 251 for (s = hashtab[i]; s != nil; s = s->next_sym) { 252 if (container(s) == f) { 253 if (should_print(s)) { 254 printv(s, frame); 255 putchar('\n'); 256 } else if (s->class == MODULE) { 257 dumpvars(s, frame); 258 } 259 } 260 } 261 } 262 } 263 264 /* 265 * Create a builtin type. 266 * Builtin types are circular in that btype->type->type = btype. 267 */ 268 269 public Symbol maketype(name, lower, upper) 270 String name; 271 long lower; 272 long upper; 273 { 274 register Symbol s; 275 276 s = newSymbol(identname(name, true), 0, TYPE, nil, nil); 277 s->language = findlanguage(".c"); 278 s->type = newSymbol(nil, 0, RANGE, s, nil); 279 s->type->symvalue.rangev.lower = lower; 280 s->type->symvalue.rangev.upper = upper; 281 return s; 282 } 283 284 /* 285 * These functions are now compiled inline. 286 * 287 * public String symname(s) 288 Symbol s; 289 { 290 checkref(s); 291 return ident(s->name); 292 } 293 294 * 295 * public Address codeloc(f) 296 Symbol f; 297 { 298 checkref(f); 299 if (not isblock(f)) { 300 panic("codeloc: \"%s\" is not a block", ident(f->name)); 301 } 302 return f->symvalue.funcv.beginaddr; 303 } 304 * 305 */ 306 307 /* 308 * Reduce type to avoid worrying about type names. 309 */ 310 311 public Symbol rtype(type) 312 Symbol type; 313 { 314 register Symbol t; 315 316 t = type; 317 if (t != nil) { 318 if (t->class == VAR or t->class == FIELD) { 319 t = t->type; 320 } 321 while (t->class == TYPE or t->class == TAG) { 322 t = t->type; 323 } 324 } 325 return t; 326 } 327 328 public Integer level(s) 329 Symbol s; 330 { 331 checkref(s); 332 return s->level; 333 } 334 335 public Symbol container(s) 336 Symbol s; 337 { 338 checkref(s); 339 return s->block; 340 } 341 342 /* 343 * Return the object address of the given symbol. 344 * 345 * There are the following possibilities: 346 * 347 * globals - just take offset 348 * locals - take offset from locals base 349 * arguments - take offset from argument base 350 * register - offset is register number 351 */ 352 353 #define isglobal(s) (s->level == 1 or s->level == 2) 354 #define islocaloff(s) (s->level >= 3 and s->symvalue.offset < 0) 355 #define isparamoff(s) (s->level >= 3 and s->symvalue.offset >= 0) 356 #define isreg(s) (s->level < 0) 357 358 public Address address(s, frame) 359 Symbol s; 360 Frame frame; 361 { 362 register Frame frp; 363 register Address addr; 364 register Symbol cur; 365 366 checkref(s); 367 if (not isactive(s->block)) { 368 error("\"%s\" is not currently defined", symname(s)); 369 } else if (isglobal(s)) { 370 addr = s->symvalue.offset; 371 } else { 372 frp = frame; 373 if (frp == nil) { 374 cur = s->block; 375 while (cur != nil and cur->class == MODULE) { 376 cur = cur->block; 377 } 378 if (cur == nil) { 379 cur = whatblock(pc); 380 } 381 frp = findframe(cur); 382 if (frp == nil) { 383 panic("unexpected nil frame for \"%s\"", symname(s)); 384 } 385 } 386 if (islocaloff(s)) { 387 addr = locals_base(frp) + s->symvalue.offset; 388 } else if (isparamoff(s)) { 389 addr = args_base(frp) + s->symvalue.offset; 390 } else if (isreg(s)) { 391 addr = savereg(s->symvalue.offset, frp); 392 } else { 393 panic("address: bad symbol \"%s\"", symname(s)); 394 } 395 } 396 return addr; 397 } 398 399 /* 400 * Define a symbol used to access register values. 401 */ 402 403 public defregname(n, r) 404 Name n; 405 Integer r; 406 { 407 register Symbol s, t; 408 409 s = insert(n); 410 t = newSymbol(nil, 0, PTR, t_int, nil); 411 t->language = findlanguage(".s"); 412 s->language = t->language; 413 s->class = VAR; 414 s->level = -3; 415 s->type = t; 416 s->block = program; 417 s->symvalue.offset = r; 418 } 419 420 /* 421 * Resolve an "abstract" type reference. 422 * 423 * It is possible in C to define a pointer to a type, but never define 424 * the type in a particular source file. Here we try to resolve 425 * the type definition. This is problematic, it is possible to 426 * have multiple, different definitions for the same name type. 427 */ 428 429 public findtype(s) 430 Symbol s; 431 { 432 register Symbol t, u, prev; 433 434 u = s; 435 prev = nil; 436 while (u != nil and u->class != BADUSE) { 437 if (u->name != nil) { 438 prev = u; 439 } 440 u = u->type; 441 } 442 if (prev == nil) { 443 error("couldn't find link to type reference"); 444 } 445 find(t, prev->name) where 446 t->type != nil and t->class == prev->class and 447 t->type->class != BADUSE and t->block->class == MODULE 448 endfind(t); 449 if (t == nil) { 450 error("couldn't resolve reference"); 451 } else { 452 prev->type = t->type; 453 } 454 } 455 456 /* 457 * Find the size in bytes of the given type. 458 * 459 * This is probably the WRONG thing to do. The size should be kept 460 * as an attribute in the symbol information as is done for structures 461 * and fields. I haven't gotten around to cleaning this up yet. 462 */ 463 464 #define MINCHAR -128 465 #define MAXCHAR 127 466 #define MINSHORT -32768 467 #define MAXSHORT 32767 468 469 public Integer size(sym) 470 Symbol sym; 471 { 472 register Symbol s, t; 473 register int nel, elsize; 474 long lower, upper; 475 int r; 476 477 t = sym; 478 checkref(t); 479 switch (t->class) { 480 case RANGE: 481 lower = t->symvalue.rangev.lower; 482 upper = t->symvalue.rangev.upper; 483 if (upper == 0 and lower > 0) { /* real */ 484 r = lower; 485 } else if (lower >= MINCHAR and upper <= MAXCHAR) { 486 r = sizeof(char); 487 } else if (lower >= MINSHORT and upper <= MAXSHORT) { 488 r = sizeof(short); 489 } else { 490 r = sizeof(long); 491 } 492 break; 493 494 case ARRAY: 495 elsize = size(t->type); 496 nel = 1; 497 for (t = t->chain; t != nil; t = t->chain) { 498 s = rtype(t); 499 lower = s->symvalue.rangev.lower; 500 upper = s->symvalue.rangev.upper; 501 nel *= (upper-lower+1); 502 } 503 r = nel*elsize; 504 break; 505 506 case VAR: 507 case FVAR: 508 r = size(t->type); 509 if (r < sizeof(Word)) { 510 r = sizeof(Word); 511 } 512 break; 513 514 case CONST: 515 r = size(t->type); 516 break; 517 518 case TYPE: 519 if (t->type->class == PTR and t->type->type->class == BADUSE) { 520 findtype(t); 521 } 522 r = size(t->type); 523 break; 524 525 case TAG: 526 r = size(t->type); 527 break; 528 529 case FIELD: 530 r = (t->symvalue.field.length + 7) div 8; 531 break; 532 533 case RECORD: 534 case VARNT: 535 r = t->symvalue.offset; 536 if (r == 0 and t->chain != nil) { 537 panic("missing size information for record"); 538 } 539 break; 540 541 case PTR: 542 case REF: 543 case FILET: 544 r = sizeof(Word); 545 break; 546 547 case SCAL: 548 if (t->symvalue.iconval > 255) { 549 r = sizeof(short); 550 } else { 551 r = sizeof(char); 552 } 553 break; 554 555 case FPROC: 556 case FFUNC: 557 r = sizeof(Word); 558 break; 559 560 case PROC: 561 case FUNC: 562 case MODULE: 563 case PROG: 564 r = sizeof(Symbol); 565 break; 566 567 default: 568 if (ord(t->class) > ord(TYPEREF)) { 569 panic("size: bad class (%d)", ord(t->class)); 570 } else { 571 error("improper operation on a %s", classname(t)); 572 } 573 /* NOTREACHED */ 574 } 575 if (r < sizeof(Word) and isparam(sym)) { 576 r = sizeof(Word); 577 } 578 return r; 579 } 580 581 /* 582 * Test if a symbol is a parameter. This is true if there 583 * is a cycle from s->block to s via chain pointers. 584 */ 585 586 public Boolean isparam(s) 587 Symbol s; 588 { 589 register Symbol t; 590 591 t = s->block; 592 while (t != nil and t != s) { 593 t = t->chain; 594 } 595 return (Boolean) (t != nil); 596 } 597 598 /* 599 * Test if a symbol is a var parameter, i.e. has class REF. 600 */ 601 602 public Boolean isvarparam(s) 603 Symbol s; 604 { 605 return (Boolean) (s->class == REF); 606 } 607 608 /* 609 * Test if a symbol is a variable (actually any addressible quantity 610 * with do). 611 */ 612 613 public Boolean isvariable(s) 614 register Symbol s; 615 { 616 return (Boolean) (s->class == VAR or s->class == FVAR or s->class == REF); 617 } 618 619 /* 620 * Test if a symbol is a block, e.g. function, procedure, or the 621 * main program. 622 * 623 * This function is now expanded inline for efficiency. 624 * 625 * public Boolean isblock(s) 626 register Symbol s; 627 { 628 return (Boolean) ( 629 s->class == FUNC or s->class == PROC or 630 s->class == MODULE or s->class == PROG 631 ); 632 } 633 * 634 */ 635 636 /* 637 * Test if a symbol is a module. 638 */ 639 640 public Boolean ismodule(s) 641 register Symbol s; 642 { 643 return (Boolean) (s->class == MODULE); 644 } 645 646 /* 647 * Test if a symbol is builtin, that is, a predefined type or 648 * reserved word. 649 */ 650 651 public Boolean isbuiltin(s) 652 register Symbol s; 653 { 654 return (Boolean) (s->level == 0 and s->class != PROG and s->class != VAR); 655 } 656 657 /* 658 * Test if two types match. 659 * Equivalent names implies a match in any language. 660 * 661 * Special symbols must be handled with care. 662 */ 663 664 public Boolean compatible(t1, t2) 665 register Symbol t1, t2; 666 { 667 Boolean b; 668 669 if (t1 == t2) { 670 b = true; 671 } else if (t1 == nil or t2 == nil) { 672 b = false; 673 } else if (t1 == procsym) { 674 b = isblock(t2); 675 } else if (t2 == procsym) { 676 b = isblock(t1); 677 } else if (t1->language == nil) { 678 b = (Boolean) (t2->language == nil or 679 (*language_op(t2->language, L_TYPEMATCH))(t1, t2)); 680 } else { 681 b = (Boolean) (*language_op(t1->language, L_TYPEMATCH))(t1, t2); 682 } 683 return b; 684 } 685 686 /* 687 * Check for a type of the given name. 688 */ 689 690 public Boolean istypename(type, name) 691 Symbol type; 692 String name; 693 { 694 Symbol t; 695 Boolean b; 696 697 t = type; 698 checkref(t); 699 b = (Boolean) ( 700 t->class == TYPE and t->name == identname(name, true) 701 ); 702 return b; 703 } 704 705 /* 706 * Test if the name of a symbol is uniquely defined or not. 707 */ 708 709 public Boolean isambiguous(s) 710 register Symbol s; 711 { 712 register Symbol t; 713 714 find(t, s->name) where t != s endfind(t); 715 return (Boolean) (t != nil); 716 } 717 718 typedef char *Arglist; 719 720 #define nextarg(type) ((type *) (ap += sizeof(type)))[-1] 721 722 private Symbol mkstring(); 723 private Symbol namenode(); 724 725 /* 726 * Determine the type of a parse tree. 727 * Also make some symbol-dependent changes to the tree such as 728 * changing removing RVAL nodes for constant symbols. 729 */ 730 731 public assigntypes(p) 732 register Node p; 733 { 734 register Node p1; 735 register Symbol s; 736 737 switch (p->op) { 738 case O_SYM: 739 p->nodetype = namenode(p); 740 break; 741 742 case O_LCON: 743 p->nodetype = t_int; 744 break; 745 746 case O_FCON: 747 p->nodetype = t_real; 748 break; 749 750 case O_SCON: 751 p->value.scon = strdup(p->value.scon); 752 s = mkstring(p->value.scon); 753 if (s == t_char) { 754 p->op = O_LCON; 755 p->value.lcon = p->value.scon[0]; 756 } 757 p->nodetype = s; 758 break; 759 760 case O_INDIR: 761 p1 = p->value.arg[0]; 762 chkclass(p1, PTR); 763 p->nodetype = rtype(p1->nodetype)->type; 764 break; 765 766 case O_DOT: 767 p->nodetype = p->value.arg[1]->value.sym; 768 break; 769 770 case O_RVAL: 771 p1 = p->value.arg[0]; 772 p->nodetype = p1->nodetype; 773 if (p1->op == O_SYM) { 774 if (p1->nodetype->class == FUNC) { 775 p->op = O_CALL; 776 p->value.arg[1] = nil; 777 } else if (p1->value.sym->class == CONST) { 778 if (compatible(p1->value.sym->type, t_real)) { 779 p->op = O_FCON; 780 p->value.fcon = p1->value.sym->symvalue.fconval; 781 p->nodetype = t_real; 782 dispose(p1); 783 } else { 784 p->op = O_LCON; 785 p->value.lcon = p1->value.sym->symvalue.iconval; 786 p->nodetype = p1->value.sym->type; 787 dispose(p1); 788 } 789 } else if (isreg(p1->value.sym)) { 790 p->op = O_SYM; 791 p->value.sym = p1->value.sym; 792 dispose(p1); 793 } 794 } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) { 795 s = p1->value.arg[0]->value.sym; 796 if (isreg(s)) { 797 p1->op = O_SYM; 798 dispose(p1->value.arg[0]); 799 p1->value.sym = s; 800 p1->nodetype = s; 801 } 802 } 803 break; 804 805 /* 806 * Perform a cast if the call is of the form "type(expr)". 807 */ 808 case O_CALL: 809 p1 = p->value.arg[0]; 810 if (p1->op == O_SYM and 811 (p1->value.sym->class == TYPE or p1->value.sym->class == TAG)) { 812 s = p1->value.sym; 813 dispose(p1); 814 p1 = p->value.arg[1]; 815 assert(p1->op == O_COMMA); 816 if (p1->value.arg[1] != nil) { 817 error("unexpected comma within type conversion"); 818 } 819 p->op = O_RVAL; 820 p->value.arg[0] = p1->value.arg[0]; 821 p->nodetype = s; 822 p->value.arg[0]->nodetype = s; 823 dispose(p1); 824 } else { 825 p->nodetype = rtype(p1->nodetype)->type; 826 } 827 break; 828 829 case O_ITOF: 830 p->nodetype = t_real; 831 break; 832 833 case O_NEG: 834 s = p->value.arg[0]->nodetype; 835 if (not compatible(s, t_int)) { 836 if (not compatible(s, t_real)) { 837 beginerrmsg(); 838 prtree(stderr, p->value.arg[0]); 839 fprintf(stderr, "is improper type"); 840 enderrmsg(); 841 } else { 842 p->op = O_NEGF; 843 } 844 } 845 p->nodetype = s; 846 break; 847 848 case O_ADD: 849 case O_SUB: 850 case O_MUL: 851 case O_LT: 852 case O_LE: 853 case O_GT: 854 case O_GE: 855 case O_EQ: 856 case O_NE: 857 { 858 Boolean t1real, t2real; 859 Symbol t1, t2; 860 861 t1 = rtype(p->value.arg[0]->nodetype); 862 t2 = rtype(p->value.arg[1]->nodetype); 863 t1real = compatible(t1, t_real); 864 t2real = compatible(t2, t_real); 865 if (t1real or t2real) { 866 p->op = (Operator) (ord(p->op) + 1); 867 if (not t1real) { 868 p->value.arg[0] = build(O_ITOF, p->value.arg[0]); 869 } else if (not t2real) { 870 p->value.arg[1] = build(O_ITOF, p->value.arg[1]); 871 } 872 } else { 873 if (t1real) { 874 convert(&(p->value.arg[0]), t_int, O_NOP); 875 } 876 if (t2real) { 877 convert(&(p->value.arg[1]), t_int, O_NOP); 878 } 879 } 880 if (ord(p->op) >= ord(O_LT)) { 881 p->nodetype = t_boolean; 882 } else { 883 if (t1real or t2real) { 884 p->nodetype = t_real; 885 } else { 886 p->nodetype = t_int; 887 } 888 } 889 break; 890 } 891 892 case O_DIVF: 893 convert(&(p->value.arg[0]), t_real, O_ITOF); 894 convert(&(p->value.arg[1]), t_real, O_ITOF); 895 p->nodetype = t_real; 896 break; 897 898 case O_DIV: 899 case O_MOD: 900 convert(&(p->value.arg[0]), t_int, O_NOP); 901 convert(&(p->value.arg[1]), t_int, O_NOP); 902 p->nodetype = t_int; 903 break; 904 905 case O_AND: 906 case O_OR: 907 chkboolean(p->value.arg[0]); 908 chkboolean(p->value.arg[1]); 909 p->nodetype = t_boolean; 910 break; 911 912 case O_QLINE: 913 p->nodetype = t_int; 914 break; 915 916 default: 917 p->nodetype = nil; 918 break; 919 } 920 } 921 922 /* 923 * Create a node for a name. The symbol for the name has already 924 * been chosen, either implicitly with "which" or explicitly from 925 * the dot routine. 926 */ 927 928 private Symbol namenode(p) 929 Node p; 930 { 931 register Symbol r, s; 932 register Node np; 933 934 s = p->value.sym; 935 if (s->class == REF) { 936 np = new(Node); 937 np->op = p->op; 938 np->nodetype = s; 939 np->value.sym = s; 940 p->op = O_INDIR; 941 p->value.arg[0] = np; 942 } 943 /* 944 * Old way 945 * 946 if (s->class == CONST or s->class == VAR or s->class == FVAR) { 947 r = s->type; 948 } else { 949 r = s; 950 } 951 * 952 */ 953 return s; 954 } 955 956 /* 957 * Convert a tree to a type via a conversion operator; 958 * if this isn't possible generate an error. 959 * 960 * Note the tree is call by address, hence the #define below. 961 */ 962 963 private convert(tp, typeto, op) 964 Node *tp; 965 Symbol typeto; 966 Operator op; 967 { 968 #define tree (*tp) 969 970 Symbol s; 971 972 s = rtype(tree->nodetype); 973 typeto = rtype(typeto); 974 if (compatible(typeto, t_real) and compatible(s, t_int)) { 975 tree = build(op, tree); 976 } else if (not compatible(s, typeto)) { 977 beginerrmsg(); 978 prtree(stderr, s); 979 fprintf(stderr, " is improper type"); 980 enderrmsg(); 981 } else if (op != O_NOP and s != typeto) { 982 tree = build(op, tree); 983 } 984 985 #undef tree 986 } 987 988 /* 989 * Construct a node for the dot operator. 990 * 991 * If the left operand is not a record, but rather a procedure 992 * or function, then we interpret the "." as referencing an 993 * "invisible" variable; i.e. a variable within a dynamically 994 * active block but not within the static scope of the current procedure. 995 */ 996 997 public Node dot(record, fieldname) 998 Node record; 999 Name fieldname; 1000 { 1001 register Node p; 1002 register Symbol s, t; 1003 1004 if (isblock(record->nodetype)) { 1005 find(s, fieldname) where 1006 s->block == record->nodetype and 1007 s->class != FIELD and s->class != TAG 1008 endfind(s); 1009 if (s == nil) { 1010 beginerrmsg(); 1011 fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname)); 1012 printname(stderr, record->nodetype); 1013 enderrmsg(); 1014 } 1015 p = new(Node); 1016 p->op = O_SYM; 1017 p->value.sym = s; 1018 p->nodetype = namenode(p); 1019 } else { 1020 p = record; 1021 t = rtype(p->nodetype); 1022 if (t->class == PTR) { 1023 s = findfield(fieldname, t->type); 1024 } else { 1025 s = findfield(fieldname, t); 1026 } 1027 if (s == nil) { 1028 beginerrmsg(); 1029 fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname)); 1030 prtree(stderr, record); 1031 enderrmsg(); 1032 } 1033 if (t->class == PTR and not isreg(record->nodetype)) { 1034 p = build(O_INDIR, record); 1035 } 1036 p = build(O_DOT, p, build(O_SYM, s)); 1037 } 1038 return p; 1039 } 1040 1041 /* 1042 * Return a tree corresponding to an array reference and do the 1043 * error checking. 1044 */ 1045 1046 public Node subscript(a, slist) 1047 Node a, slist; 1048 { 1049 register Symbol t; 1050 register Node p; 1051 Symbol etype, atype, eltype; 1052 Node esub, olda; 1053 1054 olda = a; 1055 t = rtype(a->nodetype); 1056 if (t->class != ARRAY) { 1057 beginerrmsg(); 1058 prtree(stderr, a); 1059 fprintf(stderr, " is not an array"); 1060 enderrmsg(); 1061 } 1062 eltype = t->type; 1063 p = slist; 1064 t = t->chain; 1065 for (; p != nil and t != nil; p = p->value.arg[1], t = t->chain) { 1066 esub = p->value.arg[0]; 1067 etype = rtype(esub->nodetype); 1068 atype = rtype(t); 1069 if (not compatible(atype, etype)) { 1070 beginerrmsg(); 1071 fprintf(stderr, "subscript "); 1072 prtree(stderr, esub); 1073 fprintf(stderr, " is the wrong type"); 1074 enderrmsg(); 1075 } 1076 a = build(O_INDEX, a, esub); 1077 a->nodetype = eltype; 1078 } 1079 if (p != nil or t != nil) { 1080 beginerrmsg(); 1081 if (p != nil) { 1082 fprintf(stderr, "too many subscripts for "); 1083 } else { 1084 fprintf(stderr, "not enough subscripts for "); 1085 } 1086 prtree(stderr, olda); 1087 enderrmsg(); 1088 } 1089 return a; 1090 } 1091 1092 /* 1093 * Evaluate a subscript index. 1094 */ 1095 1096 public int evalindex(s, i) 1097 Symbol s; 1098 long i; 1099 { 1100 long lb, ub; 1101 1102 s = rtype(s)->chain; 1103 lb = s->symvalue.rangev.lower; 1104 ub = s->symvalue.rangev.upper; 1105 if (i < lb or i > ub) { 1106 error("subscript out of range"); 1107 } 1108 return (i - lb); 1109 } 1110 1111 /* 1112 * Check to see if a tree is boolean-valued, if not it's an error. 1113 */ 1114 1115 public chkboolean(p) 1116 register Node p; 1117 { 1118 if (p->nodetype != t_boolean) { 1119 beginerrmsg(); 1120 fprintf(stderr, "found "); 1121 prtree(stderr, p); 1122 fprintf(stderr, ", expected boolean expression"); 1123 enderrmsg(); 1124 } 1125 } 1126 1127 /* 1128 * Check to make sure the given tree has a type of the given class. 1129 */ 1130 1131 private chkclass(p, class) 1132 Node p; 1133 Symclass class; 1134 { 1135 struct Symbol tmpsym; 1136 1137 tmpsym.class = class; 1138 if (rtype(p->nodetype)->class != class) { 1139 beginerrmsg(); 1140 fprintf(stderr, "\""); 1141 prtree(stderr, p); 1142 fprintf(stderr, "\" is not a %s", classname(&tmpsym)); 1143 enderrmsg(); 1144 } 1145 } 1146 1147 /* 1148 * Construct a node for the type of a string. While we're at it, 1149 * scan the string for '' that collapse to ', and chop off the ends. 1150 */ 1151 1152 private Symbol mkstring(str) 1153 String str; 1154 { 1155 register char *p, *q; 1156 register Symbol s; 1157 1158 p = str; 1159 q = str; 1160 while (*p != '\0') { 1161 if (*p == '\\') { 1162 ++p; 1163 } 1164 *q = *p; 1165 ++p; 1166 ++q; 1167 } 1168 *q = '\0'; 1169 s = newSymbol(nil, 0, ARRAY, t_char, nil); 1170 s->language = findlanguage(".s"); 1171 s->chain = newSymbol(nil, 0, RANGE, t_int, nil); 1172 s->chain->language = s->language; 1173 s->chain->symvalue.rangev.lower = 1; 1174 s->chain->symvalue.rangev.upper = p - str + 1; 1175 return s; 1176 } 1177 1178 /* 1179 * Free up the space allocated for a string type. 1180 */ 1181 1182 public unmkstring(s) 1183 Symbol s; 1184 { 1185 dispose(s->chain); 1186 } 1187 1188 /* 1189 * Figure out the "current" variable or function being referred to, 1190 * this is either the active one or the most visible from the 1191 * current scope. 1192 */ 1193 1194 public Symbol which(n) 1195 Name n; 1196 { 1197 register Symbol s, p, t, f; 1198 1199 find(s, n) where s->class != FIELD and s->class != TAG endfind(s); 1200 if (s == nil) { 1201 s = lookup(n); 1202 } 1203 if (s == nil) { 1204 error("\"%s\" is not defined", ident(n)); 1205 } else if (s == program or isbuiltin(s)) { 1206 t = s; 1207 } else { 1208 /* 1209 * Old way 1210 * 1211 if (not isactive(program)) { 1212 f = program; 1213 } else { 1214 f = whatblock(pc); 1215 if (f == nil) { 1216 panic("no block for addr 0x%x", pc); 1217 } 1218 } 1219 * 1220 * Now start with curfunc. 1221 */ 1222 p = curfunc; 1223 do { 1224 find(t, n) where 1225 t->block == p and t->class != FIELD and t->class != TAG 1226 endfind(t); 1227 p = p->block; 1228 } while (t == nil and p != nil); 1229 if (t == nil) { 1230 t = s; 1231 } 1232 } 1233 return t; 1234 } 1235 1236 /* 1237 * Find the symbol which is has the same name and scope as the 1238 * given symbol but is of the given field. Return nil if there is none. 1239 */ 1240 1241 public Symbol findfield(fieldname, record) 1242 Name fieldname; 1243 Symbol record; 1244 { 1245 register Symbol t; 1246 1247 t = rtype(record)->chain; 1248 while (t != nil and t->name != fieldname) { 1249 t = t->chain; 1250 } 1251 return t; 1252 } 1253