|
|
1.1 ! root 1: .bp ! 2: .ce 10 ! 3: \f3Appendix A \(em The Parse Tree\fR ! 4: .ce 0 ! 5: .sp 1 ! 6: .PP ! 7: The parse tree is a collection of nodes, described below, ! 8: rooted at a ! 9: \f3proc\fR ! 10: node. ! 11: Nodes have a common format: ! 12: the first field contains the node type, ! 13: the second and third fields contain a line and column number ! 14: relating the node to the source program, ! 15: and the next zero to four fields contain node-dependent information. ! 16: The line and column numbers are usually those of the first token ! 17: or the primary token of the construct; ! 18: for example, in ! 19: \f3binop\fR ! 20: nodes, they are the location of the operator; in ! 21: \f3if\fR ! 22: nodes, they are the location of the ! 23: \fMif\fR ! 24: token. ! 25: .PP ! 26: The following list of node types ! 27: gives a brief description of the node and ! 28: a list of the node-dependent fields and their uses. ! 29: The fields are named ! 30: .I val ! 31: if they contain an integer value, ! 32: .I str ! 33: if they contain a pointer to a string, or ! 34: .I tree ! 35: if they contain a pointer to another node (a leaf or subtree). ! 36: A digit between ! 37: 0 and 3 ! 38: is appended indicating its position in the node. ! 39: .PP ! 40: Seven of the nodes \(em ! 41: \f3cset\fR, ! 42: \f3id\fR, ! 43: \f3int\fR, ! 44: \f3op\fR, ! 45: \f3real\fR, ! 46: \f3res\fR, ! 47: and ! 48: \f3str\fR ! 49: \(em are leaf nodes. ! 50: These nodes, allocated and returned by the lexical analyzer, ! 51: represent source program tokens. ! 52: The remaining nodes contain one or more pointers to other nodes, ! 53: either leaves or subtrees. ! 54: .LP ! 55: .nr Z \n(PD ! 56: .nr PD \nZ ! 57: .de X ! 58: .IP \f3\\$1\fR 8n ! 59: .. ! 60: .de Y ! 61: .nr PD 0 ! 62: .IP \h'10n'\fI\\$1\fR \w'\fItree1'u+12n ! 63: .. ! 64: .sp \nZu ! 65: .KS ! 66: .X activat ! 67: A transmission expression (\fIe1\fR @ \fIe2\fR). ! 68: .Y tree0 ! 69: The operator (an \f3op\fR node). ! 70: .Y tree1 ! 71: \fIe1\fR. ! 72: .Y tree2 ! 73: \fIe2\fR. ! 74: .KE ! 75: .sp \nZu ! 76: .KS ! 77: .X alt ! 78: An alternation expression (\fIe1\fR | \fIe2\fR). ! 79: .Y tree0 ! 80: \fIe1\fR. ! 81: .Y tree1 ! 82: \fIe2\fR. ! 83: .KE ! 84: .sp \nZu ! 85: .KS ! 86: .X augop ! 87: An augmented assignment expression (\fIe1\fR \(ci\fM:=\fR \fIe2\fR). ! 88: .Y tree0 ! 89: The operator. ! 90: .Y tree1 ! 91: \fIe1\fR. ! 92: .Y tree2 ! 93: \fIe1\fR. ! 94: .KE ! 95: .sp \nZu ! 96: .KS ! 97: .X bar ! 98: A repeated alternation expression (\^\^|\fIe\fR). ! 99: .Y tree0 ! 100: \fIe\fR. ! 101: .KE ! 102: .sp \nZu ! 103: .KS ! 104: .X binop ! 105: A binary operation (\fIe1\fR \(ci \fIe2\fR). ! 106: .Y tree0 ! 107: The operator. ! 108: .Y tree1 ! 109: \fIe1\fR. ! 110: .Y tree2 ! 111: \fIe2\fR. ! 112: .KE ! 113: .sp \nZu ! 114: .KS ! 115: .X break ! 116: A ! 117: \fMbreak\fR ! 118: expression (\fMbreak [\fIe\fM]\fR). ! 119: .Y tree0 ! 120: \fIe\fR. ! 121: .KE ! 122: .sp \nZu ! 123: .KS ! 124: .X case ! 125: A ! 126: \fMcase\fR ! 127: expression (\fMcase \fIe\fM of { \*(El }\fR). ! 128: .Y tree0 ! 129: \fIe\fR. ! 130: .Y tree1 ! 131: The list of case clauses. ! 132: If there is only one case clause, this field points to the ! 133: \f3ccls\fR ! 134: node; if there are more, it points to a ! 135: \f3clist\fR ! 136: node. ! 137: .KE ! 138: .sp \nZu ! 139: .KS ! 140: .X ccls ! 141: A case clause ! 142: (\fIe1\fR : \fIe2\fR). ! 143: .Y tree0 ! 144: \fIe1\fR. ! 145: For a ! 146: \fMdefault\fR ! 147: clause, this field points to a ! 148: \f3res\fR ! 149: node that contains the reserved word ! 150: \fMdefault\fR. ! 151: .Y tree1 ! 152: \fIe2\fR. ! 153: .KE ! 154: .sp \nZu ! 155: .KS ! 156: .X clist ! 157: A list of case clauses. ! 158: The list is represented as a binary tree, ! 159: with left branches pointing to case clauses ! 160: and right branches pointing to a list of the remaining case clauses. ! 161: The right branch of the last ! 162: \f3clist\fR ! 163: node points directly to a ! 164: \f3ccls\fR ! 165: node. ! 166: .Y tree0 ! 167: A case clause (pointer to a ! 168: \f3ccls\fR ! 169: node). ! 170: .Y tree1 ! 171: Pointer to another ! 172: \f3clist\fR ! 173: node, or to the last ! 174: \f3ccls\fR ! 175: node in the list. ! 176: .KE ! 177: .sp \nZu ! 178: .KS ! 179: .X conj ! 180: A conjunction expression (\fIe1 \fM&\fI e2\fR). ! 181: .Y tree0 ! 182: \fIe1\fR. ! 183: .Y tree1 ! 184: \fIe2\fR. ! 185: .KE ! 186: .sp \nZu ! 187: .KS ! 188: .X create ! 189: A \fMcreate\fR expression (\fMcreate\fI e\fR). ! 190: .Y tree0 ! 191: \fIe\fR. ! 192: .KE ! 193: .sp \nZu ! 194: .KS ! 195: .X cset ! 196: A leaf node representing a cset literal. ! 197: .Y str0 ! 198: The string equivalent of the literal. ! 199: .Y val1 ! 200: The length of the string. ! 201: .KE ! 202: .sp \nZu ! 203: .KS ! 204: .X elist ! 205: An expression list, as in a list construction ! 206: or the argument list in a procedure call. ! 207: An expression list, like a list of case clauses, ! 208: is represented as a binary tree. ! 209: .Y tree0 ! 210: An expression. ! 211: .Y tree1 ! 212: Pointer to another ! 213: \f3elist\fR ! 214: node, or to the last expression in the list. ! 215: .KE ! 216: .sp \nZu ! 217: .KS ! 218: .X empty ! 219: This node is used as a placeholder for missing expressions in ! 220: control structures and expression lists. ! 221: .KE ! 222: .sp \nZu ! 223: .KS ! 224: .X field ! 225: A field reference to a record (\fIe\fM . \fIident\fR). ! 226: .Y tree0 ! 227: \fIe\fR. ! 228: .Y tree1 ! 229: Pointer to an ! 230: \f3id\fR ! 231: node, containing the field name \fIident\fR. ! 232: .KE ! 233: .sp \nZu ! 234: .KS ! 235: .X id ! 236: A leaf node representing an identifier. ! 237: .Y str0 ! 238: The name of the identifier. ! 239: .KE ! 240: .sp \nZu ! 241: .KS ! 242: .X if ! 243: An ! 244: \fMif\fR ! 245: expression (\fMif\fI e1 \fMthen\fI e2 \fM[\fMelse\fI e3\fM]\fR). ! 246: .Y tree0 ! 247: \fIe1\fR. ! 248: .Y tree1 ! 249: \fIe2\fR. ! 250: .Y tree2 ! 251: \fIe3\fR. ! 252: .KE ! 253: .sp \nZu ! 254: .KS ! 255: .X int ! 256: A leaf node representing an integer literal. ! 257: .Y str0 ! 258: The string representation of the literal. ! 259: .KE ! 260: .sp \nZu ! 261: .KS ! 262: .X invok ! 263: A procedure call or mutual evaluation expression (\fIe\fM ( \fIargs\fM )\fR). ! 264: .Y tree0 ! 265: \fIe\fR. ! 266: .Y tree1 ! 267: The argument list \fIargs\fR. ! 268: If there is one argument, this field points to the expression; ! 269: if there are more, it points to an ! 270: .I elist ! 271: node. ! 272: .KE ! 273: .sp \nZu ! 274: .KS ! 275: .X key ! 276: A keyword reference (\fM&\fI\^ident\fR). ! 277: .Y val0 ! 278: The index of the keyword \fIident\fR, defined in the file ! 279: \fMtran/keyword.h\fR. ! 280: .KE ! 281: .sp \nZu ! 282: .KS ! 283: .X limit ! 284: A limitation expression (\fIe1\fR \e \fIe2\fR). ! 285: .Y tree0 ! 286: \fIe1\fR. ! 287: .Y tree1 ! 288: \fIe2\fR. ! 289: .KE ! 290: .sp \nZu ! 291: .X list ! 292: A list (\^\fM[\fIe1\fR, \fIe2\fR, \*(El \fM]\fR). ! 293: .Y tree0 ! 294: The list of elements. ! 295: If there is one element, this field points to the expression; ! 296: if there are more, it points to an ! 297: \f3elist\fR ! 298: node. ! 299: .KE ! 300: .sp \nZu ! 301: .KS ! 302: .X loop ! 303: A loop expression (\fIloop\fR \fIe1\fR [\fMdo\fI e2\fR]). ! 304: .Y tree0 ! 305: The style of loop. ! 306: This field points to a ! 307: \f3res\fR ! 308: node, which identifies the reserved word that introduced the loop. ! 309: .Y tree1 ! 310: \fIe1\fR. ! 311: .Y tree2 ! 312: \fIe2\fR. ! 313: .KE ! 314: .sp \nZu ! 315: .KS ! 316: .X next ! 317: A ! 318: \fMnext\fR ! 319: expression. ! 320: .Y ! 321: .sp -1 ! 322: .KE ! 323: .sp \nZu ! 324: .KS ! 325: .in 0 ! 326: .X not ! 327: A ! 328: \fMnot\fR ! 329: expression (\fNnot \fIe\fR). ! 330: .Y tree0 ! 331: \fIe\fR. ! 332: .KE ! 333: .sp \nZu ! 334: .KS ! 335: .X op ! 336: A leaf node representing an operator. ! 337: .Y val0 ! 338: The token type of the operator. ! 339: .KE ! 340: .sp \nZu ! 341: .KS ! 342: .X proc ! 343: A procedure. ! 344: This node is always at the root of the parse tree. ! 345: .Y tree0 ! 346: The procedure name. ! 347: This field points to an ! 348: \f3id\fR ! 349: node containing the name. ! 350: .Y tree1 ! 351: The ! 352: \fMinitial\fR ! 353: clause. ! 354: .Y tree2 ! 355: The procedure body. ! 356: If there is one expression in the procedure body, ! 357: this field points to it; ! 358: if there are more, it points to an ! 359: \f3elist\fR ! 360: node. ! 361: .Y tree3 ! 362: A node containing the ! 363: \fMend\fR ! 364: token. ! 365: This field is used to supply a line number for the implicit return ! 366: at the end of a procedure. ! 367: .KE ! 368: .sp \nZu ! 369: .KS ! 370: .X real ! 371: A leaf node representing a real number literal. ! 372: .Y str0 ! 373: The string representation of the literal. ! 374: .KE ! 375: .sp \nZu ! 376: .KS ! 377: .X res ! 378: A leaf node representing a reserved word. ! 379: .Y val0 ! 380: The token type of the reserved word. ! 381: .KE ! 382: .sp \nZu ! 383: .KS ! 384: .X ret ! 385: A ! 386: \fMreturn\fR ! 387: or ! 388: \fMfail\fR ! 389: expression. ! 390: .Y tree0 ! 391: The type of return. ! 392: This field points to a ! 393: \f3res\fR ! 394: node, which contains the reserved word ! 395: \fMreturn\fR ! 396: or ! 397: \fMfail\fR. ! 398: .Y tree1 ! 399: The expression following ! 400: \fMreturn\fR, ! 401: or a pointer to an ! 402: \f3empty\fR ! 403: node. ! 404: .KE ! 405: .sp \nZu ! 406: .KS ! 407: .X scan ! 408: A scanning expression (\fIe1\fR \fM?\fR \fIe2\fR). ! 409: .Y tree0 ! 410: The operator. ! 411: .Y tree1 ! 412: \fIe1\fR. ! 413: .Y tree2 ! 414: \fIe2\fR. ! 415: .KE ! 416: .sp \nZu ! 417: .KS ! 418: .X sect ! 419: A section expression (\fIe1\fR [\fIe2\fR : \fIe3\fR]). ! 420: .Y tree0 ! 421: \fIe1\fR. ! 422: .Y tree1 ! 423: \fIe2\fR. ! 424: .Y tree2 ! 425: \fIe3\fR. ! 426: .KE ! 427: .sp \nZu ! 428: .KS ! 429: .X slist ! 430: A list of expressions separated by semicolons, ! 431: as in a procedure body (a statement list). ! 432: This list, like expression lists and case lists, ! 433: is represented as a binary tree. ! 434: .Y tree0 ! 435: An expression in the list. ! 436: .Y tree1 ! 437: A pointer to another ! 438: \f3slist\fR ! 439: node, or to the last expression in the list. ! 440: .KE ! 441: .sp \nZu ! 442: .KS ! 443: .X str ! 444: A leaf node representing a string literal. ! 445: .Y str0 ! 446: The string value of the literal. ! 447: .Y val1 ! 448: The length of the string, ! 449: necessary because the string may contain the \s-2ASCII\s+2 ! 450: .I null ! 451: character, which would otherwise terminate the string. ! 452: .KE ! 453: .sp \nZu ! 454: .KS ! 455: .X susp ! 456: A ! 457: \fMsuspend\fR ! 458: expression (\fMsuspend\fR [\fIe\fR]). ! 459: .Y tree0 ! 460: \fIe\fR. ! 461: .KE ! 462: .sp \nZu ! 463: .KS ! 464: .X toby ! 465: A ! 466: \fMto-by\fR ! 467: expression (\fIe1\fM to \fIe2\fM by \fIe3\fR). ! 468: .Y tree0 ! 469: \fIe1\fR. ! 470: .Y tree1 ! 471: \fIe2\fR. ! 472: .Y tree2 ! 473: \fIe3\fR. ! 474: .KE ! 475: .sp \nZu ! 476: .KS ! 477: .X to ! 478: A ! 479: \fMto\fR ! 480: expression (\fIe1\fM to \fIe2\fR). ! 481: .Y tree0 ! 482: \fIe1\fR. ! 483: .Y tree1 ! 484: \fIe2\fR. ! 485: .KE ! 486: .sp \nZu ! 487: .KS ! 488: .X unop ! 489: A unary operation (\(ci \fIe\fR). ! 490: .Y tree0 ! 491: The operator. ! 492: .Y tree1 ! 493: \fIe\fR. ! 494: .KE ! 495: .nr PD \nZ ! 496: .bp ! 497: .ce 10 ! 498: \f3Appendix B \(em Icon Grammar\fR ! 499: .ce 0 ! 500: .sp 1 ! 501: .PP ! 502: The following grammar describes the Icon language. ! 503: Reserved words and operators ! 504: are shown in a sans-serif type face; ! 505: nonterminals are in italics. ! 506: The nonterminals ! 507: .I ident , ! 508: .I literal , ! 509: .I strliteral , ! 510: and ! 511: .I empty ! 512: are left undefined in the syntax. ! 513: .sp 2 ! 514: .ta 1.5iR 1.5i+1mL ! 515: .ft I ! 516: .tr |\(br ! 517: .tr -\- ! 518: .tr +\(pl ! 519: .tr /\(sl ! 520: .tr *\(** ! 521: .ss 9 ! 522: .de X ! 523: \t\\$1\h'1m'\(->\t\\$2 ! 524: .br ! 525: .. ! 526: .de Y ! 527: .if n .sp 1 ! 528: .if t .sp .5 ! 529: .. ! 530: .X program "decls" ! 531: .Y ! 532: .ne 2 ! 533: .X decls "empty" ! 534: .X "" "decls decl" ! 535: .Y ! 536: .ne 3 ! 537: .X decl "record" ! 538: .X "" "proc" ! 539: .X "" "global" ! 540: .X "" "link" ! 541: .Y ! 542: .X link "\fMlink\fI lnklist" ! 543: .Y ! 544: .ne 2 ! 545: .X lnklist "lnkfile" ! 546: .X "" "lnklist , lnkfile" ! 547: .Y ! 548: .X lnkfile "ident" ! 549: .X "" "strliteral" ! 550: .Y ! 551: .ne 2 ! 552: .X global "\fMglobal\fI idlist" ! 553: .Y ! 554: .X record "\fMrecord\fI ident \fM(\fI arglist \fM)\fI" ! 555: .Y ! 556: .X proc "prochead \fM;\fI locals initial procbody \fMend\fI" ! 557: .Y ! 558: .X prochead "\fMprocedure\fI ident \fM(\fI arglist \fM)\fI" ! 559: .Y ! 560: .ne 2 ! 561: .X arglist "empty" ! 562: .X "" "idlist" ! 563: .Y ! 564: .ne 2 ! 565: .X idlist "ident" ! 566: .X "" "idlist \fM,\fI ident" ! 567: .Y ! 568: .ne 2 ! 569: .X locals "empty" ! 570: .X "" "locals retention idlist \fM;\fI" ! 571: .Y ! 572: .ne 2 ! 573: .X retention "\fMlocal\fI" ! 574: .X "" "\fMstatic\fI" ! 575: .X "" "\fMdynamic\fI" ! 576: .Y ! 577: .ne 2 ! 578: .X initial "empty" ! 579: .X "" "\fMinitial\fI expr \fM;\fI" ! 580: .Y ! 581: .ne 2 ! 582: .X procbody "empty" ! 583: .X "" "nexpr \fM;\fI procbody" ! 584: .Y ! 585: .ne 2 ! 586: .X nexpr "empty" ! 587: .X "" "expr" ! 588: .Y ! 589: .ne 2 ! 590: .X expr "expr1a" ! 591: .X "" "expr \fM&\fI expr1a" ! 592: .Y ! 593: .ne 2 ! 594: .X expr1a "expr1" ! 595: .X "" "expr1a \fM?\fI expr1" ! 596: .Y ! 597: .ne 5 ! 598: .X expr1 "expr2" ! 599: .X "" "expr2 op1 expr1" ! 600: .X "" "expr2 op1a expr1" ! 601: .X "" "expr2 \fM?:=\fI expr1" ! 602: .X "" "expr2 \fM&:=\fI expr1" ! 603: .X "" "expr2 \fM@:=\fI expr1" ! 604: .Y ! 605: .ne 6 ! 606: .X op1 "\fM:= | :=: | <- | <->\fI" ! 607: .Y ! 608: .if n .X op1a "\fM+:= | -:= | *:= | /:= | %:= | ^:=\fI" ! 609: .if n .X "" "\fM++:= | --:= | **:= | \(or\(or:= | \(or\(or\(or:=\fI" ! 610: .if t .X op1a "\fM+:= | -:= | *:= | /:= | %:= | ^:= | ++:= | \ ! 611: --:= | **:= | \(or\(or:= | \(or\(or\(or:=\fI" ! 612: .X "" "\fM<:= | <=:= | =:= | >=:= | >:= | ~=:= \fM" ! 613: .X "" "\fM<<:= | <<=:= | ==:= | >>=:= | >>:= | ~==:=\fI" ! 614: .X "" "\fM===:= | ~===:=\fI" ! 615: .Y ! 616: .ne 3 ! 617: .X expr2 "expr3" ! 618: .X "" "expr2 \fMto\fI expr3" ! 619: .X "" "expr2 \fMto\fI expr3 \fMby\fI expr3" ! 620: .Y ! 621: .ne 2 ! 622: .X expr3 "expr4" ! 623: .X "" "expr4 \(or expr3" ! 624: .Y ! 625: .ne 2 ! 626: .X expr4 "expr5" ! 627: .X "" "expr4 op4 expr5" ! 628: .Y ! 629: .ne 3 ! 630: .X op4 "\fM< | <= | = | >= | > | ~=\fI" ! 631: .X "" "\fM<< | <<= | == | >>= | >> | ~==\fI" ! 632: .X "" "\fM=== | ~===\fI" ! 633: .Y ! 634: .ne 2 ! 635: .X expr5 "expr6" ! 636: .X "" "expr5 op5 expr6" ! 637: .Y ! 638: .ne 2 ! 639: .X op5 "\fM\(or\(or | \(or\(or\(or\fI" ! 640: .Y ! 641: .ne 2 ! 642: .X expr6 "expr7" ! 643: .X "" "expr6 op6 expr7" ! 644: .Y ! 645: .X op6 "\fM+ | - | ++ | --\fI" ! 646: .Y ! 647: .ne 2 ! 648: .X expr7 "expr8" ! 649: .X "" "expr7 op7 expr8" ! 650: .Y ! 651: .X op7 "\fM* | / | % | **\fI" ! 652: .Y ! 653: .ne 2 ! 654: .X expr8 "expr9" ! 655: .X "" "expr9 ^ expr8" ! 656: .Y ! 657: .ne 2 ! 658: .X expr9 "expr10" ! 659: .X "" "expr9 \fM\e\fI expr10" ! 660: .X "" "expr9 \fM @ \fIexpr10" ! 661: .Y ! 662: .ne 5 ! 663: .X expr10 "expr11" ! 664: .X "" "\fMnot\fI expr10" ! 665: .X "" "\fM@\fI expr10" ! 666: .X "" "\(or expr10" ! 667: .X "" "op10 expr10" ! 668: .Y ! 669: .X op10 "\fM. | ! | + | - | ~ | = | * | / | \e | ? | ^\fI" ! 670: .Y ! 671: .ne 20 ! 672: .X expr11 "ident" ! 673: .X "" "literal" ! 674: .X "" "\fM&\fI ident" ! 675: .X "" "expr11 \fM.\fI ident" ! 676: .X "" "expr11 \fM[\fI nexpr \fM]\fI" ! 677: .X "" "expr11 \fM(\fI exprlist \fM)\fI" ! 678: .X "" "expr11 \fM{\fR exprlist \fM}\fI" ! 679: .X "" "\fM[\fI exprlist \fM]\fI" ! 680: .X "" "\fM(\fI exprlist \fM)\fI" ! 681: .X "" "{ compound }" ! 682: .X "" "while" ! 683: .X "" "until" ! 684: .X "" "every" ! 685: .X "" "repeat" ! 686: .X "" "\fMnext\fI" ! 687: .X "" "\fMbreak\fI nexpr" ! 688: .X "" "\fMcreate\fI expr" ! 689: .X "" "if" ! 690: .X "" "case" ! 691: .X "" "return" ! 692: .X "" "section" ! 693: .Y ! 694: .ne 2 ! 695: .X while "\fMwhile\fI expr" ! 696: .X "" "\fMwhile\fI expr \fMdo\fI expr" ! 697: .Y ! 698: .ne 2 ! 699: .X until "\fMuntil\fI expr" ! 700: .X "" "\fMuntil\fI expr \fMdo\fI expr" ! 701: .Y ! 702: .ne 2 ! 703: .X every "\fMevery\fI expr" ! 704: .X "" "\fMevery\fI expr \fMdo\fI expr" ! 705: .Y ! 706: .X repeat "\fMrepeat\fI expr" ! 707: .Y ! 708: .ne 2 ! 709: .X if "\fMif\fI expr \fMthen\fI expr" ! 710: .X "" "\fMif\fI expr \fMthen\fI expr \fMelse\fI expr" ! 711: .Y ! 712: .X case "\fMcase\fI expr \fMof\fI { caselist }" ! 713: .Y ! 714: .ne 2 ! 715: .X caselist "cclause" ! 716: .X "" "caselist \fM;\fI cclause" ! 717: .Y ! 718: .ne 2 ! 719: .X cclause "\fMdefault\fM :\fI expr" ! 720: .X "" "expr \fM:\fI expr" ! 721: .Y ! 722: .ne 3 ! 723: .X return "\fMfail\fI" ! 724: .X "" "\fMreturn\fI nexpr" ! 725: .X "" "\fMsuspend\fI nexpr" ! 726: .Y ! 727: .X section "expr11 \fM[\fI expr sectop expr \fM]\fI" ! 728: .Y ! 729: .X sectop "\fM: | +: | -:\fI" ! 730: .Y ! 731: .ne 2 ! 732: .X exprlist "nexpr" ! 733: .X "" "exprlist \fM,\fI nexpr" ! 734: .Y ! 735: .ne 2 ! 736: .X compound "nexpr" ! 737: .X "" "nexpr \fM;\fI compound" ! 738: .ss 4 ! 739: .tr || ! 740: .tr -- ! 741: .tr ++ ! 742: .tr // ! 743: .tr ** ! 744: .uf I ! 745: .ft R ! 746: .bp ! 747: .de Op ! 748: .if \\n(.$=2 .IP \h'3n'\f3\\$1\h'2n'\fI\\$2\fR 6n ! 749: .if \\n(.$=1 .IP \h'3n'\f3\\$1\fR 6n ! 750: .br ! 751: .. ! 752: .ce 10 ! 753: \f3Appendix C \(em Ucode\fR ! 754: .ce 0 ! 755: .sp 1 ! 756: .PP ! 757: The intermediate ucode generated by the Icon translator ! 758: resembles a stack-oriented assembly language. ! 759: A ucode program is a sequence of labels and instructions. ! 760: A label marks a location in the program to which other instructions ! 761: may transfer control. ! 762: Labels are of the form \*(oq\f3lab L\fIn\fR\*(cq, where ! 763: .I n ! 764: is a decimal number. ! 765: A ucode instruction either describes an imperative operation ! 766: or communicates information to the Icon linker. ! 767: Instructions consist of an opcode followed by zero or more arguments. ! 768: Arguments can be decimal or octal integers, ! 769: names, or label references. ! 770: .PP ! 771: The intermediate language operates exclusively on the stack. ! 772: There are several kinds of objects that can appear on the stack: ! 773: descriptors, which represent Icon values and variables; ! 774: procedure frame markers, which mark the beginning of a new procedure frame; ! 775: expression frame markers, which delimit expression instances; ! 776: and generator frame markers, which mark inactive generators. ! 777: For more details about the stack, refer to Section 3.2. ! 778: .PP ! 779: The opcodes and their arguments are described in three groups below. ! 780: The global symbol table file has a similar format. ! 781: The opcodes used there are described in the fourth group. ! 782: .sp 1 ! 783: .SH ! 784: Imperative Instructions ! 785: .PP ! 786: The instructions below, ! 787: together with the operators described in the next section, ! 788: represent run-time actions for which code is executed. ! 789: .KS ! 790: .Op bscan ! 791: Save the values of \fM&subject\fR and \fM&pos\fR on the stack ! 792: and establish values for them. ! 793: This operation is reversible. ! 794: .KE ! 795: .KS ! 796: .Op ccase ! 797: Duplicate the value on the stack ! 798: just below the current expression frame. ! 799: Used in ! 800: \fMcase\fR ! 801: expressions. ! 802: .KE ! 803: .KS ! 804: .Op chfail lab ! 805: Change the failure label for the current expression frame to ! 806: .I lab . ! 807: Used for repeated evaluation. ! 808: .KE ! 809: .KS ! 810: .Op coact ! 811: Switch co-expression evaluation. Create a procedure frame on the current ! 812: co-expression stack. Transfer the result from old stack to new stack, ! 813: dereferencing if necessary. Set the activator field in new stack block to ! 814: point to old co-expression stack block. Return from procedure frame on ! 815: new co-expression stack. ! 816: .KE ! 817: .KS ! 818: .Op cofail ! 819: Fail from current co-expression to activating co-expression. ! 820: Create a procedure frame on current co-expression stack. Fail from ! 821: procedure frame on activator's co-expression stack. ! 822: .KE ! 823: .KS ! 824: .Op coret ! 825: Switch evaluation to activating co-expression. ! 826: Create a procedure frame on current co-expression stack. Transfer ! 827: the result from old stack to activator's stack, dereferencing it if the result ! 828: is on the old stack. ! 829: Return from the procedure frame on new co-expression stack. ! 830: .KE ! 831: .KS ! 832: .Op create ! 833: Create a co-expression. Allocate ! 834: co-expression stack and heap blocks. Copy the arguments ! 835: and locals variables from the current procedure frame into the heap block. ! 836: Create a procedure frame in the new co-expression stack using the arguments ! 837: and other locals from current procedure frame. Create a procedure ! 838: frame for dummy call to \fMcoact\fR on the new co-expression stack. ! 839: Push a descriptor representing the new co-expression onto current co-expression ! 840: stack. ! 841: .KE ! 842: .KS ! 843: .Op cset n ! 844: Push a descriptor representing the cset literal at constant table location ! 845: .I n ! 846: onto the stack. ! 847: .KE ! 848: .KS ! 849: .Op dup ! 850: Push a descriptor representing the null value onto the stack, and then duplicate the value that ! 851: was the previous top of the stack. ! 852: Used in most augmented assignments. ! 853: .KE ! 854: .KS ! 855: .Op efail ! 856: Signal failure in the current expression. ! 857: If there are any inactive generators, reactivate the most recent one. ! 858: If there are none, branch to the failure label ! 859: for the current expression frame. ! 860: If the failure label is null, ! 861: exit the current expression frame, ! 862: and signal failure in the enclosing one. ! 863: .KE ! 864: .KS ! 865: .Op eret ! 866: Return a value from an expression. ! 867: Save the value on top of the stack, ! 868: exit the current expression frame, ! 869: and push the value onto the stack as part of the enclosing expression frame. ! 870: .KE ! 871: .KS ! 872: .Op escan ! 873: Restore ! 874: \fM&subject\fR ! 875: and ! 876: \fM&pos\fR ! 877: from the stack. ! 878: This operation is reversible. ! 879: .KE ! 880: .KS ! 881: .Op esusp ! 882: Suspend a value from an expression. ! 883: The value on the top of the stack is saved, ! 884: and a generator frame hiding the current expression frame is created. ! 885: The surrounding expression frame is duplicated, ! 886: and the value is pushed onto the stack as part of that expression frame. ! 887: When reactivated, ! 888: \f3esusp\fR ! 889: in turn reactivates any inactive generators in the suspended expression. ! 890: .KE ! 891: .KS ! 892: .Op field name ! 893: Access the field ! 894: .I name ! 895: of the record on the top of the stack. ! 896: .KE ! 897: .KS ! 898: .Op file name ! 899: Set the file name to ! 900: .I name ! 901: for use in error messages and tracing. ! 902: Used at the beginning of each procedure. ! 903: .KE ! 904: .KS ! 905: .Op goto lab ! 906: Transfer control to the instruction following label ! 907: .I lab . ! 908: .KE ! 909: .KS ! 910: .Op incres ! 911: Increment result count field in current co-expression stack block. ! 912: .KE ! 913: .KS ! 914: .Op init? lab ! 915: If the initialization statement for the current procedure ! 916: has already been executed once, go to ! 917: .I lab . ! 918: .KE ! 919: .KS ! 920: .Op int n ! 921: Push a descriptor representing the integer literal at constant table location ! 922: .I n ! 923: onto the stack. ! 924: .KE ! 925: .KS ! 926: .Op invoke n ! 927: Invoke a procedure or create a record. ! 928: The number of arguments or fields on the stack is given by ! 929: .I n . ! 930: The procedure (which may be a record constructor) is on the stack, ! 931: just beyond the arguments. ! 932: After invocation, the arguments are popped from the stack, ! 933: and the returned value is pushed (see ! 934: \f3pret\fR). ! 935: .KE ! 936: .KS ! 937: .Op keywd n ! 938: Push a descriptor representing a value or trapped variable representing keyword ! 939: .I n ! 940: onto the stack. ! 941: (See ! 942: \fMtran/keyword.h\fR ! 943: for keyword numbers.) ! 944: .KE ! 945: .KS ! 946: .Op limit ! 947: Check the value on the top of the stack for a legal limitation value. ! 948: If the value is zero, failure is signalled in the current expression (see ! 949: \f3efail\fR). ! 950: .KE ! 951: .KS ! 952: .Op line n ! 953: Set the line number to ! 954: .I n ! 955: for use in error messages and tracing. ! 956: .KE ! 957: .KS ! 958: .Op llist n ! 959: Create a list of ! 960: .I n ! 961: values. ! 962: The values are popped from the stack ! 963: and the created list is pushed back onto the stack. ! 964: .KE ! 965: .KS ! 966: .Op lsusp ! 967: Decrement the limitation counter for the current expression frame. ! 968: If the counter becomes zero, then return a value ! 969: from the current expression frame (see ! 970: \f3eret\fR); ! 971: otherwise, suspend a value from the current expression frame (see ! 972: \f3esusp\fR). ! 973: .KE ! 974: .KS ! 975: .Op mark lab ! 976: Save the current expression and generator frame pointers on the stack, ! 977: then create a new expression frame, with failure label ! 978: .I lab . ! 979: Control is transferred to ! 980: .I lab ! 981: if failure occurs in the expression frame and there are no suspended ! 982: generators to reactivate (see ! 983: \f3efail\fR). ! 984: The failure label \fML0\fR indicates that control is to be ! 985: transferred to the failure label in the enclosing expression. ! 986: .KE ! 987: .KS ! 988: .Op pfail ! 989: Return from the current procedure, and signal failure (see ! 990: \f3efail\fR). ! 991: .KE ! 992: .KS ! 993: .Op pnull ! 994: Push a descriptor representing the null value onto the stack. ! 995: .KE ! 996: .KS ! 997: .Op pop ! 998: Pop the top element off of the stack. ! 999: .KE ! 1000: .KS ! 1001: .Op pret ! 1002: Return from the current procedure ! 1003: with the result that is on top of the stack. ! 1004: .KE ! 1005: .KS ! 1006: .Op psusp ! 1007: Suspend from the current procedure ! 1008: with the result that is on top of the stack. ! 1009: .KE ! 1010: .KS ! 1011: .Op push1 ! 1012: Push a descriptor representing the integer 1 onto the stack. ! 1013: .KE ! 1014: .KS ! 1015: .Op pushn1 ! 1016: Push a descriptor representing the integer \-1 onto the stack. This is used as default in ! 1017: mutual goal-directed evaluation. ! 1018: .KE ! 1019: .KS ! 1020: .Op real n ! 1021: Push a descriptor representing the real literal at constant table location ! 1022: .I n ! 1023: onto the stack. ! 1024: .KE ! 1025: .KS ! 1026: .Op refresh ! 1027: Allocate space for a new co-expression stack. Create a procedure frame ! 1028: in new co-expression stack using arguments and other locals from ! 1029: entry block for co-expression operand. Create a procedure frame for ! 1030: dummy call to \fMcoact\fR on new co-expression stack. ! 1031: Push a descriptor representing the new co-expression onto current co-expression ! 1032: stack. ! 1033: .KE ! 1034: .KS ! 1035: .Op sdup ! 1036: Duplicate the descriptor on the top of the stack. ! 1037: Used in assignment augmented with string scanning. ! 1038: .KE ! 1039: .KS ! 1040: .Op str n ! 1041: Push a descriptor representing the string literal at constant table location ! 1042: .I n ! 1043: onto the stack. ! 1044: .KE ! 1045: .KS ! 1046: .Op unmark n ! 1047: Exit from ! 1048: .I n ! 1049: expression frames. ! 1050: No value is pushed onto the stack in their place. ! 1051: .KE ! 1052: .KS ! 1053: .Op var n ! 1054: Push the descriptor for the variable at location ! 1055: .I n ! 1056: in the local symbol table onto the stack. ! 1057: .KE ! 1058: .sp 1 ! 1059: .SH ! 1060: Operators ! 1061: .PP ! 1062: The instructions below perform the functions ! 1063: corresponding to the indicated Icon operator. ! 1064: The operands are evaluated and pushed onto the stack from left to right, ! 1065: so that the topmost element of the stack is the rightmost operand. ! 1066: The operands are popped before ! 1067: the result of the operation is pushed onto the stack. ! 1068: All operations dereference their operands as necessary, ! 1069: but only after all operands have been evaluated and pushed onto the stack. ! 1070: All operations attempt to convert their operands to an appropriate type. ! 1071: If this implicit conversion fails, an error is issued. ! 1072: Relational tests fail if the specified condition is not met; ! 1073: the result of a successful comparison is the value of the right-hand operand. ! 1074: Arithmetic operations cause an error to be issued ! 1075: if the result overflows or underflows. ! 1076: If an operation cannot be performed for some other reason, ! 1077: it fails. ! 1078: .LP ! 1079: .ta 0.5i 1.5i 3.5i 4.5i ! 1080: .de X ! 1081: \t\f3\\$1\fM\t\\$2\t\f3\\$3\fM\t\\$4\fR ! 1082: .br ! 1083: .. ! 1084: .ne 21 ! 1085: .tr |\(or ! 1086: .tr +\(pl ! 1087: .tr -\- ! 1088: .tr /\(sl ! 1089: .tr *\(** ! 1090: .ss 9 ! 1091: .X asgn "x := y" null "/x" ! 1092: .X bang "!x" number "+x" ! 1093: .X cat "x || y" numeq "x = y" ! 1094: .X compl "~x" numge "x >= y" ! 1095: .X diff "x -- y" numgt "x > y" ! 1096: .X div "x / y" numle "x <= y" ! 1097: .X eqv "x === y" numlt "x < y" ! 1098: .X inter "x ** y" numne "x ~= y" ! 1099: .X lconcat "x ||| y" plus "x + y" ! 1100: .X lexeq "x == y" power "x ^ y" ! 1101: .X lexge "x >>= y" random "?x" ! 1102: .X lexgt "x >> y" rasgn "x <- y" ! 1103: .X lexle "x <<= y" rswap "x <-> y" ! 1104: .X lexlt "x << y" sect "x\^[\^y:z]" ! 1105: .X lexne "x ~== y" size "*x" ! 1106: .X minus "x - y" subsc "x\^[\^y]" ! 1107: .X mod "x % y" swap "x :=: y" ! 1108: .X mult "x * y" tabmat "=x" ! 1109: .X neg "-x" toby "x to y by z" ! 1110: .X neqv "x ~=== y" unioncs "x ++ y" ! 1111: .X nonnull "\ex" value ".x" ! 1112: .tr || ! 1113: .tr ++ ! 1114: .tr -- ! 1115: .tr // ! 1116: .tr ** ! 1117: .ss 4 ! 1118: .sp 1 ! 1119: .SH ! 1120: Non-Imperative Instructions ! 1121: .PP ! 1122: The following instructions generate no executable code. ! 1123: Instead, they communicate various information to the linker ! 1124: each procedure and its symbol table. ! 1125: An Icon procedure is translated into a sequence of ucode ! 1126: instructions beginning with a ! 1127: \f3proc\fR ! 1128: instruction, followed by a sequence of ! 1129: \f3local\fR ! 1130: instructions, a sequence of ! 1131: \f3con\fR ! 1132: instructions, a ! 1133: \f3declend\fR ! 1134: instruction, then the imperative instructions describing ! 1135: the procedure body. ! 1136: An ! 1137: \f3end\fR ! 1138: instruction terminates the procedure. ! 1139: .KS ! 1140: .Op proc name ! 1141: Begin a new procedure with the indicated name. ! 1142: The local and constant tables are initialized. ! 1143: The procedure block is not generated at this time, ! 1144: since the local identifiers have not yet been declared. ! 1145: .KE ! 1146: .KS ! 1147: .Op local n,flags,name ! 1148: Enter ! 1149: .I name ! 1150: into the current procedure's local symbol table at location ! 1151: .I n . ! 1152: The symbol's ! 1153: .I flags ! 1154: indicate information about the symbol, its scope, and its retention. ! 1155: All identifiers referred to in a procedure appear in the ! 1156: local symbol table. ! 1157: If an identifier is undeclared, ! 1158: its scope is determined by consulting the global symbol table ! 1159: and a list of functions. ! 1160: .KE ! 1161: .KS ! 1162: .Op con n,flags,value ! 1163: Enter ! 1164: .I value ! 1165: into the current procedure's constant table at location ! 1166: .I n ! 1167: in the table. ! 1168: The type of the constant (integer, real, or string) is indicated by ! 1169: .I flags . ! 1170: For integer and real literals, ! 1171: .I value ! 1172: is an 11-digit octal number; ! 1173: for string and cset literals, ! 1174: it is a comma-separated list of 3-digit octal numbers, ! 1175: each representing one byte in the string. ! 1176: .KE ! 1177: .KS ! 1178: .Op declend ! 1179: Signal the end of the procedure prologue. ! 1180: The procedure block is generated at this point. ! 1181: .KE ! 1182: .KS ! 1183: .Op end ! 1184: Signal the end of a procedure. ! 1185: .KE ! 1186: .sp 1 ! 1187: .SH ! 1188: Global Symbol Table Instructions ! 1189: .PP ! 1190: A single global symbol table file is output during each translation. ! 1191: Record declarations appear first in the file; ! 1192: they are output as they are encountered in the Icon source program. ! 1193: The first instruction following the record declarations is ! 1194: \f3impl\fR, ! 1195: which may be followed by a ! 1196: \f3trace\fR ! 1197: instruction, then by the global declarations. ! 1198: The global declarations are output at the end of translation. ! 1199: .KS ! 1200: .Op record name,n ! 1201: Declare a record with the indicated name and ! 1202: .I n ! 1203: fields. ! 1204: One line for each field follows this line, ! 1205: each containing the field number and name. ! 1206: .KE ! 1207: .KS ! 1208: .Op impl scope ! 1209: Declare the implicit scope as indicated. ! 1210: .I Scope ! 1211: can be either ! 1212: \f3local\fR ! 1213: or ! 1214: \f3error\fR. ! 1215: If the implicit scope is ! 1216: \f3error\fR, ! 1217: undeclared identifiers are flagged as warnings during linking; ! 1218: otherwise, they are made local variables. ! 1219: The implicit scope is ! 1220: \f3error\fR ! 1221: if the ! 1222: \f3\-u\fR ! 1223: option was given on the translator command line, otherwise it is ! 1224: \f3local\fR. ! 1225: .KE ! 1226: .KS ! 1227: .Op trace ! 1228: Enable run-time tracing. ! 1229: This instruction is present if the ! 1230: \f3\-t\fR ! 1231: option was given on the translator command line, ! 1232: and causes the keyword ! 1233: \fM&trace\fR ! 1234: to be initialized to \-1. ! 1235: .KE ! 1236: .KS ! 1237: .Op global n ! 1238: Begin the global symbol table. ! 1239: There are ! 1240: .I n ! 1241: global declarations following, one per line. ! 1242: Each global declaration contains a sequence number, ! 1243: the flags, the identifier name, ! 1244: and the number of formal parameters (for procedures) or fields (for records). ! 1245: .KE ! 1246: .KS ! 1247: .Op link name ! 1248: Search each directory named in the \fIIPATH\fR environment variable ! 1249: for a file named \fIname.u1\fR. If the file is ! 1250: located, it is added to the list of files to link. ! 1251: .KE ! 1252: .bp ! 1253: .if \nv .ss 9 ! 1254: .ce 10 ! 1255: \f3Appendix D \(em Data Representations\fR ! 1256: .ce 0 ! 1257: .sp 1 ! 1258: .SH ! 1259: Descriptor Formats ! 1260: .PP ! 1261: The figures below depict each of the six descriptor types ! 1262: mentioned in Section 3.1. ! 1263: Each descriptor is two words long; ! 1264: the first word is shown on top of the second. ! 1265: .sp 1 ! 1266: .TS ! 1267: center tab(:) ; ! 1268: L0w(2.2i) | L0w(2n)e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e | ! 1269: LI | L S S S S S S S S S S S S S S C | ! 1270: L | L S S S S S S S S S S S S S S S | ! 1271: L | L S S S S S S S S S S S S S S C | ! 1272: L | L S S S S S S S S S S S S S S S | . ! 1273: :_ ! 1274: Null::0 ! 1275: :_ ! 1276: ::0 ! 1277: :_ ! 1278: .TE ! 1279: .sp 1 ! 1280: .TS ! 1281: center tab(:) ; ! 1282: L0w(2.2i) | L0w(2n)e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e | ! 1283: LI | C | CI S S S S S S S S S S S S S S | ! 1284: L | L S S S S S S S S S S S S S S S | ! 1285: L | CI S S S S S S S S S S S S S S S | ! 1286: L | L S S S S S S S S S S S S S S S | . ! 1287: :_ ! 1288: String Qualifier:0:length ! 1289: :_ ! 1290: :address of string ! 1291: :_ ! 1292: .TE ! 1293: .sp 1 ! 1294: .TS ! 1295: center tab(:) ; ! 1296: L0w(2.2i) | L0w(2n)e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e | ! 1297: LI | C | C | CI S S S S S S S | CI S S S S S | ! 1298: L | L S S S S S S S S S S S S S S S | ! 1299: LI | CI S S S S S S S S S S S S S S S | ! 1300: L | L S S S S S S S S S S S S S S S | . ! 1301: :_ ! 1302: Integer:1:0:flags:type = \fR1 ! 1303: :_ ! 1304: :integer ! 1305: :_ ! 1306: .TE ! 1307: .sp 1 ! 1308: .TS ! 1309: center tab(:) ; ! 1310: L0w(2.2i) | L0w(2n)e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e | ! 1311: LI | C | C | CI S S S S S S S | CI S S S S S | ! 1312: L | L S S S S S S S S S S S S S S S | ! 1313: LI | CI S S S S S S S S S S S S S S S | ! 1314: L | L S S S S S S S S S S S S S S S | . ! 1315: :_ ! 1316: Value:1:0:flags:type \(>= \fR2 ! 1317: :_ ! 1318: :address of data block ! 1319: :_ ! 1320: .TE ! 1321: .sp 1 ! 1322: .TS ! 1323: center tab(:) ; ! 1324: L0w(2.2i) | L0w(2n)e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e | ! 1325: LI | C | C | C | CI S S S S S S S S S S S S | ! 1326: L | L S S S S S S S S S S S S S S S | ! 1327: LI | CI S S S S S S S S S S S S S S S | ! 1328: L | L S S S S S S S S S S S S S S S | . ! 1329: :_ ! 1330: Variable:1:1:0:offset ! 1331: :_ ! 1332: :address of descriptor ! 1333: :_ ! 1334: .TE ! 1335: .sp 1 ! 1336: .TS ! 1337: center tab(:) ; ! 1338: L0w(2.2i) | L0w(2n)e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e S0e | ! 1339: LI | C | C | C | CI S S S S S S | CI S S S S S | ! 1340: L | L S S S S S S S S S S S S S S S | ! 1341: LI | CI S S S S S S S S S S S S S S S | ! 1342: L | L S S S S S S S S S S S S S S S | . ! 1343: :_ ! 1344: Trapped Variable:1:1:1:flags:type ! 1345: :_ ! 1346: :address of data block ! 1347: :_ ! 1348: .TE ! 1349: \fINotes:\fR The offset in a variable descriptor is the number of words from ! 1350: the top of the block in which the descriptor that is pointed to occurs. ! 1351: The second word in the descriptors for the trapped variables for \fM&pos\fR, \fM&random\fR, ! 1352: and \fM&trace\fR contain addresses of locations in statically allocated data. ! 1353: .bp ! 1354: .SH ! 1355: Data Block Formats ! 1356: .PP ! 1357: The data blocks used by the Icon system are pictured below. ! 1358: The data type code, ! 1359: shown as both a mnemonic and an integer, ! 1360: is always the first word of the block and has the same ! 1361: value as the type code in the ! 1362: .I value ! 1363: or ! 1364: .I "trapped variable" ! 1365: descriptor that refers to it. ! 1366: All ! 1367: .I name ! 1368: fields in the data blocks are ! 1369: .I "string qualifier" ! 1370: descriptors, and all ! 1371: .I pointers ! 1372: in the data blocks are ! 1373: .I "variable" ! 1374: descriptors. ! 1375: .sp 1 ! 1376: .KS ! 1377: .TS ! 1378: center tab(:) ; ! 1379: L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) | ! 1380: LI | C S S | . ! 1381: :_ ! 1382: Long Integer Block:T_LONGINT = 2 ! 1383: :_ ! 1384: .T& ! 1385: L | L CI L | ! 1386: L | L ^ L | ! 1387: L | L ^ L | ! 1388: L | L S S | . ! 1389: ::32-bit integer ! 1390: :_::_ ! 1391: ! 1392: :_ ! 1393: .TE ! 1394: \fINote:\fR Long integers apply only when \fMsizeof(int) != sizeof(long)\fR ! 1395: .sp ! 1396: .KE ! 1397: .sp 1 ! 1398: .KS ! 1399: .TS ! 1400: center tab(:) ; ! 1401: L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) | ! 1402: LI | C S S | . ! 1403: :_ ! 1404: Real Block:T_REAL = 3 ! 1405: :_ ! 1406: .T& ! 1407: L | L CI L | ! 1408: L | L ^ L | ! 1409: L | L ^ L | ! 1410: L L ^ L ! 1411: L | L ^ L | ! 1412: L | L ^ L | ! 1413: L | L ^ L | ! 1414: L | L S S | . ! 1415: ::double-precision real ! 1416: :_::_ ! 1417: ! 1418: ! 1419: ! 1420: :_::_ ! 1421: ! 1422: :_ ! 1423: .TE ! 1424: .KE ! 1425: .sp 1 ! 1426: .KS ! 1427: .TS ! 1428: center tab(:) ; ! 1429: L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) | ! 1430: LI | C S S | . ! 1431: :_ ! 1432: Cset Block:T_CSET = 4 ! 1433: :_ ! 1434: .T& ! 1435: L | L CI L | ! 1436: L | L ^ L | ! 1437: L | L ^ L | ! 1438: L | L ^ L | ! 1439: L | L ^ L | ! 1440: L L ^ L ! 1441: L | L ^ L | ! 1442: L | L ^ L | ! 1443: L | L ^ L | ! 1444: L | L ^ L | ! 1445: L | L ^ L | ! 1446: L | L S S | . ! 1447: ::256-bit character set ! 1448: :_::_ ! 1449: ! 1450: :_::_ ! 1451: ! 1452: ! 1453: ! 1454: :_::_ ! 1455: ! 1456: :_::_ ! 1457: ! 1458: :_ ! 1459: .TE ! 1460: .KE ! 1461: .sp 1 ! 1462: .KS ! 1463: .TS ! 1464: center tab(:) ; ! 1465: L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) | ! 1466: LI | C S S | . ! 1467: :_ ! 1468: File Block:T_FILE = 5 ! 1469: :_ ! 1470: .T& ! 1471: L | CI S S | . ! 1472: :\s-2UNIX\s+2 file descriptor ! 1473: :_ ! 1474: :file status ! 1475: :_ ! 1476: .T& ! 1477: L | L CI L | ! 1478: L | L ^ L | ! 1479: L | L ^ L | ! 1480: L | L S S | . ! 1481: ::file name ! 1482: :_::_ ! 1483: ! 1484: :_ ! 1485: .TE ! 1486: .KE ! 1487: .sp 1 ! 1488: .KS ! 1489: .TS ! 1490: center tab(:) ; ! 1491: L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) | ! 1492: LI | C S S | . ! 1493: :_ ! 1494: Procedure Block:T_PROCEDURE = 6 ! 1495: :_ ! 1496: .T& ! 1497: L | CI S S | . ! 1498: :size of this data block ! 1499: :_ ! 1500: :entry point address ! 1501: :_ ! 1502: :number of arguments ! 1503: :_ ! 1504: :number of dynamic locals ! 1505: :_ ! 1506: :number of static locals ! 1507: :_ ! 1508: :index of first static local ! 1509: :_ ! 1510: .T& ! 1511: L | L CI L | ! 1512: L | L ^ L | ! 1513: L | L ^ L | ! 1514: L | L S S | . ! 1515: ::procedure name ! 1516: :_::_ ! 1517: ! 1518: :_ ! 1519: .T& ! 1520: L | L CI L | ! 1521: L | L ^ L | ! 1522: L | L ^ L | ! 1523: L | L S S | . ! 1524: ::name of first identifier ! 1525: :_::_ ! 1526: ! 1527: :_ ! 1528: .T& ! 1529: L | L CB L | ! 1530: L L CB L ! 1531: L | L CB L | ! 1532: L | L S S | . ! 1533: ::. ! 1534: ::. ! 1535: ::. ! 1536: :_ ! 1537: .T& ! 1538: L | L CI L | ! 1539: L | L ^ L | ! 1540: L | L ^ L | ! 1541: L | L S S | . ! 1542: ::name of last identifier ! 1543: :_::_ ! 1544: ! 1545: :_ ! 1546: .TE ! 1547: \fINotes:\fR Identifiers include arguments and locals. ! 1548: Similar blocks are used for built-in functions; in this ! 1549: case the word for the number of dynamic locals contains \-1. ! 1550: For functions, there are no argument names. Functions like \fMwrite\fR, ! 1551: which have an arbitrary number of argument, are indicated by ! 1552: the value \-1 in place of the number of arguments. Record constructors ! 1553: are distinguished from other functions by the value \-2 ! 1554: in place of the number of dynamic locals. Each record declaration ! 1555: is distinguished by a unique record identification number, which ! 1556: appears in place of the number of static locals. ! 1557: .sp ! 1558: .KE ! 1559: .sp 1 ! 1560: .KS ! 1561: .TS ! 1562: center tab(:) ; ! 1563: L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) | ! 1564: LI | C S S | . ! 1565: :_ ! 1566: List Header Block:T_LIST = 7 ! 1567: :_ ! 1568: .T& ! 1569: L | CI S S | . ! 1570: :current size of list ! 1571: :_ ! 1572: .T& ! 1573: L | L CI L | ! 1574: L | L ^ L | ! 1575: L | L ^ L | ! 1576: L | L S S | . ! 1577: ::pointer to first list block ! 1578: :_::_ ! 1579: ! 1580: :_ ! 1581: .T& ! 1582: L | L CI L | ! 1583: L | L ^ L | ! 1584: L | L ^ L | ! 1585: L | L S S | . ! 1586: ::pointer to last list block ! 1587: :_::_ ! 1588: ! 1589: :_ ! 1590: .TE ! 1591: .KE ! 1592: .sp 1 ! 1593: .KS ! 1594: .TS ! 1595: center tab(:) ; ! 1596: L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) | ! 1597: LI | C S S | . ! 1598: :_ ! 1599: List Element Block:T_LELEM = 11 ! 1600: :_ ! 1601: .T& ! 1602: L | CI S S | . ! 1603: :size of this data block ! 1604: :_ ! 1605: :number of slots in this block ! 1606: :_ ! 1607: :index of first slot used ! 1608: :_ ! 1609: :number of slots used ! 1610: :_ ! 1611: .T& ! 1612: L | L CI L | ! 1613: L | L ^ L | ! 1614: L | L ^ L | ! 1615: L | L S S | . ! 1616: ::pointer to previous list block ! 1617: :_::_ ! 1618: ! 1619: :_ ! 1620: .T& ! 1621: L | L CI L | ! 1622: L | L ^ L | ! 1623: L | L ^ L | ! 1624: L | L S S | . ! 1625: ::pointer to next list block ! 1626: :_::_ ! 1627: ! 1628: :_ ! 1629: .T& ! 1630: L | L CI L | ! 1631: L | L ^ L | ! 1632: L | L ^ L | ! 1633: L | L S S | . ! 1634: ::first slot ! 1635: :_::_ ! 1636: ! 1637: :_ ! 1638: .T& ! 1639: L | L CB L | ! 1640: L L CB L ! 1641: L | L CB L | ! 1642: L | L S S | . ! 1643: ::. ! 1644: ::. ! 1645: ::. ! 1646: :_ ! 1647: .T& ! 1648: L | L CI L | ! 1649: L | L ^ L | ! 1650: L | L ^ L | ! 1651: L | L S S | . ! 1652: ::last slot ! 1653: :_::_ ! 1654: ! 1655: :_ ! 1656: .TE ! 1657: .KE ! 1658: .sp 1 ! 1659: .KS ! 1660: .TS ! 1661: center tab(:) ; ! 1662: L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) | ! 1663: LI | C S S | . ! 1664: :_ ! 1665: Table Header Block:T_TABLE = 8 ! 1666: :_ ! 1667: .T& ! 1668: L | CI S S | . ! 1669: :current table size ! 1670: :_ ! 1671: .T& ! 1672: L | L CI L | ! 1673: L | L ^ L | ! 1674: L | L ^ L | ! 1675: L | L S S | . ! 1676: ::default value ! 1677: :_::_ ! 1678: ! 1679: :_ ! 1680: .T& ! 1681: L | L CI L | ! 1682: L | L ^ L | ! 1683: L | L ^ L | ! 1684: L | L S S | . ! 1685: ::first hash bucket ! 1686: :_::_ ! 1687: ! 1688: :_ ! 1689: .T& ! 1690: L | L CB L | ! 1691: L L CB L ! 1692: L | L CB L | ! 1693: L | L S S | . ! 1694: ::. ! 1695: ::. ! 1696: ::. ! 1697: :_ ! 1698: .T& ! 1699: L | L CI L | ! 1700: L | L ^ L | ! 1701: L | L ^ L | ! 1702: L | L S S | . ! 1703: ::last hash bucket ! 1704: :_::_ ! 1705: ! 1706: :_ ! 1707: .TE ! 1708: .KE ! 1709: .sp 1 ! 1710: .KS ! 1711: .TS ! 1712: center tab(:) ; ! 1713: L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) | ! 1714: LI | C S S | . ! 1715: :_ ! 1716: Table Element Block:T_TELEM = 10 ! 1717: :_ ! 1718: .T& ! 1719: L | CI S S | . ! 1720: :hash number ! 1721: :_ ! 1722: .T& ! 1723: L | L CI L | ! 1724: L | L ^ L | ! 1725: L | L ^ L | ! 1726: L | L S S | . ! 1727: ::pointer to next element ! 1728: :_::_ ! 1729: ! 1730: :_ ! 1731: .T& ! 1732: L | L CI L | ! 1733: L | L ^ L | ! 1734: L | L ^ L | ! 1735: L | L S S | . ! 1736: ::entry value ! 1737: :_::_ ! 1738: ! 1739: :_ ! 1740: .T& ! 1741: L | L CI L | ! 1742: L | L ^ L | ! 1743: L | L ^ L | ! 1744: L | L S S | . ! 1745: ::assigned value ! 1746: :_::_ ! 1747: ! 1748: :_ ! 1749: .TE ! 1750: .KE ! 1751: .sp 1 ! 1752: .KS ! 1753: .TS ! 1754: center tab(:) ; ! 1755: L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) | ! 1756: LI | C S S | . ! 1757: :_ ! 1758: Set Header Block:T_SET = 20 ! 1759: :_ ! 1760: .T& ! 1761: L | CI S S | . ! 1762: :current set size ! 1763: :_ ! 1764: .T& ! 1765: L | L CI L | ! 1766: L | L ^ L | ! 1767: L | L ^ L | ! 1768: L | L S S | . ! 1769: ::first hash bucket ! 1770: :_::_ ! 1771: ! 1772: :_ ! 1773: .T& ! 1774: L | L CB L | ! 1775: L L CB L ! 1776: L | L CB L | ! 1777: L | L S S | . ! 1778: ::. ! 1779: ::. ! 1780: ::. ! 1781: :_ ! 1782: .T& ! 1783: L | L CI L | ! 1784: L | L ^ L | ! 1785: L | L ^ L | ! 1786: L | L S S | . ! 1787: ::last hash bucket ! 1788: :_::_ ! 1789: ! 1790: :_ ! 1791: .TE ! 1792: .KE ! 1793: .sp 1 ! 1794: .KS ! 1795: .TS ! 1796: center tab(:) ; ! 1797: L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) | ! 1798: LI | C S S | . ! 1799: :_ ! 1800: Set Element Block:T_SELEM = 21 ! 1801: :_ ! 1802: .T& ! 1803: L | CI S S | . ! 1804: :hash number ! 1805: :_ ! 1806: .T& ! 1807: L | L CI L | ! 1808: L | L ^ L | ! 1809: L | L ^ L | ! 1810: L | L S S | . ! 1811: ::member value ! 1812: :_::_ ! 1813: ! 1814: :_ ! 1815: .T& ! 1816: L | L CI L | ! 1817: L | L ^ L | ! 1818: L | L ^ L | ! 1819: L | L S S | . ! 1820: ::pointer to next member ! 1821: :_::_ ! 1822: ! 1823: :_ ! 1824: .TE ! 1825: .KE ! 1826: .sp 1 ! 1827: .KS ! 1828: .TS ! 1829: center tab(:) ; ! 1830: L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) | ! 1831: LI | C S S | . ! 1832: :_ ! 1833: Record Block:T_RECORD = 9 ! 1834: :_ ! 1835: .T& ! 1836: L | CI S S | . ! 1837: :size of this data block ! 1838: :_ ! 1839: :pointer to record constructor ! 1840: :_ ! 1841: .T& ! 1842: L | L CI L | ! 1843: L | L ^ L | ! 1844: L | L ^ L | ! 1845: L | L S S | . ! 1846: ::first field of record ! 1847: :_::_ ! 1848: ! 1849: :_ ! 1850: .T& ! 1851: L | L CB L | ! 1852: L L CB L ! 1853: L | L CB L | ! 1854: L | L S S | . ! 1855: ::. ! 1856: ::. ! 1857: ::. ! 1858: :_ ! 1859: .T& ! 1860: L | L CI L | ! 1861: L | L ^ L | ! 1862: L | L ^ L | ! 1863: L | L S S | . ! 1864: ::last field of record ! 1865: :_::_ ! 1866: ! 1867: :_ ! 1868: .TE ! 1869: .KE ! 1870: .sp 1 ! 1871: .KS ! 1872: .TS ! 1873: center tab(:) ; ! 1874: L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) | ! 1875: LI | C S S | . ! 1876: :_ ! 1877: Co-Expression Stack Block:T_ESTACK = 18 ! 1878: :_ ! 1879: .T& ! 1880: L | L CI L | ! 1881: L | L ^ L | ! 1882: L | L ^ L | ! 1883: L | L S S | . ! 1884: ::most recent activator ! 1885: :_::_ ! 1886: ! 1887: :_ ! 1888: .T& ! 1889: L | CI S S | . ! 1890: :stack base ! 1891: :_ ! 1892: :stack pointer ! 1893: :_ ! 1894: :address pointer ! 1895: :_ ! 1896: :Icon/C boundary ! 1897: :_ ! 1898: :number of results produced ! 1899: :_ ! 1900: .T& ! 1901: L | L CI L | ! 1902: L | L ^ L | ! 1903: L | L ^ L | ! 1904: L | L S S | . ! 1905: ::pointer to refresh block ! 1906: :_::_ ! 1907: ! 1908: :_ ! 1909: .T& ! 1910: L | L CB L | ! 1911: L L CB L ! 1912: L | L CB L | ! 1913: L | L S S | . ! 1914: ::. ! 1915: ::. ! 1916: ::. ! 1917: :_ ! 1918: .TE ! 1919: .KE ! 1920: .sp 1 ! 1921: .KS ! 1922: .TS ! 1923: center tab(:) ; ! 1924: L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) | ! 1925: LI | C S S | . ! 1926: :_ ! 1927: Co-Expression Heap Block:T_EBLOCK = 19 ! 1928: :_ ! 1929: .T& ! 1930: L | CI S S | . ! 1931: :size of this data block ! 1932: :_ ! 1933: :entry point address ! 1934: :_ ! 1935: :number of arguments ! 1936: :_ ! 1937: :number of locals ! 1938: :_ ! 1939: .T& ! 1940: L | L CI L | ! 1941: L | L ^ L | ! 1942: L | L ^ L | ! 1943: L | L S S | . ! 1944: ::procedure ! 1945: :_::_ ! 1946: ! 1947: :_ ! 1948: .T& ! 1949: L | L CI L | ! 1950: L | L ^ L | ! 1951: L | L ^ L | ! 1952: L | L S S | . ! 1953: ::value of first identifier ! 1954: :_::_ ! 1955: ! 1956: :_ ! 1957: .T& ! 1958: L | L CB L | ! 1959: L L CB L ! 1960: L | L CB L | ! 1961: L | L S S | . ! 1962: ::. ! 1963: ::. ! 1964: ::. ! 1965: :_ ! 1966: .T& ! 1967: L | L CI L | ! 1968: L | L ^ L | ! 1969: L | L ^ L | ! 1970: L | L S S | . ! 1971: ::value of last identifier ! 1972: :_::_ ! 1973: ! 1974: :_ ! 1975: .TE ! 1976: \fINote:\fR Identifiers include arguments and locals. ! 1977: .sp ! 1978: .KE ! 1979: .sp 1 ! 1980: .KS ! 1981: .TS ! 1982: center tab(:) ; ! 1983: L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) | ! 1984: LI | C S S | . ! 1985: :_ ! 1986: Substring Trapped Variable:T_TVSUBS = 12 ! 1987: :_ ! 1988: .T& ! 1989: L | CI S S | . ! 1990: :length of substring ! 1991: :_ ! 1992: :relative position of substring ! 1993: :_ ! 1994: .T& ! 1995: L | L CI L | ! 1996: L | L ^ L | ! 1997: L | L ^ L | ! 1998: L | L S S | . ! 1999: ::variable containing substring ! 2000: :_::_ ! 2001: ! 2002: :_ ! 2003: .TE ! 2004: .KE ! 2005: .sp 1 ! 2006: .KS ! 2007: .TS ! 2008: center tab(:) ; ! 2009: L0w(2.2i) | L0w(2n) S0w(28n) S0w(2n) | ! 2010: LI | C S S | . ! 2011: :_ ! 2012: Table Element Trapped Variable:T_TVTBL = 14 ! 2013: :_ ! 2014: .T& ! 2015: L | CI S S | . ! 2016: :hash number ! 2017: :_ ! 2018: .T& ! 2019: L | L CI L | ! 2020: L | L ^ L | ! 2021: L | L ^ L | ! 2022: L | L S S | . ! 2023: ::pointer to table ! 2024: :_::_ ! 2025: ! 2026: :_ ! 2027: .T& ! 2028: L | L CI L | ! 2029: L | L ^ L | ! 2030: L | L ^ L | ! 2031: L | L S S | . ! 2032: ::entry value ! 2033: :_::_ ! 2034: ! 2035: :_ ! 2036: .T& ! 2037: L | L CI L | ! 2038: L | L ^ L | ! 2039: L | L ^ L | ! 2040: L | L S S | . ! 2041: :: ! 2042: :_::_ ! 2043: ! 2044: :_ ! 2045: .TE ! 2046: \fINote\fR: The last descriptor in a table element trapped variable ! 2047: is not used until the element is inserted in the table, at which ! 2048: time the table element trapped variables is converted into a ! 2049: table element block. ! 2050: .KE ! 2051: .bp ! 2052: .ce 10 ! 2053: \f3Appendix E \(em Stack Frame Formats\fR ! 2054: .ce 0 ! 2055: .sp 1 ! 2056: .PP ! 2057: Stack frame formats depend on computer architecture and the ! 2058: C compiler that is used. Consequently, stack frame formats are ! 2059: specific to a particular implementation. This appendix gives the ! 2060: UNIX PDP-11 and VAX-11 stack frame formats. See [3] for a detailed ! 2061: description of the design of stack frame formats. ! 2062: .PP ! 2063: On the PDP-11 and VAX-11 stacks start in high memory and grow ! 2064: downward. On these computers, a push causes the stack ! 2065: pointer to decrease and a pop causes the stack pointer to ! 2066: increase, while ``top of the stack'' refers to the ! 2067: \fIlowest\fR memory location that is logically contained in the stack. ! 2068: The diagrams that follow are arranged accordingly. ! 2069: .PP ! 2070: There are three kinds of stack frames: \fIprocedure frames\fR, \fIexpression ! 2071: frames\fR, and \fIgenerator frames\fR. ! 2072: For each kind of frame, a ! 2073: .I "frame pointer" ! 2074: points to the most recent ! 2075: .I "frame marker" , ! 2076: which marks one end of the frame. ! 2077: These frame pointers are referred to as \fIpfp\fR, \fIefp\fR, and \fIgfp\fR, ! 2078: respectively. ! 2079: Each frame marker contains a pointer ! 2080: to the next most recent marker of the same kind. ! 2081: .sp 2 ! 2082: .ce ! 2083: \f3PDP-11 Stack Frame Formats\fR ! 2084: .sp 2 ! 2085: .PP ! 2086: On the PDP-11, \fIpfp\fR, \fIefp\fR, and \fIgfp\fR are in registers ! 2087: \fIr5\fR, \fIr4\fR, and \fIr3\fR, respectively, ! 2088: whenever an Icon procedure is active. ! 2089: In the interpreter implementation, ! 2090: .I r2 ! 2091: contains the interpreter's program counter (\fIipc\fR), ! 2092: which points to the next icode operation to be done. ! 2093: When a C procedure is active, ! 2094: only the procedure frame pointer is kept in a register; ! 2095: registers ! 2096: .I r2\-r4 ! 2097: are used for local variables by C procedures. ! 2098: .sp 1 ! 2099: .SH ! 2100: Procedure Frames on the PDP-11 ! 2101: .PP ! 2102: Icon procedure frames are augmented C procedure frames. ! 2103: A procedure frame contains a procedure's ! 2104: arguments, local variables, ! 2105: and temporary storage for incomplete computations. ! 2106: When an active procedure invokes another procedure, ! 2107: a new procedure frame is created for the new procedure, ! 2108: which then becomes active. ! 2109: As such, the new procedure represents an incomplete computation ! 2110: in the calling procedure, ! 2111: so the new procedure frame is ! 2112: .Q nested ! 2113: within the old one. ! 2114: The ! 2115: .I "procedure marker" ! 2116: is placed on the stack between the arguments and local variables. ! 2117: The format of the procedure frame is shown below. ! 2118: The locations are relative to \fIpfp\fR. ! 2119: .DS ! 2120: .ta 1iR 1.6i ! 2121: arguments ! 2122: 4 number of arguments ! 2123: 2 return address ! 2124: \fIpfp\fR \(-> 0 previous \fIpfp\fR ! 2125: \-2 previous \fIefp\fR ! 2126: \-4 previous \fIgfp\fR ! 2127: \-6 previous \fIipc\fR ! 2128: \-8 previous source program line number ! 2129: \-10 previous source program file name ! 2130: .DE ! 2131: Expression and generator frames are always ! 2132: contained wholly within a procedure frame, ! 2133: and their respective frame pointers are cleared to zero ! 2134: after being saved in the procedure marker. ! 2135: .PP ! 2136: The first argument to a procedure is located at 6(\fIpfp\fR), ! 2137: the second at 10(\fIpfp\fR), and so on. ! 2138: The first local variable is located at \-14(\fIpfp\fR), ! 2139: the second at \-18(\fIpfp\fR), and so on. ! 2140: .PP ! 2141: Procedure markers created for functions and operators ! 2142: do not contain the source program line number or file name, ! 2143: since functions and operators do not change it. ! 2144: Because they are C procedures, ! 2145: their local variables are not descriptors ! 2146: and are subject to C language conventions, ! 2147: but everything above the marker (higher addresses) ! 2148: is subject to Icon language conventions. ! 2149: The location of the procedure marker for functions and operators ! 2150: is considered the ! 2151: .I boundary , ! 2152: mentioned in Section 3.2. ! 2153: .sp 1 ! 2154: .SH ! 2155: Expression Frames on the PDP-11 ! 2156: .PP ! 2157: An expression frame limits the scope of backtracking. ! 2158: No inactive generator outside the current expression frame ! 2159: may be reactivated until evaluation of the current expression is complete. ! 2160: The format of an expression marker is shown below; ! 2161: locations are relative to ! 2162: \fIefp\fR. ! 2163: .DS ! 2164: .ta 1iR 1.6i ! 2165: \fIefp\fR \(-> 0 previous \fIefp\fR ! 2166: \-2 previous \fIgfp\fR ! 2167: \-4 failure label for expression frame ! 2168: .DE ! 2169: When an expression frame is created, ! 2170: the generator frame pointer is cleared after being saved ! 2171: in the expression marker, ! 2172: to indicate that there are no inactive generators that may ! 2173: be reactivated while the new expression frame is current. ! 2174: An expression frame extends from its expression marker ! 2175: to the top of the stack. ! 2176: Expression frames are not disjoint; ! 2177: new frames are always nested within older ones. ! 2178: .PP ! 2179: When failure occurs within an expression and there ! 2180: are no inactive generators to reactivate, ! 2181: the expression frame is exited, ! 2182: and control is transferred to the failure label. ! 2183: If the failure label is null, however, ! 2184: another failure occurs within the new expression frame, ! 2185: and the logic is the same. ! 2186: .PP ! 2187: For limited expressions, ! 2188: the limitation counter is contained in an Icon integer ! 2189: just above the expression marker at 2(\fIefp\fR). ! 2190: This counter is decremented each time the expression suspends a result. ! 2191: .SH ! 2192: Generator Frames on the PDP-11 ! 2193: .PP ! 2194: Generator frames are augmented procedure frames. ! 2195: A generator frame preserves the state of execution of a inactive generator. ! 2196: When a suspending procedure calls ! 2197: \fMpsusp\fR, ! 2198: a generator marker is placed on the stack ! 2199: to mark the point of suspension, ! 2200: and the most recent expression frame ! 2201: .I outside ! 2202: the suspending procedure frame ! 2203: (the expression frame that was current just prior to ! 2204: invocation of the suspending procedure) ! 2205: is then duplicated and pushed onto the stack. ! 2206: The suspending procedure then returns, ! 2207: so that the expression frame that was duplicated is current. ! 2208: Thus, the generator frame is contained within the expression frame, and ! 2209: .Q hides ! 2210: the inactive generator. ! 2211: The format of the generator marker is shown in the following table; ! 2212: locations are shown relative to \fIgfp\fR. ! 2213: .DS ! 2214: .ta 1iR 1.6i ! 2215: 10 reactivation address ! 2216: 8 previous \fIpfp\fR ! 2217: 6 previous \fIefp\fR ! 2218: 4 previous \fIgfp\fR ! 2219: 2 previous \fIipc\fR ! 2220: \fIgfp\fR \(-> 0 previous boundary address ! 2221: \-2 previous value of \fM&level\fR ! 2222: \-4 previous source program line number ! 2223: \-6 previous source program file name ! 2224: .DE ! 2225: The last five words of the generator marker ! 2226: are actually part of a procedure marker, ! 2227: created by the call to ! 2228: \fMpsusp\fR. ! 2229: Thus, the reactivation address is just the return address for ! 2230: \fMpsusp\fR. ! 2231: .PP ! 2232: When a function or operator suspends, ! 2233: there is a boundary that becomes hidden. ! 2234: This boundary address needs to be restored upon reactivation. ! 2235: It is also important to the garbage collector, ! 2236: since the portion of a generator frame between the hidden ! 2237: boundary and the generator marker does not have ! 2238: the well-defined structure that is required. ! 2239: .sp 2 ! 2240: .ce ! 2241: \f3VAX-11 Stack Frame Formats\fR ! 2242: .sp 2 ! 2243: .PP ! 2244: The C frames on the VAX are variable in size and \fIap\fR is used ! 2245: to facilitate access to the arguments. ! 2246: .SH ! 2247: Procedure Frames on the VAX-11 ! 2248: .PP ! 2249: On the VAX-11, there is a program counter (\fIpc\fR), ! 2250: a stack pointer (\fIsp\fR), ! 2251: a frame pointer (\fIfp\fR), and ! 2252: an argument pointer (\fIap\fR). ! 2253: These pointers are registers \fIr15\fR, \fIr14\fR, \fIr13\fR, and \fIr12\fR, ! 2254: respectively. ! 2255: Icon uses \fIfp\fR for \fIpfp\fR, \fIr11\fR for \fIefp\fR, and ! 2256: \fIr10\fR for \fIgfp\fR. ! 2257: .PP ! 2258: The procedure frame for the VAX-11 is: ! 2259: .DS ! 2260: .ta 1iR 1.6i ! 2261: arguments ! 2262: 4 number of arguments ! 2263: \fIap\fR \(-> 0 number of words in the argument list ! 2264: \-4 previous \fIefp\fR ! 2265: \-8 previous \fIgfp\fR ! 2266: .\^.\^. ! 2267: 16 previous \fIpc\fR ! 2268: 12 previous \fIfp\fR ! 2269: 8 previous \fIap\fR ! 2270: 4 program status word and register mask ! 2271: \fIfp\fR \(-> 0 0 (condition handler status) ! 2272: \-4 previous source program line number ! 2273: \-8 previous source program file name ! 2274: local variables ! 2275: .DE ! 2276: The first argument is at 8(\fIap\fR), the second argument is at ! 2277: 16(\fIap\fR), and so on. The first local variable is at \-16(\fIfp\fR)\fR, ! 2278: the second local variable is at \-24(\fIfp\fR), and so on. ! 2279: .SH ! 2280: Expression Frames on the VAX-11 ! 2281: .PP ! 2282: The expression frame marker for the VAX-11 is: ! 2283: .DS ! 2284: .ta 1iR 1.6i ! 2285: \fIefp\fR \(-> 0 previous \fIefp\fR ! 2286: \-4 previous \fIgfp\fR ! 2287: \-8 failure label for expression frame ! 2288: .DE ! 2289: .SH ! 2290: Generator Frames on the VAX-11 ! 2291: .PP ! 2292: The generator frame marker for the VAX-11 is: ! 2293: .DS ! 2294: .ta 1iR 1.6i ! 2295: previous \fIefp\fR ! 2296: previous \fIgfp\fR ! 2297: .\^.\^. ! 2298: last saved register ! 2299: 20 reactivation address ! 2300: 16 previous \fIfp\fR ! 2301: 12 previous \fIap\fR ! 2302: 8 program status word and register mask ! 2303: 4 0 (condition handler address) ! 2304: \fIgfp\fR \(-> 0 previous boundary address ! 2305: \-4 previous value of \fM&level\fR ! 2306: \-8 previous source program line number ! 2307: \-12 previous source program file name ! 2308: .DE ! 2309: .bp ! 2310: .ce 10 ! 2311: \f3Appendix F \(em Sample Functions\fR ! 2312: .ce 0 ! 2313: .sp 1 ! 2314: .PP ! 2315: The following routines are examples of the source code ! 2316: for Icon functions. ! 2317: As indicated in the report, ! 2318: each routine consists of a C procedure that performs the indicated ! 2319: function and a procedure block linking the C procedure with ! 2320: the Icon procedure invocation mechanism. ! 2321: .PP ! 2322: The first example is the code for the routine \fMwrite\fR, ! 2323: as supplied with the Icon distribution, and is included ! 2324: to show how a routine is written to handle a variable number ! 2325: of arguments. ! 2326: .Ds ! 2327: .ta 3.5i ! 2328: #include "../h/rt.h" ! 2329: ! 2330: /* ! 2331: * write(a,\*bb,\*b...) - write arguments. ! 2332: */ ! 2333: ! 2334: Xwrite(nargs) ! 2335: int nargs; ! 2336: { ! 2337: register int n; ! 2338: char sbuf\^[MAXSTRING]; ! 2339: struct descrip arg; ! 2340: FILE *f; ! 2341: ! 2342: f = stdout; ! 2343: arg = nullstr; ! 2344: ! 2345: for (n = 1; n \*(<= nargs; n++) { ! 2346: arg = ARG(n); ! 2347: DeRef(arg); /* dereference arguments */ ! 2348: .De ! 2349: .Ds ! 2350: .ta 3.5i ! 2351: if (!QUAL(arg) && TYPE(arg) == T_FILE) { ! 2352: if (n > 1) { ! 2353: putc('\en', f); ! 2354: fflush(f); ! 2355: } ! 2356: if ((BLKLOC(arg)->file.status & FS_WRITE) == 0) ! 2357: runerr(213, &arg); ! 2358: f = BLKLOC(arg)->file.fd; ! 2359: arg = nullstr; ! 2360: } ! 2361: else { ! 2362: if (n == 1 && (k_output.status & FS_WRITE) == 0) ! 2363: runerr(213, NULL); ! 2364: defany(&arg, &nullstr); ! 2365: if (cvstr(&arg, sbuf) == NULL) ! 2366: runerr(109, &arg); ! 2367: putstr(f, STRLOC(arg), STRLEN(arg)); ! 2368: } ! 2369: } ! 2370: .De ! 2371: .Ds ! 2372: .ta 3.5i ! 2373: putc('\en', f); ! 2374: fflush(f); ! 2375: if (STRLOC(arg) \*(>= sbuf && STRLOC(arg) < sbuf + MAXSTRING) { ! 2376: sneed(STRLEN(arg)); ! 2377: STRLOC(arg) = alcstr(STRLOC(arg), STRLEN(arg)); ! 2378: } ! 2379: ARG(0) = arg; ! 2380: } ! 2381: ! 2382: Procblock(write,\*b-1) ! 2383: .De ! 2384: The \-1 in the \fMProcblock\fR macro indicates that \fMwrite\fR ! 2385: takes an arbitrary number of arguments. ! 2386: .PP ! 2387: The following two routines are examples of ! 2388: typical functions that could ! 2389: be added to the run-time system using the technique described ! 2390: in Section 4. ! 2391: .PP ! 2392: The first of these routines, \fMseek\fR, interfaces to the C ! 2393: library routine \fMfseek\fR. ! 2394: .Ds ! 2395: .Ta 3.5i ! 2396: #include "../h/rt.h" ! 2397: ! 2398: /* ! 2399: * seek(file,\*boffset,\*bstart) - seek to offset byte from start in file. ! 2400: */ ! 2401: ! 2402: Xseek(nargs, arg3, arg2, arg1, arg0) ! 2403: int nargs; ! 2404: struct descrip arg3, arg2, arg1, arg0; ! 2405: { ! 2406: long l1, l2; ! 2407: int status; ! 2408: FILE *fd; ! 2409: long ftell(); ! 2410: ! 2411: DeRef(arg1); ! 2412: if (arg1.type != D_FILE) ! 2413: runerr(106); ! 2414: .Dd ! 2415: defint(&arg2, &l1, 0); ! 2416: defshort(&arg3, 0); ! 2417: ! 2418: fd = BLKLOC(arg1)->file.fd; ! 2419: ! 2420: if ((BLKLOC(arg1)->file.status == 0) || ! 2421: (fseek(fd, l1, arg3.value.integer) == -1)) ! 2422: fail(); ! 2423: mkint(ftell(fd), &arg0); ! 2424: } ! 2425: ! 2426: Procblock(seek,\*b3) ! 2427: .De ! 2428: The argument 3 in the \fMProcblock\fR macro indicates that ! 2429: \fMseek\fR takes three arguments. ! 2430: .PP ! 2431: The routine \fMgetenv\fR provides access to ! 2432: shell environment variables through the C library procedure \fMgetenv\fR. ! 2433: .Ds ! 2434: .ta 3.5i ! 2435: #include "../h/rt.h" ! 2436: ! 2437: /* ! 2438: * getenv(s) - return contents of environment variable s ! 2439: */ ! 2440: ! 2441: Xgetenv(nargs, arg1, arg0) ! 2442: int nargs; ! 2443: struct descrip arg1, arg0; ! 2444: { ! 2445: register char *p; ! 2446: register int len; ! 2447: char sbuf\^[MAXSTRING]; ! 2448: ! 2449: DeRef(&arg1); ! 2450: .Dd ! 2451: .ta 3.5i ! 2452: if (!QUAL(arg1)) /* check legality of argument */ ! 2453: runerr(103, &arg1); ! 2454: if (STRLEN(arg1) \*(<= 0 || STRLEN(arg1) \*(>= MAXSTRING) ! 2455: runerr(401, &arg1); ! 2456: qtos(&arg1, sbuf); /* convert argument to C-style string */ ! 2457: ! 2458: if ((p = getenv(sbuf)) != NULL) { /* get environment variable */ ! 2459: len = strlen(p); ! 2460: sneed(len); ! 2461: STRLEN(arg0) = len; ! 2462: STRLOC(arg0) = alcstr(p, len); ! 2463: } ! 2464: else /* fail if variable not in environment */ ! 2465: fail(); ! 2466: } ! 2467: ! 2468: Procblock(getenv,\*b-1) ! 2469: .De
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.