Annotation of 43BSD/contrib/icon/docs/tr83-10b.roff, revision 1.1

1.1     ! root        1: .de Ip
        !             2: .IP \\$1
        !             3: .br
        !             4: ..
        !             5: .nr $1 3
        !             6: .nr $2 7
        !             7: .nr $3 0
        !             8: .NH 3
        !             9: \*Miconx/start.s\fR
        !            10: .SH
        !            11: Overview
        !            12: .PP
        !            13: The routine \*Mmstart\fP in \*Mstart.s\fP is used to get Icon started.
        !            14: When the Icon interpreter is executed,\^ the C routine \*Mmain\fP passes
        !            15: control to \*Mmstart\fP,\^ and merely serves as a front-end for \*Mmstart\fP.
        !            16: .SH
        !            17: Generic Operation
        !            18: .Ls
        !            19: .Np
        !            20: Call the routine \*Minit\fR with the name of the
        !            21: file to interpret as its argument.
        !            22: .Np
        !            23: Make an Icon list out of the command line arguments using
        !            24: the \*Mllist\fR function.
        !            25: .Np
        !            26: Invoke the main procedure of the Icon program.
        !            27: .Le
        !            28: .SH
        !            29: \*Mstart\fP on the VAX
        !            30: .PP
        !            31: There is a short main program in \*Miconx/main.c\fP that calls \*Mmstart\fP
        !            32: with two arguments:
        !            33: .Ds
        !            34: .S1
        !            35:        main(argc, argv)
        !            36:        int argc;
        !            37:        char **argv;
        !            38:        {
        !            39:                mstart(argc, argv);
        !            40:        }
        !            41: .De
        !            42: .PP
        !            43: The number of command line arguments is in \*Margc\fP, and \*Margv\fP is a
        !            44: pointer to an array of pointers to strings representing the arguments.
        !            45: \*Margv\^[0]\fP is the command used to invoke the interpreter and \*Margv\^[1]\fP
        !            46: is the name of the file being interpreted.  Additional command line arguments
        !            47: are passed along to the main procedure of the Icon program.  When
        !            48: \*Mmstart\fP gets control, \*M4(ap)\fP is the \*Margc\fP value and 
        !            49: \*M8(ap)\fP is the argv value.
        !            50: .PP
        !            51: The first action taken by \*Mmstart\fP is to call \*Minit\fR to initialize the
        !            52: Icon run-time system.  \*Minit\fR loads the header and code portions of
        !            53: the interpretable file into memory,\^ so \*Minit\fR needs the
        !            54: name of the interpretable file.  The word at \*M8(ap)\fP is loaded into
        !            55: \*Mr9\fP, pointing it at \*Margv\^[0]\fP.  Then the name of the file to interpret
        !            56: (\*Margv\^[1]\fP), residing at \*M4(r9)\fP, is pushed on the stack as the
        !            57: argument for \*Minit\fP, which is then called.
        !            58: .PP
        !            59: In order to provide conformity with the usual execution environment
        !            60: of Icon procedures,\^ an expression frame is created for the execution
        !            61: of the main procedure.  Both the old expression frame pointer and the
        !            62: old generator frame pointer are set to be 0 in the expression frame
        !            63: for \*Mmain\fP.  The failure label must point to an interpreter opcode that
        !            64: will terminate execution of the program.  The opcode 0 is used
        !            65: for this purpose.  A word of storage,\^ \*Mflab\fR,\^ is declared and
        !            66: initialized to 0.  The failure label points to \*Mflab\fR.  Thus,\^ if
        !            67: \*Mmain\fP fails,\^ the interpreter executes the \*Mquit\fR opcode.
        !            68: .PP
        !            69: The next task is to push the descriptor for the procedure main
        !            70: on the stack for later use by \*Minvoke\fR.  The variable
        !            71: \*M_globals\fR contains the address of the list of global variable
        !            72: descriptors.
        !            73: The first global variable descriptor is always the one for the
        !            74: procedure main; if no main procedure was found when the program
        !            75: was linked,\^ the descriptor
        !            76: will be \*M&null\fR.  The value of \*M_globals\fR is loaded into
        !            77: \*Mr0\fR and the word then referenced by \*Mr0\fR is checked to see if it
        !            78: is equal to \*MD_PROC\fR.  (The first word of a descriptor for a procedure
        !            79: is always equal to \*MD_PROC\fR.)
        !            80: .\"\^[? not sure if we really need to check for D_PROC,\^
        !            81: .\"I think just checking for ~= 0 will suffice.]
        !            82: If the word is not equal
        !            83: to \*MD_PROC\fR,\^ a branch is made to \*Mnomain\fR which generates
        !            84: the appropriate run-time error.  Otherwise,\^ the descriptor
        !            85: for \*Mmain\fP is pushed onto the stack.  (The effect of the instruction
        !            86: \*Mmovq\ (r0),\^\-(sp)\fR
        !            87: is to move 8 bytes (the size of a quadword)
        !            88: starting at the address referenced by \*Mr0\fR to the
        !            89: 8 bytes referenced by the \*Msp\fR after subtracting 8 from the
        !            90: \*Msp\fR.)
        !            91: .PP
        !            92: The main procedure is to be invoked with a list consisting of the command
        !            93: line arguments (if any).  The Icon run-time routine \*Mllist\fR is used to
        !            94: make the list that is passed to the main procedure.  \*Mllist\fR stores
        !            95: the descriptor for the list that it creates in the descriptor above its
        !            96: first argument descriptor,\^ so to accommodate the result,\^ a null descriptor
        !            97: is pushed on the stack using the \*Mclrq\fR instruction.  Note that
        !            98: because \*Mllist\fP calls \*Msetbound\fP and \*Mclrbound\fP,\^ it is not
        !            99: possible to execute all of \*Mstart\fP until \*Mrt/setbound.s\fP has been
        !           100: completed.
        !           101: .PP
        !           102: At the beginning of this routine,\^ \*Mr9\fR was set to point
        !           103: at the first word of the argument list.
        !           104: Neither the name of the Icon interpreter nor the name of the interpretable
        !           105: file is desired in the argument list passed to main,\^ so \*Mr9\fR is
        !           106: twice incremented by 4 (the size in bytes of a word)
        !           107: to point it at the first actual program argument.
        !           108: .PP
        !           109: The next step is to construct the argument list for \*Mllist\fR.  For
        !           110: each command line argument,\^ the address of the string and then its
        !           111: length are pushed on the stack.  The length and address pairs form
        !           112: descriptors that \*Mllist\fP makes an Icon list from.
        !           113: \*Mr8\fR is used to count the arguments.
        !           114: After the addresses and lengths of each argument have been pushed,\^ the
        !           115: number of arguments is pushed on the stack.
        !           116: At this point,\^ the stack looks like this:
        !           117: .Ds
        !           118: .ft R
        !           119: .S1
        !           120:        descriptor for main procedure (2 4-byte words)
        !           121:        a null descriptor (2 words containing 0)
        !           122:        address of first argument to Icon program
        !           123:        length of first argument
        !           124:        \*(El
        !           125:        address of last argument to Icon program
        !           126:        length of last argument
        !           127: \*Msp\fR \*(ar number of arguments
        !           128: .De
        !           129: .LP
        !           130: All addresses and lengths are one word in size.  The \*Mcalls\fR
        !           131: instruction needs to be told how many words are in its argument list.
        !           132: (This is necessary because when a return is made from the subroutine,\^
        !           133: the specified number of words are removed from the stack.)  There
        !           134: are two words for each argument and an additional word for the number
        !           135: of arguments.  (Do not confuse the argument count for the \*Mllist\fR
        !           136: subroutine and the argument list size.)
        !           137: \*Mr8*2+1\fP is calculated in \*Mr8\fP.  This value is used
        !           138: as the argument list length for the \*Mcalls\fR instruction.
        !           139: When \*Mllist\fR returns,\^ the arguments are stripped from the
        !           140: stack and the stack looks like this:
        !           141: .Ds
        !           142: .ft R
        !           143: .S1
        !           144:        descriptor for main procedure
        !           145: \*Msp\fR \*(ar descriptor for list of command line arguments
        !           146: .De
        !           147: .LP
        !           148: Note that the null descriptor pushed earlier received the result of
        !           149: the \*Mllist\fR function.
        !           150: .PP
        !           151: At this point,\^ the main procedure is ready to be invoked.  The descriptor for
        !           152: the main procedure is \*(a0 and the descriptor for the list of
        !           153: command line arguments is \*(a1.  Before invoking the main procedure,\^
        !           154: the procedure frame pointer and the generator frame pointer are cleared.
        !           155: The main procedure is being invoked with one argument,\^ so a constant
        !           156: 1 is pushed on the stack.  The \*Mcalls\fR instruction is given an
        !           157: argument of 3 because a word is used for the number of arguments and
        !           158: two additional words are used for the descriptor for the list of command
        !           159: line arguments.
        !           160: .PP
        !           161: If the main procedure fails,\^ the interpreter will encounter the
        !           162: 0 opcode discussed earlier.  If the main procedure returns (this
        !           163: usually isn't done),\^ the return will manifest itself as \f3invoke\fR
        !           164: returning.  If this happens,\^ \*M_c_exit\fR is called with an
        !           165: argument of 0.  Incidentally,\^ this also happens when the interpreter
        !           166: hits the 0 opcode.
        !           167: .PP
        !           168: There is a block of code labeled \*Mnomain\fR that is executed when
        !           169: no main procedure is found.  This calls the routine \*Mrunerr\fR to
        !           170: produce an error message.  The actual call made is \*Mrunerr(117,\^0)\fR.
        !           171: The number 117 is looked up in a table of run-time errors.  If the second
        !           172: argument to \*Mrunerr\fR is non-zero,\^ it is interpreted as being the
        !           173: address of a descriptor and the descriptor is examined to produce
        !           174: an ``offending value'' to accompany the run-time error.
        !           175: .PP
        !           176: The last portion of executable code in \f3start.s\fR is the subroutine
        !           177: \*M_c_exit\fR.  If the variable \*M_monres\fR is non-zero,\^ it indicates
        !           178: that profiling is on,\^ and it must be turned off.  This is accomplished
        !           179: by calling \*M_monitor(0)\fR.  The routine \*M__cleanup\fR is then
        !           180: called to shut down the i/o system.  Finally,\^ \*M_exit\fR is called
        !           181: with the argument of \*M_c_exit\fR to terminate execution of the
        !           182: Icon interpreter.
        !           183: .PP
        !           184: There are several data declarations in \*Mstart.s\fR.  The first data
        !           185: declaration is a \*M.space 60\fR.  This is an accommodation for the
        !           186: garbage collector.  It
        !           187: insures that enough of the start of the data section
        !           188: is used up to force the addresses of other data objects to be
        !           189: greater than the defined constant \*MMAXTYPE\fR in \f3h/rt.h\fR.
        !           190: .PP
        !           191: Some assorted declarations are next. \*Mflab\fR is referenced
        !           192: by the interpreter if the main procedure fails.  It must be at
        !           193: least a byte long and contain a 0.  \*M_boundary\fR must be a
        !           194: word long and contain a 0.  \*M_environ\fR must be a word long;
        !           195: its contents are unimportant as it is written into at the beginning
        !           196: of \*Mstart.s\fR.
        !           197: .PP
        !           198: The \*M_tended\fR array is also used in conjunction with garbage
        !           199: collection.  It must declare space for five descriptors (two words
        !           200: per descriptor) that are initialized to 0.
        !           201: .\"\^[?]
        !           202: The label \*M_etended\fR
        !           203: is used to mark the end of the \*M_tended\fR array.
        !           204: .ne 1i
        !           205: .NH 3
        !           206: \*Mrt/setbound.s\fR
        !           207: .SH
        !           208: Overview
        !           209: .PP
        !           210: \*Msetbound.s\fP contains code for \*Msetbound\fP and \*Mclrbound\fP.
        !           211: \*Msetbound\fP sets \*M_boundary\fP under appropriate conditions and
        !           212: \*Mclrbound\fP clears \*M_boundary\fP under appropriate conditions.
        !           213: .SH
        !           214: Generic Operation
        !           215: .PP
        !           216: When a call is made from Icon into C,\^ \*M_boundary\fP must be set to point
        !           217: at the procedure frame on the top of the stack.  C routines that can
        !           218: be called from Icon have a call to \*Msetbound\fP as their first
        !           219: operation.  If \*Msetbound\fP is called and \*M_boundary\fP is not
        !           220: set,\^ that is,\^ \*M_boundary\fP has a value of zero,\^ \*Mboundary\fP is
        !           221: set to value of the \*Mfp\fP of the calling procedure.
        !           222: .PP
        !           223: When a C routine returns to Icon,\^ \*M_boundary\fP must be cleared.
        !           224: If \*M_boundary\fP has the same value as \*Mfp\fP,\^ the routine was
        !           225: called from Icon and thus when it returns,\^ it returns to Icon.
        !           226: At appropriate return points in routines,\^ a call to \*Mclrbound\fP is
        !           227: made.  If the return takes control back to Icon,\^ \*M_boundary\fP
        !           228: is cleared.
        !           229: .SH
        !           230: \*Msetbound\fP on the VAX
        !           231: .PP
        !           232: The value of \*M_boundary\fP is tested.  If \*Mboundary\fP is not set,\^
        !           233: that is,\^ if it has a value of zero,\^ it is set to the value of the
        !           234: \*Mfp\fP in the calling procedure.  Because the call to
        !           235: \*Msetbound\fP creates a procedure frame,\^ the \*Mfp\fP value saved in
        !           236: the frame is used.  If \*M_boundary\fP is already set,\^ it is not
        !           237: changed.
        !           238: .SH
        !           239: \*Mclrbound\fP on the VAX
        !           240: .PP
        !           241: The value of \*M_boundary\fP is compared to the \*Mfp\fP in the
        !           242: calling procedure.  If the values are the same,\^ the calling procedure
        !           243: was called from Icon and when it returns it returns to Icon.
        !           244: If this is the case,\^ \*M_boundary\fP is cleared.
        !           245: .SH
        !           246: An Alternative Approach
        !           247: .PP
        !           248: If the C system on the target machine uses calls at the beginning and
        !           249: end of C routines to save and restore registers,\^ it is possible to
        !           250: modify these routines to set and clear the boundary.  This approach is
        !           251: used on the PDP-11.
        !           252: .PP
        !           253: The file \*Mrt/csv.s\fP contains replacement
        !           254: routines for \*Mcsv\fP and \*Mcret\fP.  When \*Mcsv\fP is called to
        !           255: save registers,\^ if \*M_boundary\fP is 0,\^ \*Msp\fP is saved in
        !           256: \*M_boundary\fP.  This insures that the first call from Icon into C
        !           257: leaves \*M_boundary\fP at the top of the stack at that point.
        !           258: When \*Mcret\fP is called to restore registers,\^ if the procedure
        !           259: frame pointer is equal to \*M_boundary\fP,\^ the return is taking
        !           260: control back to Icon code and \*M_boundary\fP is cleared.
        !           261: .PP
        !           262: Note the resemblance between calling \*Msetbound\fP at the start of a
        !           263: C routine and having \*Mcsv\fP set \*M_boundary\fP whenever a C routine
        !           264: is entered.  Similarly,\^ there is a resemblance between calling
        !           265: \*Mclrbound\fP at appropriate points and having \*Mcret\fP clear
        !           266: \*M_boundary\fP when necessary.
        !           267: .PP
        !           268: The initial implementation of Icon was on the PDP-11 and the modified
        !           269: \*Mcsv\fP and \*Mcret\fP approach was used.  When the system was
        !           270: ported to the VAX,\^ the subsumption of \*Mcsv\fP and \*Mcret\fP by the
        !           271: hardware required that a software approach be taken.  The trade-offs
        !           272: are marginal if the target machine uses save and restore routines.
        !           273: Having a distinct \*Msetbound\fP and \*Mclrbound\fP may be easier to
        !           274: implement,\^ but using modified save and restore routines is
        !           275: definitely faster.
        !           276: .PP
        !           277: If this approach is used,\^ then \*MSetBound\fP and \*MClearBound\fP in
        !           278: \*Mrt.h\fP should be defined,\^ but given no value.
        !           279: .NH 3
        !           280: \*Mlib/invoke.s\fR
        !           281: .SH
        !           282: Overview
        !           283: .LP
        !           284: \*Minvoke.s\fP handles four specific tasks.  These are
        !           285: .Ds
        !           286: .ft R
        !           287: call a built-in function
        !           288: call an Icon procedure
        !           289: create a record
        !           290: perform mutual evaluation
        !           291: .De
        !           292: .LP
        !           293: Note that all of these operations rise from a source code
        !           294: expression of the form
        !           295: .Ds
        !           296: \*(e0(\*(e1,\^\*(El,\^\*(en)
        !           297: .De
        !           298: where each \*(ai is an expression of some type.
        !           299: Icon has strict left-to-right evaluation and thus,\^ for the preceding
        !           300: expression,\^ \*(e0 is evaluated first,\^ then \*(e1,\^ and so forth
        !           301: through \*(en.  As each expression is evaluated,\^ its result
        !           302: is pushed on the stack.  After the expressions have been evaluated
        !           303: (and assuming none failed),\^ the stack looks something like
        !           304: .Ds
        !           305: .ft R
        !           306: .S1
        !           307:        value from \*(e0
        !           308:        value from \*(e1
        !           309:        \*(El
        !           310:        value from \*(ei
        !           311:        \*(El
        !           312: \*Msp\fR \*(ar value from \*(en
        !           313: .De
        !           314: Then,\^ \*(e0 is \fIinvoked\fP.
        !           315: .PP
        !           316: Recall that stacks are represented as growing downward.  Thus,\^
        !           317: \*(en is on the ``top'' of the stack.  Also note that each
        !           318: ``value'' on the stack is actually a two-word descriptor.
        !           319: .\"The various \*(ei may be referred to as \fIarguments\fP.
        !           320: .SH
        !           321: Generic Operation
        !           322: .PP
        !           323: \*Minvoke\fP is an interpreter opcode that takes a single operand
        !           324: specifying how many \*(ei are present (\*(e0 is not counted).
        !           325: \*Minvoke\fP is also called from \*Mstart.s\fP to invoke the \*Mmain\fP
        !           326: procedure.
        !           327: .Ls
        !           328: .Np
        !           329: \*Minvoke\fP must determine whether it is to call a built-in function,\^
        !           330: call an Icon procedure,\^ create a record,\^ or perform mutual evaluation.  If
        !           331: \*(e0 is not something that can be invoked,\^
        !           332: \*Minvoke\fP notes this as a run-time error.
        !           333: .Np
        !           334: If mutual evaluation is to be done,\^ \*Minvoke\fP selects the
        !           335: value of \*(ei that corresponds to the value of \*(e0.  That is,\^
        !           336: if \*(e0 is 2,\^ then \*(e2 is selected and returned.  If \*(e0
        !           337: references a value that is out of range,\^ \*Minvoke\fP fails.
        !           338: .Np
        !           339: If an Icon procedure or built-in procedure
        !           340: is being called,\^ the argument list is adjusted
        !           341: to conform to the number of arguments that the procedure or function
        !           342: is expecting.  
        !           343: This may mean supplying \*M&null\fP for missing values,\^ or discarding
        !           344: the last few \*(ei.  Some built-in functions take a variable number of
        !           345: arguments,\^ but all Icon procedures take a fixed number of arguments.
        !           346: If the desired operation is creation of a record,\^ \*Minvoke\fP treats
        !           347: this just like invocation of a built-in procedure.  
        !           348: .Le
        !           349: .LP
        !           350: Built-in functions and Icon procedures are handled in very different ways.
        !           351: If a built-in function is being invoked,\^ it is simply called.  (The
        !           352: calling sequence is somewhat convoluted on the VAX and is
        !           353: described later.)
        !           354: Calling an Icon procedure is more involved; the following actions
        !           355: are taken.
        !           356: .Ls
        !           357: .Np
        !           358: Each \*(ei in the (adjusted) argument list is dereferenced.
        !           359: .Np
        !           360: If \*M&trace\fP has a non-zero value,\^ the function \*Mctrace\fP is
        !           361: called with appropriate arguments.  \*Mctrace\fP produces output
        !           362: that includes the name of the procedure being called and the arguments
        !           363: that are being passed to it.
        !           364: .Np
        !           365: The remainder of the procedure frame (partially constructed by the
        !           366: call itself) is built.  This includes pushing values for \*M_file\fP
        !           367: and \*M_line\fP on the stack.  \*M_file\fP is a pointer to a string
        !           368: that names the source file from which the code currently being
        !           369: executed came.  \*M_line\fP is the number of the source line
        !           370: that is currently being executed.  A descriptor for
        !           371: \*M&null\fP is pushed on the
        !           372: stack for each dynamic local of the procedure.
        !           373: .Np
        !           374: The generator frame pointer is cleared (because a new expression
        !           375: context is being entered).  \*Mipc\fP
        !           376: is loaded with the entry point of the procedure being called.
        !           377: Control is then passed back to the interpreter using a jump
        !           378: instruction.
        !           379: .Le
        !           380: .SH
        !           381: \*Minvoke\fP on the VAX
        !           382: .PP
        !           383: On the VAX,\^ immediately after \*Minvoke\fP has been entered,\^ the stack is
        !           384: .Ds
        !           385: .ft R
        !           386: .St
        !           387:                value from \*(e0
        !           388:                value from \*(e1
        !           389:                \*(El
        !           390:        8       value from \*(en
        !           391:        4       number of expressions \- 1 (\*Mnargs\fR)
        !           392: \*Map\fR \*(ar 0       number of words in argument list (\*Mnwords\fR)
        !           393:        -4      saved \*Mr11\fR
        !           394:        -8      saved \*Mr10\fR
        !           395:                \*(El
        !           396:                saved \*Mr1\fR
        !           397:                saved \*Mpc\fR
        !           398:        12      saved \*Mfp\fR
        !           399:        8       saved \*Map\fR
        !           400:        4       program status word and register mask
        !           401: \*Msp\fR,\^ \*Mfp\fR \*(ar     0       0 (condition handler address)
        !           402: .De
        !           403: .PP
        !           404: The first action of \*Minvoke\fP is to set \*M_boundary\fP to the
        !           405: value of \*Mfp\fP.  This is done because \*Minvoke\fP may be
        !           406: invoking a built-in procedure.
        !           407: .PP
        !           408: The number of arguments with which \*(e0 is to be invoked is contained
        !           409: in the \fInargs\fP word,\^ which resides at \*M4(ap)\fP.  This value
        !           410: is frequently used and is put into \*Mr8\fP.
        !           411: .PP
        !           412: \*Minvoke\fP makes
        !           413: frequent use of \*(e0,\^ but its address is not a fixed distance
        !           414: from any known point.  Rather,\^ the address of \*(e0 must be calculated
        !           415: using the address of \*(en and the number of arguments.  The VAX
        !           416: \*Mmovaq\fP instruction makes this calculation easy.  The desired
        !           417: calculation is
        !           418: .Ds
        !           419: r11 = 8 + ap + (r8 * 8)
        !           420: .De
        !           421: and is performed by
        !           422: .Ds
        !           423: movaq  8(ap)\^[r8],\^r11
        !           424: .De
        !           425: \*(e0 may be a
        !           426: variable and if so,\^ it needs to be dereferenced.
        !           427: \*Mr11\fP,\^ which contains the address of \*(e0 is pushed on
        !           428: the stack and \*Mderef\fP is called.  The dereferencing is done
        !           429: ``in place''; the previous value of \*(e0 is replaced with the
        !           430: dereferenced value.  The dereferenced value is a descriptor
        !           431: whose first word contains type information and whose second word
        !           432: (in some cases) contains the address of a data block which holds
        !           433: the actual value of the object.  Note that \*Mr11\fP points to
        !           434: the first word of this descriptor.
        !           435: .PP
        !           436: Recall that the first task of \*Minvoke\fP is to determine what
        !           437: \*(e0 is and to act accordingly.  The simplest case is when \*(e0
        !           438: is a procedure.  That is checked for by comparing \*M0(r11)\fP with
        !           439: \*MD_PROC\fP.  If \*(e0 is a procedure,\^ a forward jump is made to
        !           440: \*Mdoinvk\fP.
        !           441: .PP
        !           442: It is more interesting if \*(e0 is not a procedure.  The first
        !           443: alternative investigated is mutual evaluation.  mutual evaluation is similar to a procedure
        !           444: call,\^ but rather than \*(e0 being a procedure,\^ it is an integer
        !           445: that selects one of the \*(ei.  The selected \*(ei is the outcome of
        !           446: the mutual evaluation.  The routine \*Mcvint\fP is used to
        !           447: try to convert \*(e0 to an integer.  If \*(e0 cannot be converted to
        !           448: an integer,\^ a forward branch is taken to \*Mtrystr\fP to explore another
        !           449: possibility.
        !           450: For mutual evaluation,\^ a non-positive value of \*(e0
        !           451: is acceptable and is converted to a positive value using the
        !           452: \*Mcvpos\fP routine.  (Expressions in the argument list are indexed
        !           453: the same way that characters in a string are indexed.)  If the
        !           454: position is greater than the number of expressions in the list,\^ that
        !           455: is,\^ if the reference is out of range,\^ the mutual evaluation fails by calling
        !           456: the routine \*Mfail\fP.  If the position is in range,\^ the selected
        !           457: \*(ei must be returned as the result of the invocation (and the
        !           458: result of the mutual evaluation).  The \*(ei to return is selected by multiplying
        !           459: the position by 8 (each \*(ei is a descriptor) and subtracting
        !           460: that from \*Mr11\fP,\^ which points at \*(e0.  The descriptor thus
        !           461: referenced is copied into the location of \*(e0.  (Recall that \*(e0
        !           462: is used to receive the result of an operation.)  \*M_boundary\fP
        !           463: is then cleared and \*Minvoke\fP returns.
        !           464: .PP
        !           465: If \*(e0 is not convertible to an integer,\^ conversion to a
        !           466: procedure is attempted.  (Note that this is an experimental extension
        !           467: to Icon.)  \*(e0 is first converted to a string
        !           468: using \*Mcvstr\fP.  If the conversion is successful,\^ the routine
        !           469: \*Mstrprc\fP is called to see if the string ``names'' a procedure.
        !           470: The conversion performed by \*Mstrprc\fP is ``in place'',\^ i.e.,\^
        !           471: \*(e0 becomes a descriptor for a procedure.  If either the
        !           472: conversion in \*Mcvstr\fP or \*Mstrprc\fP fails,\^ \*(e0 is deemed
        !           473: to be uninvocable and this is noted by run-time Error 106.
        !           474: .PP
        !           475: At this point (the label \*Mdoinvk\fP),\^ \*(e0 is a descriptor to a procedure
        !           476: to be invoked and \*Mr11\fP points to \*(e0.
        !           477: .PP
        !           478: The next operation is to make the number of arguments supplied
        !           479: conform to the number of arguments that the procedure is expecting.
        !           480: The number of arguments that a procedure expects is in the fifth
        !           481: word of its procedure block.  This value for the procedure being
        !           482: invoked is obtained and placed in \*Mr10\fP.
        !           483: If the value is negative,\^ the number
        !           484: of arguments that the procedure expects is variable.  Only built-in
        !           485: procedures can have a variable number of arguments,\^ so if the
        !           486: desired argument count is negative,\^ control passes to the label
        !           487: \*Mbuiltin\fP.
        !           488: .PP
        !           489: \*Mr8\fP contains the number of arguments given and \*Mr10\fP contains
        !           490: the number of arguments desired.  The value of \*Mr10\fP is subtracted
        !           491: from \*Mr8\fP,\^ leaving \*Mr8\fP with the difference.  If the
        !           492: number of arguments supplied is the same as the number expected,\^
        !           493: no adjustment is needed and a forward jump is made to
        !           494: \*Mdoderef\fP.  Otherwise,\^ the stack must be adjusted.
        !           495: .PP
        !           496: First,\^ \fInwords\fR and \fInargs\fR on the stack are adjusted.  Recall
        !           497: that \fInargs\fR
        !           498: is used by Icon and is the number of arguments for a procedure.
        !           499: \fInwords\fR is used by the VAX hardware and is the number of words that
        !           500: the argument list for a subroutine occupies.  \fInargs\fR resides at
        !           501: \*M4(ap)\fP and is updated by storing \*Mr10\fP in \*M4(ap)\fP.
        !           502: \fInwords\fR is trickier because only the low-order byte of the \fInwords\fR word
        !           503: is to be used for the word count.  The low-order byte of \*Mr10\fP is
        !           504: stored in \*M0(ap)\fP,\^ doubled,\^ and then incremented by one.  (The
        !           505: increment by one is to allow for the \fInargs\fR word that is part of
        !           506: the argument list.)
        !           507: .PP
        !           508: The deletion of excess arguments or addition of \*M&null\fP for
        !           509: missing arguments is accomplished by moving the lower portion of
        !           510: the stack up or down to overwrite excess arguments or to leave
        !           511: space for missing arguments.  Consider the following:  A procedure
        !           512: that expects one argument has been invoked with three arguments.
        !           513: The stack is
        !           514: .Ds
        !           515: .ft R
        !           516: .St
        !           517:        128     \*(e0
        !           518:        120     \*(e1
        !           519:        112     \*(e2
        !           520:        104     \*(e3
        !           521:        100     \*Mnargs\fR (3 at call,\^ 1 after adjustment)
        !           522: \*Map\fR \*(ar         96      \*Mnwords\fR (7 at call,\^ 3 after adjustment)
        !           523:        92      \*Mr11\fR
        !           524:                \*(El
        !           525:        48      \*Mr1\fR
        !           526:        44      \*Mpc\fR
        !           527:        40      \*Mfp\fR
        !           528:        36      \*Map\fR
        !           529:        32      \*Mpsw\fR
        !           530: \*Msp\fR,\^ \*Mfp\fR \*(ar     28      0
        !           531: .De
        !           532: The situation desired is
        !           533: .Ds
        !           534: .ft R
        !           535:        128     \*(e0
        !           536:        120     \*(e1
        !           537:        116     \*Mnargs\fR (1)
        !           538: \*Map\fR \*(ar         112     \*Mnwords\fR (3)
        !           539:        108     \*Mr11\fR
        !           540:                \*(El
        !           541:        64      \*Mr1\fR
        !           542:        60      \*Mpc\fR
        !           543:        56      \*Mfp\fR
        !           544:        52      \*Map\fR
        !           545:        48      \*Mpsw\fR
        !           546: \*Msp\fR,\^ \*Mfp\fR \*(ar     44      0
        !           547: .De
        !           548: Note the address field (which has been arbitrarily assigned).
        !           549: Observe that \*(e0 and \*(e1 are in
        !           550: the same place,\^ but that the lower portion of the stack has moved up.
        !           551: Consider what would be desired if the
        !           552: procedure being invoked requires five arguments and only three are
        !           553: supplied.  The desired stack configuration is
        !           554: .Ds
        !           555: .ft R
        !           556: .St
        !           557:        128     \*(e0
        !           558:        120     \*(e1
        !           559:        112     \*(e2
        !           560:        104     \*(e3
        !           561:        96      \*M&null\fP (\*(e4)
        !           562:        88      \*M&null\fP (\*(e5)
        !           563:        84      \*Mnargs\fR (5)
        !           564: \*Map\fR \*(ar         80      \*Mnwords\fR (11)
        !           565:        76      \*Mr11\fR
        !           566:                \*(El
        !           567:        32      \*Mr1\fR
        !           568:        28      \*Mpc\fR
        !           569:        24      \*Mfp\fR
        !           570:        20      \*Map\fR
        !           571:        16      \*Mpsw\fR
        !           572: \*Msp\fR,\^ \*Mfp\fR \*(ar     12      0
        !           573: .De
        !           574: As before,\^ the ``good'' arguments are in the same place,\^ but the
        !           575: stack has moved down to make room for \*(e4 and \*(e5 and a value
        !           576: of \*M&null\fP is supplied for them.
        !           577: .PP
        !           578: The VAX hardware makes these stack manipulations easy.  Recall that
        !           579: \*Mr8\fP contains
        !           580: .Ds
        !           581: .ft R
        !           582: number of arguments expected \- number of arguments supplied
        !           583: .De
        !           584: Thus,\^ in the first case \*Mr8\fP has a value of 2,\^ while in the second
        !           585: case \*Mr8\fP is \-2.  The value of \*Mr8\fP is multiplied by
        !           586: 8 to turn the argument count into a byte count.  This byte count
        !           587: is added to \*Msp\fP,\^ effectively moving it to where it should
        !           588: be.  Now,\^ a block of memory starting at where \*Mfp\fP points
        !           589: must be moved to where \*Msp\fP points.  The size of the
        !           590: block needs to be considered.  It starts at the fp and contains
        !           591: the condition handler,\^ the old psw,\^ \*Map\fP,\^ \*Mfp\fP and \*Mpc\fP
        !           592: \(em five words.
        !           593: Eleven saved registers are included; eleven more words. (A constant,\^
        !           594: \*MINVREGS\fP,\^ is used to represent the number of saved registers.)
        !           595: Finally,\^ two words for \fInargs\fR and \fInwords\fR \(em a total of 18
        !           596: words.  The VAX
        !           597: instruction that makes the move is
        !           598: .Ds
        !           599: movc3  $(INVREGS+7)*4,\^(fp),\^(sp)
        !           600: .De
        !           601: which moves 18*4 (=72) bytes from where \*Mfp\fP is pointing to
        !           602: where \*Msp\fP pointing.  The VAX allows the source and
        !           603: destination fields to overlap without producing ``curious'' results.
        !           604: .PP
        !           605: Some housekeeping must be performed after the move is made.
        !           606: \*Mfp\fP is set to point to the same word \*Msp\fP points to,\^
        !           607: and the boundary is set to point to the same place.  \*Map\fP is
        !           608: adjusted to point to the \fInwords\fR word.
        !           609: .PP
        !           610: If arguments were deleted,\^ the adjustment process is done.  If
        !           611: arguments were added,\^ \*M&null\fP must be supplied as the value
        !           612: for each argument that was added.  Because the descriptor for
        !           613: \*M&null\fP consists of two words containing 0,\^ the task amounts to filling
        !           614: in null bytes in the ``hole'' that was made.  \*Mr8\fP contains
        !           615: the number of bytes in the ``hole''.  \*Mr8\fP is negative and it
        !           616: is negated to obtain a positive byte count.  The instruction
        !           617: .Ds
        !           618: movc5  $0,\^(r0),\^$0,\^r8,\^(INVREGS+7)*4(sp)
        !           619: .De
        !           620: does all the work.  Specifically,\^ this instruction moves bytes of zeroes
        !           621: starting at \*M(r0)\fP to a field that starts at \*M72(sp)\fP and
        !           622: extends for \*Mr8\fP bytes.  The third operand of the instruction
        !           623: is a ``fill character'' that is used in the event that the destination
        !           624: field is longer than the source field.  In this case,\^ the source
        !           625: field is 0 bytes long,\^ and a null-byte fill character is moved into
        !           626: each byte of the destination field.  This is the usual way to zero
        !           627: out a block of memory on the VAX.
        !           628: .PP
        !           629: At this point,\^ the correct number of arguments for the procedure
        !           630: are on the stack.
        !           631: .PP
        !           632: For an Icon procedure,\^ all arguments must be dereferenced before
        !           633: the procedure is called.  Procedure blocks have a field that tells
        !           634: how many dynamic local variables the procedure has.  For built-in
        !           635: procedures this field has a value of \-1.  If a built-in procedure
        !           636: is to be invoked,\^ control jumps to the label \*Mbuiltin\fP.
        !           637: If an Icon procedure is to be invoked,\^ but it has no arguments (and
        !           638: thus they do not need to be dereferenced),\^ a forward jump is made
        !           639: to \*Mcktrace\fP.
        !           640: .PP
        !           641: \*Mr11\fP points to the descriptor for \*(e0.  The address of \*(e1
        !           642: is used later in \*Minvoke\fP,\^ and its address is calculated using \*Mr11\fP
        !           643: because it's handy.  \*Mr10\fP contains the number of arguments and
        !           644: this value is stored in \*Mr5\fP for subsequent use of \*Mr5\fP as a
        !           645: counter.  The arguments must be dereferenced,\^ this is done by calling
        !           646: \*Mderef\fP with the address of each argument.  The instruction
        !           647: .Ds
        !           648: pushaq  -(r11)
        !           649: .De
        !           650: is used to decrement \*Mr11\fP by 8 and then push the value of \*Mr11\fP
        !           651: on the stack.  Because \*Mr11\fP initially references \*(e0,\^ the first
        !           652: time through \*Mr11\fP is decremented to point at \*(e1 and
        !           653: \*Mderef\fP is called with the address of \*(e1.  \*Mr11\fP is backed
        !           654: down through the expression list,\^ with each \*(ei being dereferenced
        !           655: in turn.  Note that the \*Msobgeq\fP instruction is used as a loop
        !           656: controller,\^ decrementing \*Mr5\fP and jumping back to \*Mnxtarg\fP as
        !           657: long as \*Mr5\fP is not 0.
        !           658: .PP
        !           659: At this point,\^ an Icon procedure is being
        !           660: invoked; it has the correct number of arguments and they
        !           661: have been dereferenced.
        !           662: .PP
        !           663: If tracing is on,\^ (indicated by a non-zero value for \*M_k_trace\fP),\^
        !           664: a trace message must be produced at this point.
        !           665: The routine \*Mctrace\fP does all the work.  It needs to be called
        !           666: with the appropriate arguments.  \*Mctrace\fP requires three
        !           667: arguments: procedure block address,\^ number of arguments,\^ and the
        !           668: address of the first argument.  These are pushed on the stack and
        !           669: \*Mctrace\fP is called.
        !           670: .PP
        !           671: The portion of the stack from \*(e0 on down constitutes a partial
        !           672: procedure frame and it must be completed.  \*M_line\fP and \*M_file\fP
        !           673: are pushed on the stack.  To complete the frame,\^ the local variables
        !           674: must be pushed on the stack.  Local variables have an initial value
        !           675: of \*M&null\fP,\^ and the \*Mmovc5\fP idiom used previously is used
        !           676: again to zero out the space required for the local variables.
        !           677: .PP
        !           678: Because an Icon procedure is being invoked,\^ the boundary is cleared and
        !           679: \*M_k_level\fP (the \*M&level\fP keyword) is incremented.  The entry
        !           680: point for a procedure is stored in the third word of the procedure
        !           681: block.  This value is loaded into \*Mipc\fP.
        !           682: A new expression context is being entered,\^ and both
        !           683: \*Mgfp\fP and \*Mefp\fP are cleared using a \*Mclrq\fP instruction.
        !           684: .PP
        !           685: Control is passed back to the main loop of the interpreter
        !           686: by jumping to \*Minterp\fP.
        !           687: The Icon procedure is now being executed.  The procedure
        !           688: eventually terminates by use of \*Mpret\fP or \*Mpfail\fP.
        !           689: .LP
        !           690: The section of code following \*Mbuiltin:\fP
        !           691: handles the case where a built-in procedure is to be invoked.
        !           692: .PP
        !           693: If nothing is changed,\^ when a built-in function returns,\^ it would
        !           694: return to the instruction after the call to \*Minvoke\fP.  This
        !           695: is unsatisfactory,\^ since the boundary needs to be cleared because
        !           696: of the transition from the C environment to the Icon environment.
        !           697: Rather than having a call to \*Mclrbound\fP at
        !           698: the end of each built-in procedure,\^ the boundary is cleared at
        !           699: a common return point.
        !           700: .PP
        !           701: The \*Mpc\fP value that is stored at \*M16(fp)\fP is ``hidden''
        !           702: at \*M20(fp)\fP where the value of \*Mr1\fP should be saved.
        !           703: \*M16(fp)\fP is replaced with the address of the forward label
        !           704: \*Mbprtn\fP.  Thus,\^ when the built-in procedure returns,\^ it goes
        !           705: right to \*Mbprtn\fP.  Because a C environment is being entered,\^
        !           706: the boundary is set to the current value of \*Mfp\fP.  The third
        !           707: word of the procedure block contains the entry point of the built-in
        !           708: procedure and it is jumped to.  It is important to understand that
        !           709: the procedure is not called because the call frame has already been
        !           710: constructed.  Also,\^ the entry point address stored in the procedure
        !           711: block \fImust\fR be past any instructions that are used to establish
        !           712: the stack environment for the routine because this environment
        !           713: should already be on the stack.
        !           714: .PP
        !           715: When the built-in procedure returns,\^ it comes to \*Mbprtn\fP.
        !           716: The boundary is cleared because execution is back in an Icon
        !           717: environment. The procedure return restores \*Mr1\fP,\^ which contains
        !           718: the \*Mpc\fP value that \*Minvoke\fP should return to.  Because
        !           719: the return has already swept off the old frame,\^ \*M0(r1)\fP is
        !           720: jumped to and \*Minvoke\fP is finished.  Note that the built-in
        !           721: procedure has left its result in \*(e0,\^ which is left on the
        !           722: stack.  Thus,\^ the direct result of \*Minvoke\fP is an additional
        !           723: value on the stack.
        !           724: .SH
        !           725: Some Comments on \*Minvoke\fR
        !           726: .PP
        !           727: It is important to understand the purpose of \*Minvoke\fP.  Unless
        !           728: mutual evaluation is being performed,\^
        !           729: the task of \*Minvoke\fP is to create a procedure frame for an Icon or
        !           730: built-in procedure and then transfer control to the procedure.
        !           731: .PP
        !           732: On the VAX and the PDP-11,\^ the call to \*Minvoke\fP partially
        !           733: creates the procedure frame.  \*Minvoke\fP then completes the
        !           734: frame.  For Icon procedures,\^ control eventually passes out of
        !           735: \*Minvoke\fP and goes back to the interpreter loop.  However,\^
        !           736: for built-in procedures,\^ after the frame is built,\^ \*Minvoke\fP
        !           737: \fIbranches into\fP the C code for the procedure.  Thus,\^ it appears
        !           738: that the built-in procedure was called directly.  This scheme is
        !           739: facilitated by the fact that entry points of C routines on the
        !           740: VAX and PDP-11 are a constant distance from the start of the routine.
        !           741: (The \*MEntryPoint\fP macro in \*Mrt.h\fP specifies the distance.)
        !           742: On some machines this may not be practical and other schemes may need
        !           743: to be developed.
        !           744: .PP
        !           745: Another point that needs to be addressed is that of argument removal.
        !           746: When a built-in procedure,\^ Icon procedure,\^ or built-in operation is
        !           747: performed,\^ the net result almost always is
        !           748: simply the addition of a descriptor to the stack.  More precisely,\^
        !           749: the new descriptor is actually a replacement for \*(a0,\^ which
        !           750: is the descriptor for the procedure being called,\^ or in the case
        !           751: of a built-in operation is \*M&null\fP.  Recall that arguments are below \*(a0
        !           752: on the stack.  The \*(a0 word must be on top of the
        !           753: stack when a procedure or operation is complete.  The VAX does
        !           754: this via hardware,\^ which manages the stack and removes arguments when
        !           755: a procedure call is complete.  The PDP-11 does not have such hardware
        !           756: facilities and thus the arguments must be removed manually.  The
        !           757: problem is compounded by the fact that for built-in operations,\^
        !           758: \*Minvoke\fP is never called; rather,\^ the interpreter loop calls the
        !           759: appropriate subroutine directly.
        !           760: .PP
        !           761: The method employed on the PDP-11 uses the \*Mcret\fP routine to
        !           762: remove arguments.  \*Mcret\fP is called at the end of each C routine
        !           763: to restore registers.  Icon has a replacement for \*Mcret\fP that
        !           764: restores registers but also removes arguments when appropriate.
        !           765: \*Mrt/csv.s\fP contains the replacement routine.  When \*Mcret\fP is
        !           766: called,\^ if \*Mr5\fP (the \*Mpfp\fP on the PDP-11) is equal to
        !           767: \*M_boundary\fP,\^ then \*Mcret\fP is returning to Icon code and any
        !           768: arguments on the stack are removed,\^ leaving \*(a0 on the top of the
        !           769: stack.
        !           770: A similar technique may be needed on the target machine.
        !           771: .PP
        !           772: \*Mrt/csv.s\fP also contains a replacement for the \*Mcsv\fP routine
        !           773: which saves registers upon entry to C functions
        !           774: on the PDP-11.  Both \*Mcsv\fP and \*Mcret\fP also contain code that
        !           775: is used to set and clear the boundary at appropriate times.  See
        !           776: the description of \*Mrt/setbound.s\fP for more details.
        !           777: .NH 3
        !           778: \*Miconx/interp.s\fR
        !           779: .SH
        !           780: Overview
        !           781: .PP
        !           782: \*Minterp.s\fP is the main loop for the interpreter.
        !           783: The execution of an Icon program is stack based.
        !           784: As the interpreter executes an Icon program,\^ it
        !           785: fetches instructions and accompanying operands out of the instruction
        !           786: stream of the interpretable file.  Operands for
        !           787: interpreter instructions are pushed on the stack and results
        !           788: accumulate on the stack as operands for other instructions.
        !           789: In addition to simple incremental and decremental stack changes,\^
        !           790: the expression evaluation mechanism may cause portions of the
        !           791: stack to be duplicated and may also cause the top portion of
        !           792: the stack to be removed.
        !           793: .SH
        !           794: Generic Operation
        !           795: .PP
        !           796: An Icon program is executed by interpreting the interpretable file
        !           797: produced by the linker.  The interpretation process itself is fairly
        !           798: simple.  \*Mipc\fP points at the next
        !           799: instruction to be executed.  (Recall that the interpretable file is
        !           800: loaded into memory.)  The opcode of the instruction is fetched
        !           801: and the corresponding
        !           802: word in the jump table is taken as the address of a sequence of
        !           803: instructions that perform the desired operations.  A branch is
        !           804: taken to the referenced location and the operation is performed.
        !           805: The operation may require operands; if so,\^ they appear in the
        !           806: instruction stream following the opcode.  The segment of code that
        !           807: performs a particular operation is responsible for fetching the
        !           808: appropriate operands out of the stream.  When the
        !           809: operation is complete,\^ a jump is taken to the top of the interpreter
        !           810: loop and the process continues.
        !           811: .PP
        !           812: Interpreter operations are of two types.  Operations of the first type
        !           813: call a routine to perform a task.  Operations of the second type are
        !           814: executed entirely by the interpreter; no subroutine call is necessary.
        !           815: .PP
        !           816: Operations that require a call to be made call routines in the
        !           817: \*Moperators\fP or \*Mlib\fP directories.  The routine being called
        !           818: may require one or more arguments.  If arguments are required,\^ they
        !           819: appear on the stack.  When the routine returns,\^ it removes
        !           820: any arguments that it was called with from the stack and leaves its
        !           821: result on the top of the stack.
        !           822: .PP
        !           823: To facilitate the calling of
        !           824: routines,\^ a table known as \*Moptab\fP parallels the jump table.
        !           825: An opcode \fIn\fP references the \fIn\fPth word of the jump table.
        !           826: If the operation designated by the opcode requires a call,\^ the
        !           827: \fIn\fPth word of \*Moptab\fP contains the address of the routine
        !           828: that should be called.
        !           829: .PP
        !           830: The interpreter saves space in its
        !           831: instruction stream by encoding operand information in some opcodes.
        !           832: For example,\^ the \*Mline\fP instruction has one operand that
        !           833: is used to set the value of \*M_line\fP,\^ the current source line
        !           834: number.  The \*Mlinex\fP instruction is an alternate form of
        !           835: \*Mline\fP which encodes the line number as the low order bits of the
        !           836: opcode.  Specifically,\^ the opcodes from 192 to 256 are \*Mlinex\fP
        !           837: opcodes.  For example,\^ opcode 195 is equivalent to a \*Mline\fP
        !           838: opcode with an operand of 3.
        !           839: .SH
        !           840: Implementing the Interpreter Loop
        !           841: .PP
        !           842: \*Minterp.s\fP stands alone among the assembly language files as one that is
        !           843: well suited to coding in a macro fashion.  Most of the interpreter loop is
        !           844: written in terms of \fIcpp\fP macros and thus porting it is largely a
        !           845: matter of writing the macros for the target machine.
        !           846: .LP
        !           847: The following \*M#define\fPs must be made.
        !           848: .Ip \*MOp\ \ \ \ \ \fP
        !           849: .br
        !           850: The operand register.  Any general purpose register will do.  The
        !           851: value of the register need not preserved between instructions; its
        !           852: lifetime is only from the time that an operand is fetched until the
        !           853: next opcode is fetched or a routine is called.
        !           854: .Ip \*MGetOp\fP
        !           855: This must expand into code that fetches the next operand out of
        !           856: the instruction stream and places it in the register \*MOp\fP.
        !           857: Recall that operand size is determined by
        !           858: the \*M#define\fP for \*MOPNDSIZE\fP in the linker.
        !           859: On the VAX,\^ \*MGetOp\fP is merely
        !           860: .Ds
        !           861: .ta 0.6i +0.6i +0.6i +0.6i
        !           862: movl   (ipc)+,\^Op
        !           863: .De
        !           864: This is because operands are one word long and can begin on any byte
        !           865: boundary.  If the VAX did not support word fetching from arbitrary
        !           866: boundaries,\^ it would be necessary to get the bytes from the
        !           867: instruction stream one at a time and make a word out of them using
        !           868: boolean operations.  If such were the case,\^ a reasonable alternative
        !           869: would be to make opcodes one word in size and thus all instruction
        !           870: stream objects (opcodes,\^ operands,\^ and words),\^ would be of the same
        !           871: size and lie on word boundaries.
        !           872: .\".IP \*MGetWord\fP
        !           873: .\"\*MGetWord\fP is similar to \*MGetOp\fP,\^ but rather than loading the
        !           874: .\"next operand,\^ it loads the next \fIword\fP from the instruction stream into
        !           875: .\"the \*MOp\fP register.  Recall that the size of a word is defined by
        !           876: .\"the \*MWORDSIZE\fP in the linker.  If words are the same size as
        !           877: .\"operands on the target machine,\^ \*MGetWord\fP should be identical to
        !           878: .\"\*MGetOp\fP.
        !           879: .Ip \*MPushOp\fP
        !           880: Push the \*MOp\fP register on the stack.  The VAX uses
        !           881: .ta .6i
        !           882: .Ds
        !           883: pushl  Op
        !           884: .De
        !           885: .Ip \*MPushNull\fP
        !           886: Push a descriptor for \*M&null\fP on the stack.  That is,\^ push two
        !           887: words of zeroes.  The VAX \*Mclrq\fP instruction does the trick:
        !           888: .Ds
        !           889: clrq   -(sp)
        !           890: .De
        !           891: .Ip \*MPush_R(x)\fP,\^\ \*MPush_S(x)\fP,\^\ \*MPush_K(x)\fP
        !           892: Push the value of \*Mx\fP on the stack.  To accommodate machines with
        !           893: non-orthogonal instruction sets,\^ \*MPush_R\fP is used to push a register
        !           894: value,\^ and \*MPush_S\fP is used to push the contents of a storage
        !           895: location.  \*MPush_K\fP is used to push a constant value.
        !           896: The VAX uses
        !           897: .Ds
        !           898: pushl  x
        !           899: .De
        !           900: for both \*MPush_R(x)\fP and \*MPush_S(x)\fP,\^ while
        !           901: .Ds
        !           902: pushl  $x
        !           903: .De
        !           904: is used for \*MPush_K(x)\fP.
        !           905: .Ip \*MPushOpSum_R(x)\fP,\^\ \*MPushOpSum_S(x)\fP
        !           906: \*MPushOpSum_R(x)\fP adds the value
        !           907: of the register \*Mx\fP to \*MOp\fP and pushes the result on the stack.
        !           908: \*MPushOpSum_S(x)\fP is similar,\^ adding the value in the memory
        !           909: location \*Mx\fP to \*MOp\fP and pushing the result.  On the VAX,\^
        !           910: .Ds
        !           911: addl3  Op,\^x,\^-(sp)
        !           912: .De
        !           913: is used for both.
        !           914: .Ip \*MNextInst\fP
        !           915: Branch to the top of the interpreter loop.  The VAX uses
        !           916: .Ds
        !           917: jmp    _interp
        !           918: .De
        !           919: .Ip \*MCallN(n)\fP
        !           920: Call the routine corresponding to the current opcode with \*Mn\fP
        !           921: arguments.  On the VAX,\^ the opcode fetching segment loads \*Mr0\fP
        !           922: with a byte offset into the jump table.  This same byte offset
        !           923: references the location in \*Moptab\fP which contains the address
        !           924: of the routine which corresponds to the current opcode.
        !           925: \*MCallN(n)\fP expands to
        !           926: .Ds
        !           927: pushl  $n
        !           928: calls  $((n*2)+1),\^*optab(r0)
        !           929: .De
        !           930: \*Mpushl $n\fP pushes the number of arguments on the stack.  This
        !           931: word becomes the \fInargs\fP word of the procedure frame.  The
        !           932: first of operand of the \*Mcalls\fP instruction is the length of
        !           933: words in the argument list,\^ since each argument is a two word
        !           934: descriptor and the \fInargs\fP word occupies another word,\^
        !           935: \*Mn*2+1\fP is used as the length of the argument list.  The
        !           936: address contained in the \*Moptab\fP word referenced by \*Mr0\fP is
        !           937: the routine to call.
        !           938: .Ip \*MCallNameN(n,\^f)\fP
        !           939: Call the routine named \*Mf\fP with \*Mn\fP arguments.  This is very
        !           940: similar to \*MCallN\fP,\^ the only difference being that the routine
        !           941: to call is explicitly named rather than being implicitly determined
        !           942: from the opcode value.  The VAX uses
        !           943: .Ds
        !           944: pushl  $n
        !           945: calls  $((n*2)+1),\^f
        !           946: .De
        !           947: .Ip \*MBitClear(m)\fP
        !           948: The constant value \*Mm\fP designates bits in the \*MOp\fP register
        !           949: to leave on.  All other bits in \*MOp\fP should be turned off.  That
        !           950: is,\^ the complement of \*Mm\fP is \*MAND\fPed with the contents of
        !           951: \*MOp\fP and the result is placed in \*MOp\fP.  This is used to
        !           952: decode opcodes with encoded operands.  The VAX uses
        !           953: .Ds
        !           954: bicl2  $0!m,\^Op
        !           955: .De
        !           956: .Ip \*MJump(lab)\fP
        !           957: Branch to the label \*Mlab\fP.  The destination label is close to the
        !           958: jump,\^ so a short jump of some type may be used.  The VAX uses
        !           959: .Ds
        !           960: jbr    lab
        !           961: .De
        !           962: .Ip \*MLongJump(lab)\fP
        !           963: \*MLongJump\fP is like \*MJump\fP with the exception that \*Mlab\fP
        !           964: may be quite distant.  The VAX uses
        !           965: .Ds
        !           966: jmp    lab
        !           967: .De
        !           968: .Ip \*MLabel(lab)\fP
        !           969: Generate a label declaration for \*Mlab\fP.  The VAX uses
        !           970: .Ds
        !           971: lab:
        !           972: .De
        !           973: .SH
        !           974: VAX Specific Sections of \*Minterp\fR
        !           975: .PP
        !           976: Several sections of \*Minterp\fP are machine specific and must be
        !           977: coded on a per-machine basis.  The sections in question are explained
        !           978: on an individual basis:
        !           979: .Ip \*M_interp\fP
        !           980: The next opcode is fetched and loaded into \*Mr0\fP.  \*Mmovzbl\fP
        !           981: moves a byte and zero extends it to a word value.  Because a byte was
        !           982: fetched,\^ \*Mipc\fP is incremented by 1.  The opcode is saved in
        !           983: \*MOp\fP in case it contains an encoded operand.  \*Mr0\fP is
        !           984: multiplied by 4 to turn it into a byte offset.  A jump is made to the
        !           985: address indexed by \*Mr0\fP in \*Mjumptab\fP to perform the desired
        !           986: operation.  Eventually,\^ a jump returns control to the label
        !           987: \*M_interp\fP to fetch and execute the next instruction.
        !           988: .Ip \*Mop_bscan\fP
        !           989: A descriptor for \*M_k_subject\fP is pushed on the stack.  Then
        !           990: the value of \*M_k_pos\fP is pushed,\^ followed by the constant
        !           991: \*MD_INTEGER\fP.  The routine corresponding to \*Mop_bscan\fP,\^
        !           992: \*M_bscan\fP,\^ is called with 0 arguments.  (This causes the
        !           993: descriptors for \*M_k_subject\fP and the value of \*M_k_pos\fP to be
        !           994: left on the stack.)  When \*M_bscan\fP returns,\^ a branch is made to
        !           995: \*M_interp\fP.
        !           996: .Ip \*Mop_ccase\fP
        !           997: A null descriptor is pushed on the stack.  The word immediately
        !           998: above the current expression frame is then pushed on the stack.
        !           999: .Ip \*Mop_chfail\fP
        !          1000: The operand of \*Mchfail\fP is fetched into \*MOp\fP.  \*MOp\fP and
        !          1001: \*Mipc\fP are added together and the result replaces the failure
        !          1002: address in the current expression frame.
        !          1003: .Ip \*Mop_dup\fP
        !          1004: A null descriptor is pushed on the stack.  The value that was on top
        !          1005: of the stack is now at \*M8(sp)\fP,\^ and it is copied to the top of the
        !          1006: stack using a \*Mmovq\fP.
        !          1007: .Ip \*Mop_eret\fP
        !          1008: \*Meret\fP gets the value on top of the stack,\^ removes the current
        !          1009: expression frame and puts the previous top of stack value back on the
        !          1010: top of the stack.  First of all,\^
        !          1011: .Ds
        !          1012: movq   (sp)+,\^r0
        !          1013: .De
        !          1014: moves the descriptor on the top of the stack into the \*Mr0\-r1\fP
        !          1015: register pair and increments the stack pointer by 8.  The \*Mgfp\fP
        !          1016: is loaded with the \*Mgfp\fP value stored in the expression frame
        !          1017: marker.  \*Msp\fP is loaded from \*Mefp\fP,\^ bringing the expression
        !          1018: marker to the top of the stack.  The old \*Mefp\fP value from the
        !          1019: marker is loaded into \*Mefp\fP.  Finally,\^ the value stored in the
        !          1020: \*Mr0\-r1\fP pair is pushed on the stack.
        !          1021: .Ip \*Mop_file\fP
        !          1022: The operand of \*Mfile\fP is loaded into \*MOp\fP.  \*MOp\fP and the
        !          1023: value of \*M_ident\fP are added and the result in placed in
        !          1024: \*M_file\fP.
        !          1025: .Ip \*Mop_goto\fP
        !          1026: The operand is loaded into \*MOp\fP and then added to \*Mipc\fP.
        !          1027: .Ip \*Mop_incres\fP
        !          1028: The eighth word of the co-expression heap block for the current
        !          1029: expression is incremented by one.
        !          1030: .Ip \*Mop_init\fP
        !          1031: This one is tricky.  The \*Minit\fP instruction arises from the
        !          1032: \*Minitial\fP statement in Icon and is used to effect one-time
        !          1033: execution of a segment of code.  The operand of \*Minit\fP is the
        !          1034: address of the first instruction after the segment that is to be
        !          1035: executed once.  The instruction
        !          1036: .Ds
        !          1037: movb   $59,\^-(ipc)
        !          1038: .De
        !          1039: decrements \*Mipc\fP by 1 and then stores the constant 59 in the byte
        !          1040: that \*Mipc\fP references,\^ which is the \*Minit\fP opcode.  The magic
        !          1041: number 59 is the opcode for \*Mgoto\fP,\^ so in effect,\^ the \*Minit\fP
        !          1042: had been made into a goto that skips a section of code.  By adding 5
        !          1043: to \*Mipc\fP,\^ it leaves \*Mipc\fP pointing at the first instruction
        !          1044: of the \*Minitial\fP code.  The constant 5 is derived from the
        !          1045: width of the opcode and associated operand,\^ i.e.,\^
        !          1046: \*MOPSIZE+OPNDSIZE\fP.
        !          1047: .Ip \*Mop_invoke\fP
        !          1048: This section has two entry points: \*Mop_invoke\fP gets control if
        !          1049: \*Minvoke\fP has an operand,\^ and \*Mop_invkx\fP gets control if the
        !          1050: operand is encoded in the opcode.  If an operand is specified,\^ it is
        !          1051: fetched into \*MOp\fP.  If the operand is encoded,\^ \*MBitClear(7)\fP is
        !          1052: used to isolate the operand in \*MOp\fP.  Control converges at
        !          1053: \*Mdoinvoke\fP.  The operand is the number of arguments to
        !          1054: invoke the procedure with and it is pushed on the stack as
        !          1055: the \fInargs\fP word.  (The arguments are already on the stack.)
        !          1056: The \*Mcalls\fP instruction needs the length of the argument list,\^ so
        !          1057: \*MOp\fP is multiplied by 2 and then incremented by 1.  \*Minvoke\fP
        !          1058: is called.
        !          1059: .Ip \*Mop_int\fP
        !          1060: As in \*Mop_invoke\fP,\^ \*Mop_int\fP has a secondary entry point,\^
        !          1061: \*Mop_intx\fP,\^ for operands encoded in the opcode.  At the \*Mop_int\fP
        !          1062: entry point,\^ a \*MWORDSIZE\fP value is fetched out of the instruction
        !          1063: stream and loaded into \*MOp\fP.  At the \*Mop_intx\fP entry point,\^
        !          1064: the \*MOp\fP value is decoded from the operand.  The \*MOp\fP value is
        !          1065: pushed on the stack and is followed by a \*MD_INTEGER\fP word,\^ forming
        !          1066: an integer descriptor.
        !          1067: .Ip \*Mop_line\fP
        !          1068: Like \*Mop_invoke\fP and \*Mop_int\fP,\^ \*Mop_line\fP has a secondary
        !          1069: entry point.  The operand value is obtained and then moved into \*M_line\fP.
        !          1070: .Ip \*Mop_llist\fP
        !          1071: \*Mllist\fP is similar to \*Minvoke\fP in that it has a number of
        !          1072: arguments already on the stack and that the operand specifies the
        !          1073: number.  The operand is fetched into \*MOp\fP and pushed on the
        !          1074: stack to become the \fInargs\fP argument of \*Mllist\fP.  \*MOp\fP is
        !          1075: then multiplied by 2 and incremented by 1 to serve as an argument
        !          1076: list size for \*Mcalls\fP.
        !          1077: .Ip \*Mop_mark\fP
        !          1078: The operand is fetched into \*MOp\fP and \*Mipc\fP is added to it.
        !          1079: \*Mefp\fP is pushed on the stack and the new \*Msp\fP value is put in
        !          1080: \*Mefp\fP.  \*Mgfp\fP is pushed on the stack and cleared.  \*MOp\fP
        !          1081: is pushed on the stack.
        !          1082: .Ip \*Mop_mark0\fP
        !          1083: Like \*Mop_mark\fP,\^ with an implicit operand value of zero.
        !          1084: .Ip \*Mop_pop\fP
        !          1085: The two \*Mtstl\fP instructions serve to add 8 to \*Msp\fP which
        !          1086: removes the top value from the stack.
        !          1087: .Ip \*Mop_sdup\fP
        !          1088: The descriptor on the top of the stack is pushed on the stack,\^
        !          1089: duplicating it.
        !          1090: .Ip \*Mop_unmark\fP
        !          1091: The operand,\^ the number of expression frames to remove from the
        !          1092: stack,\^ is fetched into \*MOp\fP.  \*Mefp\fP is
        !          1093: restored from the current expression frame.  The instruction
        !          1094: .Ds
        !          1095: sobgtr Op,\^unmkjmp
        !          1096: .De
        !          1097: decrements \*MOp\fP and then branches to \*Mdounmark\fP if \*MOp\fP is not
        !          1098: zero.  This chains through the number of expression frames specified
        !          1099: by the operand.  \*Mgfp\fP is restored from the current expression
        !          1100: marker.  \*Mefp\fP is loaded into \*Msp\fP to move the expression
        !          1101: marker to the top of the stack.  Finally,\^ \*Mefp\fP is restored
        !          1102: from the marker and \*Msp\fP is incremented to remove the last word
        !          1103: of the marker.
        !          1104: .Ip \*Mop_unmk1-7\fP
        !          1105: Similar to \*Munmark\fP,\^ but uses successive restorations of
        !          1106: \*Mefp\fP rather than a loop.
        !          1107: .Ip \*Mop_global\fP
        !          1108: Dual entry points are used to deal with possible operand encoding.
        !          1109: The operand,\^ which is a number of a variable in the global region,\^
        !          1110: is multiplied by 8 to provide a byte offset from the start of
        !          1111: the global region.  The sum of \*MOp\fP and the value of \*Mglobals\fP
        !          1112: is pushed on the stack to provide a descriptor address.  The constant
        !          1113: \*MD_VAR\fP is pushed on the stack to complete the descriptor for the
        !          1114: global variable.
        !          1115: .Ip \*Mop_static\fP
        !          1116: Identical to \*Mop_global\fP except that \*Mstatics\fP is used
        !          1117: instead of \*Mglobals\fP.
        !          1118: .Ip \*Mop_local\fP
        !          1119: The operand value is the number of a local variable for which a
        !          1120: variable descriptor is to be pushed on the stack.  Recall that the
        !          1121: local variables lie below the procedure frame and,\^ on the VAX,\^ the
        !          1122: descriptor for the first one is at \*M\-16(fp)\fP.  \*MOp\fP is
        !          1123: negated.  The instruction
        !          1124: .Ds
        !          1125: pushaq -16(fp)\^[Op]
        !          1126: .De
        !          1127: performs the calculation
        !          1128: .Ds
        !          1129: -16 + fp + (Op * 8)
        !          1130: .De
        !          1131: which computes the address of the descriptor of the desired variable
        !          1132: and pushes it on the stack.  The variable descriptor is completed by
        !          1133: pushing \*MD_VAR\fP on the stack.
        !          1134: .Ip \*Mop_arg\fP
        !          1135: Like  \*Mop_local\fP,\^ but it uses \*M8(ap)\fP as the base for the
        !          1136: address calculation and the operand value is not negated.
        !          1137: .Ip \*Mquit\ \ \ \ \ \fP
        !          1138: Push a 0 on the stack and call the routine \*M_c_exit\fP to terminate
        !          1139: execution of the Icon program.
        !          1140: .Ip \*Merr\ \ \ \ \ \fP
        !          1141: \*Merr\fP should never be encountered during normal execution.
        !          1142: Reaching it indicates that an invalid opcode was encountered.
        !          1143: It need not do anything more than abort execution.  On the VAX,\^
        !          1144: it calls \*Msprintf\fP to create a string containing the invalid
        !          1145: opcode and the \*Mipc\fP where it was encountered and then calls
        !          1146: \*Msyserr\fP with the string as an argument.
        !          1147: .NH 3
        !          1148: \*Mlib/efail.s\fR
        !          1149: .SH
        !          1150: Overview
        !          1151: .PP
        !          1152: \*Mefail\fP handles the failure of an expression.  When
        !          1153: Icon evaluates an expression,\^ it tries to produce a result from it.
        !          1154: If at some point in the evaluation of an expression the expression
        !          1155: fails,\^ Icon resumes inactive generators in the expression in
        !          1156: an attempt to make the expression succeed. \*Mefail\fP is at the
        !          1157: heart of this activity.
        !          1158: .LP
        !          1159: \*Mefail\fP has three distinct outcomes:
        !          1160: .Ls
        !          1161: .Np
        !          1162: Resumption of the newest inactive generator in the current
        !          1163: expression frame.
        !          1164: .Np
        !          1165: Failure of the current expression with execution continuing
        !          1166: at the failure address contained in the expression marker.
        !          1167: .Np
        !          1168: Failure of the current expression with propagation of failure
        !          1169: to the enclosing expression frame.  This is similar to (2),\^
        !          1170: but occurs when the failure address is 0.  After the current
        !          1171: expression fails,\^ \*Mefail\fP loops back to its entry point
        !          1172: to fail again.
        !          1173: .Le
        !          1174: .PP
        !          1175: \*Mefail\fP is branched to rather than being
        !          1176: called.  This is because it
        !          1177: serves as a ``back-end'' for several failure
        !          1178: actions that may occur during the course of execution:
        !          1179: .Ls
        !          1180: .Np
        !          1181: When a built-in procedure fails,\^ it calls the routine \*Mfail\fP,\^ which
        !          1182: in turn branches to \*Mefail\fP.
        !          1183: .Np
        !          1184: When an Icon procedure fails via the \*Mpfail\fP routine,\^ \*Mpfail\fP
        !          1185: terminates by branching to \*Mefail\fP.
        !          1186: .Np
        !          1187: When the \*Mefail\fP opcode is executed by the interpreter,\^ \*Mefail\fP
        !          1188: is branched to.
        !          1189: .Np
        !          1190: The generator frames built by \*Mesusp\fP and \*Mlsusp\fP use \*Mefail\fP
        !          1191: as a return address.  This is explained in detail later.
        !          1192: .Le
        !          1193: .SH
        !          1194: Generic Operation
        !          1195: .PP
        !          1196: \*Mefail\fP is essentially a simple routine.  There are two separate
        !          1197: paths of execution that \*Mefail\fP may take.  The first is to
        !          1198: resume an inactive generator.  The second is to cause failure of
        !          1199: the expression in lieu of an inactive generator.
        !          1200: .PP
        !          1201: If there is an inactive generator in the current expression frame,\^
        !          1202: it must be resumed.
        !          1203: If the generator is an Icon procedure and tracing is in on,\^
        !          1204: \*Matrace\fP is called with appropriate arguments.  \*M_k_level\fP,\^
        !          1205: \*M_line\fP,\^ and \*M_file\fP are restored from the generator frame.  A return
        !          1206: is performed and the net result is that the stack is restored to
        !          1207: the state that it was in before the suspension that created the
        !          1208: generator.
        !          1209: .PP
        !          1210: If there are no inactive generators that can be resumed,\^ the
        !          1211: expression being evaluated must fail.  This is done by popping
        !          1212: the stack back through the current expression frame and resuming
        !          1213: execution at the point indicated by the failure address in
        !          1214: the expression marker.  This is a two-step process.  The first
        !          1215: is to pop the frame and the second is to resume execution.
        !          1216: When the frame is popped,\^ the expression has failed.  The
        !          1217: failure address in the expression marker is saved before
        !          1218: the frame is popped.  If this address is not zero,\^ execution
        !          1219: is continued by branching to the address.  If the address is
        !          1220: zero,\^ the failure is propagated to the enclosing expression by
        !          1221: branching to efail.
        !          1222: .PP
        !          1223: Zero failure addresses are generated by the ucode instruction
        !          1224: .Ds
        !          1225: mark  L0
        !          1226: .De
        !          1227: Such instructions are used to avoid a special case during code
        !          1228: generation and the only purpose they serve during program execution
        !          1229: is to create an expression marker for the corresponding
        !          1230: \*Munmark\fP instruction to remove.  (\*Mmark\fP and \*Munmark\fP
        !          1231: instructions are paired.)
        !          1232: Thus,\^ whenever \*Mefail\fP pops an expression whose marker has a
        !          1233: zero failure address,\^ \*Mefail\fP causes failure in the enclosing
        !          1234: expression.
        !          1235: .SH
        !          1236: \*Mefail\fP on the VAX
        !          1237: .PP
        !          1238: The first action is to determine if there is an inactive generator
        !          1239: that can be reactivated.  If the generator frame pointer
        !          1240: is non-zero,\^ it points to the newest inactive generator.
        !          1241: Note that whenever a new expression frame is created,\^ the generator
        !          1242: frame pointer is zeroed.  Thus,\^ if \*Mgfp\fP is non-zero,\^ the
        !          1243: generator frame that it points to belongs to a generator in the
        !          1244: current expression frame.
        !          1245: .PP
        !          1246: If an inactive generator is available,\^ it must be reactivated.
        !          1247: First,\^ \*M_boundary\fP is restored from the generator frame.
        !          1248: The stack is popped back to the generator frame by loading
        !          1249: \*Mfp\fP from \*Mgfp\fP.  But,\^ before \*Mfp\fP is loaded,\^
        !          1250: its value is saved in \*Mr0\fP.  \*Mfp\fP now points at
        !          1251: word 0 of the generator frame,\^ but that is a word below the
        !          1252: actual stack frame that it should be pointing at,\^ so \*Mfp\fP is
        !          1253: incremented by 4 using a \*Mtstl\fP.
        !          1254: .LP
        !          1255: There are three types of generators that may be encountered
        !          1256: by \*Mefail\fP.
        !          1257: .Ls
        !          1258: .Np
        !          1259: An Icon procedure that did a \*Msuspend\fP.  In such cases,\^ the
        !          1260: routine \*Mpsusp\fP handled the suspension.
        !          1261: .Np
        !          1262: A built-in procedure that called the C function \*Msuspend()\fP.
        !          1263: .Np
        !          1264: A generator created by an \*Mesusp\fP or \*Mlsusp\fP instruction.
        !          1265: Such generators
        !          1266: arise from source code constructs like \*M\*(x1 |\ \^\*(x2\fP,\^ \*M|\*(xx\fR,\^ and
        !          1267: \*M\*(x1 \e\ \^\*(x2\fR,\^ which are referred to as \fIcontrol regimes\fP.
        !          1268: .Le
        !          1269: .PP
        !          1270: The generators may be treated the same way as far as resumption goes.
        !          1271: However,\^ if an Icon procedure is being resumed,\^ a tracing message must
        !          1272: be generated if \*M_k_trace\fP is not 0.
        !          1273: .PP
        !          1274: If the value of \*M_boundary\fP is not the same as \*Mfp\fP,\^ the
        !          1275: generator is a built-in procedure and tracing is not done.
        !          1276: If the \*Mfp\fP saved in the current frame is the same as the
        !          1277: \*Mfp\fP was upon entry to \*Mefail\fP (the value was saved in
        !          1278: \*Mr0\fP),\^ the generator was made by an \*Mesusp\fP or an \*Mlsusp\fP
        !          1279: and tracing is not done.
        !          1280: .PP
        !          1281: Otherwise,\^ the generator is an Icon procedure,\^ and \*Matrace\fP must
        !          1282: be called.  \*Matrace\fP takes one argument,\^ the address of the
        !          1283: procedure block for the procedure being resumed.  Recall that \*(e0 on the
        !          1284: stack is a descriptor for the procedure block.  The address of
        !          1285: \*(e0 is calculated using
        !          1286: .Ds
        !          1287: &\*(e0 = ap + 8 + (8 * nargs)
        !          1288: .De
        !          1289: The resulting address is used as the single argument for \*Matrace\fP.
        !          1290: .PP
        !          1291: The generator is now ready to be resumed.
        !          1292: \*M_k_level\fP,\^ \*M_line\fP,\^ and \*M_file\fP are restored by popping them
        !          1293: from the generator frame.  If the generator is a built-in procedure,\^
        !          1294: \*M_boundary\fP is cleared.  A return is performed to activate the
        !          1295: generator.
        !          1296: .PP
        !          1297: The return has different effects depending on the type of generator
        !          1298: being resumed.
        !          1299: .PP
        !          1300: If the generator is a built-in procedure,\^ the return
        !          1301: restores the stack to the state it was in before \*Msuspend\fP was
        !          1302: called,\^ and execution proceeds at the point just after \*Msuspend()\fP.
        !          1303: In this case the \*Mpc\fP value being returned to references an instruction
        !          1304: in the built-in procedure.
        !          1305: .PP
        !          1306: If the generator is an Icon procedure,\^ the stack is restored to
        !          1307: the state it was in before the \*Mpsusp\fP ucode instruction
        !          1308: was executed.  The \*Mpc\fP value being returned to references an
        !          1309: instruction in the interpreter loop.  Execution of the program
        !          1310: continues with the interpreter instruction following the \*Mpsusp\fP.
        !          1311: .PP
        !          1312: If the generator is a control regime,\^ the stack is restored to
        !          1313: the state it was in before the \*Mesusp\fP or \*Mlsusp\fP that
        !          1314: created the generator was performed.  The
        !          1315: return \*Mpc\fP points to \*Mefail\fP itself.  Thus,\^ when the
        !          1316: return is done,\^ the stack is cleared,\^ and an \*Mefail\fP is performed.
        !          1317: This has the effect of transferring control to the failure label
        !          1318: in the expression marker of the bounding expression frame.
        !          1319: .\"(The failure label lies at the start of code for the alternative.)
        !          1320: .PP
        !          1321: If there is no generator to reactivate,\^ the expression must fail.
        !          1322: This is handled at the label \*Mnogen\fP.  \*Mefp\fP points to the
        !          1323: expression frame marker.  \*Mipc\fP is loaded
        !          1324: from \*M\-8(efp)\fP which contains the address to go to in the
        !          1325: event that the current expression fails.  (As it has.)
        !          1326: \*Mgfp\fP is restored from the expression marker.
        !          1327: \*Mefp\fP is restored from the marker and the marker is popped off the stack.
        !          1328: .PP
        !          1329: If the failure address in \*Mipc\fP is non-zero,\^ control is passed
        !          1330: back to the interpreter via a branch and execution of the ucode
        !          1331: resumes at the failure address.  If \*Mipc\fP is zero,\^ the expression
        !          1332: failure is transmitted to the surrounding expression frame
        !          1333: by a branch to \*Mefail\fP.  (Recall that a zero failure address
        !          1334: comes from a \*Mmark L0\fP instruction and that a failure that
        !          1335: reaches a \*Mmark L0\fP marker must be propagated to the next
        !          1336: expression marker.)
        !          1337: .NH 3
        !          1338: \*Mlib/pfail.s\fR
        !          1339: .SH
        !          1340: Overview
        !          1341: .LP
        !          1342: \*Mpfail\fP handles the failure of an Icon procedure.  An Icon
        !          1343: procedure can fail by
        !          1344: .Ds
        !          1345: .ft R
        !          1346: executing a \*Mfail\fP expression
        !          1347: executing \*Mreturn \fIexpr\fR when \fIexpr\fR fails
        !          1348: allowing the flow of control to reach the end of a procedure
        !          1349: .De
        !          1350: \*Mpfail\fP is entered via a branch when
        !          1351: the interpreter encounters the \*Mpfail\fP instruction.
        !          1352: .SH
        !          1353: Generic Operation
        !          1354: .PP
        !          1355: The task of \*Mpfail\fP is to signal failure in the expression that
        !          1356: contains the procedure call being evaluated.  This is done
        !          1357: by removing the Icon procedure frame from the stack,\^ restoring
        !          1358: appropriate registers and values,\^ and calling \*Mefail\fP.  The key is that
        !          1359: all \*Mpfail\fP needs to do is to remove the procedure frame
        !          1360: from the stack and from then on things can be handled just like expression
        !          1361: failure.
        !          1362: Thus,\^ \*Mefail\fP does most of the work.
        !          1363: .PP
        !          1364: \*Mpfail\fP calls \*Mftrace\fP to produce a trace message if
        !          1365: tracing is on.  \*Mpfail\fP also decrements \*M_k_level\fP because
        !          1366: a procedure is being exited.
        !          1367: .PP
        !          1368: Note that the procedure frame on the stack is a frame that
        !          1369: was created by \*Minvoke\fP.
        !          1370: .SH
        !          1371: \*Mpfail\fP on the VAX
        !          1372: .PP
        !          1373: After \*M_k_level\fP is decremented,\^ \*M_k_trace\fP is checked to
        !          1374: see if a trace message should be produced.  If tracing is on,\^
        !          1375: \*Mftrace\fP must be called.  \*Mftrace\fP takes one argument,\^
        !          1376: the address of the procedure block for the failing procedure.
        !          1377: \*(e0 is the descriptor for the procedure block,\^ and the address
        !          1378: of \*(e0 is calculated using
        !          1379: .Ds
        !          1380: &\*(e0 = (\fInargs\fP * 8) + 8 + ap
        !          1381: .De
        !          1382: The resulting address is pushed on the stack and \*Mftrace\fP is
        !          1383: called.
        !          1384: .PP
        !          1385: Execution continues at \*Mdofail\fP to remove the procedure frame
        !          1386: from the stack.  The frame cannot be merely popped because it
        !          1387: contains state information that must be restored.  \*M_line\fP and
        !          1388: \*M_file\fP are extracted from the frame.  \*Mefp\fP,\^ \*Mgfp\fP,\^ and
        !          1389: \*Mipc\fP are restored from the frame using addresses
        !          1390: relative to \*Map\fP.  Note that this works because \*Minvoke\fP saves
        !          1391: these registers and their location is known.
        !          1392: .PP
        !          1393: \*Map\fP and \*Mfp\fP are restored from the frame.  When \*Mfp\fP is
        !          1394: restored,\^ it serves to remove the procedure frame (made by
        !          1395: \*Minvoke\fP) from the stack.  At this point,\^ the stack is the
        !          1396: same state it was in before the interpreter performed the
        !          1397: \*Minvoke\fP instruction.  A branch is made to \*Mefail\fP to
        !          1398: cause failure in the enclosing expression.
        !          1399: .NH 2
        !          1400: Testing the Basis
        !          1401: .PP
        !          1402: At this point,\^ enough of the system has been written to run some
        !          1403: very simple Icon
        !          1404: programs.  \*Mtest/hello.icn\fP should be functional
        !          1405: and more complete testing is in order.  Refer to \fITesting the
        !          1406: Basis\fP in \^[5].

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.