LIBRARY OF THE UNIVERSITY OF ILLINOIS AT URBANA-CHAMPAIGN 510.8 TAQ>r no 547-552. cop -2. \7*-~ "rite a c*du edate bd ow 1162 j /v< or '£($$ Re P ort No - uiucDcs-R-72-550 JbSBO »2^ yyuCC^ AN APPROACH TO THE COMPILATION OF ARRAY EXPRESSIONS IN THE OL/2 LANGUAGE by September 1972 Dale Rade Jurich ^a 9 W/3 DEPARTMENT OF COMPUTER SCIENCE UNIVERSITY OF ILLINOIS AT URBANA-CHAMPAIGN URBANA, ILLINOIS Report No. UIUCDCS-R-72-550 AIT APPROACH TO THE COMPILATION OF ARRAY EXPRESSIONS IN THE OL/2 LANGUAGE "by Dale Rade Jurich September 1972 Department of Computer Science University of Illinois at Urbana- Champaign Urbana, Illinois 6l801 This work was supported in part by the National Science Foundation under Grant No. US NSF-GJ-328 and was submitted in partial ful- ri l "Lment of the requirements for the degree of Master of Science in Computer Science, September 1972. Digitized by the Internet Archive in 2013 http://archive.org/details/approachtocompil550juri Ill ACKNOWLEDGMENT I wish to sincerely thank the originator of OL/2, Professor J. R. Phillips, for his guidance, suggestions, and moral support which has lasted throughout my work on OL/2, and my entire academic endeavors in the field of Computer Science. I would also like to thank the past and present members of the OL/2 implementation team; Bob Bloemer, Barry Finkel, Cory Adams, John Latch, and John Gaffney for their cooperation and suggestions; and the University of Illinois at Urbana-Champaign for the support it has provided. Furthermore, I am indebted to Mrs. Vivian Alsip, who did such a fine job of typing this report. Last, but not least, I wish to acknowledge my father, Rade Jurich, who first kindled my interest in the sciences. IV TABLE OF CONTENTS Page 1. INTRODUCTION I 2. GENERAL STATEMENT PROCESSING 2 2.1 Statement Types 2 2.2 The Flow of Processing in the OL/2 Compiler. ,,,,... 2 2.3 Array Expression Compilation k 3. EXPRESSION PARSING 7 3.1 Goals of the Expression Parser 7 ?.2 Basic Mathematical Objects and Operations 7 3.3 Concrete Representation of Nodes 10 3 ,k Expression Tree Building Algorithm 12 3-5 Example Parse with Semantic Error Checking 19 3.6 Repeated Subexpression Handling, 2k 3-7 Other OL/2 Operations Available 28 k. TEMPORARY STORAGE MINIMIZATION 32 5. CODING PHASE 36 5.1 Description of the Code Produced 36 5.2 The Coding Algorithm hi 5.3 Example of Code Generation hh 6. RESULTS AND EXAMPLES ^9 LIST OF REFERENCES 50 APPENDIX 51 A 51 B 57 c 107 1 1. INTRODUCTION OL/2, Operator Language version 2, has "been designed as a natural language for array algorithms and has been implemented so as to insure efficient array operations for these algorithms. OL/2 provides a natural specification in that it is syntactically designed to adhere to the "language" of mathematics on which certain array algorithms are based. Oh/2 has been implemented to provide for an efficient method of carrying out the operations defined in the language through the use of assembly language operational routines. The philosophy behind the design and implementation of OL/2 involves handling the data arrays as units, rather than on an element by element basis as would be done in FORTRAN or PL/l. Hopefully, this philosophy will provide in practice an array processing system that will allow the convenient specifi- cation of array algorithms (minimizing parallel processes), while it will also provide for powerful array processing facilities which may very possibly suggest nev; breeds of array processing hardware organizations. This thesis deals with the compilation of array expressions x^hich form a most vital part of the OL/2 language. A more complete description of the language and its design philosophy as a whole can be found in the refer- ences [7, 8] . 2. GENERAL STATEMENT PROCESSING 2.1 Statement Types The OL/2 language contains various types of statements which reflect the array capabilities of the language as well as the usual program structure that is found in many procedure oriented languages. The following is a "broad classification of the various types of statements. 1. Declarations or data definition statements. 2. Array partition and array set statements. 3. Array and scalar assignment statements. h. Procedure definition and block structure control statements. 5- Program control statements (e.g., FOR, GO TO, and IF state- ments) . 6. Input and output statements. This thesis is primarily concerned with array assignment statements and array expressions which incidentally are used by the control statements and input-output statements. Appendix A contains a syntactic specification for OL/2 assignment statements and array expressions. 2.2 The Flow of Processing in the 0l/2 Compiler Figure 2.1 outlines the components of the OL/2 system as it is currently implemented on the IBM 360 at the University of Illinois. Basically, the TACOS compiler-compiler system (see Appendix A) is utilized to build a top down syntax directed compilation system. A linked list syntax table, built by the TACOS system for OL/2, is utilized by the TACOS parser/scanner module to control the syntax analysis of OL/2. At various points in the analysis, semantic action routines, written in Pl/l, are called to undertake the semantic analysis and code generation for an OL/2 source program. The 0l/2 compiler, OL/2 SOURCE PROGRAM paser/ LINKED LIST SYNTAX TABLE module (asm) a SEMANTIC ACTION ROUTINES (PL/l) ERROR MESSAGE TABLE OL/2 SKELETON CODE (PL/l) pl/i representation of OL/2 source program, passed on if no OL/2 errors OL/2 COMPILER OL/2 SOURCE LIST AND ERROR MESSAGES PL/l COMPILER 360 OBJECT MODULE REPRESENTATION LINKAGE EDITOR OL/2 RUNTIME LIBRARY intermediate (PL/l) and operational routines (ASM) EXECUTABLE 360 LOAD MODULE Called by compiled code Figure 2.1. Block Structure of OL/2 System which consists of the syntax table, the semantic action routines, the TACOS parser/scanner module, and various routines, compiles the OL/2 source code into an intermediate language, namely, PL/l. The purpose of the Pl/l is to act as a control language to set up appropriate information structures, to redefine the data structures for all arrays, and to link these structures to OL/2 run-time routines that control the storage allocation and all array operations. The run-time routines are written in assembly language and pro- vide efficient processing for array operations. Many of the ordinary tasks are also delegated to the Pl/l compiler, such as, scalar expressions, function evaluation, and block structure control. Figure 2.2 outlines the flow of processing in the OL/2 semantic action routines. Statement type determination is done as early in the syntax analysis as possible, and an appropriate module controls the compilation of a given statement type. The compiler is not completely moduler in that inter- action between sections of the semantic action routines does exist, and many routines common to several modules are utilized. The section of the compiler, or module, that is described here is the semantic action module that compiles OL/2 array expressions. 2.3 Array Expression Compilation In OL/2, array expressions can be imbedded in various types of statements, such as FOR statements, IF statements, assignment statements, procedure statements, and input-output statements. Whenever an array ex- pression exists within an OL/2 statement, the expression processing module is activated to produce (Pl/l) "intermediate" object code for the expression. As Figure 2.2 indicates, array expression processing can be divided into three phases within the expression module. The first phase involves the STATEMENT TYPE DETERMINATION FOR DATA DESCRIPTOR MODULE FOR MODULE PROCEDURE, BEGIN IF MODULE PARTITION MODULE BUILDS MODIFIES BLOCK MODULE ASSIGNMENT STATEMENT MODULE SYMBOL TABLE ROOT NODES FOR VARIABLES IN ACTIVE BLOCKS USES COMPILE TIME DATA STRUCTURES PARSING STACK, TABLES, WORK SPACE EXPRESSION TREE ALGORITHM OPTIMIZATION PHASE CODING PHASE CALLS OL/2 EXPRESSION PROCESSOR Figure 2.2. Semantic Action Processing of OL/2 Statements syntactic and semantic analysis of an expression, and. converts the source code representation into an expression tree intermediate code representation. The second phase modifies the expression tree so as to allow an optimized coding of the expression by the third phase, the coding routine. The coding routine transforms the optimized intermediate expression tree representation into a sequential list of three operand code (operand, operand, result) that is the PL/l intermediate object code for the expression. Sections 3, k } and 5, describe the algorithmic structure of the three expression processing phases of the OL/2 compiler. Another coding algorithm that utilizes a slightly different approach to the handling of array expressions in Oh/2 is described in LATCH [ 5 ] . 3- EXPRESSION PARSING 3.1 Goals of the Expression Parser As was previously outlined, OL/2 array expressions are imbedded in many of the common OL/2 statements. During compilation, a set of modules is called at each occurrence of an OL/2 expression to translate the source ex- pression into "intermediate code", (the format of the code produced is de- scribed in section 5) • This section will discuss the process of translating the source OL/2 expressions into an expression tree form that is utilized by the optimizating and coding phases of the compiler. During the tree building phase, syntactic error checking is done, as well as some semantic error checking, and optimization in the form of repeated subexpression handling is also done. 3.2 Basic Mathematical Objects and Operations Figure 3«1 outlines the major operand types and operations that make up OL/2 expressions. The classes of objects or variable types that can be involved in an OL/2 expression are scalars, vectors, and operators. The first two classes of objects are defined in the standard sense, while the third term is used to denote the arrays of various orders or dimensionalities that are used to represent the corresponding mathematical operator. For example, a linear operator used in the above context means a matrix. When the term array is used, the objects involved may be of type vector or matrix, since in OL/2 vectors are treated, from the implementation point of view, like "degenerate" two dimensional arrays. In the figures, and elsewhere in this paper, the following conventions are used: a, f3, 7 denote scalars; x, y, z denote vectors; and A, B, C denote operators (matrices and higher dimensional arrays). In some cases the results in the figure apply to operators of dimensionality . C? re : - w O X -: W JH re -: — w re u e w S < co re co £3 o co g^ <; co re co PL, 5 o c ^ o © a ^ a ^ M cor; I" 1 3 o s * H m re re re o ;> re re Ph h© re re 8 o H c> O X w M H |> > re H i-4 rs ?; O o re a w a CD -p >3 CO ^ CO Jh o ■•> !h CO o S -P «C O re a) C\J -© re re o o E- E-i o o x w re M > > >H re <£ H 3= re Pj < o o Ph s re o < O -H OJ l® ^0 >5 ^ * •> o - o re > o o u re > -p o o Q g o 3 re -h re re o w -P E5 O S CD H >> -0 re o u CO CO re x ° b h re X •H !h ■P CO S •a CO o ■p O OJ > =1 re Sh O CD ^ ca + <3 3 o CQ C o •H -P CO !h CD P< O CO 1-4 * re * CO 00 psi-I •x • CO ffi HI o I • CQ 00 -r-l CO T3 CD •H CD CO in * O co c ^ * x< s~> CJ i in s 1 < LH -0 i O o > £ re s o o u re n w X > H re re H o o m re re s s5 Q s re H -P <: -© re X X H M re re H H 1 1 n X re H > re H & gj a re o x re H > re En p1 ^ o s o VD Eh O W CO 5] < w i-0 < GO s h© I© o GO P 00 >i !Xs) !-© © © GO < J II II GO < ■XE) © © pa * < pq II n ca < s o CVJ GO GO X X Eh Eh >h co a o •H -P CO !h 0) ft O OJ h3 o o •H CO CO TO o o *i o GO £ a g •H 8 1 bo Eh O •P CI CD GO CO II GO CO CO CO O >> d h -p u a CO CD i bO !>> •H CO CO U 10 h CO CO MA a; u g, •H (x, M W « > II 'i « P4 CO 10 greater than two, although these objects are not specifically mentioned, since the compilation process is essentially the same. The priority levels given in Figure 3-1 define the order in which the evaluation of an expression takes place, with the lowest priority operations being evaluated first. The priorities were chosen in order to minimize the number of operations when evaluating array expressions, and the tree structure built up by the parser reflects this ordering. For example, in an expression of the form A*B*a*p*y the priorities assigned are equivalent to the forced priority evaluation: (A * (B * ((a * 0) * y))). By recursively applying the "rules" given in Figure 3-1, while also allowing forced priorities with the use of parentheses, all basic OL/2 expressions can be generated, and thus the rules serve as a simplified abstract syntax for an OL/2 expression. By combining the abstract representations for each operation, keeping in mind the evaluation priorities, the abstract tree representation for the expression can be formed. The basic task of the expression parser is to build a concrete representation of the tree using PL/1 based variable structures as nodes and pointer variables as links. This concrete represen- tation is then used by subsequent compiler phases. Syntactic and semantic error checking is also done during the parsing phase so that subsequent phases can assume an essentially error free representation. Examples of OL/2 source expressions and the corresponding abstract expression tree representations are given in Figure 3-2. 3-3 Concrete Representation of Nodes PL/1 structures that represent all known information concerning each 11 EXPRESSION: y=x' * A + B * z ABSTRACT EXPRESSION TREE: A = A ARRAY SUM ARRAY-VEC * TRANS ARRAY-VEC * EXPRESSION: A -x- x * B * C ABSTRACT EXPRESSION TREE ARRAY- SCALAR * NORM ARRAY * ARRAY-VEC * Figure 3-2. OL/2 Abstract Trees 12 distinct OL/2 variable defined in a program are built up by a definition processing module group. These structures are available to the expression module when an expression is to be parsed, in complete form since a "defi- nition before use" one source pass system is used. During the definition processing phase, a symbol table is built up that contains the variable names of all variables active in the current 0l/2 block being scanned. New entries are added at the bottom of the symbol table, and thus the table is searched bottom up to locate the proper variable associated with a specific OL/2 name. When the "end" statement of an active block is encountered, the symbol table is cleared of all definition information built up in the block, since in a one pass environment it is no longer needed. The PL/l representation of an operand node, and a definition of the node fields are given in Figure 3*3 and Table 3«3« Operand nodes are linked together to form the expression tree by operator nodes that define the specific operation involved and contain information fields that are utilized by the parser, optimizer and coder phases. Figure 3-3 and Table 3-3 also present the PL/l representation of an operator node and give a definition of the infor- mation contained in the node fields . ' It should be noted that operand nodes can be "reused", possibly within a single expression, since the information that they contain is static, in the sense that it does not change within the block that the OL/2 variable is active. Operator nodes contain information that is dependent on the context in which the operator appears and therefore must be created for each occurrence of an OL/2 operational symbol. 3-^ Expression Tree Building Algorithm In the current Ob/2 system, syntax analysis proceeds in a top down 13 NODE PTR LLINK RLINK SEQj PTR STRING_PTR ^DIMENSIONS PART SIZE #_OF_TIMES TO USE TYPE EXP $TYPE CODE NEGATE TAG TRANSPOSE TAG IDENTITY_TAG TREE_NODE BASED (NODE_PTR), ( 2 RLINK, 2 LLINK, 2 SEQUENCER JPTR, 2 STRING PTR ) POINTER, 2 $#DIMENSIONS, 2 PART_SIZE, 2 #_OF_TIMES TO USE, 2 TYPE_EXP, 2 $TYPECODE ) FIXED BINARY (15-0), 2 NEGATEJTAG, 2 TRANSPOSE_TAG, 2 IDENTITY TAG ) BIT (1) Figure 3'3« Concrete Node Structure - ■ " " V : Ik FIELD NAME OPERAND NODE OPERATOR NODE RLINK LLINK SEQ # PTR STRING PTR $#DIMENSIONS PART_SIZE #_OF T IME S_TO_U S E TYPE EXP ■f.TYPE CODE NEGATE TAG TRANSPOSE TAG IDENTITY TAG Null pointer Null pointer Pointer to expression string defining an array sequence element Pointer to string containing name of operand Number of dimensions of operand: Scalar 1 Vector 2 or more Operator Pointer to right subtree Pointer to left subtree Null pointer Null pointer Number of dimen- sions of result of expression evaluation below node Used by partitioning routines Number of times a subexpression is repeated Type of operand or expression Scalar 1 Function 2 Column Vector 3 Row Vector k- Matrix 5 Null Operand 6 Boolean Result Not defined Operand is to be negated Operand is to be transposed Operand is an identity operator (do not allow an assignment to it) Type code of operator Not defined Not defined Not defined Table 3.3. Node Field Descriptions 15 manner, with various semantic action routines being called at specific points in the analysis. Appendix A contains a short description of the TACOS compiler- compiler system, and the OL/2 compiler that was developed using the TACOS system. For the purposes of this section it will be assumed that expression analysis proceeds in a left to right manner, with the required semantic routines called at the appropriate times. In this way, the actual mechanisms of the top down analysis scheme become transparent to the description of the tree building process. Two structures are important to the tree building process; the node stack, and the precedence matrix. The node stack in the abstract sense consists of two cells per level, as shown in Figure J.k. The cell labeled SUBTREE_PTR is a PL/l pointer variable that points to the root node of the subtree, which may be a single node, described by a given cell in the stack. The variable SUBTREE TYPE associated with a given cell holds a number that represents the type of object represented by the subtree described by the stack cell. The legal types are: scalar, function, column vector, row vector, matrix, null operand and boolean result. Figure 3.4 presents an example of a stack cell that represents a vector subpart of an expression. The tree building algorithm described in this section is concerned, therefore, with stacking operands in a left to right expression analysis, building subtrees from stacked operands when possible, and utilizing the precedence rules given earlier. Eventually this process will result in a single stack entry that describes the minimum oper- ation evaluation tree for the entire expression being considered. Since the multiply symbol "*" is used in the source language to represent several different priority operations, i.e., scalar * scalar, column vector * matrix, matrix * matrix, matrix * row vector, column vector * row vector, and row vector * column vector, some type of semantic test on the SUBTREE PTR Pointer to root of subtree 16 SUBTREE TYPE Type of expression that results from evaluation of a subtree (a). Expression Stack Cell TYPE NUMBERS: SCALAR 1 FUNCTION 2 COLUMN VECTOR 3 ROW VECTOR h MATRIX 5 NULL OPERAND 6 BOOLEAN RESULT (b). Expression Stack Cell for a Column Vector Expression SCALAR FUNCTION COL VEC ROW VEC MATRIX SCALAR FUNCTION COL VEC ROW VEC MATRIX 1 1 1 1 1 1 1 1 1 1 1 2 1 2 1 1 1 1 1 1 1 - DON'T UNSTACK 1 = UNSTACK 2 = ILLEGAL (c). Precedence Matrix Figure J>.h. Expression Algorithm Data Structures IT operand types is necessary during compilation to determine the actual priority of a given * encountered in a left to right analysis. Since the operand types are available in SUBTREE-TYPE entries in the stack cells, it is natural to assign a relative precedence to the "*" operation, which is to he applied to the top two stack operands, when an unstack or combining operation is possible as far as the syntax analyzer is concerned. For this purpose, a precedence matrix is defined for the "*" operation in Figure ~$.k. This is based on the types of the top two stack operands and indicates when an unstack may or may not be done, based on the operands already seen on the left, and those that may appear on the right of a given point in the expression parse. The use of the table will become clearer when the tree building algorithm and examples of its usage are presented. The expression tree building algorithm is a basic stack precedence scheme, and is similar to the scalar expression parsing algorithm described in Hopgood [ 3 ] . The addition of the multiply precedence matrix, and error checking are the main differences. It should be noted that as operands are unstacked and subtrees of the complete expression tree are created, it is necessary to define temporary variables which are needed to complete the expression evaluation at run time. For example, for the subtree given in Figure 5«5> the operator node RESULT TYPE = ARRAY RESULT DIMENSION = 3+2-2 = 3 DIMENSION = 2 DIMENSION = 3 TYPE = ARRAY TYPE = ARRAY Figure 3«5« Temporary Results 18 represents the result of the operation, i.e., in this case a temporary matrix. During parsing, sufficient information is available to fill in the number of dimensions (but not its size) and the type code node fields of the operator/ result node in all cases. This information is used by later phases of the compiler, and will be discussed in subsequent sections. The expression tree algorithm is as follows: ET1: Extract the first operand and stack it. ET2: Follow top down syntax analysis based on the next operator symbol. If illegal construct, set error flag and try to continue. If done with expression exit to next phase. ET3 : Extract the next operand and stack it . ET^: Can an unstack on the current operator symbol class be tried as far as the syntax analyzer is concerned? If yes, go to ET5; otherwise, go to ET2. ET5 : If the current operator is in the class multiply, go to ET6; otherwise, go to ET7. ET6: Consult multiply unstacking precedence table using operand type classes. If "Unstack" = 1 entry in table, go to ET7; otherwise, go to ET2. ET7: Go to RS2 of the repeated subexpression algorithm, described in section 3«5- If semantic error due to dimensionality or type of operands, set error flag and try to continue. Build an operator node, link top operand node(s) to operator node, delete top operand node(s) from stack, and replace with operator node that represents a subtree of the completed tree. Fill in dimensionality of result node. Go to ET4. 19 3. 5 Example Parse with Semantic Error Checking The steps involved in parsing an OL/2 expression will "be described to illustrate the use of the tree building algorithm with error checking. Consider the array expression x 1 = a * y + y' * (A + B) ; where x and y are column vectors, A and B matrices, and a is a scalar. The following events occur: 1. The operand x is found and identified as a column vector, through a symbol table look-up, and placed in the stack (see Figure 3«6(a)). 2. The transpose operation is recognized as applying to x, an operator node is built, and the new subtree replaces the former one in the stack (see Figure 3 '6(b)). 3- The equal sign is recognized and the syntax analyzer recurses on it, assuming the statement found is an assignment statement, and goes to look for a vector expression on the right side. h. a is identified as a scalar, and a node is stacked (see Figure 3.6(c)). 5. The syntax analyzer picks off the '*' and recurses to look for an OL/2 factor. No unstacking can be done at this point. 6. The operand y is found and identified as a column vector. A stack entry is pushed for y (see Figure 3«6(d)). 7. '+' is found which completes the OL/2 factor, and unstacking is done (after checking the precedence table) on the scalar and matrix. An operator node is created and pushed for the result (see Figure 3-6(e)). 20 8. Since a ' + ' has "been recognized, an Oh/2 term is sought by the syntax analyzer. 9. y is picked off and stacked as a column vector operand (see Figure 3.6(f)). 10. The transpose operator is recognized as applying to y, and a new row vector type subtree node is stacked (see Figure 3.6(g)). 11. '*' is picked off and the syntax analyzer looks for an OL/2 factor, 12. The syntax analyzer recurses one level for the '(', looking for a parenthe si zed construct . 13. A is recognized as an Oh/2 matrix variable and a node is stacked (see Figure 3 -6(h)). Ik. '+' is found, an OL/2 term is sought. 15- B is recognized as a matrix variable and a node is stacked (see Figure 3'6(i) ) . 16. The closing ')' is found completing the OL/2 term. Unstacking is done, an operator node of type ARRAY SUM is built and replaces the nodes for A and B in the stack. Error checking is done to assure that the dimensions of A and B are compatible. The dimension of the result is inserted into the operator node (see Figure 3.6(j)) . 17- The syntax analyzer recognizes ';' as a statement delimiter and begins to return up its parse tree. 18. y' * (A+B), row vector times matrix, constitutes a legal OL/2 factor, and an unstack is done, with an operator node repre- senting a row vector being pushed onto the expression stack (see Figure 3«6(k) ) . 21 (a) (b) COL VEC SUBTREE TYPE 1 (RLINK, LLINK) * (x) (NAME_PTR) ^DIMENSIONS) ROW VEC -t r TRANS • / 1 1 *(x) SCALAR ROW VEC • 1 1 1 (as in (b) above) (a) (a) e) COL VEC (as in (c) above) *(y) (a) > : r • * 1 (y) Figure J. 6. Stack and Node Contents for Example Parse 22 (f) (g) COL VEC (as in (e) above' ROW VEC (as in (e) above' TRANS (y) X (h) MATRIX (as in (g) above' .(A) (i) MATRIX MATRIX • . 2 • as in (g) above (B) (J) 1 * 2 (B) Figure 3.6 (continued). Stack and Node Contents for Example Parse 23 :*) ROW VEC COL VEC • ROW VEC • / 2 (A) :b) Figure 3.6 (continued). Stack and Node Contents for Example Parse 2h 19. The syntax analyzer now tries to complete an OL/2 term involving a vector addition. 20. The two top stack entries are found to be of types row vector and column vector, respectively, when an unstack is tried. The semantic error checking routines signal an error, since a row vector added to a column vector constitutes an illegal 0l/2 sub- expression. Further processing of the statement is blocked by the setting of error flags, e.g., no coding should be attempted, and appropriate error messages are written into an error file with information concerning the statement number, type of error encountered, and the probable location within the statement of the error. Normally the syntax analyzer tries to completely analyze an expression, so that all errors may be uncovered, but the expression tree is considered non-codeable after a single error although the building processes are continued so that further semantic error checking may be done. 3 »6 Repeated Subexpression Handling A repeated subexpression is defined in the context of OL/2 as follows: a repeated subexpression , within an OL/2 expression, exists when two subtrees of an expression tree are operationally identical. An example of an Oh/2 repeated subexpression is illustrated in Figure 3-7- The expression in Figure 3.8 does not contain a repeated subexpression, although subparts of the expression are repeated, due to the "minimum operation" type tree that is formed. Repeated sub- expressions are an important factor to consider in OL/2 expressions because of the number of operations that may be involved in evaluating array expressions. If a repeated subexpression is not recognized and processed in some way, code 25 a*A*B+C*A*B ARRAY SUM ARRAY- SCALAR * ARRAY * ARRAY * ARRAY * REPEATED SUBEXPRESSION / Figure 3'7« Repeated Subexpression Example A+B*x+A*B ARRAY SUM ARRAY-VEC * ARRAY-VEC * ARRAY * Figure $.Q. No Repeated Subexpression 26 will "be generated for the evaluation of the expression represented "by each of^ the duplicate subtrees and this is unacceptable in an array language. The approach in OL/2 to processing repeated subexpressions involves saving the temporary result due to the evaluation of one appearance of the sub- expression, and using this temporary result later in the expression evaluation. A storage and computation time tradeoff must be considered in this approach since the temporary variable representing the subexpression must be maintained in storage at run time in order to avoid recomputing the temporary result. Since processing time is the major concern when dealing with large arrays, assuming a storage scheme involving secondary devices is available, the implementation just described seems justified. The tasks of the expression parser in repeated subexpression handling are outlined below. 1. Recognize the existence of repeated subexpressions. 2. Restructure the expression tree so that repeated subexpressions are evaluated only once. 3. Mark the repeated subexpression when it is no longer needed (used in the coding phase) . The first and third tasks are accomplished by an algorithm based on that of Hopgood [ 3l- Figure 3*9 describes the data structures involved in the algorithm. The node field jf OF TIMES TO USE in an operation node contains the number of appearances of the expression represented by the subtree for which the operation node is the root. This node field is filled in by algorithm RS below, and provides the information needed for third task above to be satisfied. The repeated subexpression algorithm is as follows: RSI: Set the CURRENT-TABLE-POINTER to zero before the processing of each OL/2 expression. 27 RS2: (Entered from the tree building algorithm at ET7 when an unstack operation is called) . Is the current oper- ation associated with the unstack, subtree building, step allowed in an Ob/2 repeated subexpression? If yes, go to RS3; otherwise, go to RS6. RS3: Search the SUBTREE -TABLE entries, from the first to the current entry, until the following conditions are met: 1. P0INTER_T0_0PERANB_1 = pointer value on top of expression stack, 2. P0IWTER_T0_0PERAEIi_2 = pointer value on second level of expression stack, 3 • OPERATION = current operation involved in the subtree about to be built, i.e., involved in unstack operation of expression tree algorithm. If a match is found, go to RS^-; otherwise, go to RS6. RS^: In the result node, increase the field value #_OF_TIMES_ TO_USE by one. RS5: If RLINK = for either or both the first and second stack entries, then subtract 1 from #_OF_TIMES_TO_USE for either or both respective nodes referenced by the stack entries-- A multilevel repeated subexpression has been found. Delete the top two stack levels and replace them by POINTER_TO_ RESULT from the matching SUBTREE_TABLE entry found. Go to ET^ (tree building algorithm) which skips the normal unstack step. RS6: Increase value of CURRENT TABLE POINTER by one. 28 RS7: Add a new SUBTREEJTABLE entry as follows: 1. P0IWTER_T0_0PERAED_1 = pointer value on top level of expression stack, 2. P0INTER_T0_0PERAND_2 = pointer value on second level of expression stack, 3- POINTER_TO_RESULT = pointer value of the oper- ation node associated with the subtree being built, k. OPERATION - value of representative symbol for the current operation being considered. RS8: Carry out ET7 as outlined in the expression tree algorithm. The algorithm above is slightly modified for the case of a unary operation, with the top level of the expression stack considered rather than the top two levels as in the case of a binary operation. The abstract tree representation used in the case of a repeated sub- expression is best illustrated by the example in Figure 3.10. The repeated ex- pression appears once in the tree, and is linked once for each occurrence that appears in a non-repeated representation. In Figure 3«10, the operator node representing the result of A * B has #_0F_TIMES_T0_USE set to 2. Certain operations such as PART OF or SEQUENCE (described in section 3«7) cannot be considered as appearing in repeated subexpressions since these modifiers can define different operands at run time even though they modify the same OL/2 variable at compile time. Also, operations involving scalar variables only are not considered since the extra storage requirements for the temporary variables generated are negligible. 3-7 Other OL/2 Operations Available Many OL/2 operations other than the basic operations described in 29 POINTER TO OPERAND 1 POINTER _TO_ OPERAND 2 POINTER TO _RESULT OPERATION SUBTREE TABLE entry 1 SUBTREE_TABLE (50), ( 2 P0INTER_T0_0P1, 2 P0INTER_T0_0P2, 2 POINTER_TO_RESULT ) POINTER, 2 OPERATION FIXED BINARY (15, 0) CURRENT_TABLE_PTR - Array index used to reference latest SUBTREEJTABLE entry Figure 3«9« Data Structure for Repeated Subexpression Algorithm a*A*B+C*A*B ARRAY SUM ARRAY- SCALAR * ARRAY * Figure 3.10. Abstract Tree Representation of a Repeated Subexpression 30 section 3-2 are available. From the compilation point of view, these non- basic OL/2 operations are handled in the same manner as the basic operations. That is, operator nodes are built up to represent the operator and expression subtrees are created to represent the operator/operand combinations. Figure 3.11 describes some of the nonbasic OL/2 operations that have been implemented and illustrates the corresponding abstract tree structures for the operations. Reference [ 7 ] describes the complete set of OL/2 operations currently imple- mented and explains their uses. It can be noted that any unary or binary operation (and some n-ary operations n > 2) fit well into the expression tree format used in the OL/2 compiler, which eases the task of implementing compi- lation facilities for new OL/2 operations greatly. 31 & ^© ^0 K© V® kE) 3 o 02 m A < Q i — i & A CO. a v < J3 ^ < CO. a 83 m > CO CO K o <£ CO W CO W < o o CO o •H p CO u CD ft o 1-q o o •H W CO h3 O e g >h M ra : ; O co N CO CO CJ M \. M . I 05 o •> cu cfl c\j ft co A o O CO CO CD CD O p w 0) cO > w i s ° • « CO w -> M P CO C H CD CO 6 O 3 co "• -H J. CO CO n co d < CO CO o fv •> II a r A V ON 32 k. TEMPORARY STORAGE MINIMIZATION In an array language that is designed to operate on large arrays, there is the important problem of minimizing temporary storage when evaluating array expressions. Even if a large amount of secondary storage is available for temporary arrays, the number of input-output requests may increase pro- hibitively if care is not used in reducing the number of temporary arrays. This chapter will be concerned with some techniques for reducing temporary array variables and with pointing out some unusual problems which arise in an array language such as OL/2. The problem of compiling array expressions so that a minimum amount of temporary storage is utilized at run time for expression evaluation is a difficult one to solve. The difficulties arise from two sources. 1. The complete structure of an array expression must be known for minimization to be attempted, and this structure is not known to the compiler during initial expression parsing. 2. In OL/2 with dynamic partitioning, the compiler cannot determine the precise relationship of all array operands at compile time-- since subarrays may overlap or may not--depending upon the dynamics of the situation. The first problem may be overcome by noting that the expression tree generated by the parsing phase of the OL/2 compiler reflects the complete structure of the array expression. The second problem, which involves dynamic partitioning [1,93* allows one to partition arrays and define subarrays. The exact structure of the partitions can change dynamically at run time so that the sizes, shapes and relations of the subarrays may change dynamically. The most difficult problem that arises from partitioning, as far as compilation is 33 concerned, is the possible overlap of the subarrays. For instance, if an array is partitioned with two independent partitions, then the corresponding subarrays may overlap and the subarrays have elements in common. Since the subarrays may be referenced with independent identifiers, that is independent of the original array identifier, the compiler must look at the underlying structure which controls partitioning. The compiler is clearly limited to the static aspects of the problem. Several examples will be considered to illus- trate these points. If A, B, and C do not overlap, then no temporary variables need be generated in the array assignment A = B + C since the result of adding B and C can be accumulated directly into the storage for A, since A must be of the same dimensionality and size as the result of the operation B + C. If overlap occurs between A, B, or C, then one temporary vari- able must be generated, since accumulating B + C directly into A may overwrite some of the elements of A. Next, consider the array assignment and assume that the subarrays do not overlap. A=B*C + D + E In this case the order of evaluation becomes important. D + E can be evalu- ated first and accumulated into the storage for A. Then a temporary array must be created for B * C, call it TEMP21. Since operands are always combined in a binary manner, B * C cannot be put in A, since A has already been used to store D + E. But, if B * C is evaluated first and put directly into the storage for A, then D and E can be accumulated into the B * C result, one at a time, requiring no temporary variables. With subarrays of overlap the above analysis becomes much more complicated. The problems considered in the above examples become more involved 3h when one considers OL/2 "geometric" data types. For example, a tridiagonal matrix can be added to a rectangular matrix if both matrices have the same number of rows and columns, where nonexistent elements in the tridiagonal matrix, which are not stored, are implicitly defined as zero. The result is a rectangular matrix. Also, later versions of 01/2 will allow arrays to be real, complex, integer, or rational, and different combinations of operands will require different temporary storage sizes. The examples given suggest that the following points be considered in the design of an algorithm that is to produce a minimum temporary variable evaluation for an array expression. 1. The problem of overlap cannot be completely determined at compile time, due to dynamic partitioning, but some cases can be determined from the information structure that controls dynamic partitioning and some overlap cases definitely be eliminated. 2. The ordering of evaluations of expressions is important in relation to the number of temporary variables generated. J. Certain array size relations can be utilized. For example, subarrays require at most the same amount of storage as the parent array from which they are derived. Several criteria have been mentioned which are necessary for an algorithm that is to operate on an OL/2 expression tree to minimize temporary variables. One approach is to create a threaded tree and let the threads indicate the continuing scope of all possible temporary variables. However, further work is required to assure that all possible information available at compile time is utilized by the compiler. 35 Another approach to temporary variable handling would be to defer all decisions as to temporary generation until run time when all size and overlap information is known. The drawback of this technique is that essentially the coding of Oh/2 expressions would be deferred until run time with the optimized expression tree being passed to run time procedures. This technique would give optimal results in reducing temporary variable storage but might increase the execution time of a program considerably if a given expression to be coded were contained in a loop, but for very large arrays this extra computation time might be insignificant. Currently, the reuse of temporary variables that have already been generated is handled by the OL/2 run-time procedures. For example, in the expression A = B + C + D a temporary, call it TEMP21, would be generated for the result of C + D. B + TEMP21 is then accumulated into the storage available for TEMP21, assuming the storage size of TEMP21 is large enough for the various geometric types, TEMP21 could then be assigned to A to complete the evaluation. The reuse of temporary variables is only a subgoal of the general problem outlined above, and the storage allocated to A has not been used because of possible overlap. There are many problems which must be solved when considering the various possibilities that can arise in evaluating array expressions in language such as OL/2. Several important aspects of the problem associated with the generation of temporary arrays have been covered, but further work is required in this area. 36 5. CODING PHASE 5.1 Description of the Code Produced The task of the coder is to transform the intermediate code, in the form of the concrete expression tree, into "object" code that can be executed at run time. In OL/2, the object code produced consists of a series of call statements to assembly language operational routines, that with the proper information passed, can carry out the necessary matrix operations efficiently at run time. Essentially the coder transforms the expression tree into a linear list of object code calls that, when executed sequentially, produce the necessary expression evaluation. The object code is effectively a simu- lated parallel execution of array operations. The format of the object code is fairly flexible as far as the compiler is concerned and has the following properties. 1. The operation to be performed on the operands passed is specified by the name of the routine called. 2. The two operands are passed as arguments to the oper- ational routines as well as the name of the variable or temporary variable that is to be the result of the operation. 3« The operational routines handle all types of arrays, all geometric shapes, and all combinations- For example, a lower triangular matrix times a rectangular matrix is specified as a matrix times matrix operation with no special consideration given to the geometrical structure, since this is a task which is handled by the routine itself with the help of other information structures. 37 k. Storage for temporary results is created and deleted at run time by the operational routines under the control of storage flags passed as arguments to the routines. The reuse of temporary variables, if possible, is handled by the run time routines. 5. Negation and transposition of the operands and temporary results can be specified either before or after the operation is to be carried out. This is accomplished through the negate and transpose flags that are passed as arguments to the operational routines. 6. Sequence number computations are done in the operational routines, that is, sequences of arrays and the desig- nation of a specific array in the sequence is handled within the routine itself. 7. Null operands are also handled in the operational routines, (see [ 7 ]). Example call sequences generated for several OL/2 statements are shown in Table 5.1. It is interesting to note that such a set of calling statements could serve as the instruction set for an array processing computer system as indicated in [ I4. ] . In Table 5.1, it can be noted that temporary variable names must be created by the coder to represent temporary computational results, and that the storage allocation of the associated temporaries is under control of the coder generator through the storage allocation bits in the instruction calls. The handling of scalar expressions in the coder is delegated to the PL/1 compiler which compiles the object code for OL/2. That is, although scalar expressions are parsed into a precedence tree format, they are reassembled by 38 (a) EXPRESSION: A = a * B + C CODE: Call ©OLSMO (a, 0, 0, 0, 0, $B1, 1, 0, 0, 0, $TEMP2l) ; Call @0L0PS (0, 0, 0, 0, $TEMP21, 1, 0, 0, 0, $C1, 1, 0, 0, 0, $TEMP22) ; Call @OLOPS (0, 0, 0, 0, $TEMP22, 0, 0, 0, 0, $0L2MJLIr, 0, 1, 0, 0, $A1); (not a minimum temporary variable evaluation, see section k) (b) EXPRESSION CODE: (c) EXPRESSION: (3 = (x,y) * || - A || Call @0LINP (I, 0, 0, 0, $xl, I, 0, 0, 0, $yl, ^TEMPOl) Call @0LN0RM (l, 1, 0, 0, $A1, #TEMP02) ; ~ #TEMP01 * //^TEMPOS; A' = x' * a * * 7 * (-B) CODE: Call ©OLSMO (a * * y, 1, 0, 1, 0, $xl, 1, 0, 0, 0, $TEMP11) ; Call @0L0M0 (0, 0, 0, 0, $TEMP11, 1, 1, 0, 0, $B1, 1, 0, X, 0, $A1); (this is a minimum operation and temporary variable evaluation) Table 5.1. 01/2 Expressions and Code 39 the coder into expression strings and passed as a single argument in an operational routine calling statement. For example, in Table 5.1(c), the expression and its associated code illustrates this property. The information passed to the run- time operational routines is contained in the parameter values in the compiler generated call statements. The routines utilized to carry out the "basic Oh/2 operations are as follows: @OLSMO - carries out ARRAY- SCALAR * and VEC- SCALAR * operations. @OLOMO - carries out ARRAY * and ARRAY-VEC * operations. ©OLOPS - carries out ARRAY SUM operation and A = A operation. @OLINP - carries out INNER PROD operation. @OLNORM - carries out NORM operation. The parameter information contained in the operational calls can be defined by the following names: NODE_POINTER, SEQUENCER STORAGE_BIT, NEGATE_TAG, and TRANS PO SE_TAG . NODE_PO INTER is a pointer variable that points to a run- time dope vector that describes the storage format for an operand or a result. Pointers always begin with the character .+, followed by the OL/2 name of the variable declared, followed by the OL/2 block // in which the variable was declared. For example, Al is the name given to the run time pointer variable that points to the dop vector for the OL/2 variable A declared in block 1 of the OL/2 source code. SEQUENCE ,, is used for sequences of arrays or scalars. A zero value indicates no sequence, or the first element of a declared sequence. STORAGE_BIT is a flag that is used for dynamic storage allocation. For operands, "0" indicates that the run-time storage routines can free the run-time storage for the associated variable after the operation is completed. ko A "1" indicates that the variable is to be used after the operation is completed and that the run-time variable contents should be left intact. For results, a "0" indicates that storage is not required for a temporary result; a "1" indi- cates that storage should be created at run time for a temporary result. A NEGATE TAG that is "l" indicates that the array operand should be negated before doing the operation, (actually the elements of the array are negated as the operation proceeds at run time) . For an array result, a "1" means that the result should be negated after the operation. "0" means no negation. A TRANSP0SE_TAG that is "1" indicates that an operand should be accessed as a transpose, or the result stored as a transpose. "0" indicates that no transposition need be done. The calling formats for the operational routines can be illustrated using the parameter definitions above. Define an operand or result parameter sequence as follows: PARM_SEQUENCE = ST0RAGE_BIT, NEGATE_TAG, TRANSP0SE_TAG, SEQUENCER, N0DE_P0 INTER Then the calling formats are: ©0LSM0 - Call @0LSM0 (SCALAR_EXPRESSION_OPERAND, PARM_SEQUENCE for operand, PAEM_SEQUENCE for result) ; ©0L0M0, ©OLOPS - Call @0L0M0 ( ©0L0PS (PARM_SEQUENCE for first operand, PARM_SEQUENCE for second operand, PARM_SEQUENCE for result) ; ©OLINP - Call ©OLINP (PARM_SEQUENCE for first operand, PARM_ SEQUENCE for second operand, SCALAR_RESULT) ; ©0LN0RM - Call ©01N0RM (PARM_SEQUENCE for operand, SCALAR_RESULT) ; In the case of A = A, the second operand is filled in as an OL/2 null operand 41 in a call to ©OLOPS, since a null operand follows the rule A = + A, so that A = + B is equivalent to the assignment A = B. Warning conventions are followed for temporary variable names generated by the compiler. Variables that begin with $TEMP are node pointers to run time dope vectors of array variables. Variables that begin with $IEMP are the vari- able names corresponding to a scalar temporary value at run time. 5.2 The Coding Algorithm Basically, the coding algorithm traverses the expression tree, using a modified form of the right end order traveral algorithm T of Knuth [ 6 ] . "When an operator node is visited in the traversal, the proper parameters for the OL/2 run time object code call are built up, if necessary, in the variable CODE STRING. After the visit is completed, a completely coded call statement will exist in CODE STRING that represents the result of the operation being considered. The coding algorithm for the basic OL/2 operations, given a properly constructed expression tree, is given below. Coding for the OL/2 operations not mentioned is easily added to the given algorithm, although for some operations many special cases must be considered. The coding algorithm for the basic OL/2 operations is as follows : CA1: Traverse the expression tree using algorithm T from Knuth modified for an endorder traversal. The algorithm terminates with a pointer to the next node to be visited in an endorder traversal. CA2: If the node to be visited is a leaf (operand node) then go to CA1 (no processing need be done) ; other- wise, go to CA3> (an operator node has been found) . CA3: Set CODE STRING array members to the null string. 1+2 CAl+: Transfer to the appropriate section using the operator type contained in the operator node; go to CA5 for operator type = INNER PROD, or ARRAY -VEC *, or ARMY *, or VEC-SCALAR *, or ARRAY-SCALAR *, or ARRAY SUM, or NORM, or A = A or A = S; go to CA6 for operator type = ARRAY or TRANS; go to CA7 for operator type = S * S, S + S, S - S, s/s, s**s, s = s. CA5: Process an operation involving at least one array. Do for right and left operand nodes below the operator if present and not scalar operands; 51: Reduce #_OF_TIMES_TO_USE of operand node field by one. 52: If the storage for the operand can now be deleted, i.e., it is a temporary variable that is no longer needed, set STORAGE_BIT in CODE_STRING for this operand to '0'; otherwise set STORAGE BIT in C0DE_STRING to '1' to indicate that the operand is to be saved. 53: Put NEGATE_TAG and TRANSP0SE_TAG for the operand node in the proper position in the code string. 5^: Put SEQ_# associated with the operand (may be zero indicating a non- sequenced variable) in the proper C0DE_STRING position. End DO loop. Copy any scalar operands as strings into proper CODE STRING position. Go to CA8. k-3 CA6: Process a unary transpose or negate array operation. 1: Copy the operand node information into the operator node. 2: Complement the negate or transpose field of the operator node. Set link pointer in operand node to NULL value (making the operator node into a leaf operand node), and go to CA1 (no code need be generated) . CA7: Process an operation involving only scalar subexpressions. 71: Concatenate left and right operand scalar strings together with proper operator symbol in between and place in the operator node. 72: Set link pointers of the operand node to the NULL value (making the operator node into a result operand leaf node) . Go to CM (no code need be generated) . CA8: Set up name and code parameters for the temporary result. 8l: Get a name for the temporary result of the operation from the name pool and insert it in CODE_STRING. 82: Set the STORAGE_BIT for the result variable to '1' in CODE_STRING indicating that the run time routines must get storage for the result of the given operation. CA9: Insert the proper name into the CODE_STRING through a table lookup, of the operational routine that is to be called at run time. kk CA10: Set the link pointers of the operator node to the value NULL, making this node now a leaf operand node. CA11: Save the contents of CODE STRING, which is now the complete OL/2 run time code for the operation being considered. CA12: Go to CAM to visit the next node in the endorder sequence. 5.3 Example of Code Generation As an example of the application of the coding algorithm, consider the expression tree given in Figure 5«2. The information that would be put into the nodes of the expression tree by the tree building algorithm is given in the figure. The following steps would take place in coding the given tree: 1. The tree is traversed in right endorder, with the C node being visited. No action is taken since this is a leaf node. 2. (3 is visited with no action taken, a is visited with no action taken. 3. The node | S * S is visited, and since it is an operator node, (non-leaf node), involving only scalar operands, it is modified as in Figure 5.3(a), 'a * P' becomes a scalar string result of _S * S J with no code being generated. k. I ARRAY SCALAR * is visited, and since it is a binary operator node of a non- scalar type, code is generated and the tree modi- fied as in Figure 5.3(b). Notice that a temporary variable name is established for the array result of the operation. TEMP21 indicates that it is the first variable name generated for a tempo- rary of dimension 2. 5. Hie leaf node B is visited with no action being taken. ^5 EXPRESSION: A = B' + (a*p)*C EXPRESSION TREE: A = A NODE FIELDS GIVEN: TYPE_EXP TRANSPOSE_TAG NEGATAGE_TAG //_OF_TIMES_TO_USE SEQUENCE $ Figure 5.2. Example to be Coded h6 6. The operator node TRANS is visited. No code need be ;enerated for the transpose operation at this time, the tree changes are given in Figure 5.3(c). 7. The ARMY SUM operator node is visited, code is generated and the tree modified as in Figure 5«3(d). Notice that the transpose bit for the operand B in the call statement is set, indicating that the run time operational routine ©OLOPS should access the operand B in transposed order when B is used in the sum. The name TEMP22 is generated for the result, and the result storage bit is set to one, indicating that run time storage for the result must be found. The run time routines will reuse the storage allocated for TEMP21 if possible, since it is designated in the code as "free storage", by a zero storage bit, after the operation. 8. The leaf node A is visited with no processing done. 9. The root node of the tree A = A is visited, and code is generated for the assignment. Note that in the coding process, (see CA5:51 in coding algorithm), #_OF_TIMES_TO_USE is reduced to zero for the node TEMP22 . The storage bit for TEMP22 in the OL/2 code call to ©OLAASS is set to zero, indicating that at run time after executing the assignment operation the storage for TEMP22 can be deleted. (See Figure 5.3(e)). At this point the entire tree has been traversed and is, therefore, coded. The complete code generated for run time execution is then as follows: Call @OLSMO (a * B, 1, 0, 0, 0, $C1, 1, 0, 0, 0, $TEMP2l) ; Call @0L0PS (1, 0, 1, 0, $B1, 0, 0, 0, 0, $TEMP21, 1, 0, 0, 0, $TEMP22) ; ^7 (a) 00 s*s SCALAR 1 ARRAY- SCALAR * No code generated MATRIX 1 • SCALAR 1 MATRIX 1 Code generated: Call @0LSM0 (a* 0, 1, 0, 0, 0, $ CI, 1, 0, 0, 0, $TEMP2l) ; 1 < A >::=< B > + * >° < A >::=< B > * 1 or 1 < A >::=< B > ? BNF. Interpretation < A >: :=< B >|< A > < B > < A >: :=< empty >|< A > < B > < A >: :=< empty >|< B > Table A.l. IBNF Repetition Symbols IBNF Intrinsic Terminal Symbol < * I > < * N > <# N > .KEYWORD. 'DELIMITER' Meaning Test for and extract an identi- fier from the input string, if present, and put it in the string variable TEMPIDENT Test for and extract an integer number from the input string, if present, and put it in the string variable TEMPCONST Go to the semantic action routine labelled ACTION-n at this point in the parse Test for and extract the keyword enclosed in the periods, if pres- ent, in the input string and put it in the string variable TEMPSTRING Test for and extract the delimiter string within the quotes from the input string, if present, and put it in the string variable TEMPSTRING Example < * I > < * N > < # 5 > go to ACTION-5 .PROCEDURE. Table A. 2. IBNF Intrinsic Terminal Symbols 53 current analysis path continues. The variable OK can be set in the semantic action routines indicating that the phrase class "test" < #n > fails. The semantic action routines in TACOS are written in Pl/l, and contained in the external procedure ACT. The semantic routines have access to the input source code through the character string variable CHAR. Systems pro- cedures CARDNUM and CARDCOL can be called by the semantics, and return values that indicate the farthest point in the input source string which the parser scanner has reached. These features can be used for the isolation of source language errors. Additional details of the TACOS system may be found in Gaf fney [ 2 ] . The following pages of this appendix contain the IBNF syntactical description of Oh/2 array expressions. Appendix B contains the semantic action specification for Oh/2 array expressions. % /J********************************************************************/ /* *' /♦ ,. */ /* OL/2 ARRAY EXPRESSION SYNTAX. */ /. . . */ /* *' /*****»* **************************** *************************** *******/ ::= { ( § f * <0L2_LEFT_HA,\iD_SIDE> J* I ' = • I '<-■ ) ( ( «a« I •"NULL"' ) | <4<*z> J ' ; • 1 <#43> ) ; :: = <*I> <#8> J :: = <0L2_I DENT IFI ER> { •!_• <#iO •_!' )? I I '<• •>• )+ <«44> )? ( •(• •)• J? I ( <#2*> <#25> I <#4o> ) ; ::= ( ( •+• J •-• <#11> ) <#12> )* ::= <*13> ( •*• <0L2_DIVI0E> <*14> <#i6> )* <#17> ::= <0L2_FACT0R> ( •/■ I I I J <#15> <#16> )* ; ::= ( •**' <#18> )? :: = ( | ) ( •**• <#18> )? ; 55 <0L2_PRIMARY> ::= | * I : : = (• + • | •-• <#155> )? •(• <#20> <0L2_ARITHMETIC_EXPRESSI0N> •)• (•••• )? ; :: = <•♦• I ■-• <#155> )? <#19> { •!_' <#104> ■_!■ )? I ( •<• <#113> •>• )♦ <* )? ( ■■*" <#21> )? ; ::= <*I> <#23> ; ::= <*24> <#25> I < ; ::= ( ■♦■ I ■-■ <*155> )? <#19> ; ::= •(■ <#20> •)• I | | I ; ::= <6ASIC_REF> ( •->• )* ; ::= ( ».• )* ; ::= <*2b> <*I> <#39> ( »1_" <*10<»> •_!• )? ( •• , ' <#156> 1 <#157> ) ( •<• <# 11 3> •>• <#158> 1? ( '(' <«27> ( '»• <0L2_ARITHMETIC_EXPRESSI0N> <*29> )* •)' <#30> I <#31> ) <#38> J ::= I <*N> )? ( ••• )? ( <*N> )? <#33> ( «E' ( ■♦• | «-• )? <*N> ( •!' )? )? ; 56 ::= ■ ||« <0L2_AR ITHMET IC_EXPRESS I 0N> «||« ::= •(• <0L2_ARI THMET IC_EXPRESS I 0N> •,* <0L2_ARITHMETIC_EXPRESSI0N> <*35> •)' <#36> <0L2_800LEAN_EXP> :: = <#163> I • I' <0159> )* ; ::= ( •&• <#L60> )* ; ::= •(• <#161> •)• I •-• <#162> I ( <#164> j <#167> ) ; ::= ( ■ -•= • I •-»>• I •-.<• I •>=• I •<=• ) <41b5> ] { •=• | •>• | •<• ) <*166> ; ::= (•a* I •"NULl^ ) <#46> I <0L2_ARITHMETIC_EXPRESSI0N> ; 57 APPENDIX B /* */ /* */ /* */ /» OL/2 SEMANTIC ACTION ROUTINES FOR EXPRESSION HANDLING. */ /* */ /* */ /* */ ACT: /* OL/2 SEMANTIC ACTION ROUTINE PROCEDURE */ PROCEDURE(WHICH_ACTION_NUM) RECURSIVE; /*#+++rp+#*******V***+* + l* + + #+**±****+* ********* it********************** ^ /* */ /* the following declaration statements refer to variables */ /* that are commom to the parser scanner module and the */ /* semantic action routines. */ /* */ /*****.*■********+************** + ******* ************#********.******* + ***/ UCL WHICH_ACTION_NUM FIXED BIN 131,0) , 1 BRIDGE EXTERNAL, 2 GUCONDITION FIXED BIN (31,0) , 2 TEMPCJNST VARYING CHARACT ER ( 1 5 ) , 2 TEMPIDENT VARYING CHAR ACT ER I 32 ) , 2 TEMPSTRING VARYING CHARACTER (1001 , CHAR ENTRY (FIXED BIM31)) RETURNS (CHARCD), ACHAR ENTRY (FIXED BI N I 3 1 ) , CH AR ( 1 ) ) , (OK , INP) FIXED BINARY (31.0) EXTERNAL , CARDNUM EXTERNAL ENTRY RE TURNS ( F I XED BINARY (31,0)) , CARDCOL EXTERNAL E^TRY RE TURN S ( F I XED BINARY (31,0)) , ACTI0N(0:220) LABEL STATIC; DECLARE FARTHEST FIXED BIN(31,0) EXTERNAL INITIAL(l) ; DCL MOVCHAR ENTRY I, FIXED B IN I 3 I ) , F IXED BIN(31I); i » 58 /* */ /* THE VARIABLES BELOW ARE INITIALIZED AS INDICATED, THE */ /* FIRST TIME THAT THE PROCEDURE ACT IS TRANSFERED TO. */ /* */ /*************»********************************************* **+*******/ ACTION_12_ROUTINE(-l ) =ACTI 0N_12_R0UT I NE_PLUS ; ACTION_L2_RGUTINE(-2 ) =ACT I0N_12_R0UT I NE_M I NUS ; ACTI0N_12_R0UTINE(-3 ) =ACT I ON_ L2_ROUT INE_DI V I DE ; ACTI0N_12_RCUTINE(-4)=ACTION_12_R0UTINE_MULTIPLY; ACTI0N_12_R0UTINE(-5)=ACTI3N_12_kQUTlNE_EXP0NENTIATE; ACTIUN_12_RUUTINE(-6)=ACTIGN_12_K0UT[NE_INNER_PR0DUCT; ACTIGN_12_R0UTINE(-7)=ACTI0N_12_RUUTINE_EUUAL; ACTI0N_12_R0UTINE(-8)=ACTI0N_12_K0UTINE_N0RM; ACTI0N_12_R0UTINE(-9)=ACTI0N_12_R0UTINE_UNIMINUS; ACTI0N_12_R0UTINE(-10J=ACTI0,M_12_KGUTINE_TRANSP0SE; ACTIGN_12_R0UTlNE(-ll)=ACTI0N_l2_R0uTINE_SE0UENCE; ACTION_12_ROUTINE(-12)=ACTION_12_ROUTINE_MODIFY ; ACTI0N_12_R0UTINE(-13)=ACTIGN_12_RQUTINE_SEPARAT0R ; ACTI0N_12_KGUTINE(-].4)=ACT10N_12_R0UTINE_FUNCTI0N '; ACTIUiM_l2_R0UTlNE(-15)=ACTION_12_RGUriNE_CONCATENATE; ACTION_12_R0'JTINE(-16)=ACTION_12_R0UTINE_LHS_E_E ; ACTION_12_ROUTINE(-17)=ACTION_12_ROUTINE_PART_OF ; ACTI0N_L2_R0UTINE(-18)=ACTI0N_12_R0UTINE_0L2_C0MPARE; ACTI0N_12_R0UTINE<-19) = ACT I GN_12_ROUT I NE_B30L_0P ; ACTI0N_12_R0UTINE(-20J = ACT I ON_12_ROUT I NE_NOT_OP ; ALLOCATE TREE_NODE ; RLINK , LLINK = NULL ; STRING_POINTER = ADDR ( 0L2NULL_DUMMY ) ; #_OF_TIMES_TO_USE = UNDEFINED ; STYPE_CODE = ; StfDIMENSIONS = UNDEFINED ; NEGATE_TAG , TRANSPOSE_T AG » IDENTlTY.TAG = NO ; $OL2NULL = NODE_POINTER ; /* */ /* GO TO THE PROPER ACTION ROUTINE; THE ONE SPECIFIED IN */ /* SYNYAX. */ /* */ CALL GOTO( ACTION(WHICH_ACTION_NUM) ) ; 59 /************* ******* ************** ***************** ******************/ /* */ /* THE FOLLOWING ARE DECLARATIONS FOR SUBROUTINES USED */ /* BY THE EXPRESSION HANDLING MODULE OF THE SEMANTICS. */ /* */ /************* ****************************************** v * *****,,,* *** 4[ *^ DCL CODER_#_l ENTRY(POINTER); DCL ACT ENTRY (FIXED BINARY (31,0)) ; DCL SEARCH ENTRY { CHAR(32) VARYING t FIXED BIN (31,0) ) RETURNS ( POINTER ) , POINTER_TO_STRING ENTRY (CHAR (*) VARY I NG t ARE A (* ) ) RETURNS (POINTER); DCL auiLD_AND_STACK_SCALAR_NJDE ENTRY (FIXED BIN (31,0) , FIXED BIN (31,0) ) DCL BUlLD_AND_STACK_STRlNG_NODE ENTRY ( CHAR(IOO) VARYING ) DCL TERROR ENTRY ( FIXED BINARY (15,0) ) DCL IS_AN_0L2_ENTRY ENTRY ( CHAR<32) VARYING ) RETURNS ( BIT(l) ) /*********************************************************************/ /* */ /* EXPRESSION PARSING PRECEDENCE MATRIX. */ /* */ /************************* ********************************************/ DCL PRECEDENCE_TABLE (0:4,0:4) FIXED (15,0) INITIAL (0,1,1,1,1, 1,1,1,1,1, 1,1,2,1,2, 1,1,0,1,0, 1,1,0,1,1) ; /*********************************************************************/ /* */ /* THE STRUCTURE DECLARATION BELOW IS FOR THE OPERAND AND */ /* RESULT NODES. */ /* */ /*********************************************************************/ DECLARE 1 TREE_NODE BASED ( NODE_POINTER) , ( 2 RLINK , 2 LLINK , 2 SEU_tf_PTR , 2 STRING_PUINTER ) POINTER, ( 2 $*DIMENSlONSt 2 PART_SIZE , 2 *_OF_TIMES_TO_USE , 2 TYPE_EXP , 2 $TYPE_COOE ) FIXED BINARY (15,0) , ( 2 NEGATE_TAG , 2 TRANSP0SE_TAG , 2 IDENTITY_TAG ) 8IT (1) ; 6o /*£***** ********************************* *****************************/ /* */ /* THE DATA STRUCTURES UTILIZED IN REPEATED SUBEXPRESSION */ /* HANDLING ARE DECLARED BELOW. */ /* */ /*********************************************************************/ DCL 1 SUBTREE_TABLE (50) t ( 2 POINTER_TO_OPi , 2 P0INTER_T0_0P2 i 2 POINTER_TO_RESULT ) POINTER , 2 OPERATION FIXED BIN (15, 0) , CURRENT_TABLE_PTR FIXED BIN(15,0) INITIAL(O) ; /*********************************************************************/ /* */ /* THE DECLARATIONS BELOW ARE FOR MISCELLANEOUS VARIABLES */ /* REFERENCED BY THE EXPRESSION HANDLING MODULE. */ /* */ /***************************** *********** *****************************/ DECLARE { 0L2_ENTRY INITIAL (2 CURRENT_OP , SCALAR I ,COL_VEC I , MATRIX I MINUS IN I T MULTIPLY I , EXPONENT , UNIMINUS , CONCATEN , EQUAL IN , FUNCTION MODIFY_TO_ , LHS_ELEM , PART_OF , SCALAR_S , SCALAR_0 , MAX_TEMP INITIAH28 INITIALI-7 INITIALOO INITIALl-2 MATRIX_TIM INITIAH-1 INITIALING FIXED BINARY INITIAL )« , SUBT NITIAL NITIAL NITIAL IAL (-2 NITIAL IATE IN INITIA ATE INI ITIAL ( _TYPE I TYPE_PL ENT_EXP INITIAL TRING_M P INITI S_USED( ) , ILL J , BOO ) i LHS 0) , CO ES_SCAL 0) , FR ) ( 15,0) .TYP , F , R , P DIV (0) REE. (0) (2) (4) ) t (-4) , ITIAL ( L (-9) TIAL (- -07) , NITIAL 1 INITI RESSION (-17) ARKER I AL (-15 0:3) IN EGAL_OP LEAN IN _EE INI MPARE2 AR INIT EE INIT STATIC 0L2.ID INITIAL (1) , OTHER E(50) UNCTIO OW_VEC LUS IN IDE IN INNER. -5) , , TRAN 15) , SEPARA (-14) AL (-1 INITI , 0L2_ NITIAL ) ITIAL! _IN_C0 ITIAL( TIALl- I NIT IA IAL(-1 IAL(-9 N INITIAL ID INITIAL (3) ITIAL (-1) , ITIAL (-3) , PRODUCT INITIAL (-6) NORM INITIAL (-8) SPOSE INITIAL (-10) SEQUENCE INI TI AL (-11 ) TOR INITIAL (-13) i 2) , MARKER INITIAL (-25) AL (-16) COMPARE INITIAL (-18) (-50) (9)10)) , DCUBLE.SEQ DER INITIAL(IO) , OES b) ,UNDEFINED_TYPECODE 11) , C0MPARE1 L(-21) , 9) , OP_SCALAR_MULTIPLY ) , SCALAR_MATRIX 6i ( OL2_C0MPARATOR CHAR(2) VARYING STATIC ACT_20_INDEX , SCALAR_EXP_POINTER , SAvER_POI NTER , STK_PTR J FIXED BINARY 131,0) STATIC , I ELEMENT_EXPRESSION_FOUND ) BIT(l) STATIC , ( TYPE_0F_I0 ) FIXED BINARY (15,0) CONTROLLED , ( SCALAR_STRING_OPS ( -5 ; -1 ) CHAR (2) VARYING INITIAL ( i**i f i*i f •/• t t_i f • + • j ) STATIC , DCL ACTI0N_12_R0UTINE(-20:-l) LABEL STATIC ; DCL NESTED_COMPARE BIT(l) STATIC ; DCL ( BOOL_OP INITIAH-19) , NOT.OP ' IN I T I AL (-20) ) FIXED BIN I 15,0) STATIC ; DCL (XPTR1.XPTR2) POINTER STATIC ; DCL DIGIT_STRINGS (0:25) CHAR(2) VARYING INITIAL 1 1 • CO' , •!• , «2 l , •3» ♦ ■*• t '5 1 , »6' , •7 I , *8 t f •9 i t '10' , '11^ , •12' , 'U' t , 1«»« , '15' , '16' , '17 1 , 'IB* , '19« , •20' , »21« , % 2Z % , '23« , «24» , «25' ) YES INITIAL I'l'B) , NO INITIAL ('O'B), f (B_STRING , L_STRING) CHAR(200) VARYING ; DCL TRANSPOSE_ELMT CHARU) STATIC ; OCL UNIMINUS.FOUND BIT(l) STATIC I N I T I AL ( • • B) ; DCL SEQ.ELEMENT CHARKO) VARYING STATIC ; DCL SEMANTIC_ERR0R BIT(l) STATIC ; DCL 082 CHAR(l) STATIC INITIAL!* ■ /* 082 */ ) ; 62 /♦ */ /* ACTION ROUTINE 8 SCANS A PROSPECTIVE STATEMENT TO */ /» DETERMINE IF IT IS AN ASSIGNMENT STATEMENT. IF AN ASSIGN- */ /* MENT STATEMENT IS NOT FOUND, THE PARSER VARIABLE OK */ /* IS SET TO ZERO TO INDICATE THE FAILURE. IF AN ASSIGN- */ /* MENT STATEMENT IS FOUND APPROPRIATE INITIALIZATION IS DONE */ /* BEFORE THE STATEMENT BEGINS TO BE PROCESSED. */ /* */ /* ERROR 8 INDICATES THAT UNMATCHED PARENTHESES EXIST */ /» IN THE STATEMENT BEING SCANNED. */ /* */ /* + +********* + * + ** + + ******+*+***** + + ***++* + **** + ** + *.*.** * + ****** + +.** + * + / ACTION_8: /* INITIALIZE TO PROCESS AN ASSIGNMENT STATEMENT */ TEST_ASSIGN: DO WHILE! CHAR(INP) = • • ) ; INP = INP+1 ; END ; A_STRING = CHARI INP) ; IF A_STRING = ',• | A_STRING = •=• | A_STRING = ».« | A_STRING =•-« I A_STRING ■ "I* £ CHARUNP + l) = •_• | A_STRING = »<• THEN DO ; INP = BEGINNING_OF_STATEMENT_PTR ; STK_PTR = ; EXPRESSION_AREA = EMPTY J SEMANTIC_ERROR = NO ; /* SET COMMON SUB EXPRESSION POINTER */ CURRENT_TABLE_PTR = ; GO TO RETURN_TO_PARSER ; END ; IF A_STRING -= • ( • THEN GO TO SOUT ; INP = INP + 1 ; PARN_COUNT = 1 ; SCAN_AGAIN: CALL SCAN_UNT I L_P ASS i •(' , •)• , •;• ) ; A_STRING = CHARt INP) ; INP = INP ♦ 1 ; IF A_STRING = • ) ' THEN DO ; PARN_COUNT = PARN_COUNT - 1 ; IF PARN_COUNT = THEN GO TO TEST_ASSIGN ; GO TO SCAN_AGAIN ; END ; IF A_STRING = •(• THEN DO ; PARN_COUNT = PARN_COUNT ♦ 1 ; GO TO SCAN_AGAIN ; END ; CALL #ERRORI8) ; SOUT: INP = 8EGINNING_0F_STATEMENT_PTR ; GO TO SET_OK_ZERO_AND_RETURN ; 63 /*********************************************************************/ /* */ /* ACTION ROUTINE 9 SETS A POINTER TO THE BEGINNING OF THE */ /* CURRENT STATEMENT BEING PROCESSED. */ /* */ /*********************************************************************/ ACTI0N_9: /* SAVE POINTER TO BEGINNING OF STATEMENT */ BEGINNING_OF_STATEMENT_PTR = INP ; GO TO RETURN_TO_PARSER ; /******* ********** ********************* *******************************/ /* */ /* THE FOLLOWING ACTION ROUTINES ARE CALLED BY THE SYNTAX */ /* ANALYZER TO INDICATE THE OPERATIONAL SYMBOL CURRENTLY */ /* BEING PROCESSED. THESE ROUTINES ARE CALLED JUST BEFORE' /* AN UNSTACK OPERATION IS. TO BE DONE. */ /* */ /*********************************************************************/ ACTION_10: CURRENT_OP = PLUS; GO TO RETURN_TO_PARSER; ACTION_ll: CURRENT_OP = MINUS; GO TO return_to_parser; i * • v 6k /*** ***** ***.***.*************************+*****************************/ /* • */ /* ACTION ROUTINE 12 IS THE SECTION OF THE EXPRESSION */ /* MODULE THAT DOES AN UNSTACK OPERATION ON THE TOP ENTRY1S) */ /* IN THE PARSING STACK. A TRANSFER ON THE CURRENT OPERATOR */ /* TYPE TO BE HANDLED IS MADE TO THE APPROPRIATE SUBSECTION */ /* OF THE ROUTINE. IN THE SUBSECTION, AN OPERATOR NODE IS */ /* BUILT AND THE STACK ENTRY OR ENTRIES ARE LINKED TO IT. */ /* THE STACK ENTRYtFGR A UNARY OPERATOR) OR ENTRIES ( FOR */ /* A BINARY OPERATOR) ARE THEN POPPED FROM THE STACK. ERROR */ /* CHECKING IS DONE TO ASSUME THAT THE OPERANDS TO BE UN- */ /* STACKED ARE COMPATIBLE AS TO DIMENSIONALITY AND TYPE. */ /* THE NODE FIELDS OF THE OPERATOR RESULT NODE ARE FILLED */ /* IN, AND A STACK ENTRY IS PUSHED FOR THE SUBTREE THAT */ /* HAS JUST BEEN BUILT. */ /* SUBTREE TYPE CODES USED SRE AS FOLLOWS: */ /* = SCALAR, 1 = FUNCTION , 2 = COLUMN VECTOR , */ /* 3 = ROW VECTOR , 4 = MATRIX , 5 = NULL OPERAND , */ /* 6 - BOOLEAN RESULT. */ /* */ /* ERROR 6 INDICATES AN ATTEMPT TO ADD OPERANDS OF */ /* DIFFERENT TYPES. */ /* */ /* ERROR 9 INDICATES ILLEGAL OPERAND TYPES IN A SCALAR */ /* STRING CONCATENATION. */ /* */ /* ERROR 12 INDICATES AN ATTEMPT TO ADD OPERANDS */ /* OF DIFFERING DIMENSIONALITY. */ /* */ /* ERROR 13 INDICATES AN ATTEMPT TO DIVIDE AN ARRAY */ /* VARIABLE BY A NON SCALAR OPERAND. */ /* */ /* ERROR 14 INDICATES THAT A NON DECLARED OPERANO IN */ /* AN INNER PRODUCT CONSTRUCT HAS NOT BEEN SPECIFIED */ /* AS A PART OF ANOTHER ARRAY. */ /* */ /* ERROR 15 INDICATES THAT AN ILLEGAL OPERAND HAS BEEN */ /* FOUNO IN AN ARRAY**SCALAR CONSTRUCT. */ /* */ /* ERROR 16 INDICATES THAT AN ILLEGAL OPERAND, AS TO */ /* DIMENSIONALITY, IS INVOLVED IN A MULTIPLY. */ /* */ /* ERROR 17 INDICATES THAT AN ATTEMPT HAS BEEN MADE */ /* TO APPLY THE NORM OPERATION TO A NUN ARRAY OPERAND. */ /* */ /* ERROR 18 INDICATES AN UNDER FLOW IN THE EXPRESSION STACK. */ /* */ /* ERROR 19 INDICATES THAT ILLEGAL OPERAND TYPES ARE */ /* PRESENT IN A FUNCTION OPERATION. */ /* */ /* ERROR 20 INDICATES THAT THE OPERAND TYPES ARE ILLEGAL */ /* IN AN ASSIGNMENT STATEMENT. */ /* */ /* ERROR 21 INDICATES THAT AN ATTEMPT HAS BEEN MADE */ ** TO MAKE AN ASSIGNMENT TO AN IDENITY OPERATOR. */ /* */ '* ERROR 55 INDICATES THAT ILLEGAL OPERANDS ARE PRESENT */ /* IN A BOOLEAN OPERATION. */ '* */ /+* v ********* *m* ******** *+**++++ w ++*+it +++++++ *+++ ++++++ +++*++++++ ++++j 65 ACTI0N_12: ALLOCATE TREE_NODE IN (EXPRESSICN_AREA) ; STyPE_CODE=CURRENT_OP; STRING.POINTER ♦ SEQ_#_PTR = NULL ; " RLINK,LLINK=NULL; NEGATE_TAG , TRANSPOSED AG , IDENTITY.TAG = NO #_OF_TIMES_TO_USE = 1 ; PART_SIZE = ; CALL GOTQ( ACTION_l2_ROUTINE lCURRENT_OP) ) ; ACTION_12_ROUTINE_PLUS: ACT I ON_12_ROUT INE_MINUS: IF SUBTREE_TYPE(STK_PTR) = SCALAR I SUBTREE_TYPE ( STK_PTR-1) = SCALAR THEN GO TO SC ALAR_OP_FOUND ; IF SU8TREE_TYPE(STK_PTR)-.=SUBTREE_TYPEISTK_PTR-l) THEN CALL *ERR0R<6) ; XPTR1=SU3TREE_PTR(STK_PTR); XPTR2=SUBTREE_PTR(STK_PTR-l) ; IF XPTRi->S#DIMENSlGNS-»«XPTR2->J#DIMENSIONS THEN CALL #ERROR(12); $#DIMENSIONS=XPTRl->$#DIMENSIONS; TYPE_EXP=XPTR1->TYPE_EXP; GO TO LINK_6INARY_0P; ACTION_12_ROUTINE_OIVIDE: IF SUBTREE_TYPE( STK_PTR) = SCALAR L SUBTREE.TYPE ( STK_PTR-1) = SCALAR THEN GO TO SC ALAR_OP_FOUND ; IF SUBTREE_TYPE(STK_PTR)-. = THEN CALL *ERROR<13); XPTRl=SUBTREE_PTR(STK_PTR-l); $ #Dl MENS I ONS = XPTRl-> ^DIMENSIONS; TYPE_EXP=XPTRl->IYPE_EXP; GO TO LINK_BINARY_OP; ACTION_l2_ROUTINE_INNER_PRODUCT: DO I = 0,1 ; IF SUBTREE_TYPE(STK_PTR-I ) -= 2 THEN DO ; XPTR1 = SUBTREE_PTR( STK_PTR-l ) ; IF XPTRl -> $TYPE_CODE -= PART_OF THEN #ERR0R(1^J ; END ; END ; SU6TREE_rYPE(STK_PTR-l)=0; $*01MENSI0NS=0; TYPE_£XP=SCALAR; GOTO L1NK_BINARY_0P; CALL 66 ACTI0N_12_R0UTINE_EXP0NENTIATE: IF SU8TREE_TYPEl STK_PTR) = SCALAR £ SU8TREE_TYPE ( STK_PTR-1) = SCALAR THEN GO TO SCALAR_OP_FQUND ; IF SUBTREE_TYPE(STK_PTR)-» = THEN CALL #ERROR(15); IF SUBTREE_TYPE(STK_PTR-l)-»=4 THEN CALL #ERR0R115) XPTR1=SUBTREE_PTR(STK_PTR-1) ; $#DIMENSlONS=XPTRl->$*DIMENSIONS; TYPE_EXP=MATRIX; GO TO LINK_BINARY_OP; ACTI0N_12_R0UTINE_N0RM: IF SUBTREE_TYPE(STK_PTR) CALL #ERROR(17) ; SUBTREE. TYPE(STK_PTR)=0; $#DIMENSIONS=0; TYPE_EXP=SCALAR; GO TO LINK_UNIARY_OP ; < 2 THEN ACTION_l2_ROUTINt_UNlMINUS: XPTR1=SUBTREE_PTR(STK_PTR); $ ttD I MENS I ONS=XPTRl->$ //DIMENSIONS; TYPE_EXP=XPTR1->TYPE_EXPJ GO TO LINK_UNIARY_OP; ACTION_12_ROUTINE_TRANSPOSE: IF SUBTREE_TYPE(STK_PTR)=2 THEN SUBTREE_TYPEISTK_PTR) ,TYPE_EXP=3; ELSE IF SUBTREE_TYPE(STK_PTR)=3 THEN SUBTREE_TYPE( STK_PTR) ,TYPE_EXP=2; /* IGNORE TRANSPOSE OF A SCALAR ELSE IF SUBTREE_TYPE(STK_PTR) <= 1 THEN DO; FREE TREE_NODE; GOTO RETURN_TO_PARSER; END; ELSE do; TYPE_EXP=MATRIX; END; XPTR1=SUBTREE_PTR(STK_PTR) ; $#DIMENSIQNS=XPTRl->$#DIMENSIONS; GO TO LINK_UNIARY_OP; */ 67 ACTI0N_12_R0UTINE_MULTIPLY: IF SUBTREE_TYPE(STK_PTR) = SCALAR £ SU3TREE_TYPE( STK_PTR-1) = SCALAR THEN GO TO SC ALAR_OP_FOUND ; IF SUBTREE_TYPE(STK_PTR)<=1 THEN DO; XPTR1=SUBTREE_PTR(STK_PTR-1); $ HO I Mb NS I GNS=XPTRl->$ ^DIMENSIONS; TYPE_EXP=XPTR1->TYPE_EXP; CURRENT_OP = MATRIX_TIMES_SCALAR ; GO TO LINK_BINARY_OP; END; "" IF SUBTREE_TYPEISTK_PTR-1K=1 THEN DO; SUBTREE_TYPEISTK_PTR-1)=SUBTREE_TYPE(STK_PTR) XPTR1=SUBTREE_PTR(STK_PTR) ; $#DI ME NS I ONS=XPTRL->$ ^DIMENSIONS; TYPE_EXP=XPTR1->TYPE_EXP; CURRENT_OP = MATRIX_TIMES_SCALAR ; GO TO LINK_BINARY_OP; END; IF SUBTREE_TYPE(STK_PTR-l)=2 THEN DO; IF SUBTREE_TYPE( STK_PTR)=3 THEN DO; SUBTREE_TYPE{STK_PTR-1)=4; $*DIMENSIONS=2; TYPE_EXP=MATRIX; GO TO LINK_BINARY_OP; END; ELSE CALL KERR0RU6); GO TO RETURN_TO_PARSER ; END; IF SUBTREE_TYPE( STK_PTR-1)=3 THEN DO; IF SUBTREE_TYPE( STK_PTR)=2 THEN DO *, SUBTREE_TYPE(STK_PTR-1) = ; StfDIMENSlONS = ; CURRENT.OP = INNER_PRODUCT ; GO TO LINK_blNARY_OP ; END ; IF SUBTREE_TYPEl STK_PTR)=4 THEN DO; XPTR1=SUBTREE_PTR(STK_PTR); $ #DI MENS I ONS = XPTRi-> ^DIMENSIONS- 1; IF S*DIMENSIONS=l THEN DO; SUBTPEE_rYPE( STK_PTR-1 j=3 ; TYPE_EXP=RO*_VEC ; END; ELSE SU3TREE_TYPEISTK_PTR-1),TYPE_EXP=MATRIX; GO TO LINK_bINARY_OP; END; END; IF SUBTREE_TYPE(STK_PTR-1)=4 THEN DO; TYPE_EXP=MATRIX; XPTR1=SUB1REE_PTR(STK_PTR-1) ; XPTR2=SUBTREE_PTK(STK_PTR) ; t HD I ME NS 1 ON S = XPTR l->$* DIMENSIONS* XPTk2->$^DIMENSIONS-2; IF S*DlMENSIONb=l THEN SUBTKEF_TYPE(STK_PTR-l).TYPE_EXP=COL_VEC; GO TO LINK_BINARY_OP; END; 68 ACTION_12_ROUTINE_EQUAL: IF SUBTREE_TYPEISTK_PTR) = SUBTREE_TYPE< STK_PTR-1 ) | SUBTREE_rYPE( STK.PTRI = 5 I SUBTREE_TYPE ( STK_PTR-1 } > 1 | SU8TREE_TYPE( STK_PTR) = I SU6TREE_TYPE (STK_PTR-1) >= 2 & SUBTREE_TYPE(STK_PTR-1) <= 4 THEN DO ; XPTR1 = SUBTREE_PTR{STK_PTR-1) ; XPTR2 = SUBTREE_PTR(STK_PTR) ; IF XPTR1 -> IDENTITY_TAG THEN CALL #ERROR(21) ; $#DIMENSIONS=XPTR2->$»DIMENSIONS; TYPE_EXP=XPTR1->TYPE_EXP; GO TO LI NK_BINARY_OP; END ; CALL #ERR0R(20) ; GO TO return_to_parser; ACTION_12_R0UTINE_LHS_E_E: SrRlNG„P0INTER = POI NTER_TO_STR I NG ( A_STRING , EXPRESSIGN_AREA) ; $*DIMENSIONS = ; "] GO TO LINK_U,MIARY_0P ; ACTI0N_12_R0UTINE_SEQUENCE: ■ SEQ_#_PTR = POINTER_TO_STRING( TEMPSTRING EXPRESSION_AREA) ; A12S: XPTR1 = SUBTREE_PTR ( STK_PTR) ;' $#OIMENSIGNS = XPTR1 -> $#DlMENSIONS ; GO TO LINK_UNIARY_OP ; ACTI0N_12_R0UT INE_PART_OF: XPTR1=SU8TREE_PTR(STK_PTR) ; TREE_NGOt^XPTRL->TREE_NODE; ' XPTR1,SU3TREE_PTR(STK_PTR)=N0DE_P0INTER; XPTR1->STRING_POINTER=PQINTER_TO_STRING( B_STRING f EXPRESSICN_AREA) ; GO TO CHECK_PRINT; ACTION_12_ROUTINE_CONCATENATE: IF SUBTREE_TYPE(STK_PTR-l) -.= I SUBTREE_TYPE(STK_PTR) -.= THEN CALL #ERR0R(9) $#DIMENSIONS=0; CURRENT_OP = SCALAR_OP ; GO TO LINK_BINARY_0P; GO TO return_to_parser; ACTION_12_ROLITINE_SEPARATOR: S*DJMENSIONS=0; STRING_POINTER = AODR { COMMA_DUMMY ) CURkENT_OP = SCALAR_OP ; GO TO LINK._BINARY_OP; 69 ACTI0N_12_R0UTINE_FUNCTI0N: IF SUBTREE_TYPEISTK_PTR-l) = 1 THEN DO ; SUBTREE_TYPE(STK_PTR-l) = ; $#DIMENSIONS=0; GO TO LINK_BINARY_OP; ENO; ELSE CALL *ERR0R(19) ; /* ILLEGAL FUNCTION */ GO TO RETURN_TO_PARSER; ACTION_12_ROUTINE_MODIFY: $*DIMENSIONS=0; SUBTREE_TYPE(STK_PTR)=0; GO TO LINK_UNIARY_OP; ACTION_l2_ROUTINE_OL2_COMPARE: /* PROCESS AN OL/2 COMPARE OPERATOR */ IF SUBTREE_TYPE( STK_PTR) = SCALAR £ SUBTREE_TYPE ( STK_PTR-1) = SCALAR THEN CUKRENT_OP = SCALAR.OP ; ELSE IF SUBTREE_TYPE(STK_PTRJ = SCALAR | SUBTREE_TYPE(STK_PTR-l) = SCALAR THEN CURRENT_OP = COMPARE2 ; ELSE CURRENT_OP = COMPARE1 ; STRING.POINTER = PO I NTER_TO_STR ING ( OL2_COMP ARATOR , EXPRESSION_AREA ) ; SUBTREE_TYPE(STK_PTR - 1} = BOOLEAN ; $#DlMENSIONS = ; GO TO LlNK_BINARY_OP ; ACTION_12_ROUTINE_BOOL_OP: IF SU6TREE_TYPE(STK_PTR) -= BOOLEAN I SUBTREE.TYPE (STK_PTR-1) -= BOOLEAN THEN CALL #ERROR(55) ; $«OIMENSIONS = ; STRING_POINTER = POl NTER_TO_STRI NG ( T EMPSTR I NGt EXPRESSION_AREA) ; CURRENT_OP = SCALAR_OP ; GO TO LINKBINARYOP ; ACTION_l2_ROUTINE_NOT_OP: IF SUBTREE_TYPE(STK_PTR) -= BOOLEAN THEN CALL //ERR0R<55) ; $#DIMENSl(JNS = ; GO TO LINK_UNI ARY_OP ; 70 /*****»*****» ************************************************** *******/ /* */ /* THIS SECTICN OF THE ROUTINE DOES THE REPEATED SUBEXPRESS- */ /* ION HANDLING AS DESCRIBED IN ALGORITHM RS OF THE TEXT. */ /* */ /***m************ ******************************************* **********/ LINK_UNIARY_OP: IF CURRENT_OP = SEQUENCE I CURRENT_OP = PART_OF | CURRENT_OP = LHS_ELEMENT_EXPRESSION THEN GO TO LINK_U ; DO K = 1 TO CURRENT_TABLE_PTR ; IF SUBTREE_TABLE(KJ . PO I NTER_TO_OP 1 = SUBTREE_PTR( STK_PTR) C SUBTREE_TABLE(K). OPERATION = CURRENT_OP THEN DO ; XPTR1 = SUBTREE_TABLE(K) . PO I NTER_TO_RESULT ; XPTR1 -> #_OF_TIMES_TO_USE = XPTR1 -> #_OF_TIMES_TO_USE + 1 ; SUBTREE_PTR(STK_PTR) = XPTR1 ; XPTR1 = XPTR1 -> RLINK ; IF XPTR1 -> RLINK -*= NULL THEN XPTRl -> #_OF_TIKES_TO_USE = XPTRl -> #_OF_TIMES_TO_USE - 1 ; GO TO RETURN_TO_PARSER ; END ; END ; CURRENT_TABLE_PTR = CURRENT_TABLE_PTR + 1 ; SUBTREE_TABLE(CURRENT_TABLE_PTR) .POI NTER_TO_OP 1 = SUBTREt_PTR(STK_PTR) ; SUBTREE_TABLE(CURRENT_TABLE_PTR).P0INTER_T0_0P2 = NULL ; SUBTREE_TABLE(CURRENT_TABLE_PTR) .OPERATION = CURRENT_OP ; SUBTREE_TA8LE(CURRENT_TABLE_P0INTER).P0INTER_T0_RESULT = NODE_POINTER ; /*** *m * ^******** *************************** i* ***y/:****m**v** ******* *****/ /* */ I* THIS SECTION OF ACTION ROUTINE 12 DOES THE LINKING OF */ /* AN OPERAND NODE TO THE OPERATOR NODE FOR UNARY OPERATORS. */ /* */ J *************************** ****************^.***********^*****yt******* I LINK_U: RLINK = SUBTREE_PTR(STK_PTRJ ; CHECK_PRINT: SUBTREE_PTRiSTK_PTR)=NODE_PO INTER; IF STK_PTR = THEN CALL #ERR0RU3) ; GO TO RETURN_TO_PARSER; SCALAR_OP_FOUND: STRING_PCINTER = PO I NTER_TO_STR I NG ( SC AL AR_STR ING.OPS I CURRENT_OP) , EXPRESSION_AREA ) ; CURRENT_OP = SCALAR_OP ; StfDIMENSIONS = ; 71 LINK_B IF CUR CURRE THEN DO K = I E END ; CURREN SUBTRE SUBTR SUBTRE SUBTR SUBTRE INARY_ RENT_0 NT_0P GO TO 1 TO F SUBT STK_PT URRENT SUBTRE XP XP # ST su XP XP IF u H IF H # GO NO ; OP: P = SCALAR_OP | CURRENT.OP = EQUAL I = COMPARE! | CURRENT_OP = C0MPARE2 LINK_B ; CURRENT_TABLE_PTR ; REE_TABLE(KJ . PU I NTER_T0_OP2 = SUBTREE_PTR( R) L SUBTREE_TABLE(K). OPERATION = _0P L SU3TREE_TABLE(K) . POI NTER_TO_OP 1 = E_PTR(STK_PTR-1) THEN 00 ; TRl = SUBTREE_TABLE(KJ.POINTER_TO_RESULT TR1 -> tf_OF_TIMES_TO_USE = XPTRl -> _OF_TIMES_TO_USE + 1 ; K_PTR = STK_PTR - 1 ; BTREE_PTR(STK_PTR) = XPTRl ; TR2 = XPTRl -> LLINK ; TRl = XPTRl -> RLINK ; XPTRl -> RLINK -= NULL THEN XPTRl -> OF_TIMES_TO_USE = XPTRl -> l ; NULL THEN XPTR2 -> XPTR2 -> 1 ; _OF_TIMES_TO_USE - XPTR2 -> RLINK -» = _OF_TIMES_TU_USE = _OF_TIMES_TO_USE - TO RETURN_TO_PARSER ; T_TABLE_PTR = CURRENT_TABLE_PTR + I ; E_TABLE(CURRENT_TAbLE_PTRJ.POINTER_TO_OPl = EE_PTR(STK_PTR-1) ; E_TABLE(CURRENT_TABLE_PTR) .POI NT ER_T0_0P2 = Et_PTR(STK_PTR) ; E_TABLE(CURRENT_TABLE_PTR) .OPERATION = CURRENT_OP /*++****** + * + + *** + *** + + *** + * +++ ++*+*. it************************ *****#**/ t* */ /* THIS SECTIUN OF ACTION ROUTINE 12 LINKS THE OPERAND NODES */ /» TO THE OPERATOR NODE FOR A BINARY OPERATION. */ /* */ /I********************************************************************/ LINK_B : LLINK=SUBTREE_PTR(STK_PTR-1) ; RLINK=SUBTREE_PTR(STK_PTR); tTYPE.COOE ■ CURRENT_OP ; STK_PTR=STK_PTR-l; IF STK_PTR = THEN CALL 0ERRORU8) SUBTRE E_PTR( ST K_PTR)=NUDE_PO INTER; GO TO return_to_parser; 72 /» */ /* ACTION ROUTINE 13 STACKS A MARKER IN THE PARSING STACK TO */ /* INDICATE THE BEGINNING OF A POSSIBLE SERIES OF MULTIPLY */ /* OPERATIONS. */ /* */ ACTION_13: SUBTKEE_TYPEISTK_PTR+1)=SU3TREE_TYPE( STK_PTR); SUBTREE_PTR(STK_PTR+1)=SU6TREE_PTR(STK_PTR) ; SU6TREE_TYPE(STK_PTR)=MARKER; STK_PTR=STK_PTR+l; GO TO return_to_parser; /*********************************************************************/ /* */ /* ACTION 14 SETS THE CURRENT OPERATION TO BE INVOLVED IN */ /* AN UNSTACK TO BE THE MULTIPLY OPERATION. */ /* */ /* ACTION 15 SETS THE CURRENT OPERATION TO BE INVOLVED IN */ /* AN UNSTACK TO BE THE DIVIDE OPERATION. */ /* */ / * ** ** * * *** ♦♦J*********************?******************** ******* *******/ ACTION. 14: CURRENT_OP=MULTIPLY; GO TO RETURN_TO_PARSER; ACTION_15: CURRENT_OP=D I V IDE ; GO TO RETUKN_TO_PARSER ; 73 /♦ */ /* ACTION ROUTINE 16 CONSULTS THE MULTIPLY PRECEDENCE */ /* MATRIX TO DETERMINE IF AN UNSTACK CAN BE DONE. IF SO, */ /* ACTION ROUTINE 12 IS CALLED TO DO THE UNSTACK, AND THE */ /* ABOVE PROCEDURE IS REPEATED. OTHERWISE, IF AN UNSTACK CANNOT »/ /* BE DONE, THE ROUTINE IMMEDIATLY RETURNS TO THE PARSER. */ /* »/ /* + *+ + * + *** + + ****** + **** + ************#**** + **■************** + #*# + ***#**/ ACTI0N_16: IF CURRENT_OP = CIVIDE THEN GO TO ACTION_12 ; AGAIN_16: IF PRECEDENCE_TABLE { SUBTRtE_T YPE ( STK_PTR-1 J , SUBTREE_TYPE(STK_PTR))=0 THEN DO ; IF SUBTREE_TYPE(STK_PTR-1 J=3 & SUBTREE_TYPE(STK_PTR) -.= 2 £ SUBTREE_TYPE(STK_PTR-2)=0 THEN DO ; STK_PTR=STK_PTR-l; CURRENT_OP = MULTIPLY ; CALL ACTI12); SUBTREE_TYPE(STK_PTR+1)=SUBTREE_TYPEISTK_PTR*2) ; SUBTREE_PTR(STK_PTR+l)=SUBTRE£_PTR(STK_PTR+2) ; STK_PTR=STK_PTR-»-i; eno; current_op = multiply ; CALL ACTI12) ; IF SUBTREE_TYPE( STK_PTR-1)=MARKER THEN GO TO RETURN_TO_PARSER; GO TO AGAIN_16 ; END ; GO TO RETURN_TO_PARSER ; 7^ /* */ /* ACTION ROUTINE 17 UNSTACKS ALL RESIDUAL ELEMENTS IN THE */ /* PARSING STACK, DOWN TO A MARKER, WHEN A SEQUENCE OF MULTIPLY */ /* OPERATIONS HAS ENDED. THE PRECEDENCE MATRIX IS CONSULTED TO */ /» DETERMINE IF ALL THE MULTIPLICATIONS ARE LEGAL. */ /* */ /* ERROR 11 INOICATES AN ILLEGAL MULTIPLICATION. */ /* */ ACTION_17: IF SUBTREE_TYPE( STK_PTR- 1 )=MARKER THEN DO; SUBTREE_TYPE(STK_PTR-l)=SU8TRtE_TYPE(STK_PTR); SUBTREE_PTR(STK_PTR-1)=SUBTREE_PTR(STK_PTR); STK_PTR=STK_PTR-l; GO TO RETURN_TO_PARSER; END; IF PRECEDENCE_TABLE(SU8TREE_TYPE(STK_PTR-1) , SUBTKEE_TYPE(STK_PTR) )-=2 THEN 00; CURRENT_OP = MULTIPLY ; CALL ACT( 12) ; GO TO ACTION_17; END; CALL #ERR0R(11) ; GO TO RETURN_TO_PARSER ; /* */ /* ACTION ROUTINES 18 AND 19 SET THE CURRENT OPERATOR TO BE */ /* CONSIDERED TO EXPONENTIATE OR UNARY MINUS REPPECT I VELY . */ /* */ ACTION_18: CURRENT_CP=EXPONENTI ATE; GO TO ACTION_12; ACTI0N_19: IF - UNI MINUS_FOUND THEN GO TO RETURN_TO_PARSER ; CURRENT_OP=UNIMINUS ; UNIMINUS_F0UND = NO ; GO TO ACTION_12; 75 /^^jt.^*******.^^**.**^*******^*********^*******^* **************** ********/ /* */ /♦ ACTION 20 DETERMINES IF A PARENTHESISED CGNSTRUCT IS AN */ /* INNER PRODUCT BY COUNTING PARENTHESES AND COMMAS. */ /* */ /*********************************************************************/ ACTI0N_20: PARN_C0UNT=1 ; ACT_20_INDEX=INP; ACT_20_C0MMA_CHK: IF CHAR{ ACT_20_INDEX)=« , • £ PARN_COUNT =1 THEN DO; OK = 0; GO TO RETURN_TO_PARSER; END; ELSE IF CHARl ACT_20_INDEX)=' ( • THEN PARN_C0UNT=PARN_C0UNT+1 ; ELSE IF CHAR(ACT_20_INDEX) = « i • THEN DO; PARN_COUNT=PARN_COUNT-l; IF PARN_COUNT=0 THEN DO; OK=l; GO TO RETURN_TO_PARSER; END; END; ACT_20_INDEX=ACT_20_INDEX+l; GO TO ACT_20_C0MMA_CHK; /*********************************************************************/ /* */ /* ACTION ROUTINES 21 AND ZZ SET THE CURRENT OPERATION TO' */ I* BE CONSIDERED, AND GO TO ACTION ROUTINE 12 TO DO AN */ /* UNSTACK. */ /* */ /^t********** ********************************* ************************/ ACTI0N_2l: CURRENT_OP=TRANSPOSE ; GO TO ACTI0N_12; ACTION_22: CURRENT_OP = SEUUENCE ; GO TO ACTI0N_12; 76 /******?**************************************************************/ /* /* /* /* /* /* /* /* /* /* /* ACTION ROUTINE 23 STACKS AN IDENTIFER INTO THE EXPRESSION STACK, AFTER TESTING TO SEE IF IT IS OF THE PROPER TYPE AND HAS BEEN OEFINED. ERROR NGT.IMPLEMENTED INDICATES THE USE OF A FEATURE THAT IS NOT CURRENTLY IMPLEMENTED. ERROR 24 INDICATES THAT AN EXPRESSION STACK OVERFLOW HAS TAKEN PLACE . */ */ */ */ */ */ */ */ */ */ */ /*** + ** + + *** + *******■ + ****************** + **■***+************ ****** + * + ***/ actign_2 3: xptr i =search { temp i dent , j ) ; if xptr1=null then do; ok=o; go to return_to_parser; END; IF XPTR1 -> $TYPE_CODE = BLOCK_ARRAY | XPTR1 -> $TYPE_CODE = VECTOR_SPACE THEN CALL #ERROR{ NOT_IMPLEMENTED ) ; IDENT_DEFINED = YES; SP = XPTR1 -> STRING.POINTER ; 8_STRING = STRINGS ; SUQTREE_PTR(STK_PTR+1)=XPTR1; SUdTREE_TYPE(STK_PTR+l ) =XPTR 1->T YPE_EXP ; STK_PTR = STK_PTR ♦ 1 ; IF STK_PTR > MAX_STACK THEN CALL #ERR0R(24) ; GO TO RETURN_TO_PARSER *, /***.***** + **v* ******************* ********■********** + *** + ** ************/ /* */ /» ACTION ROUTINE 24 SETS A POINTER TO THE BEGINNING OF A */ /* SCALAR STRING AND STACKS A MARKER IN THE EXPRESSION STACK. */ /* */ /******i/ *V*V**^-***^* *************************** ***********************/ ACTI0N_24: /* SET POINTER TO BEGINNING OF A SCALAR STRING t */ SCALAR_EXP_POINTER = INP ; STK_PTR = STK_PTR *■ 1 ; SU3TREE_TYPE(STK_PTR) = SCAL AR_STR I NG.MARKER ; GO TO RETURN_TO_PARSER ; ACTION_25: /* FINISH UP SCALAR PROCESSING */ IF SCALAR_EXP_POINTER -.= INP THEN CALL BUILD_AND_STACK_SCALAR_NOJE( SC AL AR_EXP_PO INTER , INP-1 ); DO rtHILE ( SUBTREE_TYPE( STK_PTR - 1 ) - = SCALAR_STRING_MARKER ) ; CURRENT_GP = CONCATENATE ; CALL ACT112J ; END ; STK_PTR = STK_PTR - 1 ; SJ3TREE_TYPE(STK_PTR) = SUBT REE.TYPE ( STK_PTR+l ) ; SU6TREE_PTR( STK_PTR) = SUBTRE E_PTR ( STK_PTR + I ) ; GO TO RETURN_TO_PARSER ; 77 /♦ */ /* ACTION ROUTINE 26 SAVES A POINTER TO THE BEGINNING OF */ /* AN IDENTIFIER. ♦/ /* */ / 4.*+ +* + + *.*■*******.*** + *.********+* + +**+*****.************** + * ********+***/ ACTI0N_26: /* SAVE A POINTER TO THE BEGINNING OF THE IDENTIFIER */ SAVER_POINTER = INP ; ELEMENT_EXPRESSION_FQUNO = NO ; GO TO RETURN_TO_PARSER ; /* */ /* ACTION ROUTINE 27 PROCESSES A PAR ENThhS I ZED CONSTRUCT */ /* AFTER AN IDENTIFIER. AND STACKS A NUDE FOR THE IDENTIFIER. */ /* THE ACTION 70 ENTRY INTO ACTION 27 PROCESSES A PARENTHE- */ /* SIZED CONSTRUCT AND DOES NOT STACK A NODE. */ /* */ /* ERROR 11 INDICATES AN ILLEGAL MULTIPLICATION. /* */ /* ERROR UNMATCHED.PARNS INDICATES UNMATCHED PARENTHESES. */ /* */ ACTION_27: /* PROCESS PARENTHESIZED CONSTRUCT AFTER THE IDENTIFIER */ IF TYPt_OF_ID -= 0L2.ID THEN GO TU BNOT ; IF SCALAR_EXP_POINTER -.= SA VER_POI NTER THEN CALL BUILD_AND_STACK_SCALAR_N0DEI SCALAR_EXP_POINTER . S AVER_PO I NTER - 1 ) ; SEQ_ELEMENT = TEMPSTRING ; IF IO_STAT THcN CALL CRUNCH25 ACTI0N_70: A_STRING * •■ ; PARN_COUNT =1 ; DO WHILE ( PARN_COUNT > ) ; CALL SCAN_UNT1L_KEEPC J • . • { ■ t • ; • t ■ t ' I ; A_STRING = A_STRING II TEMPSTRING ; CHARACTER_SCANNED = CHAR! INP) ; IF CHARACTER_SCANNED = •)• THEN DO ; PARN_COUNT = PARN_C0UNT-1 ; IF PARN_COUNT = THEN GO TO BREADY ; end ; ELSE IF CHARACTER_SCANNED = •{• THEN PARN_COUNT a PAKN_COUNT * 1 • ELSE IF CHARACTER_SCANNED = •;■ THEN CALL TERROR! UNMATCHED_PARNS ) ; ELSE IF CHARACTER_SCANNED = •»• THEN DO; A_STRING=A_STRING| I • ,• ; END; INP = INP «■ l; end ; 78 BREADY: IF WHICH_ACTI0N_NUM = 70 THEN GO TO RETURN_TO_PARSER ; IF IO_STAT THEN CALL CRUNCH; INP = INP + 1 ; SAVfcR_POINTER = INP ; SCALAR_EXP_POINTER=INP; XPTRl = SEARCHITEMPIDENT, I) ; XPTR1 = XPTRl -> STRING_POINTER ; TEMPIDENT = XPTR 1->STR I NGS ; CALL BUILO_AND_STACK_STRING_NODel« cDOLEREn* •0 ,, B f ' II TRANSPOSE_ELMT| I • ,• I I SEQ.fcLEM ENT | | ',« I I TEMPI DENT I I '.• II A_STRING II ' )• ) ; NAMES_USED(-13) = YES ; ELEMENT_EXPRESSION_FOUND = YES ; GO TO SET_OK_ZERO_ANO_RETURN ; BNOT: IF SCALAR_EXP_POINTER -= SAVER_PO I NTER THEN CALL BUILD_ANO_STACK_SCALAR_NODE( SCAL AR_EXP_PO I NTER , SAVER_POINTER - 1 ) ; CALL BUlLD_AND_STACK_SCALAR_NODE( SAVER.POINTER , inp - l ) ; SUBTREE_TYPE ( STK_PTR ) = FUNCTION ; GO TO RETURN_TO_PARSER ; /****#*>?********.********** ********************** *** ******* ************/ /♦ */ /* ACTION ROUTINE 28 HANDLES A PL/1 FUNCTION THAT HAS AN CL/2 */ /* ARGUMENT. */ /* */ /**************************************** *****************************/ ACTI0N_28: /* SEE IF PL i FUNCTION WITH 0L2 ARGUMENT */ IF SU6TRE£_TYPE( STK_PTR ) -.= SCALAR THEN DO ; IF TYPE_OF_ID = OTHER THEN DO ; CURRENT_OP = M0DIFY_T0_TYPE_PL1 ; GO TO ACTI0N_12 ; END ; END ; GO TO RETURN_TO_PARSER ; 79 /*********************************************************************/ /* */ /* ACTION ROUTINES 29 ANO 30 SET THE CURRENT OPERATOR TO */ /* BE CONSIDERED, FOR VARIOUS OL/2 OPERATIONS, AND TRANSFER TO */ /* ACTION ROUTINE 12, THE UNSTACKING ROUTINE. */ /♦ */ /****** ********** *********************** ***^** **************** ********/ ACTI0N_29: /* BUILD AN ARGUEMANT SUBTREE */ CURRENT_OP= SEPARATOR ; GO TO ACTI0N_12 ; ACTION_30: /* FINISH OFF A FUNCTION SUBTREE */ CURRENT_OP = FUNCTION_TYPE ; SCALAR_EXP_POINTER = INP ; GO TO ACTI0N_12 ; /*********************************************************************/ I* */ /* ACTION ROUTINE 31 PROSSES AN ELEMENT EXPRESSION CON- */ /* STRUCT , IF PRESENT, AFTER AN OL/2 IDENTIFIER. */ /* */ f ********************************************************************* f ACTI0N_3i: /* HAS AN OL/2 IDENTIFIER ALONE BEEN FOUND ? */ IF TYPE_0f_ID=0L2_ID L ELEMENT_EXPRESS ION_FOUND THEN DO; INP = SAVfcR_POINTER ; GO TO return_to_parser; END ; IF TYPE_OF_ID = 0L2_ID £ -. ELEMENT_EXPRESS I ON_FOUND THEN DO ; IF SAVE_IDENT -> $#DIMENSIONS = THEN DO ; IF SCALAR_EXP_P0INTER -= S AVER_POI NTER £. CHAR(SCALAR_EXP_POINTER) -= '-• THEN CALL BUlLD_AND_iTACK_SCALAR_NODE < SCALAR_EXP_POINTER , SAVER_POI NTER - 1 ) ; SP = SAVE_IDENT -> STRI NG_PO I NTER ; A_STRING = STRINGS ; CALL BUILD_AND_STACK_STRING_[NODE < ■aOLSCALl* II A.STRING II •,* IITEMPSTRING ||«)« ); NAMES_USED(-12) = YES ; SCALAR_EXP_POINTER = INP ; ' OK = 1 ; END ; ELSE DO ; ok = o ; FREE TYPE_OF_ID ; END ; END ; GO TO RETURN_TO_PARSER J 8o /* */ /* ACTION ROUTINES 32 AND 33 ARE INVOLVED WITH THE */ /* PROCESSING OF AN ARITHMETIC CONSTANT. */ /* */ ACTION_32: /* INITIALIZE TO TEST FOR AN ARITHMETIC CONSTANT */ TEMPCONST = •■ ; GO TO RETURN_TO_PARSER ; ACTI0N_33: /* HAS ONLY A '.• BEEN FOUND ? */ IF TEMPCONST = •■ THEN OK = ; GO TO RETURN_TO_PARSER ; /* */ /* ACTION ROUTINES 34. AND 36 SET THE CURRENT OPERATION TO */ /* BE CONSIDERED FOR THE NORM AND INNER PRODUCT OPERATIONS */ /* AND TRANSFER TO THE UNSTACKING ROUTINES. */ /* */ / X*****.*#** V itZ****** ******** ******************* + ******.****%*&**** ?.*&*$ / ACTI0N_34: /* PROCESS A NORM */ CURRENT_OP = NORM ; SCALAR_EXP_POINTER = INP ; GO TO ACTI0N_12 ; ACTI0N_36: CURRENT_OP= INNER_PRODUCT; SCALAR_EXP_POINTER = INP ; GO TO ACTI0N_12 ; 8i z^^^****w.**m****** ********** *************** it**************************/ /* */ /* ACTION ROUTINES 38 AND 39 ARE INVOLVED WITH IDENTIFIER" */ /» PROCESSING: ACTION ROUTINE 39 DETERMINES THE TYPE OF */ /* IDENTIFIER PRESENT. */ /* */ /^^^^*^^**^w*** ************* *******^********^*=f- ********** **********■****/ ACTION_38: /* DON'T NEED THIS ANY MORE */ FREE TYPE_OF_ID ; GO TO RETURN_TO_PARSER " ; ACTI0N_39: /* FIND THE TYPE OF THE IDENTIFIER */ TEMPSTRING = • 0* ; ALLOCATE TYPE_OF_ID ; T£MP_POINTEkl = SEARCH( TEMPIDENT , I ) ; IF TEMP_POINTERl = NULL THEN DO ; INPUT_TYPE = IOENTIFlER_TYPECODE( I); IF IS_AN_OL2_ENTRY( TEMPIDENT ) THEN TYPE_OF_ID » 0L2_ENTRY ; ELSE rYPE_OF_ID = OTHER ; END ; ELSE DO ; TYPE_OF_ID » OL2_ID ; SAVE_IDENT = TEMP_PO INTER 1 ; END ; GO TO RETURN_TO_PARSER ; / 0^**^*^it.*^it w ********************************************************* / /* */ /* ACTION ROUTINES 35, 37, AND ^0 ARE INVOLVED WITH SCALAR */ /* STRING PROCESSING. */ /* */ /m************ *************************************************** *****/ ACTI0N_35: /* MOVE OVER A »,• OR A •)• */ SCALAR_EXP_POINTER = INP + l ; GO TO return_to_parser; ACTION.37: /* PROCESS A POSSIBLE PREVIOUS SCALAR STRING */ K = INP - 2 ; T0_37: IF SCAL AR_EXP_PO INTER «■* K THEN DO ;' CALL BUILD_AND_STACK_SCALAR_NJDE( SCALAR_EXP_POINTER , K-l) ; END ; GO TO RETURN_TO_PARSER _ t ACTI0N_40: /* UNSTACK SCALAR MARKER */ STK_PTR = STK_PTR - 1 ; GO TO SET_OK_ZERO_AND_RETURN ; 82 /* */ /* ACTION ROUTINE 41 CALLS THE EXPRESSION TREE CODER , IF NO */ /* ERRORS HAVE BEEN FOUND, WHEN THE EXPRESSION PARSING */ /» ALGORITHM HAS FINISHED BUILDING THE EXPRESSION TREE. */ /* */ /* ERROR 23 INDICATES THAT A SEMANTIC ERROR WAS */ /* OF THE EXPRESSION TREE SHOULD NOT BE DONE. */ /* FOUND BY THE EXPRESSION PARSER, AND THAT CODING */ /* OF THE EXPRESSION TREE SHOULD NOT BE DONE. */ /* */ /******♦*******»*******»**************** *****<=*************** *********/ ACTI0N_4l: /* CALL EXPRESSION TREE CODER */ IF SEMANTIC_ERROR THEN CALL #ERR0R123) ; ELSE CALL C0DER_#_1 ( SUBTREE_PTR ( STK_PTR ) ) ; GO TO RETURN_TO_PARSER; /****♦♦********»**»*********»***»*** ************************* **********/ /* */ /* ACTION ROUTINES 42 AND 43 FINISH UP PROCESSING OF AN */ /* ASSIGNMENT STATEMENT, WHICH MAY HAVE A MULTIPLE LEFT */ /* HAND SIDE, BY CALLING ACTION 12, THE UNSTACKING ROUTINE, */ /* WITH THE CURRENT OPERATION TO BE CONSIDERED SET TO */ /* EQUAL. */ /* */ /* ERROR 23 INDICATES THAT A SEMANTIC ERROR WAS */ /* FOUND BY THE EXPRESSION PARSER, AND THAT CODING */ /* OF THE EXPRESSION TREE SHOULD NOT BE DONE. */ /* */ /* ERROR 30 INDICATES THAT AN ILLEGAL OL/2 OPERATION */ /* HAS BEEN FOUND. */ /* */ ACTI0N_42: /* HANDLE ASSIGNMENT , MULTIPLE IF NECESSARY */ DO I = STK._PTR TO 2 BY -1 ; CURRENT_OP = EQUAL ; CALL ACTI12) ; END ; GO TO RETURN_TO_PARSER ; ACTI0N_43: /* HANDLE ERRORS IN AN ASSIGNMENT STATEMENT */ IF SEMANTIC_ERROR THEN CALL #ERR0R(23) ; ELSE DO ; IF FARTHEST > 6 THEN INP = FARTHEST ; CALL #ERR0R(30) ; END ; CALL SCAN_UNTlL_PASS{ f ;• ,••);/* SECOND IS 082 */ INP = INP + 1 ; GO TO RETURN_TO_PARSER ; 83 /*** ******************** ******************************* ****** *********/ /* */ /» ACT IO.NI ROUTINES 44 AND 43 SET THE CURRENT OPERATION */ /* TO BE CONSIDERED AND TRANSFER TO THE UNSTACKING ROU- */ /* TINEt ACTICN 12. */ /» */ /********************************* ****** ****** ************************/ ACTI0N_44: /* PROCESS PART-CF CONSTRUCT */ CURKENT_OP = PART_OF ; GO TO ACTI0N.12 ; ~ ACTI0N_45: /* PROCESS OL/2 ELEMENT EXPRESSION ON LHS OF */ /* AN ASSIGNMENT OPERATOR */ CURRENT_OP = LHS_ELEMENT_EXPRESSION' ; GO TO ACTION_12 ; /******«*«************************************************************/ /* */ /* ACTION ROUTINE 46 STACKS AN OL/2 NULL OPERAND. */ /*******************************************»*************************/ ACTI0N_46: /* PROCESS A "NULL" OPERAND */ STK_PTR = STK_PTR +1 ; SUBTREE_PTR(STK_PTR) = SOL2NULL ; SUBTREE_TYPE(STK_PTR) = 5 ; GO TO RETURN_TO_PARSER ; Qk /* */ /* ACTION ROUTINE 104 PROCESSES AN 01/2 SEQUENCE EXPRESSION. */ /* */ /* ERROR 53 INDICATES THAT UNMATCHED SEQUENCE BRACKETS */ /♦ EXIST. */ /* */ /****** * *.*********************** ************** ************ ****** ******/ ACTI0N_104:/* PICK UP SEQUENCE EXPRESSION */ IF IO_STAT THEN CALL CRUNCH2; CALL SCAN_UNTIL_KEEP( •_! • » •;• t f • ) ; /* LAST IS 082 */ IF CHAR(INP) = ';* THEN CALL TERROR I 21 i) ; /* TEST FOR 082 */ IF CHAR(INP) = • ' THEN DO ; CALL #ERR0R(53) ; GO TO SET_OK_ZERO_AND_RETURN ; END ; IF IO_STAT THEN CALL CRUNCH; GO TO RETURN_TO_PARSER ; /*********************************************************************/ /* */ /* ACTION ROUTINE 113 PROCESSES SUBARRAY INDICES WITHIN A */ /* PART_OF CONSTRUCT. */ /* */ /********** ******************************************** ***************/ ACTI0N_113:/* PROCESS SUBARRAY INDICES */ TEST_FOR_PART_0F: I = INP ; CALL SCAN_UNTIL_PASS( ' • /* 082 */ f •<• . •>• t • = • . • I • . ■£• , •;■ , ■-.« ) ; IF CHAR(INP) -*= •>» THEN DO ; IF CHAR(INP) = • • /* 082 */ THEN CALL #ERR0R(55) ; GO TO SET_OK_ZERO_AND_RETURN ; END ; 85 J = INP ; Inp = INP ♦ 1 ; 00 WHILE(CHAR{ INP) = • • ) ; INP = INP + 1 ; END ; DCL CH CHAR (1) STATIC; CH = CHAR(INP); IF CH -= ■■•« THEN IF CH -= •*« THEN IF CH ^= •/• THEN IF CH -= •+• THEN IF CH -= ■-■ THEN IF CH -*= • = • THEN IF CH -»= ';• THEN IF CH -.= •)' THEN IF CH -*= •<■ THEN IF -I0_STAT THEN IF -I_STAT THEN GO TO SET_OK_ZERO_AND_RETURN; ELSE DO; IF CH -= • ,« THEN GO TO set_ok_zero_and_return; end; else if ch -•= »,' then if ch -*= 'i' then if ch -.= •:• then go to set_ok_zero_and_return; if ident.defined = no then do ; INP = J ; GO TO RETURN_TO_PARSER ; END ; INP = I ; IF IO_STAT THEN CALL CRUNCH2; /**************,r**********;(.********»**t******»»**• , •<• ,■=•); A_STRING * CHAR( INP) ; IF A_STRING = • J" I A_STRING = •£■ THEN IOUT: DO ; INP = K ; GO TO SET_OK_ZERO_AND_RETURN ; END ; IF A_STRING = •;• THEN DO; CALL #ERR0R(53) ; GO TO IOUT ; END ; 87 IF A_STRING ■ M" THEN 00 ; PARN_C0UNT = PARN_C0UNT ♦ 1 ; INP = INP ♦ 1 ; GO TO I SCAN ; END ; IF A_STRING = •)• THEN DO *, PARN_COUNT = PARN_COUNT - 1 ; IF PARN_COUNT = THEN 00 ; IF -* NESTED_COMPARE THEN GO TO IOUT ; INP = K ; GO TO RETURN_TO_PARSER ; ENO ; INP * INP ♦ l ; GO TO I SCAN ; END ; IF A_STRING = • • /* 082 */ THEN DO ; CALL *ERR0R155) ; GO TO SET_OK_ZERO_AND_RETURN ; " END ; NESTED_COMPARE = YES ; INP = INP «• I ; GO TO ISCAN ; ACTI0N_162:/* HANDLE A '•■." OPERATCR */ CURRENT_OP = NOT_OP ; GO TO ACTI0N_12 ; ACTI0N_163: STK_PTR = ; EXPRESSION_AREA = EMPTY ; SEMANTIC_ERROR = NO ; CURRENT_TAbLE_PTR = ; GO TO RETURN_TO_PARSER ; ACTI0N_164: CURRENT_OP = 0L2_C0MPARE ; GO TO ACTI0N_12 ; 88 ACTI0N.165: 0L2_CCMPARAT0R = • • ; K * INP ; 00 WHILE I CHAR! INP) = ' • ) ; INP = INP - 1 ; END ; CALL M0VCHAR(0L2_C0MPARATOR, INP-1, INP J ; INP = K ; GO TO RETURN_TO_PARSER ; ACTI0N_166: 0L2_CCMPARAT0R = CHAR(INP-I) ; GO TO RETURN_TO_PARSER ; ACTI0N_167: SUBTREE_TYPE(STK_PTR) = BOOLEAN ; GO TO RETURN_TO_PARSER ; ACTI0N_168: IF SEMANTIC_ERRQR THEN CALL #ERRGR(23) ; ELSE CALL C0DER_#_1 ( SUBTREE_PTR( STK_PTR)) ; XPTR1 = SUBTREE_PTR(STK_PTR) ; XPTR1 = XPTRl->STRING_POINTER ; 0UTPUT_6UFFER = XPTR 1->STRI NGS ; OUTPUT_BUFFER = 'IF • || OUT PUT_BUFFER || • THEN • CALL SKIP_AND_OUTPUT ; OUTPUT_BUFFER = • CO /* THEN DO */ ;• ; CALL SKIP_AND_OUTPUT ; GO TO RETURN_TO_PARSER ; 8 9 /*******************************************»*************************/ /* */ /* THE FOLLOWING PROCEDURES ARE INTERNAL TO THE SEMANTIC */ /* ROUTINES OF THE EXPRESSOON HANDLING MODULE. */ /* */ /**********************************«**********************************/ /****** ¥ *************************+****************«r*:t********** + ******/ /* */ /* THE PROCEDURE SK I P_AND_OUTPUT WRITES THE PL/1 REPRE- */ /* SENTATIGN OF THE OL/2 SOURCE CODE FROM THE STRING */ /* VARIABLE CUTPUT_BUFFER, WHICH THE COMPILER HAS FILLED, */ /* INTU A FILE THAT WILL LATER BE PROCESSED BE THE PL/1 */ /* COMPILER. */ /* */ /******* ******* ****************** *********** ******************** ******/ SKIP_AND_OUTPUT: PROCEOURE ; DCL DIVIDE BUILTIN ; OCL I I . J , K ) FIXED BIN (15,0) STATIC ; I = DIVIDE ( LENGTH ( OUTPUT_BUFFER ) , 71 , 15 , ) ; J = MOD ( LENGTH ( OUTPU T_BUFFER ) , 71 ) ; DO K = I TO I ; PUT FILE(SYSPUNCH) EDIT (SUbSTR ( OUTPUT_BUFFER , 71*K-70 , 71 I ) I XII) i AI79) I ; PUT FILE(PLICODE) EDIT (SUBSTR ( 0UTPUT_8UFFER , 7l*K-70 , 71 ) ) ( X(l) , A(79) ) ; END ; IF J ■-= THEN DO ; PUT FILEISYSPUNCH) EDIT (SUBSTR ( OUTPUT_BUFFER , 71*1*1 , J ) ) ( XI 1) , A (79) ) ; PUT FILE(PLICODE) EDIT (SUBSTR ( OUT PUT_BUFFER , 71*1+1 , J ) ) ( X( 1) , A (79) ) ; END ; OUTPUT_BUFFER = ■■ ; END SKIP_AND_OUTPUT ; 90 /*******************************************************"<»** ***********/ /* */ /* THE PROCEDURE #ERROR HANDLES CL/2 ERRORS THAT HAVE */ /* BEEN FOUND. */ /* */ /*******»*************************************************************/ #ERROR: PROCEDURE ( ERROR_CODE_# ) ; DECLARE ERROR_CODE_# FIXED BINARY (15,0) ; IF ERRCR_CGDE_# >= 200 THEN ERROR_CODE_tf = ERROR_CODE_# - 170 ; ELSE IF ERROR_COOE_# >= 8 L ERROR_CODE_tf <= 21 I ERROR_CODE_# = 100 THEN SEMANTIC_ERROR = YES J ERROR.PTR = ERROR.PTR + 1 ; ERkGR_CODES( ERROR_PTR) = ERROR_CODE_# ; ERROR_ON_CARD(ERROR_PTR) = CARDNUM ; ERRCR_NEAR_COLUMN( ERROR_PTR) = CARDCOL ;' ERROR_NEAR_INP(ERROR_PTR) = INP ; IF ERROR_PTR = 50 THEN SIGNAL ERROR ; END TERROR ; /* ******* *** *»* 4c * * * *** ** ********************** **** * ** *****************/ /* */ /* THE PROCEDURE PO I NTER_TO_STRING ALLOCATES SPACE FOR */ /* A CHARACTER STRING THAT HAS BEEN. PASSED TO IT, IN */ /* AN AREA RESVERVED FOR SUCH STRINGS, AND RETURNS A */ /* POINTER TO THE STRING. */ /* */ /*****************»»********************* *** V * ****** y*v* A*************/ POINTER_TO_STRING: PROCEDURE I STRING , AREA ) RETURNS ( POINTER ) ; DECLARE STRING CHARACTER (*) VARYING , AREA AREA!*); STRING_LENGTH = LENGTH ( STRING ) ALLOCATE V AR I ABL E_STR ING IN ( AREA ) STRINGS = STRING RETURN ( SP ) END POINTER_TO_STRING 91 /* */ /* THE FOLLOWING TWC PROCEDURES bUlLD A NODE FOR A SCAL'AR */ /* STRING AND A CHARACTER STRING RESPECTIVELY, AND STACK */ /* THE NUDE IN THE EXPRESSION STACK. */ /* */ /* ERROR 24 INDICATES AN EXPRESSION STACK OVERFLOW. */ BUlLC_AND_STACK_SCALAR_\ODE: PROCEDURE ( INP1 , INP2 ) DCL ( INP1 , INP2 ) FIXED BINARY (31,0) A_STRING = • • CALL MUVCHARI A.STRING , INPl , INP2 ) GO TO LABI BUILC_AND_STACK_STRING_NODE: ENTRY ( STRING ) DCL STRING CHAR (100) VARYING A_STRING = STRING LABI: STK_PTR = STK_PTR ♦ L IF STK_PTR > MAX_STACK THEN CALL #ERR0R(24) ; ALLOCATE TREE_N0CE IN { EXPR ESS I ON_ARE A ) SUcJTREE_PTRl STK_PTR ) = NODE_POINTER SUBTREE_TYPE( STK_PTR ) = SCALAR LLINK , RLINK = NULL $#DlMENSIONS = STRING_POINTER = POI NTER_TO_S TRI NG 1 A_STRING , EXPRESSION_AREA ) #_OF_TlMES_TO_USE = UNDEFINED $TYPt_COCE,TYPE_EXP= SCALAR; SEQ_«_PTR = NULL TRANSPOSE_TAG , NEGATE_TAG , IDENTITY_TAG = NO PART_SIZE = 5 END BUILD_AND_STACK_SCALAR_NODE 92 /************ ** *************************************************** ****/ /* */ /* THE PROCEDURE SEARCH SEARCHES THE OL/2 SYMBOL TABLE FOR A */ /* SPECIFIC IDENTIFIER AND RETURNS A POINTER TO THE ROOT NODE */ /* ASSOCIATED WITH THE VARIABLE REPRESENTED BY THE IDENTIFIER. */ /* */ /***** ****9**?** ******** ********>**** ********************** ******* *****/ SEARCH; PROCEDURE. { IDENTIFIER , J J RETURNS ( POINTER ) DECLARE IDENTIFIER CHARJ32) VARYING , ITEMP_PP POINTER , ( J , I ) FIXED BINARY (31,0) ) STATIC DO I = CURRENT_ID - 1 TO 1 BY -1 TEMP_PP = IDENTIFIER_NAME_POINTER(I) IF TEMP_PP -> STRINGS = IDENTIFIER THEN DO J = I RETURN { IDENTIFIER_NODE_POINTERlI> ) END END J = RETURN I NULL ) END SEARCH ACTI0N_54: SET_OK_ZERO_AND_RETURN: OK RETURN_TO_PARSER: RETURN END ACT; i - 93 /******************************** ******** *****************************/ /* */ /* OL/2 EXPRESSION TREE CODER */ /* */ /* THE CODER WORKS BASICALLY AS OUTLINED IN THE TEXT, */ /» SEE ALGORITHM CA. THE PROCEDURE IS CALLED FROM THE */ /* SEMANTIC ROUTINES WITH THE PROCEDURE ARGUMENT POINTING */ /* TO THE ROOT OF THE COMPLETED EXPRESSION TREE. */ /* */ /*********************************************************************/ CODER_#_l: PROCEDURE ( ROOT_NODE_POINTER ) ; /******************************»******»************»****+**********:***/ /* */ /* ERROR HANDLING FACILIES FOR INTERRUPTS THAT OCCUR DURING */ /* COOING. */ /* */ /at***************!*****************************************************/ ON ERROR BEGIN ; PUT SKIP LIST{CODE_STRING ) ; GO TO END_CODER ; END ; /************************************************************«********/ /* */ /* LOCAL DECLARATIONS FOR THE CODER. */ /* */ /************«************#****+*»*;********************»■<-**********+**/ CCL EXTEMP STATIC POINTER ; DCL ( ROOT_NODE_POINTER , (P , TEMP , XPTR1 , XPTR2 ) STATIC ) POINTER , 1 STACK CONTROLLED , 2 STK_P POINTER , 2 STK_D 61 T ( 1 ) ; DCL f ( I • J ) STATIC , TEMPS_USED (0:8) INITIAL ((9X0)) ) FIXED BIN ( 15,0) ; DCL FREE_TfcMPS CHARJ9) VARYING CONTROLLED , CODc_STRlNG (1:16) CHAR(IUO) VARYING STATIC ; DCL PREC_NcEDED BIT(L) STATIC ; DCL COPY_UP ENTRY ; DCL( PTR POINTER , U FIXED BIN (15,0) ) STATIC ; 9h /»*# ********#*»* ************************************************* *****/ /* */ /» TREE TRAVERSAL ALGORITHM T FROM KNUTH. ' */ /» */ /********** ******»************************+********************* ******/ END_Tl: P = ROOT_NODE_POINTER ; END_T2: IF P = NULL THEN GO TO END_T4 ; EN0_T3: ALLOCATE STACK ; STK_P = P ; STK_0 = NO ; IF P->$TYPE_CODE = FUNC T ION_TYPE THEN DO J ALLOCATE FREE_TEMPS J FREE_TEMPS = •MARKER* ; END ; P = P->RLINK ; GO TO END_T2 ; END_T4: IF -. ALLOCAT ION (STACK) THEN GO TO END_CODER ; IF - STK_D THEN 00 ; STK_0 = YES ; P = STK_P->LLINK ; GO TO EN0_T2 ; END ; P = STK_P ; FREE STACK ; /* */ /* VISIT THE NEXT NODE IN A RIGHT ENDORDER SEQUENCE. */ /* */ VISIT: TYPE_CODE = P->$TYPE_CODE ; IF TYPE_CODE -*< THEN GO TO END.T4 ; 95 COD£_STRING = • • ; /****#*m+V+*m* + #+ + Z****yr+* + **.V. I*************************** ************/ /* */ /* TRANSFER TO PROPER SECTION OF CODER BASED ON OPERATOR TYPE. */ /* */ /*** ***it ****^*** ******** ******************* v ************** ************/ /*********************************************************************/ /* */ /* THIS SECTION PROCESSES THE OL/2 OPERATORS UNARY MINUS */ /* AND MODIFY_TO_TYPE_PLl. */ /* */ /*********************************************************************/ OPERATOR_FUUND: IF TYPE_CODE <= UNIMINUS & TYPE_CODE >= MUDIFY_TO_TYPE_PLl THEN DO *, XPTR1 - P->RLINK ; P->STRING_POINTER = X PTR 1->STRI NG_PO I NTER ; P->#_OF_TlMES_TO_USE = XPTR l->rt_OF_T I MES_TG_USE ; P->NEGATE_TAG = XPTkl->NEGAT E_T AG ; P->TRANSPOSE_TAG = XP IR l->Tk A,\lSPOSE_T AG ; IF TYPE_CODE = UNIMINUS THEN P->NEGAT E_T AG = - (P->NEGATE_TAG) ; ELSE IF TYPE_CODE = TRANSPOSE THEN P-> TRANSPOSE_TA& = -. ( P-> T RANSPOSE.T AG) ; ELSE IF TYPE_CODE = MOD 1 F Y..TO_T YPE_PL 1 THEN DO ; XPTR2 = XPTRl->STRING_POINTER ; A_STRING = XPTR2->STRINGS ; P->STRING_POINTER = POI NTER_TO_ST RI NG< A_STRING I I • -> #kOOT_NOOE.$ORIGIN' , EXPRESSION_AREA) ; END ; 96 /* */ /* THIS SECTICN PROCESSES THE OL/2 OPERATOR SEQUENCE. */ /* */ /************»*** ************************************** ***************/ ELSE DO ; /* TYPE CODE = SEQUENCE */ XPTR2 = XPTR1->SEQ_#_PTR ; IF XPTR2 -•= NULL THEN CALL TERROR ID0UBLE_SEQ) ; GO TO C0DER_1 ; END ; P->SEQ_#_PTR = XPTR1->SEQ_#_PTR ; CODER_i: P->$TYPE_CODE = XPTR1->$TYPE_C0DE ; P -> IDENTITY_TAG = XPTR 1->I DENT I TY_TAG ; P->RLINK,P->LLINK = NULL ; GO TO END_T4 ; END ; /******************************************»**************************/ /* */ /* THIS SECTION PROCESSES THE OL/2 OPERATOR FUNCT ION_T YPE */ /* AND ALSO HANDLES OPERATIONS INVOLVING STRICTLY SCALAR */ /* OPERANOS. */ /* */ /****************************************************************«****/ IF TYPE_CODE = SCALAR_OP | TYPE_CODE = FUNCTI ON_TYPE THEN DO ; PREC_NEEDED = NO ; TEMP = P->LLINK ; EXTEMP = P->RLINK ; XPTR1 = TEMP->STRING_POINTER ; XPTR2 = EXTEMP->STRING_POINTER ; A_STRING = XPTR1->STRINGS ; IF TEMP -> NEGATE_TAG THEN A_STRING = •-(• I I A_STRING II • )■ J TEMP = P-> STRING_POINTER ; IF TEMP -»= NULL THEN DO *, B_STRING = TEMP-> STRINGS ; IF B_STRING = • , • THEN DO ; n = o ; TEMP = P-> RLINK ; 97 C00ER_2: IF TEMP->$TYPE_CODE >= THEN DO; TEMP->#_GF_TIMES_TO_USE = TEMP-> #_OF_TIMES_TO_USE - 1 ; IF TEMP->#_OF_TIMES_TO_USE = THEN DO ; ALLOCATE FREE_TEMPS ; PTR = TEMP->STRING_POINTER ; FREE.TEMPS = PTK->STRINGS ; END ; END ; #=# + !; IF # = 2 THEN GO TO CODER_3 ; TEMP = P->LLINK ; GO TO C0DER_2 ; CODER_3: END ; ELSE PREC_NEEDED = YES ; A_STRING = A_STRING I I B_STRING ; END ; B_STRING = XPTR2->STRINGS ; IF EXTEMP -> NEGATE_TAG THEN B_STRING = ■-(■ I I B_STRING II • )• ; A_STRING = A.STRING I I B_STRING ; IF TYPE_CODE = F UNCT I ON_T YPE THEN DO ; TEMPS_USED(0) = TEMPS_USED ( ) + 1 ; B_STRING = l «TEMPO_» II DI G I T_STR INGS ( TEMPS_USED(0) ) ; OUTPUT_BUFFER = B.STRING II » = ' II A_STRING II • );• ; CALL SKIP_AND_OUTPUT ; A_STRING = B_STRING ; DO WHILE(FREE_TEMPS -= 'MARKER' ) ; OUTPUT_BUFFER = 'CALL • II NAMES (FREE) I I ■•( • II FREE_TEMPS II • ) ;• CALL SKlP_AND_OUTPUT ; FREE FREt_TEMPS ; NAMES_USED(FREE) = YES *, END ; FREE FREE.TEMPS ; END ; IF PREC_NEEDED THEN A_STRING = •(■ II A.STRING II •)• ; P->STRIKG_POINTER = POI N TER_TO_STRI NG I A_STR I NG , EXPRESSION_AREA) ; P->RL INK, P->LLINK = NULL '; P->STYPE_CGDE = SCALAR ; GO TO END_T4 ; END ; 9 8 IF TYPE_CODE = LHS_ELEMENT_EXPRESS ION THEN GO TO END.T*; /**+**** ******************************************************** ******/ /* */ /» THIS SECTION PROCESSES THE OL/2 OPERATORS PLUS, MINUSi */ /* AND MULTIPLY. */ /* */ /*********************** ***********-^********** ********* ***************/ IF TYPE_CODE = PLUS I TYPE_CGDE = MINUS I TYPE_CODE = MULTIPLY THEN DO ; PTR = P->LLINK ; # = 2 ; CALL COPY_UP ; PTR = P->RLINK ; » = 7 ; CALL COPY.UP ; IF TYPE_CODE = MINUS THEN DO ; IF C0DE_STRING18) = '••O^B' THEN CODE_STR I NG ( 8 ) 1» »B« ELSE CODE_STRING(8) = »»•0 ,, B• TYPE_CODE = PLUS END ; CODt_STRlNG(12) C0DE_STRING(13) CGDE_STRING(14) CODc_STRING(15) "'1 U B' I « IQI l B l I I «QI Igl •o« ; J = P->$#DIMENSIONS ; TEMPS_USED( J) = TEMPS_USED(J)+1 ; C0DE_STRING(16) = «$TEMP« |] DI GI T_STR I NGS ( J ) It •_• II OIGIT_STRINGS(TEMPS_USED(J) ) ; IF TEMPS_USED(J) > MAX_TEMPS_USED ( J ) THEN MAX_TEMPS_USED{ J ) = T£MPS_USED(J) ; CCDE_STRING(1) = NAMES! TYPE_CODE ) ; NAMES_USED(TYPE_CODE) = YES ; NAMES_USED(PLUS) = YES ; P->$TYPE_CODE = UNDEF I N ED_TYPECODE ; P->RLINK,P->LLINK = NULL ; P->STRING_P0INTER = PO I NTER_TO_STRING (CODE.STRI NG( 16) , EXPRESSICN_AREA ) ; GO TO PRINT_CODE ; END ; 99 /* */ /* THIS SECTION PROCESSES THE OL/2 OPERATOR EQUAL. */ /* */ IF TYPE_CODE = EQUAL THEN DO ; XPTR1 = P->RLINK ; XPTR2 = P-> LLINK ; IF XPTRl->$#OlMENSlUNS >0 THEN DO PTR = XPTRl ; * = 2 ; CALL COPY_UP ; C0CE_STR1NG(7) = •"1 I, B' C0DE_STRING(8J = •••0 ,, B« COOE_STRING(9) = •••0 , »B' CODE_STRING(10) = ' Q* ; CODE_STRING{ 11) = «$OLNULL» ; PTR = XPTR2 ; U = 12 ; CALL COPY_UP ; C0DE_STRING(12) ^••O^'S 1 5 IF ALLCCATION(STACK) THEN DO; P->$TYPE_CODE = XPTRl->$TYPE_CODE ; P~>NEGATE_TAG = XPTR 1->NEGAT E_T AG ; P->TRANSPLiSE_TAG = XPTRl -> TRANSPOSE.TAG P->SEQ_*_PTR = XPTR1->SEQ_#_PTR ; P->RLINK,P->LLINK = NULL ; P->STRlNG_POINTtR = XPTR 1->STR I NG_PO I NTER END ; C0DE_STRINGU) = NAMES(PLUS) ; NAMES_USED(PLUS) = YES ; GO TO PRINT_CODE ; END ; 100 IF XPTR2->$#DIMENSI0NS>0 THEN DO ; CQDE_STRING(1) = NAMES(NQRM) ; NAMES_USED(NORM) = YES ; PTR = XPTR2 ; * = 2 ; CALL COPY_UP ; TEMP = XPTR1->STRING_P0INTER ; C0DE_STRING(7) = TEMP->STRI NGS ; IF XPTR1->NEGATE_TAG THEN CODE_STR I NG ( 7 ) •-(• II C0Dc_STRING(7) II • )• ; C0DE_STRING(8) = '6' ; IF ALLOCATIONlSTACK) THEN DO ; P->NEGATE_TAG = XPTR 1->NEGATE_TAG ; P->$TYPE_COOE = SCALAR ; P->STRING_POINTER = TEMP ; END ; P->RLINK,P->LLINK = NULL ; GO TO PRINT_CODE ; END ; IF XPTR2 -> $TYPE_CODE = LHS_ELEMENT_EXPRESSION THEN DO; C00E_STRING(1) = 'aOLEASS'; NAMES_USED(-13) = YES; C0DE_STRING(2) = • • • 0' • B , • • 0* • B« ; PTR = XPTR2 -> RLINK; TEMP = PTR -> SEQ_#_PTR; IF TEMP = NULL THEN COOE_STR I NG ( 3 ) * •O i ; ELSE C0UE_STRING(3) = TEMP->STR I NGS ; TEMP=PTR -> STRING.POINTER; CODE_STRlNGK) = TEMP->STR I NGS ; TEMP = XPTR1 -> STRING_P0INTER; C0DE_STRING(5) = TEMP->STR I NGS ; TEMP = XPTR2 -> STRING_POINTER; C0DE_STRING(6) = TEMP -> STRINGS; GO TO COPY_UP_NODE; END; 101 IF XPTR2->$rYPE_C0DE = SCALAR_MATR I X THEN 00 ; C0QE_STRING(1) = NAMES { LHS_EE ) ; NAM£S_USED(LHS_EE) = YES *, TEMP = XPTR2->STRING_PUINTER ; CGDE_STRING(2) = TEMP-> STR INGS ; TEMP = XPTR2 -> SEQ_#_PTR; IF TEMP = NULL THEN CQDE_STRING ( 3 ) = •0»; ELSE C0DE_STRING(3) = T EMP->STR I NGS ; TEMP = XPTR1 -> STRING_POINTER ; C0DE_STRING(<») = TEMP->STR I NGS ; IF XPTR1->NEGATE_TAG THEN C0DE_STRING U ) = '- ( ■ 1 I C0DE_STRINGU) I I ' J • ; C0PY_UP_N0DE: IF ALLOCATION(STACK) THEN DO ; P->STRI.\G_POINTER = XPTR 1->STR ING.POI NTER P->NEGATE_TAG = XP TR 1->NEGATE_TAG ; P->RLINK,P->LLINK = NULL ; P->$TYPE_CODE = SCALAR ; END ; GO TO PRINT_COOE ; ENO ; [ /* BOTH SCALARS */ TEMP = XPTR2->STRING_P0IMTER ; A_STRING = TEMP->STRINGS ; OUTPUT_BUFFER = A_STRING II • "■ • ; TEMP = XPTR1->STRING_P01NTER ; CO0E_STRING( 1) = TEMP-> STR I NGS ; IF XPTRl->NfcGATE_TAG THEN CODE_STR ING ( 1 ) = •-!• II COOE_STRING( 1) II ■)• ; OUTPUT_bUFFER = OUTPUT_BUFFER | | CODE_STR ING( 1 ) I I • ;' ; CALL SKIP_AND_OUTPUT ; IF ALLOCATION(STACK) THEN DO ; P->STRING_POINTER = XPT K 1->STRI NG_POI NTER ; P->NEGATE_TAG = XPTR 1->NEGATE_TAG ; P->RL INK,P->LLINK = NULL ; P->$TYPE_CODE = SCALAR ; END ; GO TO END_T4 ; END ; 102 /* */ /* THIS SECTION PROCESSES THE OL/2 OPERATIONS MATRIX. */ /* TIMES.SCALAR, DIVIDE, AND EXPONENTIATE. */ /* */ IF TYPE_CODE = MATRIX_T TYPE_CODE = EXPONENTIA IF TYPE_CODE = MAT XPTR1 = P->RL IF XPTR1->$#D XPTR2 = XPTR1 = END ; ELSE XPTR2 = TYPE_COD END ; ELSE DO ; XPTR1 = P->LL XPTR2 = P->RL END ; C0DE_STRING(1) = N TEMP = XPTR2->STRI C0DE_STRING(2) = T IF XPTR2->NEGATE_T •-(' II CODE IF TYPE_CODE CODE_STR II ')• TYPE_COD END ; NAMES_USEDlTYPE_CO PTR = XPTRi ; » = 3 ; CALL COPY_UP ; C0DE_STRING(8) = • ••1"B» ; C0DE_STRING(9) = •••0 ,, B' ; C0DE_STRING{ 10) = •••0 ,, B» ; C0DE_STRINGU1) = 'O 1 ; J = P->$#DIMENSIONS ; TEMPS_USED( J) = TEMPS_USED(J CODE_STRING( 12J = «$TEMP« || OIGIT_STRINGSlTEMPS_USEDU) IF TEMPS_USEDU) > MAX_TEMPS TEMPS_USED( J) ; P->$TYPE_CODE = XP P->RLINK, P->LLINK P->STRING_POINTER I12J,EXPRESSI0N_A GO TO PRINT_CODE ; END ; IMES_SCALAR | TYPE_CODE = DIVIDE | TE THEN DO ; RIX_TIMES_SCALAR THEN DO ; INK ; IMENSIONS = THEN DO ; XPTRI ; P->LLINK ; P->LLINK ; t= OP_SCALAR_MULTIPLY ; INK ; INK ; AMES(TYPE_CODE) ; NG.POINTER ; EMP->STRINGS ; AG THEN C0DE_STRING(2J = _STRING(2) II ' ) ' ; = DIVIDE THEN DO ; INGI2J = , 1.00/( i II C0DE_STRING(2) E=OP_SCALAR_MULTIPLY ; DEI = YES ; m ; DIGIT_STRINGS( J) II ■_■ II ) ; _USEO(J) THEN MAX_TEMPS_USED(J) = TR1->$TYPE_C0DE ; = NULL ; = POINTER_TO_STRING(CODE_STRING REA J ; 105 /* */ /* THIS SECTION PROCESSES THE OL/2 OPERATION INNER PROO. */ /* */ /it*************.****************************************.***-***********/ IF TYPE_CODE = I NNER_PRGDUCT THEN DO ; C00E_STRING(1) = NAMES (CURRENT_INNER_PRODUCT) ; NAMES_USED(CURRENT_INNER_PROOUCT) = YES ; PTR = P->LLINK ; # = 2 ; CALL COPY_UP ; PTR = P->RLINK ; # = 7 ; CALL COPY_UP ; TEMPS_USED(G) = TEMPS_USED (0 ) +1 ; C00E_STRING(12) = •*TEMPO_' || DI G IT_STR I NGS I TEMPS_USED(0) ) ; P->STRING_POINTER = PO I NTER_TO_STR I NG I C0DE_STRING(12) , EXPRESS I ON_AREA ) ; P->$TYPE_CODE = SCALAR ; P->RLINK = NULL ; GO TO PRINT_CODE ; END ; /* */ /* THIS SECTION PROCESSES THE OL/2 OPERATION NORM. */ /* */ /******«*** *******»*i**» + **«** + *****»*********»*»**** + *******»*** + ♦■****/ IF TYPE_CODE = NORM THEN DO ; CODE_STRING( 1 ) = NAMES ( NORM) ; NAMfcS_UStD(NaKM) = YES ; PTR = P->RLINK ; # = 2 ; CALL COPY_UP ; TEMPS_USED10) = TE MPS_USED ( ) ♦ 1 ; C0DE_STRING(7) = •rfTEMPO.' II D I GI T_STR I NGS ( TEMPS_USED(0) ) ; P->STRING_P0INTER = PU I NTER_TO_STR I NG ( C0DE_STRING(7) , t XPR E SS I ON_AR E A ) ; C0DE_STRING(8) = D I G I T_STR IMGS ( CURRENT_NORM ) ; P->STYPE_CODE = SCALAR ; P->RLINK = NULL ; GO TO PRINT_CODE ; END ; 104 /* */ /* THIS SECTION PROCESS THE OL/2 COMPARE OPERATIONS. */ /* */ /*********♦***»»***«************»**********»************#**»**********/ IF TYPE_COOE = C0MPARE1 I TYPE_CODE = C0MPARE2 THEN DO ; PTR = P->LLINK ; » = l ; CALL COPY_UP ; IF TYPE_COOE = C0MPARE2 THEN DO ; XPTRL = P->RLINK ; XPTR2 = XPTR1->STRING_P0INTER ; C0DE_STRING(6) = XPTR2->STR I NGS I IF XPTR1->NEGATE_TAG THEN COOE.STRI NG (6 ) = »-(• II C0DE_STRING(6) I I ■ )• ; END ; ELSE DO ; PTR = P->RLINK ; # = 6 ; CALL COPY_UP ; END ; XPTR1 = P->STRING_POINTER ; A_STRING = XPTRl->STRINGS ; /* PUT IN NAMES USED */ IF TYPE_CODE = C0MPARE1 THEN DO ; B_STRING = •aiOLUCO' ; NAMES_USEDI-14) = YES ; END ; ELSE DO *, B_STRING = •aCLOCS' ; NAMES_USED(-07) = YES ; END ; A_STRING = B_STRING j| ■ (••• II A_STRING II •••» ; J = 1 ; DO WHILE (CODE_STRING( J) -«= ••> ; A_STRING = A.STRING II •»• II CODE_STRI NG ( J ) ; J = J+l ; END ; A_STRING = A_STRING II •)• ; P->STRING_P«JINTER = PO I NTER_TO_STR I NG { A_STR I NG , EXPRESSION_AREA ) ; P->RLINK,P->LLINK = NULL ; P->$TYPE_CODE = BOOLEAN ; GO TO ENQ_T4 ; END ; 105 IF TYPE_C0DE = PART_0F THEN DO ; P -> RLINK = NULL ; GO TO END_T4 ; /* PUT IN NAMES USED */ END ; IF TYPE_COOE = NOT_OP THEN DO ; XPTRl = P-> RLINK ; XPTR2 = XPTRl -> STRING.POINTER ; A_STRING = XPTR2 -> STRINGS ; P -> STRING_PGINTER = PO I NTER_TO_STR ING ( ■-•• I I A.STRING , EXPRESSION.AREA) ; P -> RLINK = NULL ; IF XPTRl -> NEGATE_TAG I XPTR1->TRANSP0SE_TAG I XPTRl -> SEQ_#_PTR -*= NULL I XPTRl -> IDENTITY_TAG THEN CALL 4ERROR(55) ; GO TO END_T4 ; CALL TERROR ( I L LEGAL_OP_IN_CODER )'; GO TO END_CODER ; /******^*^^^****wr')-***** ********* *w****f******^* *********************/ /* */ /* PRINT_CODE PRINTS THE PL/l OBJECT CODE THAT HAS BEEN */ /* BUILT UP IN CODE_STRING. */ /* */ /***,****m**** *************************************************** *******/ PRINT_CODE: OUTPUT_BUFF ER = 'CALL ' II COCE_STR I NG( 1 ) I I •(• II C0DE_STRING(2) ; 00 J = 3 TO 16 ^HILElCODt_STRING( J) i= »■ )', OUTPUT_BUFFER = OUTPUT_BUF FE R I I • . • II CODE_STRING (J) ; END ; OUTPUT_BUFFER = OUT PUT_BUF F ER II •);« ; CALL SKIP_ANO_OUTPUT ; GO TO END_T^ ; io6 ***************** ********#******#****»****************** **************/ /* */ /* C0PY_UP COPYS THE FIELDS IN THE NOOE REFERENCED BY PTR */ /» . INTO THE MEM3ER CF CODE_STRING STARTING AT THE VALUE OF #. */ /* •/ CCPY_UP: PKOC ; DCL XPTR2 POINTER STATIC ; IF PTR->#_OF_TIMES_TO_USE > THEN PTR->#_OF_T I MES_TO_USE = PTR->*_OF_TIMES_TO_USE - I ; IF PTR->«_OF_TIMES_TO_USE = THEN CODE_STR I NG ( » ) = •••0"B» ; ELSE CODE_STRINGU) = ,,, 1 ,, B' ; IF PTR->NEGATE_TAG THEN CODE_STRI NG ( #+1 ) = •••1««B' ; ELSE C0DE_STRINGU + 1) = •• , ,, B' ; IF PTR->TRANSPOSE_TAG THEN CODE_STRI NG ( tf + 2 ) = •••1 ,, B' ; ELSE C0DE_STRINGltf+2} = •• , ,, B I ; XPTR2 = PTR->SEQ_#_PTR ; IF XPTR2 = NULL THEN CODE_ST RING ( #+3 ) = «0» ; ELSE C0DE_STRINGU + 3) = XPTR2->STRI NGS ; XPTR2 = PTR->STRING_POINTER ; C0DE_STRINGl#+4) = XPTR2->STRINGS ; END COPY„UP ; END_CODER: IF TEMPS_USED ( ) > MAX_TEMPS_USED ( ) THEN MAX_TEMPS_USED(OJ = TEMPS_USED 10 ) ; END CODER_tf_l ; \ ' /* */ /* VARIABLES DECLARED IN ACT THAT ARE USED BY THE CODER. */ /* */ DCL NAMES_USED(-30:-l) BIT(l) STATIC INITIAL((30) ( 1J 'O'B J t DCL NAMES (-11:-1) CHAR{7) VARYING INITIAL ( 'aOLAASS' , •aOLSMO* , 'aOLFREE' t 'aOLNORM* , •oJOLXXX' , 'aOLINP' » 'aJOLEXP' , •aOLOtfO' , •aOLSMO* t •aoLOPS' , 'aoLOPS 1 ) static ; 107 APPENDIX C a 3 C* to CM V, J » » < o * * » * • E •» * * % * ♦ H ■* * * 2 * * ♦ 'J * + (N - t» * ^ » \ , ♦ 'Z • * ^^ a n to • o a * u o — '^ ♦ M u * * 3 3 * 10 Q * # * » W o * * 3S » < u * -• • * * » — • w ♦ »o to * * to a r-. m * * — o M ~s ??&, a * M * » H 3 ^ o a * < o * (0 j *H * £h E^ • ■« * o H a to < » 75 * 2 b ~ ~ """ * O J * >< X o IH K p f2 * u a * £ D O CH < * < * • —• U &. a • * 5 H • * •» a — Q * C > "3 * • X «. K * ■* 2 * * • o * a tO a < * O Eh • • X to * ^ > a * » _. w » D <; * S to ♦ a — . * H (M "3 3 N ^ » [H # ■« U \ £j * cm n * + N ^*. C) • J U < a a * v.m * * u n • o ~1 O 5 a * a ^ * ■ < * s a a * .M a < » * t> 3 • ^^ • + a Ul a to # C a < * H * < £ a a * * re * to < • ■ * < + a, M * 75 u >< a. » H H • •-' to =r * H »J ♦ 5 to • D * 7^ >< ■« a to • =»• (N <5 □ X < • H • U *-* r— u • o • 13 • V, p * » * + m. + — < a cu to O «*l -5 <11 * » X _• II 5 3 a u M O •• »5 rx Q —• X £h p; H Eh * *^ ."3 V II II II ii 3 g < a O Eh to 3- * «», k y a Eh fn O h q ♦ ■""4 »^ ^ N X X b a S c HI » C 1 HM a U n H o Eh to H H << O H .* J H g to &, M O . °*i J to "4 J? Q a 1 :j 9 ° fc- a to — D Ch O M M P S O a to CM w «— a " .J a X \ a a o ^ 53 a o a zz a u ,.H a o 5X a. a a io8 CM T- I -. www a n u n X a ft. a 1 o Lh .1 c/; :j i— Eh V -A n. « CM •» ftj ~ a - 3< EH'- t »- »>«• i » „ ft. o r: o o u »E-i * » cv a a a o o o I «•>. » te t- ft. «- >- r5 ft. ~ »- »— ~ r- CQ -» x - H" En a M T— *-s T— ~-* E-i «v E-" «- 1 Vt- CM 1 ■ t- m- a ca ■ ca CQ - - a a * * • « o o * * - o o - • o o www ca ca ca o * ca ca ca ca ca- ca ca ca ca ta m - - .. a a - o o o o o O O ca o o o o o - O O — • o o o o • - cr O O ■ ■ ■ ■ + * * ■ " > ■ ■ N " " ■ ~ ^^*. » "k- 1 * ■ *■ *■ * * . * * * * "ca * * * * * * *■ a o ft. * * ca ca ca ca .— * ca ca ca ca ca- ca aa * ca ca ca ca - a a m m < • - » T- < - - - - o il Eh - - T- O o o 1 i- o r- O c - o o 5 r~ O t- o ? " - i-i v>- o o U U * < "^ Eh w » w "• Q - 9 ' t/1 w » u o > o * O v>- K o w > ft. ft. • ft. «- ft. ^ ^ IZ O IZ o ft. o ca S3 X 5 ca §- a O 1 o a — • o ca c ca w - ^ w o a a- «-* a- J i- j ,-; —. j- j - ►a J a » a a o«- C 3 o «- o «- O ft. o p C '- o «- o o C o o p ca 5 ra - ca s ii C3 - (3 - ra a - a -.> J J -a ca a a- < «- < * < •" < "- < < * < «- < «- <- < < < (J u CJ « \ u >< (_> < U » u - V. U Sh U C3 D O u o » u * u — — 109 a o a o I - a o o a o o I «*» (N l« 1 k-' r-'.. ^^ * 0. » « (N .-« r— « fc t- a. C3 ~* £-. (N Si c< r: C -^ »— M C3 «— E 1 § r~ ^« ^ a tix * ►^ »^ H - *N ■» a «- d •* X •- a h T— , * v> o r- -^ E-i C e-i »— -— s. *— ^^ [HO H •- — • <-> r- m ^ <*• W r- W- CN v> Ol-V — • 1 » 1 a 1 1 ft ft CN *. -(N *E-" « ^ .— %r— ft ft ft • 0, cu o J" o :: ca o :.; o o o n O 1^ o o o a ft * a * a a ft * »M o »H * * «En »£-• ft ft ft t* a - » o wv * o % — ^ — ^ — * *. * ft - o — ~ — • o - o o o O o o - o o *■■ - o ^ a - o - m • # ^ - o - o ^ ■ " * * * a ^~ * * »o ■ -» \ * * * * a "• * :< u oq - a a a a •• S * q a a a a- a a • - o * » » - - - o • • * c o - o o o O tN £ o o o o o - o o • ■ ft *"l.. " ■ - a 1 O a < ■* • * ■ • » ■ " u * *. o — « «. - o »c + N » k ft ft ft ft ft .-a a, r- • — (M * a + .-a a - = 1 a a a a a 1 a a a a a a- a a - - o i , «— O • - • — • r* • • < «- o • H a. •- o o O m= C + r- c •- o O - o o * — • » — " . .' • - - a • ^;- • - • ■ - ft ft *■" " ■^ '~l >-^ *-* m ^^ « a >i *w «-^ ^— ft ftrf — O » E2 E-> co - O r- c H o » •A - to CO •• rz o r: t/y C- ;" - ^ *— 3t + CL, C- r- CU ii o ^ I ; CO o a O M | *^ o a c a O 1 o a 3 - ,_^ -3 » d - ►a * J »- >i a- a - a •- a a < c «~ o T o o c« II o «- o«- o a, O 3 H ro - n O o o - C3 f- rd B n a - ca - ra ^ <3 3 a X a a a -J * a a - ►a - a «- a h < X a » a » a h a o .-^ •a J a ►a <.> a o H a a a '.t a <.> » < r < < a < «~ < ^ a * < ,— < r- *c < \ >J * u u - u < u - u * a 110 9 1 y H O to r-r-r-t-fr-<-r-l-^OirgtNNM(NN(NOIM O * + * « < * * 2 u * * »o w X ^ t, -j a T- ° a a M a co < a si 9 fc " - ? 5 O H < o u t, a * o > a * ■« zz * a co a < * ^ ><« * D 5 K N < CN a \ a « H a u < p a 5 a o o * K a < v * Q< a < * * 2 u>S * M g*£ CM £ a < a a O •• s s * CN -< < * 5 a * 2 < * o g t-i a S | a i Hi M « ****** — • * a w H (N S \ a a a- p E-i 00 < 3 H H CO < E-i 2 O a u ° 3 H 2i to o CO o < 25 a 2 (N a Ph o o w ~ M u p < p a as * * + + II X o o « I CO M CO a Ill es E* 75 t H jH M f * M ,* »^ .Tj ^5 j • id y M O a u 13 3 J j 03 H 1 „-« ;-* j] E< < M *£ * > r£ » ^ E-i 10 ~h "H z* 1 w t/1 !0 ^ Ul » > a 3 \ 73 3 13 3 ~5 as h-t -d a M Ht -5 M o z & M O o 3 73 ^ a U a •• M J K :j j a + to M .■3 (-H M 73 M • M -J 72 -3 J < J > 0. - Z !j 2 73 3 73 a J O to j o o 73 O M 72 M < M M c-i M Ei O H t< H =-1 O $4 M 1 5 3 5 5 u 5 g 73 ;^ •A :j 3 c 3 z Z & rH _1 C. a. J- c o O o 73 ■^-* O o r" O M H u b U) C3 u o a 'J u < U z H M u M M M M u > c-, Id Si r< E-" t, H 7^ M 7J C3 £-i a .J O a H Q 73 ~* " 7^ a 335 E- < ™ 73 H 77J IN ^-* O t-» <"-. U Eh u \ M 2 o M M 3 M j J c Z ™ 33 T d § o < E-" M < < O < 3 £4 C3 E- J J U 'J J J (X J < < g 3 M < c g ft g & u a n U ;-} u y u 5 J ■j < z J -J Z J u J j H a J J 73 a z M w W u 1 I ■ I ■ s 1 • * < + ■ s •* •* N •* •* _ ^^ ■* "* o u • - — * n 5 a < < • \ "S n ii X • a to I I ■ ■ ■ ■ ■ * ■ K cs c; ~- c: 74 ~ (X a 2 < u u 5 •J 5 5 < g z z z 2 ZS 73 z z z »- •- 3 H :a H 73 a 3 D 73 73 77> 77> •3 3 3 c _1 a ■J J s J J J J ii C 3 3 o O 3 O O u CJ O u 'O U U U O -• ~: § x ;; K cs a c n < .^ •3 ,3 < d < ic 73 u u a J 'A J £S 77 73 z z 77 72 z Z o tfl L0 • u ^r 3- r> o O n r> n vo a s •" *~ "~ IN CM IN IN IN IN ►d 03 • a u y Id u Id -] U Id to a u y y y U ■J U y y y W (A B. u Id a U 3 7J Id O 71 33 .71 B — « 3 3 3 3 n Id 6 o o O C 3 H • m 77 i_; 1J 3 73 7J U a :j 3 • z • ^ in UJ 10 CO w 10 w 10 10 Z to OCM 3 • H ;-• 33 M fr , in m r- o •: r-t p» ^ r-l 3> 3 E-> 10 !S- 1 1 ^ rt L"> IN j) IN *■ «■ IN c- O s« '3 3 77 C c* O c « >. K ^ C3 C3 33 73 77 33 *; 33 CC M »C C H ; ._. r* ; 7> 3 C 73 3 r> O 3 O C M ■ ■ -1 [ * 13 C3 K K 33 7" a (d C — 73 CI •3 73 33 73 33 33 O t- J 1J ._; J a -) -3 7J 73; .3 73 a O i_ O M i: a M c. fN . i IN •C IN IN IN KTI IN IN IN IN IN •— Q ~ ^v ! V, \ V SB X S. V V, \ V a z J J a n3 J . 7 _3 J J a J J 73 y a 3 W O o O O g 3 O c c u JIBLIOGRAPHIC DATA HEET 1. Report No. UIUCDCS-R-72-550 3. Recipient's Accession No. . Title and Subtitle j AN APPROACH TO THE COMPILATION OF ARRAY EXPRESSIONS IN THE OL/2 LANGUAGE 5. Report Date September 1972 . Author(s) Dale Rade Jurich 8. Performing Organization Rept. UIUCDCS-R-72-550 No Performing Organization Name and Address University of Illinois at Urbana- Champaign Department of Computer Science Urbana, Illinois 6l801 10. Project/Task/Work Unit No. 11. Contract/Grant No. US NSF-GJ-328 2. Sponsoring Organization Name and Address National Science Foundation Washington, D. C. 20550 13. Type of Report & Period Covered 14. 5. Supplementary Notes 5. Abstracts This report is concerned with the compilation of array expressions, such as appear ■in the language OL/2, Operator Language 2. The basic operation and operand types that may appear in an array expression in OL/2 are defined, as well as the data structures used to represent them. The parsing of source expressions into an inter- mediate expression tree form is described, and an algorithm for generating object code from the intermediate representation is given. The problem of reducing, through compilation techniques, the storage necessary for run time temporary results is dis- cussed. The array expression compilation module for OL/2, as implemented, is pre- sented in the Appendix. '. Key Words and Document Analysis. 17a. Descriptors Array Expression, Compilation, Array Language, Array Computation b. Identifiers/Open-Ended Terms c ( OSAT1 Field/Group ail ability Statement nlimited 19. Security Class (This Report) UNCLASSIFIED 20. Security Class (This Page UNCLASSIFIED 21. No. of Pages 22. Price RM NTIS-35 ( 10- /0) USCOMM-DC 40329-P71 9 \973